Skip to content

Commit 56fb73b

Browse files
committed
test: add test for the second machine
More to come. Signed-off-by: Alexey Palazhchenko <[email protected]>
1 parent e5b7738 commit 56fb73b

File tree

2 files changed

+140
-52
lines changed

2 files changed

+140
-52
lines changed

internal/integration/helpers_test.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package integration
66

77
import (
88
"context"
9+
"crypto/x509"
10+
"encoding/pem"
911
"flag"
1012
"fmt"
1113
"os"
@@ -16,8 +18,11 @@ import (
1618

1719
"github.com/stretchr/testify/assert"
1820
"github.com/stretchr/testify/require"
19-
"github.com/talos-systems/talos/pkg/machinery/config"
21+
talosclient "github.com/talos-systems/talos/pkg/machinery/client"
22+
talosclientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
23+
machineconfig "github.com/talos-systems/talos/pkg/machinery/config"
2024
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/apimachinery/pkg/types"
2126
"k8s.io/client-go/kubernetes/scheme"
2227
capiv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
2328
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -67,6 +72,10 @@ func createCluster(ctx context.Context, t *testing.T, c client.Client, namespace
6772
},
6873
Spec: capiv1.ClusterSpec{
6974
ClusterNetwork: &capiv1.ClusterNetwork{},
75+
ControlPlaneEndpoint: capiv1.APIEndpoint{
76+
Host: clusterName + ".host",
77+
Port: 12345,
78+
},
7079
},
7180
}
7281

@@ -134,6 +143,56 @@ func createTalosConfig(ctx context.Context, t *testing.T, c client.Client, machi
134143
return talosConfig
135144
}
136145

146+
// waitForReady waits for TalosConfig to be reconciled (ready).
147+
func waitForReady(ctx context.Context, t *testing.T, c client.Client, talosConfig *bootstrapv1alpha3.TalosConfig) {
148+
t.Helper()
149+
150+
for ctx.Err() == nil {
151+
key := types.NamespacedName{
152+
Namespace: talosConfig.Namespace,
153+
Name: talosConfig.Name,
154+
}
155+
156+
err := c.Get(ctx, key, talosConfig)
157+
require.NoError(t, err)
158+
159+
if talosConfig.Status.Ready {
160+
break
161+
}
162+
163+
t.Log("Waiting ...")
164+
sleepCtx(ctx, 3*time.Second)
165+
}
166+
}
167+
168+
// parsePEMCertificate parses PEM-encoded x509 certificate.
169+
func parsePEMCertificate(t *testing.T, b []byte) *x509.Certificate {
170+
block, rest := pem.Decode(b)
171+
assert.Empty(t, rest)
172+
require.NotEmpty(t, block.Bytes)
173+
cert, err := x509.ParseCertificate(block.Bytes)
174+
require.NoError(t, err)
175+
return cert
176+
}
177+
178+
// validateClientConfig validates talosctl configuration.
179+
func validateClientConfig(t *testing.T, config *talosclientconfig.Config) *talosclient.Credentials {
180+
t.Helper()
181+
182+
assert.Len(t, config.Contexts, 1)
183+
assert.NotEmpty(t, config.Context)
184+
context := config.Contexts[config.Context]
185+
require.NotNil(t, context)
186+
187+
assert.Empty(t, context.Endpoints)
188+
assert.Empty(t, context.Nodes)
189+
creds, err := talosclient.CredentialsFromConfigContext(context)
190+
require.NoError(t, err)
191+
assert.NotEmpty(t, creds.CA)
192+
193+
return creds
194+
}
195+
137196
type runtimeMode struct {
138197
requiresInstall bool
139198
}
@@ -147,4 +206,4 @@ func (m runtimeMode) RequiresInstall() bool {
147206
}
148207

149208
// check interface
150-
var _ config.RuntimeMode = runtimeMode{}
209+
var _ machineconfig.RuntimeMode = runtimeMode{}

internal/integration/integration_test.go

Lines changed: 79 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@ package integration
66

77
import (
88
"testing"
9-
"time"
109

1110
"github.com/AlekSi/pointer"
1211
"github.com/stretchr/testify/assert"
1312
"github.com/stretchr/testify/require"
14-
"github.com/talos-systems/talos/pkg/machinery/client"
15-
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
16-
"github.com/talos-systems/talos/pkg/machinery/config"
13+
talosclientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
14+
machineconfig "github.com/talos-systems/talos/pkg/machinery/config"
1715
"github.com/talos-systems/talos/pkg/machinery/config/configloader"
18-
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
16+
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/generate"
17+
"gopkg.in/yaml.v2"
1918
corev1 "k8s.io/api/core/v1"
2019
"k8s.io/apimachinery/pkg/types"
2120
)
@@ -30,76 +29,106 @@ func TestIntegration(t *testing.T) {
3029
cluster := createCluster(ctx, t, c, namespaceName)
3130
machine := createMachine(ctx, t, c, cluster)
3231
talosConfig := createTalosConfig(ctx, t, c, machine)
32+
waitForReady(ctx, t, c, talosConfig)
3333

34-
// wait for TalosConfig to be reconciled
35-
for ctx.Err() == nil {
36-
key := types.NamespacedName{
37-
Namespace: namespaceName,
38-
Name: talosConfig.Name,
39-
}
40-
41-
err := c.Get(ctx, key, talosConfig)
34+
// check talosConfig
35+
{
36+
assert.Equal(t, machine.Name+"-bootstrap-data", pointer.GetString(talosConfig.Status.DataSecretName), "%+v", talosConfig)
37+
clientConfig, err := talosclientconfig.FromString(talosConfig.Status.TalosConfig)
4238
require.NoError(t, err)
43-
44-
if talosConfig.Status.Ready {
45-
break
46-
}
47-
48-
t.Log("Waiting ...")
49-
sleepCtx(ctx, 5*time.Second)
39+
creds := validateClientConfig(t, clientConfig)
40+
talosCA := parsePEMCertificate(t, creds.CA)
41+
_ = talosCA
42+
// t.Logf("Talos CA:\n%s", spew.Sdump(talosCA))
5043
}
5144

52-
assert.Equal(t, machine.Name+"-bootstrap-data", pointer.GetString(talosConfig.Status.DataSecretName), "%+v", talosConfig)
53-
54-
clientConfig, err := clientconfig.FromString(talosConfig.Status.TalosConfig)
55-
require.NoError(t, err)
56-
assert.Len(t, clientConfig.Contexts, 1)
57-
assert.NotEmpty(t, clientConfig.Context)
58-
context := clientConfig.Contexts[clientConfig.Context]
59-
require.NotNil(t, context)
60-
61-
assert.Empty(t, context.Endpoints)
62-
assert.Empty(t, context.Nodes)
63-
creds, err := client.CredentialsFromConfigContext(context)
64-
require.NoError(t, err)
65-
assert.NotEmpty(t, creds.CA)
66-
45+
// get <cluster>-ca secret
6746
var caSecret corev1.Secret
6847
key := types.NamespacedName{
6948
Namespace: namespaceName,
7049
Name: cluster.Name + "-ca",
7150
}
7251
require.NoError(t, c.Get(ctx, key, &caSecret))
73-
assert.Len(t, caSecret.Data, 2)
74-
assert.Equal(t, corev1.SecretTypeOpaque, caSecret.Type) // TODO why not SecretTypeTLS?
75-
assert.NotEmpty(t, creds.Crt.Certificate, caSecret.Data[corev1.TLSCertKey]) // TODO decode and load
76-
assert.NotEmpty(t, caSecret.Data[corev1.TLSPrivateKeyKey])
7752

53+
// check <cluster>-ca secret
54+
{
55+
assert.Len(t, caSecret.Data, 2)
56+
assert.Equal(t, corev1.SecretTypeOpaque, caSecret.Type) // TODO why not SecretTypeTLS?
57+
assert.NotEmpty(t, caSecret.Data[corev1.TLSCertKey])
58+
assert.NotEmpty(t, caSecret.Data[corev1.TLSPrivateKeyKey])
59+
kubeCA := parsePEMCertificate(t, caSecret.Data[corev1.TLSCertKey])
60+
_ = kubeCA
61+
// t.Logf("kubeCA:\n%s", spew.Sdump(kubeCA))
62+
}
63+
64+
// get <cluster>-talos secret
7865
var talosSecret corev1.Secret
7966
key = types.NamespacedName{
8067
Namespace: namespaceName,
8168
Name: cluster.Name + "-talos",
8269
}
8370
require.NoError(t, c.Get(ctx, key, &talosSecret))
84-
assert.Len(t, talosSecret.Data, 3)
85-
assert.NotEmpty(t, talosSecret.Data["certs"]) // TODO more tests
86-
assert.NotEmpty(t, talosSecret.Data["kubeSecrets"])
87-
assert.NotEmpty(t, talosSecret.Data["trustdInfo"])
8871

72+
// check <cluster>-talos secret
73+
{
74+
assert.Len(t, talosSecret.Data, 3)
75+
assert.NotEmpty(t, talosSecret.Data["certs"])
76+
assert.NotEmpty(t, talosSecret.Data["kubeSecrets"])
77+
assert.NotEmpty(t, talosSecret.Data["trustdInfo"])
78+
}
79+
80+
// get <machine>-bootstrap-data secret
8981
var bootstrapDataSecret corev1.Secret
9082
key = types.NamespacedName{
9183
Namespace: namespaceName,
9284
Name: machine.Name + "-bootstrap-data",
9385
}
9486
require.NoError(t, c.Get(ctx, key, &bootstrapDataSecret))
95-
assert.Len(t, bootstrapDataSecret.Data, 1)
96-
provider, err := configloader.NewFromBytes(bootstrapDataSecret.Data["value"])
97-
require.NoError(t, err)
9887

99-
provider.(*v1alpha1.Config).ClusterConfig.ControlPlane.Endpoint.Host = "FIXME"
88+
// check <machine>-bootstrap-data secret
89+
var provider machineconfig.Provider
90+
{
91+
assert.Len(t, bootstrapDataSecret.Data, 1)
92+
var err error
93+
provider, err = configloader.NewFromBytes(bootstrapDataSecret.Data["value"])
94+
require.NoError(t, err)
95+
_, err = provider.Validate(runtimeMode{false}, machineconfig.WithStrict())
96+
require.NoError(t, err)
97+
}
98+
99+
// cross-checks
100+
{
101+
secretsBundle := generate.NewSecretsBundleFromConfig(generate.NewClock(), provider)
102+
103+
var certs generate.Certs
104+
require.NoError(t, yaml.Unmarshal(talosSecret.Data["certs"], &certs))
105+
assert.NotEmpty(t, certs.Admin)
106+
certs.Admin = nil
107+
assert.Equal(t, secretsBundle.Certs, &certs)
108+
assert.Equal(t, caSecret.Data[corev1.TLSCertKey], certs.K8s.Crt)
109+
110+
var kubeSecrets generate.Secrets
111+
require.NoError(t, yaml.Unmarshal(talosSecret.Data["kubeSecrets"], &kubeSecrets))
112+
assert.Equal(t, secretsBundle.Secrets, &kubeSecrets)
113+
114+
var trustdInfo generate.TrustdInfo
115+
require.NoError(t, yaml.Unmarshal(talosSecret.Data["trustdInfo"], &trustdInfo))
116+
assert.Equal(t, secretsBundle.TrustdInfo, &trustdInfo)
117+
}
118+
119+
// create the second machine
120+
machine2 := createMachine(ctx, t, c, cluster)
121+
talosConfig2 := createTalosConfig(ctx, t, c, machine2)
122+
waitForReady(ctx, t, c, talosConfig2)
123+
124+
// get <machine>-bootstrap-data secret
125+
var bootstrapDataSecret2 corev1.Secret
126+
key = types.NamespacedName{
127+
Namespace: namespaceName,
128+
Name: machine2.Name + "-bootstrap-data",
129+
}
130+
require.NoError(t, c.Get(ctx, key, &bootstrapDataSecret2))
100131

101-
// TODO more tests
102-
_, err = provider.Validate(runtimeMode{false}, config.WithStrict())
103-
require.NoError(t, err)
132+
assert.Equal(t, bootstrapDataSecret.Data, bootstrapDataSecret2.Data) // ?!
104133
})
105134
}

0 commit comments

Comments
 (0)