diff --git a/go.mod b/go.mod index d25480d..fc86bfe 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,6 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect @@ -73,14 +72,12 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/net v0.0.0-20220906165146-f3363e06e74c // indirect golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect - golang.org/x/tools v0.1.12 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect diff --git a/go.sum b/go.sum index a9971eb..e494010 100644 --- a/go.sum +++ b/go.sum @@ -290,8 +290,6 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= -github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= @@ -445,8 +443,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -649,8 +645,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/scope/mvm.go b/internal/scope/mvm.go index 6386fe9..f04f4da 100644 --- a/internal/scope/mvm.go +++ b/internal/scope/mvm.go @@ -159,6 +159,7 @@ func (m *MicrovmScope) GetBasicAuthToken() (string, error) { // If it's not there, that's fine; we will log and return an empty string token := string(tokenSecret.Data["token"]) + fmt.Println(tokenSecret.Data) if token == "" { m.Info( @@ -186,7 +187,7 @@ func (m *MicrovmScope) GetTLSConfig() (*flclient.TLSConfig, error) { } tlsSecret := &corev1.Secret{} - if err := m.client.Get(context.TODO(), secretKey, tlsSecret); err != nil { + if err := m.client.Get(m.ctx, secretKey, tlsSecret); err != nil { return nil, err } diff --git a/internal/scope/mvm_test.go b/internal/scope/mvm_test.go new file mode 100644 index 0000000..d802c1e --- /dev/null +++ b/internal/scope/mvm_test.go @@ -0,0 +1,321 @@ +package scope_test + +import ( + "testing" + + "github.com/go-logr/logr/testr" + . "github.com/onsi/gomega" + + flclient "github.com/weaveworks-liquidmetal/controller-pkg/client" + "github.com/weaveworks-liquidmetal/controller-pkg/types/microvm" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + infrav1 "github.com/weaveworks-liquidmetal/microvm-operator/api/v1alpha1" + "github.com/weaveworks-liquidmetal/microvm-operator/internal/scope" +) + +func TestMicrovmProviderID(t *testing.T) { + RegisterTestingT(t) + + scheme, err := setupScheme() + Expect(err).NotTo(HaveOccurred()) + + mvmName := "m-1" + mvm := newMicrovm(mvmName, "") + + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(mvm).Build() + mvmScope, err := scope.NewMicrovmScope(scope.MicrovmScopeParams{ + Client: client, + MicroVM: mvm, + }) + Expect(err).NotTo(HaveOccurred()) + + mvmScope.SetProviderID("abcdef") + Expect(mvmScope.GetProviderID()).To(Equal("microvm://fd1/abcdef")) +} + +func TestMachineGetInstanceID(t *testing.T) { + RegisterTestingT(t) + + scheme, err := setupScheme() + Expect(err).NotTo(HaveOccurred()) + + mvmName := "m-1" + uid := "abcdef" + providerID := "microvm://fd1/" + uid + mvm := newMicrovm(mvmName, providerID) + + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(mvm).Build() + mvmScope, err := scope.NewMicrovmScope(scope.MicrovmScopeParams{ + Client: client, + MicroVM: mvm, + }) + Expect(err).NotTo(HaveOccurred()) + + instanceID := mvmScope.GetInstanceID() + Expect(instanceID).To(Equal(uid)) +} + +// This is all temporary +func TestMachineGetBasicAuthToken(t *testing.T) { + RegisterTestingT(t) + + scheme, err := setupScheme() + Expect(err).NotTo(HaveOccurred()) + + mvmName := "testcluster" + secretName := "testsecret" + hostName := "hostwiththemost" + token := "foo" + + mvm := newMicrovmWithSpec(mvmName, infrav1.MicrovmSpec{ + Host: infrav1.HostSpec{ + Host: microvm.Host{ + Endpoint: hostName, + }, + BasicAuthSecret: secretName, + }, + }) + otherMvm := newMicrovm(mvmName, "") + secret := newSecret(secretName, map[string][]byte{"token": []byte(token)}) + otherSecret := newSecret(secretName, map[string][]byte{"nottoken": []byte(token)}) + + tt := []struct { + name string + expected string + expectedErr func(error) + initObjects []client.Object + mvm *infrav1.Microvm + }{ + { + name: "when the token is found in the secret, it is returned", + initObjects: []client.Object{ + mvm, secret, + }, + mvm: mvm, + expected: token, + expectedErr: func(err error) { + Expect(err).NotTo(HaveOccurred()) + }, + }, + { + name: "when the secret does not exist, returns the error", + initObjects: []client.Object{mvm}, + mvm: mvm, + expected: "", + expectedErr: func(err error) { + Expect(err).To(HaveOccurred()) + }, + }, + { + name: "when the secret does not contain the token, an empty string is returned", + initObjects: []client.Object{mvm, otherSecret}, + mvm: mvm, + expected: "", + expectedErr: func(err error) { + Expect(err).NotTo(HaveOccurred()) + }, + }, + { + name: "when the secret name is not set on the cluster, empty string is returned", + initObjects: []client.Object{otherMvm}, + mvm: otherMvm, + expected: "", + expectedErr: func(err error) { + Expect(err).NotTo(HaveOccurred()) + }, + }, + } + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + RegisterTestingT(t) + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(tc.initObjects...).Build() + mvmScope, err := scope.NewMicrovmScope(scope.MicrovmScopeParams{ + Client: client, + MicroVM: tc.mvm, + Logger: testr.New(t), + }) + Expect(err).NotTo(HaveOccurred()) + + token, err := mvmScope.GetBasicAuthToken() + tc.expectedErr(err) + Expect(token).To(Equal(tc.expected)) + }) + } +} + +func TestMachineGetTLSConfig(t *testing.T) { + RegisterTestingT(t) + + scheme, err := setupScheme() + Expect(err).NotTo(HaveOccurred()) + + mvmName := "testmvm" + tlsSecretName := "testtlssecret" + + mvm := newMicrovmWithSpec(mvmName, infrav1.MicrovmSpec{ + TLSSecretRef: tlsSecretName, + }) + otherMvmNoTLS := newMicrovm(mvmName, "") + + tlsData := map[string][]byte{ + "tls.crt": []byte("foo"), + "tls.key": []byte("bar"), + "ca.crt": []byte("baz"), + } + tlsSecret := newSecret(tlsSecretName, tlsData) + + badData := map[string][]byte{ + "not": []byte("great"), + } + otherTLSSecret := newSecret(tlsSecretName, badData) + + tt := []struct { + name string + expected func(*flclient.TLSConfig, error) + initObjects []client.Object + mvm *infrav1.Microvm + }{ + { + name: "returns the TLS config from the secret", + initObjects: []client.Object{ + mvm, tlsSecret, + }, + mvm: mvm, + expected: func(cfg *flclient.TLSConfig, err error) { + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Cert).To(Equal([]byte("foo"))) + Expect(cfg.Key).To(Equal([]byte("bar"))) + Expect(cfg.CACert).To(Equal([]byte("baz"))) + }, + }, + { + name: "when the tls secret does not exist, returns an error", + initObjects: []client.Object{ + mvm, + }, + mvm: mvm, + expected: func(cfg *flclient.TLSConfig, err error) { + Expect(err).To(HaveOccurred()) + }, + }, + { + name: "when the TLSSecretRef is not set on the microvm, returns nil", + initObjects: []client.Object{ + otherMvmNoTLS, + }, + mvm: otherMvmNoTLS, + expected: func(cfg *flclient.TLSConfig, err error) { + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).To(BeNil()) + }, + }, + { + name: "when the secret data does not contain the `tls.crt` key, returns an error", + initObjects: []client.Object{ + mvm, otherTLSSecret, + }, + mvm: mvm, + expected: func(cfg *flclient.TLSConfig, err error) { + Expect(err).To(HaveOccurred()) + }, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + RegisterTestingT(t) + client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(tc.initObjects...).Build() + machineScope, err := scope.NewMicrovmScope(scope.MicrovmScopeParams{ + Client: client, + MicroVM: tc.mvm, + Logger: testr.New(t), + }) + Expect(err).NotTo(HaveOccurred()) + + tc.expected(machineScope.GetTLSConfig()) + }) + } +} + +func setupScheme() (*runtime.Scheme, error) { + scheme := runtime.NewScheme() + if err := infrav1.AddToScheme(scheme); err != nil { + return nil, err + } + if err := clusterv1.AddToScheme(scheme); err != nil { + return nil, err + } + if err := corev1.AddToScheme(scheme); err != nil { + return nil, err + } + return scheme, nil +} + +func newCluster(name string, failureDomains []string) *clusterv1.Cluster { + cluster := &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "default", + }, + } + + if len(failureDomains) > 0 { + cluster.Status = clusterv1.ClusterStatus{ + FailureDomains: make(clusterv1.FailureDomains), + } + + for i := range failureDomains { + fd := failureDomains[i] + cluster.Status.FailureDomains[fd] = clusterv1.FailureDomainSpec{ + ControlPlane: true, + } + } + } + + return cluster +} + +func newMicrovm(name string, providerID string) *infrav1.Microvm { + mvm := &infrav1.Microvm{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "default", + }, + Spec: infrav1.MicrovmSpec{ + Host: infrav1.HostSpec{ + Host: microvm.Host{ + Endpoint: "fd1", + }, + }, + }, + } + if providerID != "" { + mvm.Spec.ProviderID = &providerID + } + + return mvm +} + +func newMicrovmWithSpec(name string, spec infrav1.MicrovmSpec) *infrav1.Microvm { + mvm := newMicrovm(name, "") + mvm.Spec = spec + return mvm +} + +func newSecret(name string, data map[string][]byte) *v1.Secret { + return &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "default", + }, + Data: data, + } +}