Skip to content

Commit e5b7738

Browse files
committed
test: add more tests
More to come. Signed-off-by: Alexey Palazhchenko <[email protected]>
1 parent bc4105d commit e5b7738

File tree

7 files changed

+238
-104
lines changed

7 files changed

+238
-104
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ env-up: talosctl ## Start development environment.
135135
--name=cabpt-env \
136136
--kubernetes-version=$(K8S_VERSION) \
137137
--mtu=1450 \
138+
--skip-kubeconfig \
138139
--crashdump
139140
./talosctl kubeconfig kubeconfig \
140141
--talosconfig=talosconfig \

controllers/talosconfig_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
"sigs.k8s.io/controller-runtime/pkg/source"
4242

4343
bootstrapv1alpha3 "github.com/talos-systems/cluster-api-bootstrap-provider-talos/api/v1alpha3"
44+
// +kubebuilder:scaffold:imports
4445
)
4546

4647
const (

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/talos-systems/cluster-api-bootstrap-provider-talos
33
go 1.16
44

55
require (
6+
github.com/AlekSi/pointer v1.1.0
67
github.com/evanphx/json-patch v4.11.0+incompatible
78
github.com/go-logr/logr v0.1.0
89
github.com/spf13/pflag v1.0.5

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
578578
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
579579
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
580580
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
581+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
581582
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
582583
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
583584
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
package integration
6+
7+
import (
8+
"context"
9+
"flag"
10+
"fmt"
11+
"os"
12+
"strconv"
13+
"strings"
14+
"testing"
15+
"time"
16+
17+
"github.com/stretchr/testify/assert"
18+
"github.com/stretchr/testify/require"
19+
"github.com/talos-systems/talos/pkg/machinery/config"
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
"k8s.io/client-go/kubernetes/scheme"
22+
capiv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
23+
"sigs.k8s.io/controller-runtime/pkg/client"
24+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
25+
26+
bootstrapv1alpha3 "github.com/talos-systems/cluster-api-bootstrap-provider-talos/api/v1alpha3"
27+
// +kubebuilder:scaffold:imports
28+
)
29+
30+
var skipCleanup bool
31+
32+
func init() {
33+
const env = "INTEGRATION_SKIP_CLEANUP"
34+
def, _ := strconv.ParseBool(os.Getenv(env))
35+
flag.BoolVar(&skipCleanup, "skip-cleanup", def, fmt.Sprintf("Cleanup after tests [%s]", env))
36+
}
37+
38+
// sleepCtx blocks until ctx is canceled or timeout passed.
39+
func sleepCtx(ctx context.Context, timeout time.Duration) {
40+
sCtx, sCancel := context.WithTimeout(ctx, timeout)
41+
defer sCancel()
42+
<-sCtx.Done()
43+
}
44+
45+
// generateName generates a unique name.
46+
func generateName(t *testing.T, kind string) string {
47+
// use milliseconds since UTC midnight: unique enough, short enough, ordered
48+
now := time.Now().UTC()
49+
clock := time.Duration(now.Hour())*time.Hour +
50+
time.Duration(now.Minute())*time.Minute +
51+
time.Duration(now.Second())*time.Second +
52+
time.Duration(now.Nanosecond())
53+
n := clock / time.Microsecond
54+
55+
return fmt.Sprintf("%s-%s-%d", strings.ReplaceAll(strings.ToLower(t.Name()), "/", "-"), kind, n)
56+
}
57+
58+
// createCluster creates a Cluster with "ready" infrastructure.
59+
func createCluster(ctx context.Context, t *testing.T, c client.Client, namespaceName string) *capiv1.Cluster {
60+
t.Helper()
61+
62+
clusterName := generateName(t, "cluster")
63+
cluster := &capiv1.Cluster{
64+
ObjectMeta: metav1.ObjectMeta{
65+
Namespace: namespaceName,
66+
Name: clusterName,
67+
},
68+
Spec: capiv1.ClusterSpec{
69+
ClusterNetwork: &capiv1.ClusterNetwork{},
70+
},
71+
}
72+
73+
require.NoError(t, c.Create(ctx, cluster), "can't create a cluster")
74+
75+
cluster.Status.InfrastructureReady = true
76+
require.NoError(t, c.Status().Update(ctx, cluster))
77+
78+
return cluster
79+
}
80+
81+
// createMachine creates a Machine owned by the Cluster.
82+
func createMachine(ctx context.Context, t *testing.T, c client.Client, cluster *capiv1.Cluster) *capiv1.Machine {
83+
t.Helper()
84+
85+
machineName := generateName(t, "machine")
86+
dataSecretName := "my-test-secret"
87+
machine := &capiv1.Machine{
88+
ObjectMeta: metav1.ObjectMeta{
89+
Namespace: cluster.Namespace,
90+
Name: machineName,
91+
},
92+
Spec: capiv1.MachineSpec{
93+
ClusterName: cluster.Name,
94+
Bootstrap: capiv1.Bootstrap{
95+
DataSecretName: &dataSecretName, // TODO
96+
},
97+
},
98+
}
99+
100+
require.NoError(t, controllerutil.SetOwnerReference(cluster, machine, scheme.Scheme))
101+
102+
require.NoError(t, c.Create(ctx, machine))
103+
104+
return machine
105+
}
106+
107+
// createTalosConfig creates a TalosConfig owned by the Machine.
108+
func createTalosConfig(ctx context.Context, t *testing.T, c client.Client, machine *capiv1.Machine) *bootstrapv1alpha3.TalosConfig {
109+
t.Helper()
110+
111+
talosConfigName := generateName(t, "talosconfig")
112+
talosConfig := &bootstrapv1alpha3.TalosConfig{
113+
ObjectMeta: metav1.ObjectMeta{
114+
Namespace: machine.Namespace,
115+
Name: talosConfigName,
116+
},
117+
Spec: bootstrapv1alpha3.TalosConfigSpec{
118+
GenerateType: "init",
119+
},
120+
}
121+
122+
require.NoError(t, controllerutil.SetOwnerReference(machine, talosConfig, scheme.Scheme))
123+
124+
require.NoError(t, c.Create(ctx, talosConfig))
125+
126+
// TODO that should not be needed
127+
if !skipCleanup {
128+
t.Cleanup(func() {
129+
t.Logf("Deleting TalosConfig %q ...", talosConfigName)
130+
assert.NoError(t, c.Delete(context.Background(), talosConfig)) // not ctx because it can be already canceled
131+
})
132+
}
133+
134+
return talosConfig
135+
}
136+
137+
type runtimeMode struct {
138+
requiresInstall bool
139+
}
140+
141+
func (m runtimeMode) String() string {
142+
return fmt.Sprintf("runtimeMode(%v)", m.requiresInstall)
143+
}
144+
145+
func (m runtimeMode) RequiresInstall() bool {
146+
return m.requiresInstall
147+
}
148+
149+
// check interface
150+
var _ config.RuntimeMode = runtimeMode{}

internal/integration/integration_test.go

Lines changed: 71 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -8,99 +8,98 @@ import (
88
"testing"
99
"time"
1010

11+
"github.com/AlekSi/pointer"
12+
"github.com/stretchr/testify/assert"
1113
"github.com/stretchr/testify/require"
12-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
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"
17+
"github.com/talos-systems/talos/pkg/machinery/config/configloader"
18+
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
19+
corev1 "k8s.io/api/core/v1"
1320
"k8s.io/apimachinery/pkg/types"
14-
"k8s.io/client-go/kubernetes/scheme"
15-
capiv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
16-
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
17-
18-
bootstrapv1alpha3 "github.com/talos-systems/cluster-api-bootstrap-provider-talos/api/v1alpha3"
19-
// +kubebuilder:scaffold:imports
2021
)
2122

2223
func TestIntegration(t *testing.T) {
2324
ctx, c := setupSuite(t)
2425

25-
// namespaced objects
26-
var (
27-
clusterName = "test-cluster"
28-
machineName = "test-machine"
29-
dataSecretName = "test-secret"
30-
talosConfigName = "test-config"
31-
)
32-
3326
t.Run("Basic", func(t *testing.T) {
3427
t.Parallel()
35-
namespaceName := setupTest(ctx, t, c)
36-
37-
cluster := &capiv1.Cluster{
38-
ObjectMeta: metav1.ObjectMeta{
39-
Namespace: namespaceName,
40-
Name: clusterName,
41-
},
42-
Spec: capiv1.ClusterSpec{
43-
ClusterNetwork: &capiv1.ClusterNetwork{
44-
Pods: &capiv1.NetworkRanges{
45-
CIDRBlocks: []string{"192.168.0.0/16"},
46-
},
47-
ServiceDomain: "cluster.local",
48-
Services: &capiv1.NetworkRanges{
49-
CIDRBlocks: []string{"10.128.0.0/12"},
50-
},
51-
},
52-
},
53-
}
54-
require.NoError(t, c.Create(ctx, cluster), "can't create a cluster")
55-
56-
cluster.Status.InfrastructureReady = true
57-
require.NoError(t, c.Status().Update(ctx, cluster))
58-
59-
machine := &capiv1.Machine{
60-
ObjectMeta: metav1.ObjectMeta{
61-
Namespace: namespaceName,
62-
Name: machineName,
63-
},
64-
Spec: capiv1.MachineSpec{
65-
ClusterName: cluster.Name,
66-
Bootstrap: capiv1.Bootstrap{
67-
DataSecretName: &dataSecretName,
68-
},
69-
},
70-
}
71-
72-
require.NoError(t, controllerutil.SetOwnerReference(cluster, machine, scheme.Scheme))
73-
require.NoError(t, c.Create(ctx, machine))
74-
75-
config := &bootstrapv1alpha3.TalosConfig{
76-
ObjectMeta: metav1.ObjectMeta{
77-
Namespace: namespaceName,
78-
Name: talosConfigName,
79-
},
80-
Spec: bootstrapv1alpha3.TalosConfigSpec{
81-
GenerateType: "init",
82-
},
83-
}
84-
require.NoError(t, controllerutil.SetOwnerReference(machine, config, scheme.Scheme))
8528

86-
err := c.Create(ctx, config)
87-
require.NoError(t, err)
29+
namespaceName := setupTest(ctx, t, c)
30+
cluster := createCluster(ctx, t, c, namespaceName)
31+
machine := createMachine(ctx, t, c, cluster)
32+
talosConfig := createTalosConfig(ctx, t, c, machine)
8833

34+
// wait for TalosConfig to be reconciled
8935
for ctx.Err() == nil {
9036
key := types.NamespacedName{
9137
Namespace: namespaceName,
92-
Name: talosConfigName,
38+
Name: talosConfig.Name,
9339
}
9440

95-
err = c.Get(ctx, key, config)
41+
err := c.Get(ctx, key, talosConfig)
9642
require.NoError(t, err)
9743

98-
if config.Status.Ready {
44+
if talosConfig.Status.Ready {
9945
break
10046
}
10147

102-
t.Logf("Config: %+v", config)
103-
time.Sleep(5 * time.Second)
48+
t.Log("Waiting ...")
49+
sleepCtx(ctx, 5*time.Second)
50+
}
51+
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+
67+
var caSecret corev1.Secret
68+
key := types.NamespacedName{
69+
Namespace: namespaceName,
70+
Name: cluster.Name + "-ca",
71+
}
72+
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])
77+
78+
var talosSecret corev1.Secret
79+
key = types.NamespacedName{
80+
Namespace: namespaceName,
81+
Name: cluster.Name + "-talos",
10482
}
83+
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"])
88+
89+
var bootstrapDataSecret corev1.Secret
90+
key = types.NamespacedName{
91+
Namespace: namespaceName,
92+
Name: machine.Name + "-bootstrap-data",
93+
}
94+
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)
98+
99+
provider.(*v1alpha1.Config).ClusterConfig.ControlPlane.Endpoint.Host = "FIXME"
100+
101+
// TODO more tests
102+
_, err = provider.Validate(runtimeMode{false}, config.WithStrict())
103+
require.NoError(t, err)
105104
})
106105
}

0 commit comments

Comments
 (0)