From 6dc377ec693685cea1b5803fa5c7c97650e435b1 Mon Sep 17 00:00:00 2001 From: Joshua Reed Date: Thu, 19 May 2022 10:21:26 -0700 Subject: [PATCH] Staging to make files look moved. --- pkg/cloud/affinity_groups_test.go | 99 ---- pkg/cloud/client_test.go | 56 --- pkg/cloud/cloud_suite_test.go | 29 -- pkg/cloud/helpers_test.go | 123 ----- pkg/cloud/instance_test.go | 438 ------------------ pkg/cloud/isolated_network_test.go | 266 ----------- pkg/cloud/network_test.go | 64 --- pkg/cloud/tags_test.go | 141 ------ pkg/cloud/user_credentials_test.go | 97 ---- pkg/cloud/zone_test.go | 70 --- test/unit/cloud/affinity_groups_test.go | 99 ---- test/unit/cloud/client_test.go | 56 --- test/unit/cloud/cloud_suite_test.go | 29 -- test/unit/cloud/helpers_test.go | 129 ------ test/unit/cloud/instance_test.go | 438 ------------------ test/unit/cloud/isolated_network_test.go | 266 ----------- test/unit/cloud/network_test.go | 64 --- test/unit/cloud/tags_test.go | 141 ------ .../cloud-config-files/cloud-config-good | 5 - .../cloud-config-files/cloud-config-no-global | 5 - test/unit/cloud/user_credentials_test.go | 97 ---- test/unit/cloud/zone_test.go | 70 --- 22 files changed, 2782 deletions(-) delete mode 100644 pkg/cloud/affinity_groups_test.go delete mode 100644 pkg/cloud/client_test.go delete mode 100644 pkg/cloud/cloud_suite_test.go delete mode 100644 pkg/cloud/helpers_test.go delete mode 100644 pkg/cloud/instance_test.go delete mode 100644 pkg/cloud/isolated_network_test.go delete mode 100644 pkg/cloud/network_test.go delete mode 100644 pkg/cloud/tags_test.go delete mode 100644 pkg/cloud/user_credentials_test.go delete mode 100644 pkg/cloud/zone_test.go delete mode 100644 test/unit/cloud/affinity_groups_test.go delete mode 100644 test/unit/cloud/client_test.go delete mode 100644 test/unit/cloud/cloud_suite_test.go delete mode 100644 test/unit/cloud/helpers_test.go delete mode 100644 test/unit/cloud/instance_test.go delete mode 100644 test/unit/cloud/isolated_network_test.go delete mode 100644 test/unit/cloud/network_test.go delete mode 100644 test/unit/cloud/tags_test.go delete mode 100644 test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-good delete mode 100644 test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-no-global delete mode 100644 test/unit/cloud/user_credentials_test.go delete mode 100644 test/unit/cloud/zone_test.go diff --git a/pkg/cloud/affinity_groups_test.go b/pkg/cloud/affinity_groups_test.go deleted file mode 100644 index 83c617d1..00000000 --- a/pkg/cloud/affinity_groups_test.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "errors" - - "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("AffinityGroup Unit Tests", func() { - var ( // Declare shared vars. - mockCtrl *gomock.Controller - mockClient *cloudstack.CloudStackClient - ags *cloudstack.MockAffinityGroupServiceIface - client cloud.Client - ) - - BeforeEach(func() { - // Setup new mock services. - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = cloudstack.NewMockClient(mockCtrl) - ags = mockClient.AffinityGroup.(*cloudstack.MockAffinityGroupServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - It("fetches an affinity group", func() { - dummies.AffinityGroup.ID = "" // Force name fetching. - ags.EXPECT().GetAffinityGroupByName(dummies.AffinityGroup.Name).Return(&cloudstack.AffinityGroup{}, 1, nil) - - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - }) - It("creates an affinity group", func() { - dummies.SetDummyDomainAndAccount() - dummies.SetDummyDomainID() - ags.EXPECT().GetAffinityGroupByID(dummies.AffinityGroup.ID).Return(nil, -1, errors.New("FakeError")) - ags.EXPECT().NewCreateAffinityGroupParams(dummies.AffinityGroup.Name, dummies.AffinityGroup.Type). - Return(&cloudstack.CreateAffinityGroupParams{}) - ags.EXPECT().CreateAffinityGroup(ParamMatch(And(NameEquals(dummies.AffinityGroup.Name)))). - Return(&cloudstack.CreateAffinityGroupResponse{}, nil) - - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - }) - - Context("AffinityGroup Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - dummies.AffinityGroup.ID = "" // Force name fetching. - }) - AfterEach(func() { - mockCtrl.Finish() - }) - - It("Creates an affinity group.", func() { - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - }) - It("Associates an affinity group.", func() { - if err := client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "", - ); err != nil { - Skip("Could not create VM." + err.Error()) - } - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - Ω(client.AssociateAffinityGroup(dummies.CSMachine1, *dummies.AffinityGroup)).Should(Succeed()) - }) - It("Deletes an affinity group.", func() { - Ω(client.DeleteAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - Ω(client.FetchAffinityGroup(dummies.AffinityGroup)).ShouldNot(Succeed()) - }) - }) -}) diff --git a/pkg/cloud/client_test.go b/pkg/cloud/client_test.go deleted file mode 100644 index 395f3970..00000000 --- a/pkg/cloud/client_test.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "gopkg.in/ini.v1" -) - -// Example cloud-config ini structure. -type Global struct { - APIURL string `ini:"api-url"` - VerifySSL bool `ini:"verify-ssl"` -} - -var _ = Describe("Instance", func() { - - var () - - BeforeEach(func() { - // This test fixture is useful for development, but the actual method of parsing is confinded to the client's - // new client method. The parsing used here is more of a schema, and we don't need to test another library's - // abilities to parse said schema. - Skip("Dev test suite.") - }) - - AfterEach(func() { - }) - - Context("When fetching an INI config.", func() { - It("Handles the positive case.", func() { - cfg := &Global{} - rawCfg, err := ini.Load("../../cloud-config") - Ω(rawCfg.Section("Global")).ShouldNot(BeNil()) - Ω(err).ShouldNot(HaveOccurred()) - Ω(rawCfg.Section("Global").MapTo(cfg)).Should(Succeed()) - Ω(cfg.VerifySSL).Should(BeFalse()) - Ω(cfg.APIURL).ShouldNot(BeEmpty()) - }) - }) -}) diff --git a/pkg/cloud/cloud_suite_test.go b/pkg/cloud/cloud_suite_test.go deleted file mode 100644 index d3a8fe31..00000000 --- a/pkg/cloud/cloud_suite_test.go +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestCloud(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Cloud Suite") -} diff --git a/pkg/cloud/helpers_test.go b/pkg/cloud/helpers_test.go deleted file mode 100644 index e216c190..00000000 --- a/pkg/cloud/helpers_test.go +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "bytes" - "compress/gzip" - "encoding/base64" - "fmt" - "io/ioutil" - "os" - "path" - "reflect" - - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/onsi/gomega/types" -) - -const ( - FixturePath = "test/fixtures/cloud-config-files" -) - -var _ = Describe("Helpers", func() { - - Context("For a configuration with the 'Global' section missing", func() { - It("Gets API configuration", func() { - filepath := getConfigPath("cloud-config-no-global") - - client, err := cloud.NewClient(filepath) - - Ω(client).Should(BeNil()) - Ω(err.Error()).Should(ContainSubstring("section Global not found")) - }) - }) - - It("should compress and encode string", func() { - str := "Hello World" - - compressedAndEncodedData, err := cloud.CompressAndEncodeString(str) - - compressedData, _ := base64.StdEncoding.DecodeString(compressedAndEncodedData) - reader, _ := gzip.NewReader(bytes.NewReader(compressedData)) - result, _ := ioutil.ReadAll(reader) - - Ω(err).Should(BeNil()) - Ω(string(result)).Should(Equal(str)) - }) -}) - -func getConfigPath(filename string) string { - dir, _ := os.Getwd() - return path.Join(dir, FixturePath, filename) -} - -// This matcher is used to make gomega matching compatible with gomock parameter matching. -// It's pretty awesome! -// -// This sort of hacks the gomock interface to inject a gomega matcher. -// -// Gomega matchers are far more flexible than gomock matchers, but they normally can't be used on parameters. - -type paramMatcher struct { - matcher types.GomegaMatcher -} - -func ParamMatch(matcher types.GomegaMatcher) gomock.Matcher { - return paramMatcher{matcher} -} - -func (p paramMatcher) String() string { - return "a gomega matcher to match, and said matcher should have panicked before this message was printed." -} - -func (p paramMatcher) Matches(x interface{}) (retVal bool) { - return Ω(x).Should(p.matcher) -} - -// This generates translating matchers. -// -// The CloudStack Go API uses param interfaces that can't be accessed except through builtin methods. -// -// This generates translation matchers: -// -// Essentially it will generate a matcher that checks the value from p.Get() is Equal to an input String. -// -// DomainIDEquals = FieldMatcherGenerator("GetDomainid") -// p := &CreateNewSomethingParams{Domainid: "FakeDomainID"} -// Ω(p).DomainIDEquals("FakeDomainID") -func FieldMatcherGenerator(fetchFunc string) func(string) types.GomegaMatcher { - return (func(expected string) types.GomegaMatcher { - return WithTransform( - func(x interface{}) string { - meth := reflect.ValueOf(x).MethodByName(fetchFunc) - fmt.Println(meth.Call(nil)[0]) - - return meth.Call(nil)[0].String() - }, Equal(expected)) - }) -} - -var ( - DomainIDEquals = FieldMatcherGenerator("GetDomainid") - AccountEquals = FieldMatcherGenerator("GetAccount") - IDEquals = FieldMatcherGenerator("GetId") - NameEquals = FieldMatcherGenerator("GetName") -) diff --git a/pkg/cloud/instance_test.go b/pkg/cloud/instance_test.go deleted file mode 100644 index 5b5065e2..00000000 --- a/pkg/cloud/instance_test.go +++ /dev/null @@ -1,438 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "fmt" - - "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - - . "github.com/onsi/gomega" - "github.com/pkg/errors" - "k8s.io/utils/pointer" -) - -var _ = Describe("Instance", func() { - const ( - unknownErrorMessage = "unknown err" - offeringFakeID = "123" - templateFakeID = "456" - executableFilter = "executable" - diskOfferingFakeID = "789" - ) - - notFoundError := errors.New("no match found") - unknownError := errors.New(unknownErrorMessage) - - var ( - mockCtrl *gomock.Controller - mockClient *cloudstack.CloudStackClient - vms *cloudstack.MockVirtualMachineServiceIface - sos *cloudstack.MockServiceOfferingServiceIface - dos *cloudstack.MockDiskOfferingServiceIface - ts *cloudstack.MockTemplateServiceIface - vs *cloudstack.MockVolumeServiceIface - client cloud.Client - ) - - BeforeEach(func() { - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = cloudstack.NewMockClient(mockCtrl) - vms = mockClient.VirtualMachine.(*cloudstack.MockVirtualMachineServiceIface) - sos = mockClient.ServiceOffering.(*cloudstack.MockServiceOfferingServiceIface) - dos = mockClient.DiskOffering.(*cloudstack.MockDiskOfferingServiceIface) - ts = mockClient.Template.(*cloudstack.MockTemplateServiceIface) - vs = mockClient.Volume.(*cloudstack.MockVolumeServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - dummies.SetDummyCSMachineStatuses() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - Context("when fetching a VM instance", func() { - It("Handles an unknown error when fetching by ID", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, unknownError) - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).To(MatchError(unknownErrorMessage)) - }) - - It("Handles finding more than one VM instance by ID", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, 2, nil) - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)). - Should(MatchError("found more than one VM Instance with ID " + *dummies.CSMachine1.Spec.InstanceID)) - }) - - It("sets dummies.CSMachine1 spec and status values when VM instance found by ID", func() { - vmsResp := &cloudstack.VirtualMachinesMetric{Id: *dummies.CSMachine1.Spec.InstanceID} - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(vmsResp, 1, nil) - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should(Succeed()) - Ω(dummies.CSMachine1.Spec.ProviderID).Should(Equal(pointer.StringPtr("cloudstack:///" + vmsResp.Id))) - Ω(dummies.CSMachine1.Spec.InstanceID).Should(Equal(pointer.StringPtr(vmsResp.Id))) - }) - - It("handles an unknown error when fetching by name", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, unknownError) - - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should(MatchError(unknownErrorMessage)) - }) - - It("handles finding more than one VM instance by Name", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, 2, nil) - - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should( - MatchError("found more than one VM Instance with name " + dummies.CSMachine1.Name)) - }) - - It("sets dummies.CSMachine1 spec and status values when VM instance found by Name", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name). - Return(&cloudstack.VirtualMachinesMetric{Id: *dummies.CSMachine1.Spec.InstanceID}, -1, nil) - - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should(Succeed()) - Ω(dummies.CSMachine1.Spec.ProviderID).Should(Equal( - pointer.StringPtr(fmt.Sprintf("cloudstack:///%s", *dummies.CSMachine1.Spec.InstanceID)))) - Ω(dummies.CSMachine1.Spec.InstanceID).Should(Equal(pointer.StringPtr(*dummies.CSMachine1.Spec.InstanceID))) - }) - }) - - Context("when creating a VM instance", func() { - vmMetricResp := &cloudstack.VirtualMachinesMetric{} - - expectVMNotFound := func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - } - - It("doesn't re-create if one already exists.", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(vmMetricResp, -1, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(Succeed()) - }) - - It("returns unknown error while fetching VM instance", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, unknownError) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(unknownErrorMessage)) - }) - - It("returns errors occurring while fetching service offering information", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return("", -1, unknownError) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("returns errors if more than one service offering found", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return("", 2, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("returns errors while fetching template", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name). - Return(dummies.CSMachine1.Spec.Offering.ID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return("", -1, unknownError) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("returns errors when more than one template found", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name). - Return(dummies.CSMachine1.Spec.Offering.ID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID).Return("", 2, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("handles deployment errors", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name). - Return(offeringFakeID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name). - Return(diskOfferingFakeID, 1, nil) - vms.EXPECT().NewDeployVirtualMachineParams(offeringFakeID, templateFakeID, dummies.Zone1.ID). - Return(&cloudstack.DeployVirtualMachineParams{}) - vms.EXPECT().DeployVirtualMachine(gomock.Any()).Return(nil, unknownError) - vms.EXPECT().NewListVirtualMachinesParams().Return(&cloudstack.ListVirtualMachinesParams{}) - vms.EXPECT().ListVirtualMachines(gomock.Any()).Return(&cloudstack.ListVirtualMachinesResponse{}, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(unknownErrorMessage)) - }) - - Context("when using UUIDs and/or names to locate service offerings and templates", func() { - BeforeEach(func() { - gomock.InOrder( - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(nil, -1, notFoundError), - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{}, 1, nil)) - - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - }) - - ActionAndAssert := func() { - vms.EXPECT().NewDeployVirtualMachineParams(offeringFakeID, templateFakeID, dummies.Zone1.ID). - Return(&cloudstack.DeployVirtualMachineParams{}) - - deploymentResp := &cloudstack.DeployVirtualMachineResponse{Id: *dummies.CSMachine1.Spec.InstanceID} - vms.EXPECT().DeployVirtualMachine(gomock.Any()).Return(deploymentResp, nil) - - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(Succeed()) - } - - It("works with service offering name and template name", func() { - dummies.CSMachine1.Spec.Offering.ID = "" - dummies.CSMachine1.Spec.Template.ID = "" - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return(offeringFakeID, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering name and template name without disk offering", func() { - dummies.CSMachine1.Spec.Offering.ID = "" - dummies.CSMachine1.Spec.Template.ID = "" - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - dummies.CSMachine1.Spec.DiskOffering = v1beta1.CloudStackResourceDiskOffering{} - - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return(offeringFakeID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering ID and template name", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = "" - dummies.CSMachine1.Spec.Offering.Name = "" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: ""}, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering name and template ID", func() { - dummies.CSMachine1.Spec.Offering.ID = "" - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "" - - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return(offeringFakeID, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter).Return(&cloudstack.Template{Name: ""}, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering ID and template ID", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "" - dummies.CSMachine1.Spec.Template.Name = "" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID). - Return(&cloudstack.ServiceOffering{Name: "offering"}, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name). - Return(diskOfferingFakeID, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter). - Return(&cloudstack.Template{Name: "template"}, 1, nil) - - ActionAndAssert() - }) - - It("works with Id and name both provided", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: "offering"}, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter).Return(&cloudstack.Template{Name: "template"}, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - - ActionAndAssert() - }) - }) - - Context("when using both UUIDs and names to locate service offerings and templates", func() { - BeforeEach(func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - }) - - It("works with Id and name both provided, offering name mismatch", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: "offering-not-match"}, 1, nil) - requiredRegexp := "offering name %s does not match name %s returned using UUID %s" - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(MatchRegexp(requiredRegexp, dummies.CSMachine1.Spec.Offering.Name, "offering-not-match", offeringFakeID))) - }) - - It("works with Id and name both provided, template name mismatch", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: "offering"}, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter).Return(&cloudstack.Template{Name: "template-not-match"}, 1, nil) - requiredRegexp := "template name %s does not match name %s returned using UUID %s" - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(MatchRegexp(requiredRegexp, dummies.CSMachine1.Spec.Template.Name, "template-not-match", templateFakeID))) - - }) - }) - }) - - Context("when destroying a VM instance", func() { - expungeDestroyParams := &cloudstack.DestroyVirtualMachineParams{} - expungeDestroyParams.SetExpunge(true) - listVolumesParams := &cloudstack.ListVolumesParams{} - listVolumesResponse := &cloudstack.ListVolumesResponse{ - Volumes: []*cloudstack.Volume{ - { - Id: "123", - }, - { - Id: "456", - }, - }, - } - - It("calls destroy and finds VM doesn't exist, then returns nil", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, fmt.Errorf("unable to find uuid for id")) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy and returns unexpected error", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, fmt.Errorf("new error")) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)).Should(MatchError("new error")) - }) - - It("calls destroy without error but cannot resolve VM after", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy without error and identifies it as expunging", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{ - State: "Expunging", - }, 1, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy without error and identifies it as expunged", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{ - State: "Expunged", - }, 1, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy without error and identifies it as stopping", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{ - State: "Stopping", - }, 1, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)).Should(MatchError("VM deletion in progress")) - }) - }) -}) diff --git a/pkg/cloud/isolated_network_test.go b/pkg/cloud/isolated_network_test.go deleted file mode 100644 index 028f1ac3..00000000 --- a/pkg/cloud/isolated_network_test.go +++ /dev/null @@ -1,266 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "strconv" - - csapi "github.com/apache/cloudstack-go/v2/cloudstack" - capcv1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/pkg/errors" -) - -var _ = Describe("Network", func() { - var ( // Declare shared vars. - mockCtrl *gomock.Controller - mockClient *csapi.CloudStackClient - ns *csapi.MockNetworkServiceIface - nos *csapi.MockNetworkOfferingServiceIface - fs *csapi.MockFirewallServiceIface - as *csapi.MockAddressServiceIface - lbs *csapi.MockLoadBalancerServiceIface - rs *csapi.MockResourcetagsServiceIface - client cloud.Client - ) - - BeforeEach(func() { - // Setup new mock services. - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = csapi.NewMockClient(mockCtrl) - ns = mockClient.Network.(*csapi.MockNetworkServiceIface) - nos = mockClient.NetworkOffering.(*csapi.MockNetworkOfferingServiceIface) - fs = mockClient.Firewall.(*csapi.MockFirewallServiceIface) - as = mockClient.Address.(*csapi.MockAddressServiceIface) - lbs = mockClient.LoadBalancer.(*csapi.MockLoadBalancerServiceIface) - rs = mockClient.Resourcetags.(*csapi.MockResourcetagsServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - It("calls to create an isolated network when not found", func() { - dummies.Zone1.Network = dummies.ISONet1 - dummies.Zone1.Network.ID = "" - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{dummies.Zone1.ID: dummies.Zone1} - dummies.CSCluster.Status.PublicIPNetworkID = dummies.ISONet1.ID - - nos.EXPECT().GetNetworkOfferingID(gomock.Any()).Return("someOfferingID", 1, nil) - ns.EXPECT().NewCreateNetworkParams(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(&csapi.CreateNetworkParams{}) - ns.EXPECT().GetNetworkByName(dummies.ISONet1.Name).Return(nil, 0, nil) - ns.EXPECT().GetNetworkByID(dummies.ISONet1.ID).Return(nil, 0, nil) - ns.EXPECT().CreateNetwork(gomock.Any()).Return(&csapi.CreateNetworkResponse{Id: dummies.ISONet1.ID}, nil) - as.EXPECT().NewListPublicIpAddressesParams().Return(&csapi.ListPublicIpAddressesParams{}) - as.EXPECT().ListPublicIpAddresses(gomock.Any()). - Return(&csapi.ListPublicIpAddressesResponse{ - Count: 1, - PublicIpAddresses: []*csapi.PublicIpAddress{{Id: dummies.PublicIPID, Ipaddress: "fakeIP"}}}, nil) - as.EXPECT().NewAssociateIpAddressParams().Return(&csapi.AssociateIpAddressParams{}) - as.EXPECT().AssociateIpAddress(gomock.Any()) - fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, cloud.NetworkProtocolTCP). - Return(&csapi.CreateEgressFirewallRuleParams{}) - fs.EXPECT().CreateEgressFirewallRule(&csapi.CreateEgressFirewallRuleParams{}). - Return(&csapi.CreateEgressFirewallRuleResponse{}, nil) - - // Will add cluster tag once to Network and once to PublicIP. - createdByResponse := &csapi.ListTagsResponse{Tags: []*csapi.Tag{{Key: cloud.CreatedByCAPCTagName, Value: "1"}}} - gomock.InOrder( - rs.EXPECT().NewListTagsParams().Return(&csapi.ListTagsParams{}), - rs.EXPECT().ListTags(gomock.Any()).Return(createdByResponse, nil), - rs.EXPECT().NewListTagsParams().Return(&csapi.ListTagsParams{}), - rs.EXPECT().ListTags(gomock.Any()).Return(createdByResponse, nil)) - - // Will add creation and cluster tags to network and PublicIP. - rs.EXPECT().NewCreateTagsParams(gomock.Any(), gomock.Any(), gomock.Any()). - Return(&csapi.CreateTagsParams{}).Times(4) - rs.EXPECT().CreateTags(gomock.Any()).Return(&csapi.CreateTagsResponse{}, nil).Times(4) - - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()).Return( - &csapi.ListLoadBalancerRulesResponse{LoadBalancerRules: []*csapi.LoadBalancerRule{ - {Publicport: strconv.Itoa(int(dummies.EndPointPort)), Id: dummies.LBRuleID}}}, nil) - - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - }) - - Context("for a closed firewall", func() { - It("OpenFirewallRule asks CloudStack to open the firewall", func() { - dummies.Zone1.Network = dummies.ISONet1 - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{dummies.Zone1.ID: dummies.Zone1} - dummies.CSCluster.Status.PublicIPNetworkID = dummies.ISONet1.ID - fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, cloud.NetworkProtocolTCP). - Return(&csapi.CreateEgressFirewallRuleParams{}) - fs.EXPECT().CreateEgressFirewallRule(&csapi.CreateEgressFirewallRuleParams{}). - Return(&csapi.CreateEgressFirewallRuleResponse{}, nil) - - Ω(client.OpenFirewallRules(dummies.CSISONet1)).Should(Succeed()) - }) - }) - - Context("for an open firewall", func() { - It("OpenFirewallRule asks CloudStack to open the firewall anyway, but doesn't fail", func() { - dummies.Zone1.Network = dummies.ISONet1 - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{dummies.Zone1.ID: dummies.Zone1} - dummies.CSCluster.Status.PublicIPNetworkID = dummies.ISONet1.ID - - fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, "tcp"). - Return(&csapi.CreateEgressFirewallRuleParams{}) - fs.EXPECT().CreateEgressFirewallRule(&csapi.CreateEgressFirewallRuleParams{}). - Return(&csapi.CreateEgressFirewallRuleResponse{}, errors.New("there is already a rule like this")) - - Ω(client.OpenFirewallRules(dummies.CSISONet1)).Should(Succeed()) - }) - }) - - Context("in an isolated network with public IPs available", func() { - It("will resolve public IP details given an endpoint spec", func() { - ipAddress := "192.168.1.14" - as.EXPECT().NewListPublicIpAddressesParams().Return(&csapi.ListPublicIpAddressesParams{}) - as.EXPECT().ListPublicIpAddresses(gomock.Any()). - Return(&csapi.ListPublicIpAddressesResponse{ - Count: 1, - PublicIpAddresses: []*csapi.PublicIpAddress{{Id: "PublicIPID", Ipaddress: ipAddress}}, - }, nil) - publicIPAddress, err := client.GetPublicIP(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster) - Ω(err).Should(Succeed()) - Ω(publicIPAddress).ShouldNot(BeNil()) - Ω(publicIPAddress.Ipaddress).Should(Equal(ipAddress)) - }) - }) - - Context("The specific load balancer rule does exist", func() { - It("resolves the rule's ID", func() { - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()).Return( - &csapi.ListLoadBalancerRulesResponse{LoadBalancerRules: []*csapi.LoadBalancerRule{ - {Publicport: strconv.Itoa(int(dummies.EndPointPort)), Id: dummies.LBRuleID}}}, nil) - - dummies.CSISONet1.Status.LBRuleID = "" - Ω(client.ResolveLoadBalancerRuleDetails(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(dummies.CSISONet1.Status.LBRuleID).Should(Equal(dummies.LBRuleID)) - }) - - It("doesn't create a new load balancer rule on create", func() { - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()). - Return(&csapi.ListLoadBalancerRulesResponse{ - LoadBalancerRules: []*csapi.LoadBalancerRule{ - {Publicport: strconv.Itoa(int(dummies.EndPointPort)), Id: dummies.LBRuleID}}}, nil) - - Ω(client.GetOrCreateLoadBalancerRule(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(dummies.CSISONet1.Status.LBRuleID).Should(Equal(dummies.LBRuleID)) - }) - }) - - Context("load balancer rule does not exist", func() { - It("calls cloudstack to create a new load balancer rule.", func() { - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()). - Return(&csapi.ListLoadBalancerRulesResponse{ - LoadBalancerRules: []*csapi.LoadBalancerRule{{Publicport: "7443", Id: dummies.LBRuleID}}}, nil) - lbs.EXPECT().NewCreateLoadBalancerRuleParams(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(&csapi.CreateLoadBalancerRuleParams{}) - lbs.EXPECT().CreateLoadBalancerRule(gomock.Any()). - Return(&csapi.CreateLoadBalancerRuleResponse{Id: "2ndLBRuleID"}, nil) - - Ω(client.GetOrCreateLoadBalancerRule(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(dummies.CSISONet1.Status.LBRuleID).Should(Equal("2ndLBRuleID")) - }) - }) - - Context("Networking Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - if err := client.ResolveNetwork(&dummies.Net1); err != nil { - Skip("Could not find network.") - } - - // Delete any existing tags - existingTags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - if err != nil { - Fail("Failed to get existing tags. Error: " + err.Error()) - } - if len(existingTags) != 0 { - err = client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, existingTags) - if err != nil { - Fail("Failed to delete existing tags. Error: " + err.Error()) - } - } - }) - - It("fetches an isolated network", func() { - dummies.SetDummyIsoNetToNameOnly() - dummies.SetClusterSpecToNet(&dummies.ISONet1) - - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - Ω(dummies.ISONet1.ID).ShouldNot(BeEmpty()) - Ω(dummies.ISONet1.Type).Should(Equal(cloud.NetworkTypeIsolated)) - }) - - It("fetches a public IP", func() { - dummies.Zone1.ID = "" - dummies.SetDummyIsoNetToNameOnly() - dummies.SetClusterSpecToNet(&dummies.ISONet1) - dummies.CSCluster.Spec.ControlPlaneEndpoint.Host = "" - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - }) - }) - - Context("Network Semi-Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - - dummies.SetDummyVars() - - // Setup Isolated Network Dummy Vars. - dummies.CSISONet1.Spec.ID = "" // Make CAPC methods resolve this. - dummies.CSCluster.Spec.ControlPlaneEndpoint.Host = "" // Make CAPC methods resolve this. - dummies.CSZone1.Spec.ID = "" // Make CAPC methods resolve this. - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{} - - // Get Zone info needed for network testing. - Ω(client.ResolveZone(dummies.CSZone1)).Should(Succeed()) - dummies.CSISONet1.Spec.ID = "" - }) - - It("adds an isolated network and doesn't fail when asked to GetOrCreateIsolatedNetwork multiple times", func() { - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - // Network should now exist if it didn't at the start. - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - // Do once more. - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - }) - }) -}) diff --git a/pkg/cloud/network_test.go b/pkg/cloud/network_test.go deleted file mode 100644 index 3da65183..00000000 --- a/pkg/cloud/network_test.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - csapi "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Network", func() { - var ( // Declare shared vars. - mockCtrl *gomock.Controller - mockClient *csapi.CloudStackClient - ns *csapi.MockNetworkServiceIface - client cloud.Client - ) - - BeforeEach(func() { - // Setup new mock services. - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = csapi.NewMockClient(mockCtrl) - ns = mockClient.Network.(*csapi.MockNetworkServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - Context("for an existing network", func() { - It("resolves network by ID", func() { - ns.EXPECT().GetNetworkByName(dummies.ISONet1.Name).Return(nil, 0, nil) - ns.EXPECT().GetNetworkByID(dummies.ISONet1.ID).Return(dummies.CAPCNetToCSAPINet(&dummies.ISONet1), 1, nil) - - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - }) - - It("resolves network by Name", func() { - ns.EXPECT().GetNetworkByName(dummies.ISONet1.Name).Return(dummies.CAPCNetToCSAPINet(&dummies.ISONet1), 1, nil) - - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - }) - }) -}) diff --git a/pkg/cloud/tags_test.go b/pkg/cloud/tags_test.go deleted file mode 100644 index c2f8c2f2..00000000 --- a/pkg/cloud/tags_test.go +++ /dev/null @@ -1,141 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Tag Unit Tests", func() { - BeforeEach(func() { - dummies.SetDummyVars() - }) - - Context("Tag Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - if err := client.ResolveNetwork(&dummies.Net1); err != nil { - Skip("Could not find network.") - } - - // Delete any existing tags - existingTags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - if err != nil { - Fail("Failed to get existing tags. Error: " + err.Error()) - } - if len(existingTags) > 0 { - err = client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, existingTags) - if err != nil { - Fail("Failed to delete existing tags. Error: " + err.Error()) - } - } - }) - - It("adds and gets a resource tag", func() { - Ω(client.AddTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - Ω(client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Equal(dummies.Tags)) - }) - - It("deletes a resource tag", func() { - Ω(client.AddTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - Ω(client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - Ω(client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Equal(map[string]string{})) - }) - - It("returns an error when you delete a tag that doesn't exist", func() { - Ω(client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - }) - - It("adds the tags for a cluster (resource created by CAPC)", func() { - Ω(client.AddCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)). - Should(Succeed()) - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)). - Should(Succeed()) - - // Verify tags - tags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).ShouldNot(HaveOccurred()) - - Ω(tags[dummies.CSClusterTagKey]).Should(Equal(dummies.CSClusterTagVal)) - }) - - It("does not fail when the cluster tags are added twice", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - }) - - It("doesn't adds the tags for a cluster (resource NOT created by CAPC)", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - - // Verify tags - tags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tags[dummies.CreatedByCapcKey]).Should(Equal("")) - Ω(tags[dummies.CSClusterTagKey]).Should(Equal("")) - }) - - It("deletes a cluster tag", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - - Ω(client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID)).ShouldNot(HaveKey(dummies.CSClusterTagKey)) - }) - - It("adds and deletes a created by capc tag", func() { - Ω(client.AddCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - Ω(client.DeleteCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - }) - - It("does not fail when cluster and CAPC created tags are deleted twice", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - Ω(client.DeleteCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - }) - - It("does not allow a resource to be deleted when there are no tags", func() { - tagsAllowDisposal, err := client.DoClusterTagsAllowDisposal(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tagsAllowDisposal).Should(BeFalse()) - }) - - It("does not allow a resource to be deleted when there is a cluster tag", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - tagsAllowDisposal, err := client.DoClusterTagsAllowDisposal(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tagsAllowDisposal).Should(BeFalse()) - }) - - It("does allow a resource to be deleted when there are no cluster tags and there is a CAPC created tag", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.AddCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - - tagsAllowDisposal, err := client.DoClusterTagsAllowDisposal(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tagsAllowDisposal).Should(BeTrue()) - }) - }) -}) diff --git a/pkg/cloud/user_credentials_test.go b/pkg/cloud/user_credentials_test.go deleted file mode 100644 index 1d2c4955..00000000 --- a/pkg/cloud/user_credentials_test.go +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - . "github.com/onsi/ginkgo" - "github.com/pkg/errors" - - . "github.com/onsi/gomega" -) - -var _ = Describe("User Credentials", func() { - - BeforeEach(func() { - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - dummies.SetDummyCSMachineStatuses() - }) - - AfterEach(func() { - }) - - Context("UserCred Semi-Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - var domain cloud.Domain - var account cloud.Account - var user cloud.User - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip(errors.Wrapf(connectionErr, "Could not connect to ACS instance.").Error()) - } - - // Settup dummies. - // TODO: move these to the test dummies package. - domain = cloud.Domain{Path: "ROOT/blah/blah/subsub"} - account = cloud.Account{Name: "SuperNested", Domain: domain} - user = cloud.User{Name: "SubSub", Account: account} - }) - - It("can resolve a domain from the path", func() { - Ω(client.ResolveDomain(&domain)).Should(Succeed()) - Ω(domain.ID).ShouldNot(BeEmpty()) - }) - - It("can resolve an account from the domain path and account name", func() { - Ω(client.ResolveAccount(&account)).Should(Succeed()) - Ω(account.ID).ShouldNot(BeEmpty()) - }) - - It("can resolve a user from the domain path, account name, and user name", func() { - Ω(client.ResolveUser(&user)).Should(Succeed()) - Ω(user.ID).ShouldNot(BeEmpty()) - }) - - It("can get sub-domain user's credentials", func() { - Ω(client.ResolveUserKeys(&user)).Should(Succeed()) - - Ω(user.APIKey).ShouldNot(BeEmpty()) - Ω(user.SecretKey).ShouldNot(BeEmpty()) - }) - - It("can get an arbitrary user with keys from domain and account specifications alone", func() { - found, err := client.GetUserWithKeys(&user) - Ω(err).ShouldNot(HaveOccurred()) - Ω(found).Should(BeTrue()) - Ω(user.APIKey).ShouldNot(BeEmpty()) - }) - - It("can get create a new client as another user", func() { - found, err := client.GetUserWithKeys(&user) - Ω(err).ShouldNot(HaveOccurred()) - Ω(found).Should(BeTrue()) - Ω(user.APIKey).ShouldNot(BeEmpty()) - cfg := cloud.Config{APIKey: user.APIKey, SecretKey: user.SecretKey} - newClient, err := client.NewClientFromSpec(cfg) - Ω(err).ShouldNot(HaveOccurred()) - Ω(newClient).ShouldNot(BeNil()) - }) - }) -}) diff --git a/pkg/cloud/zone_test.go b/pkg/cloud/zone_test.go deleted file mode 100644 index 11fb4eed..00000000 --- a/pkg/cloud/zone_test.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package cloud_test - -import ( - "fmt" - - csapi "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/pkg/errors" -) - -var _ = Describe("Cluster", func() { - var ( - client cloud.Client - mockCtrl *gomock.Controller - mockClient *csapi.CloudStackClient - zs *csapi.MockZoneServiceIface - ) - - BeforeEach(func() { - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = csapi.NewMockClient(mockCtrl) - zs = mockClient.Zone.(*csapi.MockZoneServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - dummies.SetDummyDomainAndAccount() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - Context("an existing abstract dummies.CSCluster", func() { - It("handles zone not found.", func() { - expectedErr := fmt.Errorf("Not found") - zs.EXPECT().GetZoneID(dummies.Zone1.Name).Return("", -1, expectedErr) - zs.EXPECT().GetZoneByID(dummies.Zone1.ID).Return(nil, -1, expectedErr) - - err := client.ResolveZone(dummies.CSZone1) - Expect(errors.Cause(err)).To(MatchError(expectedErr)) - }) - - It("handles multiple zone IDs returned", func() { - zs.EXPECT().GetZoneID(dummies.Zone1.Name).Return(dummies.Zone1.ID, 2, nil) - zs.EXPECT().GetZoneByID(dummies.Zone1.ID).Return(nil, -1, fmt.Errorf("Not found")) - - Ω(client.ResolveZone(dummies.CSZone1)).Should(MatchError(And( - ContainSubstring("expected 1 Zone with name "+dummies.Zone1.Name+", but got 2"), - ContainSubstring("could not get Zone by ID "+dummies.Zone1.ID+": Not found")))) - }) - }) -}) diff --git a/test/unit/cloud/affinity_groups_test.go b/test/unit/cloud/affinity_groups_test.go deleted file mode 100644 index 83c617d1..00000000 --- a/test/unit/cloud/affinity_groups_test.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "errors" - - "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("AffinityGroup Unit Tests", func() { - var ( // Declare shared vars. - mockCtrl *gomock.Controller - mockClient *cloudstack.CloudStackClient - ags *cloudstack.MockAffinityGroupServiceIface - client cloud.Client - ) - - BeforeEach(func() { - // Setup new mock services. - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = cloudstack.NewMockClient(mockCtrl) - ags = mockClient.AffinityGroup.(*cloudstack.MockAffinityGroupServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - It("fetches an affinity group", func() { - dummies.AffinityGroup.ID = "" // Force name fetching. - ags.EXPECT().GetAffinityGroupByName(dummies.AffinityGroup.Name).Return(&cloudstack.AffinityGroup{}, 1, nil) - - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - }) - It("creates an affinity group", func() { - dummies.SetDummyDomainAndAccount() - dummies.SetDummyDomainID() - ags.EXPECT().GetAffinityGroupByID(dummies.AffinityGroup.ID).Return(nil, -1, errors.New("FakeError")) - ags.EXPECT().NewCreateAffinityGroupParams(dummies.AffinityGroup.Name, dummies.AffinityGroup.Type). - Return(&cloudstack.CreateAffinityGroupParams{}) - ags.EXPECT().CreateAffinityGroup(ParamMatch(And(NameEquals(dummies.AffinityGroup.Name)))). - Return(&cloudstack.CreateAffinityGroupResponse{}, nil) - - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - }) - - Context("AffinityGroup Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - dummies.AffinityGroup.ID = "" // Force name fetching. - }) - AfterEach(func() { - mockCtrl.Finish() - }) - - It("Creates an affinity group.", func() { - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - }) - It("Associates an affinity group.", func() { - if err := client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "", - ); err != nil { - Skip("Could not create VM." + err.Error()) - } - Ω(client.GetOrCreateAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - Ω(client.AssociateAffinityGroup(dummies.CSMachine1, *dummies.AffinityGroup)).Should(Succeed()) - }) - It("Deletes an affinity group.", func() { - Ω(client.DeleteAffinityGroup(dummies.AffinityGroup)).Should(Succeed()) - Ω(client.FetchAffinityGroup(dummies.AffinityGroup)).ShouldNot(Succeed()) - }) - }) -}) diff --git a/test/unit/cloud/client_test.go b/test/unit/cloud/client_test.go deleted file mode 100644 index 395f3970..00000000 --- a/test/unit/cloud/client_test.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "gopkg.in/ini.v1" -) - -// Example cloud-config ini structure. -type Global struct { - APIURL string `ini:"api-url"` - VerifySSL bool `ini:"verify-ssl"` -} - -var _ = Describe("Instance", func() { - - var () - - BeforeEach(func() { - // This test fixture is useful for development, but the actual method of parsing is confinded to the client's - // new client method. The parsing used here is more of a schema, and we don't need to test another library's - // abilities to parse said schema. - Skip("Dev test suite.") - }) - - AfterEach(func() { - }) - - Context("When fetching an INI config.", func() { - It("Handles the positive case.", func() { - cfg := &Global{} - rawCfg, err := ini.Load("../../cloud-config") - Ω(rawCfg.Section("Global")).ShouldNot(BeNil()) - Ω(err).ShouldNot(HaveOccurred()) - Ω(rawCfg.Section("Global").MapTo(cfg)).Should(Succeed()) - Ω(cfg.VerifySSL).Should(BeFalse()) - Ω(cfg.APIURL).ShouldNot(BeEmpty()) - }) - }) -}) diff --git a/test/unit/cloud/cloud_suite_test.go b/test/unit/cloud/cloud_suite_test.go deleted file mode 100644 index d3a8fe31..00000000 --- a/test/unit/cloud/cloud_suite_test.go +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestCloud(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Cloud Suite") -} diff --git a/test/unit/cloud/helpers_test.go b/test/unit/cloud/helpers_test.go deleted file mode 100644 index 6819341c..00000000 --- a/test/unit/cloud/helpers_test.go +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "bytes" - "compress/gzip" - "encoding/base64" - "fmt" - "io/ioutil" - "os" - "path" - "reflect" - - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/onsi/gomega/types" -) - -const ( - FixturePath = "test/fixtures/cloud-config-files" -) - -var _ = Describe("Helpers", func() { - - Context("For a configuration with the 'Global' section missing", func() { - It("Gets API configuration", func() { - filepath := getConfigPath("cloud-config-no-global") - - client, err := cloud.NewClient(filepath) - - Ω(client).Should(BeNil()) - Ω(err.Error()).Should(ContainSubstring("section Global not found")) - }) - }) - - It("should compress and encode string", func() { - str := "Hello World" - - compressedAndEncodedData, err := cloud.CompressAndEncodeString(str) - - compressedData, _ := base64.StdEncoding.DecodeString(compressedAndEncodedData) - reader, _ := gzip.NewReader(bytes.NewReader(compressedData)) - result, _ := ioutil.ReadAll(reader) - - Ω(err).Should(BeNil()) - Ω(string(result)).Should(Equal(str)) - }) -}) - -func getConfigPath(filename string) string { - dir, _ := os.Getwd() - return path.Join(dir, FixturePath, filename) -} - -// This matcher is used to make gomega matching compatible with gomock parameter matching. -// It's pretty awesome! -// -// This sort of hacks the gomock interface to inject a gomega matcher. -// -// Gomega matchers are far more flexible than gomock matchers, but they normally can't be used on parameters. - -type paramMatcher struct { - matcher types.GomegaMatcher -} - -func ParamMatch(matcher types.GomegaMatcher) gomock.Matcher { - return paramMatcher{matcher} -} - -func (p paramMatcher) String() string { - return "a gomega matcher to match, and said matcher should have panicked before this message was printed." -} - -func (p paramMatcher) Matches(x interface{}) (retVal bool) { - return Ω(x).Should(p.matcher) -} - -// This generates translating matchers. -// -// The CloudStack Go API uses param interfaces that can't be accessed except through builtin methods. -// -// This generates translation matchers: -// -// Essentially it will generate a matcher that checks the value from p.Get() is Equal to an input String. -// -// DomainIDEquals = FieldMatcherGenerator("GetDomainid") -// p := &CreateNewSomethingParams{Domainid: "FakeDomainID"} -// Ω(p).DomainIDEquals("FakeDomainID") -func FieldMatcherGenerator(fetchFunc string) func(string) types.GomegaMatcher { - return (func(expected string) types.GomegaMatcher { - return WithTransform( - func(x interface{}) string { - meth := reflect.ValueOf(x).MethodByName(fetchFunc) - fmt.Println(meth.Call(nil)[0]) - - return meth.Call(nil)[0].String() - }, Equal(expected)) - }) -} - -var ( - DomainIDEquals = FieldMatcherGenerator("GetDomainid") - AccountEquals = FieldMatcherGenerator("GetAccount") - IDEquals = FieldMatcherGenerator("GetId") - NameEquals = FieldMatcherGenerator("GetName") -) - -// CreateUserInSubDomain creates a sub-domain, account, and user with api-keys with a generated uuid as part of the name. -func CreateUserInSubDomain(user *cloud.User) error { - - return nil -} diff --git a/test/unit/cloud/instance_test.go b/test/unit/cloud/instance_test.go deleted file mode 100644 index 5b5065e2..00000000 --- a/test/unit/cloud/instance_test.go +++ /dev/null @@ -1,438 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "fmt" - - "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - - . "github.com/onsi/gomega" - "github.com/pkg/errors" - "k8s.io/utils/pointer" -) - -var _ = Describe("Instance", func() { - const ( - unknownErrorMessage = "unknown err" - offeringFakeID = "123" - templateFakeID = "456" - executableFilter = "executable" - diskOfferingFakeID = "789" - ) - - notFoundError := errors.New("no match found") - unknownError := errors.New(unknownErrorMessage) - - var ( - mockCtrl *gomock.Controller - mockClient *cloudstack.CloudStackClient - vms *cloudstack.MockVirtualMachineServiceIface - sos *cloudstack.MockServiceOfferingServiceIface - dos *cloudstack.MockDiskOfferingServiceIface - ts *cloudstack.MockTemplateServiceIface - vs *cloudstack.MockVolumeServiceIface - client cloud.Client - ) - - BeforeEach(func() { - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = cloudstack.NewMockClient(mockCtrl) - vms = mockClient.VirtualMachine.(*cloudstack.MockVirtualMachineServiceIface) - sos = mockClient.ServiceOffering.(*cloudstack.MockServiceOfferingServiceIface) - dos = mockClient.DiskOffering.(*cloudstack.MockDiskOfferingServiceIface) - ts = mockClient.Template.(*cloudstack.MockTemplateServiceIface) - vs = mockClient.Volume.(*cloudstack.MockVolumeServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - dummies.SetDummyCSMachineStatuses() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - Context("when fetching a VM instance", func() { - It("Handles an unknown error when fetching by ID", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, unknownError) - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).To(MatchError(unknownErrorMessage)) - }) - - It("Handles finding more than one VM instance by ID", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, 2, nil) - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)). - Should(MatchError("found more than one VM Instance with ID " + *dummies.CSMachine1.Spec.InstanceID)) - }) - - It("sets dummies.CSMachine1 spec and status values when VM instance found by ID", func() { - vmsResp := &cloudstack.VirtualMachinesMetric{Id: *dummies.CSMachine1.Spec.InstanceID} - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(vmsResp, 1, nil) - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should(Succeed()) - Ω(dummies.CSMachine1.Spec.ProviderID).Should(Equal(pointer.StringPtr("cloudstack:///" + vmsResp.Id))) - Ω(dummies.CSMachine1.Spec.InstanceID).Should(Equal(pointer.StringPtr(vmsResp.Id))) - }) - - It("handles an unknown error when fetching by name", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, unknownError) - - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should(MatchError(unknownErrorMessage)) - }) - - It("handles finding more than one VM instance by Name", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, 2, nil) - - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should( - MatchError("found more than one VM Instance with name " + dummies.CSMachine1.Name)) - }) - - It("sets dummies.CSMachine1 spec and status values when VM instance found by Name", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name). - Return(&cloudstack.VirtualMachinesMetric{Id: *dummies.CSMachine1.Spec.InstanceID}, -1, nil) - - Ω(client.ResolveVMInstanceDetails(dummies.CSMachine1)).Should(Succeed()) - Ω(dummies.CSMachine1.Spec.ProviderID).Should(Equal( - pointer.StringPtr(fmt.Sprintf("cloudstack:///%s", *dummies.CSMachine1.Spec.InstanceID)))) - Ω(dummies.CSMachine1.Spec.InstanceID).Should(Equal(pointer.StringPtr(*dummies.CSMachine1.Spec.InstanceID))) - }) - }) - - Context("when creating a VM instance", func() { - vmMetricResp := &cloudstack.VirtualMachinesMetric{} - - expectVMNotFound := func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - } - - It("doesn't re-create if one already exists.", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(vmMetricResp, -1, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(Succeed()) - }) - - It("returns unknown error while fetching VM instance", func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, unknownError) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(unknownErrorMessage)) - }) - - It("returns errors occurring while fetching service offering information", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return("", -1, unknownError) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("returns errors if more than one service offering found", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return("", 2, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("returns errors while fetching template", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name). - Return(dummies.CSMachine1.Spec.Offering.ID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return("", -1, unknownError) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("returns errors when more than one template found", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name). - Return(dummies.CSMachine1.Spec.Offering.ID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID).Return("", 2, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - ShouldNot(Succeed()) - }) - - It("handles deployment errors", func() { - expectVMNotFound() - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name). - Return(offeringFakeID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name). - Return(diskOfferingFakeID, 1, nil) - vms.EXPECT().NewDeployVirtualMachineParams(offeringFakeID, templateFakeID, dummies.Zone1.ID). - Return(&cloudstack.DeployVirtualMachineParams{}) - vms.EXPECT().DeployVirtualMachine(gomock.Any()).Return(nil, unknownError) - vms.EXPECT().NewListVirtualMachinesParams().Return(&cloudstack.ListVirtualMachinesParams{}) - vms.EXPECT().ListVirtualMachines(gomock.Any()).Return(&cloudstack.ListVirtualMachinesResponse{}, nil) - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(unknownErrorMessage)) - }) - - Context("when using UUIDs and/or names to locate service offerings and templates", func() { - BeforeEach(func() { - gomock.InOrder( - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(nil, -1, notFoundError), - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{}, 1, nil)) - - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - }) - - ActionAndAssert := func() { - vms.EXPECT().NewDeployVirtualMachineParams(offeringFakeID, templateFakeID, dummies.Zone1.ID). - Return(&cloudstack.DeployVirtualMachineParams{}) - - deploymentResp := &cloudstack.DeployVirtualMachineResponse{Id: *dummies.CSMachine1.Spec.InstanceID} - vms.EXPECT().DeployVirtualMachine(gomock.Any()).Return(deploymentResp, nil) - - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(Succeed()) - } - - It("works with service offering name and template name", func() { - dummies.CSMachine1.Spec.Offering.ID = "" - dummies.CSMachine1.Spec.Template.ID = "" - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return(offeringFakeID, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering name and template name without disk offering", func() { - dummies.CSMachine1.Spec.Offering.ID = "" - dummies.CSMachine1.Spec.Template.ID = "" - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - dummies.CSMachine1.Spec.DiskOffering = v1beta1.CloudStackResourceDiskOffering{} - - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return(offeringFakeID, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering ID and template name", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = "" - dummies.CSMachine1.Spec.Offering.Name = "" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: ""}, 1, nil) - ts.EXPECT().GetTemplateID(dummies.CSMachine1.Spec.Template.Name, executableFilter, dummies.Zone1.ID). - Return(templateFakeID, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering name and template ID", func() { - dummies.CSMachine1.Spec.Offering.ID = "" - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "" - - sos.EXPECT().GetServiceOfferingID(dummies.CSMachine1.Spec.Offering.Name).Return(offeringFakeID, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter).Return(&cloudstack.Template{Name: ""}, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - - ActionAndAssert() - }) - - It("works with service offering ID and template ID", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "" - dummies.CSMachine1.Spec.Template.Name = "" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID). - Return(&cloudstack.ServiceOffering{Name: "offering"}, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name). - Return(diskOfferingFakeID, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter). - Return(&cloudstack.Template{Name: "template"}, 1, nil) - - ActionAndAssert() - }) - - It("works with Id and name both provided", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: "offering"}, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter).Return(&cloudstack.Template{Name: "template"}, 1, nil) - dos.EXPECT().GetDiskOfferingID(dummies.CSMachine1.Spec.DiskOffering.Name).Return(diskOfferingFakeID, 1, nil) - - ActionAndAssert() - }) - }) - - Context("when using both UUIDs and names to locate service offerings and templates", func() { - BeforeEach(func() { - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - }) - - It("works with Id and name both provided, offering name mismatch", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: "offering-not-match"}, 1, nil) - requiredRegexp := "offering name %s does not match name %s returned using UUID %s" - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(MatchRegexp(requiredRegexp, dummies.CSMachine1.Spec.Offering.Name, "offering-not-match", offeringFakeID))) - }) - - It("works with Id and name both provided, template name mismatch", func() { - dummies.CSMachine1.Spec.Offering.ID = offeringFakeID - dummies.CSMachine1.Spec.Template.ID = templateFakeID - dummies.CSMachine1.Spec.Offering.Name = "offering" - dummies.CSMachine1.Spec.Template.Name = "template" - - sos.EXPECT().GetServiceOfferingByID(dummies.CSMachine1.Spec.Offering.ID).Return(&cloudstack.ServiceOffering{Name: "offering"}, 1, nil) - ts.EXPECT().GetTemplateByID(dummies.CSMachine1.Spec.Template.ID, executableFilter).Return(&cloudstack.Template{Name: "template-not-match"}, 1, nil) - requiredRegexp := "template name %s does not match name %s returned using UUID %s" - Ω(client.GetOrCreateVMInstance( - dummies.CSMachine1, dummies.CAPIMachine, dummies.CSCluster, dummies.CSZone1, dummies.CSAffinityGroup, "")). - Should(MatchError(MatchRegexp(requiredRegexp, dummies.CSMachine1.Spec.Template.Name, "template-not-match", templateFakeID))) - - }) - }) - }) - - Context("when destroying a VM instance", func() { - expungeDestroyParams := &cloudstack.DestroyVirtualMachineParams{} - expungeDestroyParams.SetExpunge(true) - listVolumesParams := &cloudstack.ListVolumesParams{} - listVolumesResponse := &cloudstack.ListVolumesResponse{ - Volumes: []*cloudstack.Volume{ - { - Id: "123", - }, - { - Id: "456", - }, - }, - } - - It("calls destroy and finds VM doesn't exist, then returns nil", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, fmt.Errorf("unable to find uuid for id")) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy and returns unexpected error", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, fmt.Errorf("new error")) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)).Should(MatchError("new error")) - }) - - It("calls destroy without error but cannot resolve VM after", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID).Return(nil, -1, notFoundError) - vms.EXPECT().GetVirtualMachinesMetricByName(dummies.CSMachine1.Name).Return(nil, -1, notFoundError) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy without error and identifies it as expunging", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{ - State: "Expunging", - }, 1, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy without error and identifies it as expunged", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{ - State: "Expunged", - }, 1, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)). - Should(Succeed()) - }) - - It("calls destroy without error and identifies it as stopping", func() { - listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID) - vms.EXPECT().NewDestroyVirtualMachineParams(*dummies.CSMachine1.Spec.InstanceID). - Return(expungeDestroyParams) - vms.EXPECT().DestroyVirtualMachine(expungeDestroyParams).Return(nil, nil) - vs.EXPECT().NewListVolumesParams().Return(listVolumesParams) - vs.EXPECT().ListVolumes(listVolumesParams).Return(listVolumesResponse, nil) - vms.EXPECT().GetVirtualMachinesMetricByID(*dummies.CSMachine1.Spec.InstanceID). - Return(&cloudstack.VirtualMachinesMetric{ - State: "Stopping", - }, 1, nil) - Ω(client.DestroyVMInstance(dummies.CSMachine1)).Should(MatchError("VM deletion in progress")) - }) - }) -}) diff --git a/test/unit/cloud/isolated_network_test.go b/test/unit/cloud/isolated_network_test.go deleted file mode 100644 index 028f1ac3..00000000 --- a/test/unit/cloud/isolated_network_test.go +++ /dev/null @@ -1,266 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "strconv" - - csapi "github.com/apache/cloudstack-go/v2/cloudstack" - capcv1 "github.com/aws/cluster-api-provider-cloudstack/api/v1beta1" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/pkg/errors" -) - -var _ = Describe("Network", func() { - var ( // Declare shared vars. - mockCtrl *gomock.Controller - mockClient *csapi.CloudStackClient - ns *csapi.MockNetworkServiceIface - nos *csapi.MockNetworkOfferingServiceIface - fs *csapi.MockFirewallServiceIface - as *csapi.MockAddressServiceIface - lbs *csapi.MockLoadBalancerServiceIface - rs *csapi.MockResourcetagsServiceIface - client cloud.Client - ) - - BeforeEach(func() { - // Setup new mock services. - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = csapi.NewMockClient(mockCtrl) - ns = mockClient.Network.(*csapi.MockNetworkServiceIface) - nos = mockClient.NetworkOffering.(*csapi.MockNetworkOfferingServiceIface) - fs = mockClient.Firewall.(*csapi.MockFirewallServiceIface) - as = mockClient.Address.(*csapi.MockAddressServiceIface) - lbs = mockClient.LoadBalancer.(*csapi.MockLoadBalancerServiceIface) - rs = mockClient.Resourcetags.(*csapi.MockResourcetagsServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - It("calls to create an isolated network when not found", func() { - dummies.Zone1.Network = dummies.ISONet1 - dummies.Zone1.Network.ID = "" - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{dummies.Zone1.ID: dummies.Zone1} - dummies.CSCluster.Status.PublicIPNetworkID = dummies.ISONet1.ID - - nos.EXPECT().GetNetworkOfferingID(gomock.Any()).Return("someOfferingID", 1, nil) - ns.EXPECT().NewCreateNetworkParams(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(&csapi.CreateNetworkParams{}) - ns.EXPECT().GetNetworkByName(dummies.ISONet1.Name).Return(nil, 0, nil) - ns.EXPECT().GetNetworkByID(dummies.ISONet1.ID).Return(nil, 0, nil) - ns.EXPECT().CreateNetwork(gomock.Any()).Return(&csapi.CreateNetworkResponse{Id: dummies.ISONet1.ID}, nil) - as.EXPECT().NewListPublicIpAddressesParams().Return(&csapi.ListPublicIpAddressesParams{}) - as.EXPECT().ListPublicIpAddresses(gomock.Any()). - Return(&csapi.ListPublicIpAddressesResponse{ - Count: 1, - PublicIpAddresses: []*csapi.PublicIpAddress{{Id: dummies.PublicIPID, Ipaddress: "fakeIP"}}}, nil) - as.EXPECT().NewAssociateIpAddressParams().Return(&csapi.AssociateIpAddressParams{}) - as.EXPECT().AssociateIpAddress(gomock.Any()) - fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, cloud.NetworkProtocolTCP). - Return(&csapi.CreateEgressFirewallRuleParams{}) - fs.EXPECT().CreateEgressFirewallRule(&csapi.CreateEgressFirewallRuleParams{}). - Return(&csapi.CreateEgressFirewallRuleResponse{}, nil) - - // Will add cluster tag once to Network and once to PublicIP. - createdByResponse := &csapi.ListTagsResponse{Tags: []*csapi.Tag{{Key: cloud.CreatedByCAPCTagName, Value: "1"}}} - gomock.InOrder( - rs.EXPECT().NewListTagsParams().Return(&csapi.ListTagsParams{}), - rs.EXPECT().ListTags(gomock.Any()).Return(createdByResponse, nil), - rs.EXPECT().NewListTagsParams().Return(&csapi.ListTagsParams{}), - rs.EXPECT().ListTags(gomock.Any()).Return(createdByResponse, nil)) - - // Will add creation and cluster tags to network and PublicIP. - rs.EXPECT().NewCreateTagsParams(gomock.Any(), gomock.Any(), gomock.Any()). - Return(&csapi.CreateTagsParams{}).Times(4) - rs.EXPECT().CreateTags(gomock.Any()).Return(&csapi.CreateTagsResponse{}, nil).Times(4) - - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()).Return( - &csapi.ListLoadBalancerRulesResponse{LoadBalancerRules: []*csapi.LoadBalancerRule{ - {Publicport: strconv.Itoa(int(dummies.EndPointPort)), Id: dummies.LBRuleID}}}, nil) - - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - }) - - Context("for a closed firewall", func() { - It("OpenFirewallRule asks CloudStack to open the firewall", func() { - dummies.Zone1.Network = dummies.ISONet1 - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{dummies.Zone1.ID: dummies.Zone1} - dummies.CSCluster.Status.PublicIPNetworkID = dummies.ISONet1.ID - fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, cloud.NetworkProtocolTCP). - Return(&csapi.CreateEgressFirewallRuleParams{}) - fs.EXPECT().CreateEgressFirewallRule(&csapi.CreateEgressFirewallRuleParams{}). - Return(&csapi.CreateEgressFirewallRuleResponse{}, nil) - - Ω(client.OpenFirewallRules(dummies.CSISONet1)).Should(Succeed()) - }) - }) - - Context("for an open firewall", func() { - It("OpenFirewallRule asks CloudStack to open the firewall anyway, but doesn't fail", func() { - dummies.Zone1.Network = dummies.ISONet1 - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{dummies.Zone1.ID: dummies.Zone1} - dummies.CSCluster.Status.PublicIPNetworkID = dummies.ISONet1.ID - - fs.EXPECT().NewCreateEgressFirewallRuleParams(dummies.ISONet1.ID, "tcp"). - Return(&csapi.CreateEgressFirewallRuleParams{}) - fs.EXPECT().CreateEgressFirewallRule(&csapi.CreateEgressFirewallRuleParams{}). - Return(&csapi.CreateEgressFirewallRuleResponse{}, errors.New("there is already a rule like this")) - - Ω(client.OpenFirewallRules(dummies.CSISONet1)).Should(Succeed()) - }) - }) - - Context("in an isolated network with public IPs available", func() { - It("will resolve public IP details given an endpoint spec", func() { - ipAddress := "192.168.1.14" - as.EXPECT().NewListPublicIpAddressesParams().Return(&csapi.ListPublicIpAddressesParams{}) - as.EXPECT().ListPublicIpAddresses(gomock.Any()). - Return(&csapi.ListPublicIpAddressesResponse{ - Count: 1, - PublicIpAddresses: []*csapi.PublicIpAddress{{Id: "PublicIPID", Ipaddress: ipAddress}}, - }, nil) - publicIPAddress, err := client.GetPublicIP(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster) - Ω(err).Should(Succeed()) - Ω(publicIPAddress).ShouldNot(BeNil()) - Ω(publicIPAddress.Ipaddress).Should(Equal(ipAddress)) - }) - }) - - Context("The specific load balancer rule does exist", func() { - It("resolves the rule's ID", func() { - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()).Return( - &csapi.ListLoadBalancerRulesResponse{LoadBalancerRules: []*csapi.LoadBalancerRule{ - {Publicport: strconv.Itoa(int(dummies.EndPointPort)), Id: dummies.LBRuleID}}}, nil) - - dummies.CSISONet1.Status.LBRuleID = "" - Ω(client.ResolveLoadBalancerRuleDetails(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(dummies.CSISONet1.Status.LBRuleID).Should(Equal(dummies.LBRuleID)) - }) - - It("doesn't create a new load balancer rule on create", func() { - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()). - Return(&csapi.ListLoadBalancerRulesResponse{ - LoadBalancerRules: []*csapi.LoadBalancerRule{ - {Publicport: strconv.Itoa(int(dummies.EndPointPort)), Id: dummies.LBRuleID}}}, nil) - - Ω(client.GetOrCreateLoadBalancerRule(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(dummies.CSISONet1.Status.LBRuleID).Should(Equal(dummies.LBRuleID)) - }) - }) - - Context("load balancer rule does not exist", func() { - It("calls cloudstack to create a new load balancer rule.", func() { - lbs.EXPECT().NewListLoadBalancerRulesParams().Return(&csapi.ListLoadBalancerRulesParams{}) - lbs.EXPECT().ListLoadBalancerRules(gomock.Any()). - Return(&csapi.ListLoadBalancerRulesResponse{ - LoadBalancerRules: []*csapi.LoadBalancerRule{{Publicport: "7443", Id: dummies.LBRuleID}}}, nil) - lbs.EXPECT().NewCreateLoadBalancerRuleParams(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). - Return(&csapi.CreateLoadBalancerRuleParams{}) - lbs.EXPECT().CreateLoadBalancerRule(gomock.Any()). - Return(&csapi.CreateLoadBalancerRuleResponse{Id: "2ndLBRuleID"}, nil) - - Ω(client.GetOrCreateLoadBalancerRule(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(dummies.CSISONet1.Status.LBRuleID).Should(Equal("2ndLBRuleID")) - }) - }) - - Context("Networking Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - if err := client.ResolveNetwork(&dummies.Net1); err != nil { - Skip("Could not find network.") - } - - // Delete any existing tags - existingTags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - if err != nil { - Fail("Failed to get existing tags. Error: " + err.Error()) - } - if len(existingTags) != 0 { - err = client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, existingTags) - if err != nil { - Fail("Failed to delete existing tags. Error: " + err.Error()) - } - } - }) - - It("fetches an isolated network", func() { - dummies.SetDummyIsoNetToNameOnly() - dummies.SetClusterSpecToNet(&dummies.ISONet1) - - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - Ω(dummies.ISONet1.ID).ShouldNot(BeEmpty()) - Ω(dummies.ISONet1.Type).Should(Equal(cloud.NetworkTypeIsolated)) - }) - - It("fetches a public IP", func() { - dummies.Zone1.ID = "" - dummies.SetDummyIsoNetToNameOnly() - dummies.SetClusterSpecToNet(&dummies.ISONet1) - dummies.CSCluster.Spec.ControlPlaneEndpoint.Host = "" - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - }) - }) - - Context("Network Semi-Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - - dummies.SetDummyVars() - - // Setup Isolated Network Dummy Vars. - dummies.CSISONet1.Spec.ID = "" // Make CAPC methods resolve this. - dummies.CSCluster.Spec.ControlPlaneEndpoint.Host = "" // Make CAPC methods resolve this. - dummies.CSZone1.Spec.ID = "" // Make CAPC methods resolve this. - dummies.CSCluster.Status.Zones = capcv1.ZoneStatusMap{} - - // Get Zone info needed for network testing. - Ω(client.ResolveZone(dummies.CSZone1)).Should(Succeed()) - dummies.CSISONet1.Spec.ID = "" - }) - - It("adds an isolated network and doesn't fail when asked to GetOrCreateIsolatedNetwork multiple times", func() { - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - // Network should now exist if it didn't at the start. - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - // Do once more. - Ω(client.GetOrCreateIsolatedNetwork(dummies.CSZone1, dummies.CSISONet1, dummies.CSCluster)).Should(Succeed()) - }) - }) -}) diff --git a/test/unit/cloud/network_test.go b/test/unit/cloud/network_test.go deleted file mode 100644 index 3da65183..00000000 --- a/test/unit/cloud/network_test.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - csapi "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Network", func() { - var ( // Declare shared vars. - mockCtrl *gomock.Controller - mockClient *csapi.CloudStackClient - ns *csapi.MockNetworkServiceIface - client cloud.Client - ) - - BeforeEach(func() { - // Setup new mock services. - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = csapi.NewMockClient(mockCtrl) - ns = mockClient.Network.(*csapi.MockNetworkServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - Context("for an existing network", func() { - It("resolves network by ID", func() { - ns.EXPECT().GetNetworkByName(dummies.ISONet1.Name).Return(nil, 0, nil) - ns.EXPECT().GetNetworkByID(dummies.ISONet1.ID).Return(dummies.CAPCNetToCSAPINet(&dummies.ISONet1), 1, nil) - - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - }) - - It("resolves network by Name", func() { - ns.EXPECT().GetNetworkByName(dummies.ISONet1.Name).Return(dummies.CAPCNetToCSAPINet(&dummies.ISONet1), 1, nil) - - Ω(client.ResolveNetwork(&dummies.ISONet1)).Should(Succeed()) - }) - }) -}) diff --git a/test/unit/cloud/tags_test.go b/test/unit/cloud/tags_test.go deleted file mode 100644 index c2f8c2f2..00000000 --- a/test/unit/cloud/tags_test.go +++ /dev/null @@ -1,141 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Tag Unit Tests", func() { - BeforeEach(func() { - dummies.SetDummyVars() - }) - - Context("Tag Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip("Could not connect to ACS instance.") - } - if err := client.ResolveNetwork(&dummies.Net1); err != nil { - Skip("Could not find network.") - } - - // Delete any existing tags - existingTags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - if err != nil { - Fail("Failed to get existing tags. Error: " + err.Error()) - } - if len(existingTags) > 0 { - err = client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, existingTags) - if err != nil { - Fail("Failed to delete existing tags. Error: " + err.Error()) - } - } - }) - - It("adds and gets a resource tag", func() { - Ω(client.AddTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - Ω(client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Equal(dummies.Tags)) - }) - - It("deletes a resource tag", func() { - Ω(client.AddTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - Ω(client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - Ω(client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Equal(map[string]string{})) - }) - - It("returns an error when you delete a tag that doesn't exist", func() { - Ω(client.DeleteTags(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.Tags)).Should(Succeed()) - }) - - It("adds the tags for a cluster (resource created by CAPC)", func() { - Ω(client.AddCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)). - Should(Succeed()) - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)). - Should(Succeed()) - - // Verify tags - tags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).ShouldNot(HaveOccurred()) - - Ω(tags[dummies.CSClusterTagKey]).Should(Equal(dummies.CSClusterTagVal)) - }) - - It("does not fail when the cluster tags are added twice", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - }) - - It("doesn't adds the tags for a cluster (resource NOT created by CAPC)", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - - // Verify tags - tags, err := client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tags[dummies.CreatedByCapcKey]).Should(Equal("")) - Ω(tags[dummies.CSClusterTagKey]).Should(Equal("")) - }) - - It("deletes a cluster tag", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - - Ω(client.GetTags(cloud.ResourceTypeNetwork, dummies.Net1.ID)).ShouldNot(HaveKey(dummies.CSClusterTagKey)) - }) - - It("adds and deletes a created by capc tag", func() { - Ω(client.AddCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - Ω(client.DeleteCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - }) - - It("does not fail when cluster and CAPC created tags are deleted twice", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.DeleteCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - Ω(client.DeleteCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - }) - - It("does not allow a resource to be deleted when there are no tags", func() { - tagsAllowDisposal, err := client.DoClusterTagsAllowDisposal(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tagsAllowDisposal).Should(BeFalse()) - }) - - It("does not allow a resource to be deleted when there is a cluster tag", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - tagsAllowDisposal, err := client.DoClusterTagsAllowDisposal(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tagsAllowDisposal).Should(BeFalse()) - }) - - It("does allow a resource to be deleted when there are no cluster tags and there is a CAPC created tag", func() { - Ω(client.AddClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - Ω(client.AddCreatedByCAPCTag(cloud.ResourceTypeNetwork, dummies.Net1.ID)).Should(Succeed()) - Ω(client.DeleteClusterTag(cloud.ResourceTypeNetwork, dummies.Net1.ID, dummies.CSCluster)).Should(Succeed()) - - tagsAllowDisposal, err := client.DoClusterTagsAllowDisposal(cloud.ResourceTypeNetwork, dummies.Net1.ID) - Ω(err).Should(BeNil()) - Ω(tagsAllowDisposal).Should(BeTrue()) - }) - }) -}) diff --git a/test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-good b/test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-good deleted file mode 100644 index a840ba7a..00000000 --- a/test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-good +++ /dev/null @@ -1,5 +0,0 @@ -[Global] -api-key = api-key1 -secret-key = secret-key1 -api-url = api-url1 - diff --git a/test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-no-global b/test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-no-global deleted file mode 100644 index cc4ed156..00000000 --- a/test/unit/cloud/test/fixtures/cloud-config-files/cloud-config-no-global +++ /dev/null @@ -1,5 +0,0 @@ -[NonGlobal] -api-key = api-key1 -secret-key = secret-key1 -api-url = api-url1 - diff --git a/test/unit/cloud/user_credentials_test.go b/test/unit/cloud/user_credentials_test.go deleted file mode 100644 index 1d2c4955..00000000 --- a/test/unit/cloud/user_credentials_test.go +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package cloud_test - -import ( - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - . "github.com/onsi/ginkgo" - "github.com/pkg/errors" - - . "github.com/onsi/gomega" -) - -var _ = Describe("User Credentials", func() { - - BeforeEach(func() { - dummies.SetDummyVars() - dummies.SetDummyClusterStatus() - dummies.SetDummyCSMachineStatuses() - }) - - AfterEach(func() { - }) - - Context("UserCred Semi-Integ Tests", func() { - client, connectionErr := cloud.NewClient("../../cloud-config") - var domain cloud.Domain - var account cloud.Account - var user cloud.User - - BeforeEach(func() { - if connectionErr != nil { // Only do these tests if an actual ACS instance is available via cloud-config. - Skip(errors.Wrapf(connectionErr, "Could not connect to ACS instance.").Error()) - } - - // Settup dummies. - // TODO: move these to the test dummies package. - domain = cloud.Domain{Path: "ROOT/blah/blah/subsub"} - account = cloud.Account{Name: "SuperNested", Domain: domain} - user = cloud.User{Name: "SubSub", Account: account} - }) - - It("can resolve a domain from the path", func() { - Ω(client.ResolveDomain(&domain)).Should(Succeed()) - Ω(domain.ID).ShouldNot(BeEmpty()) - }) - - It("can resolve an account from the domain path and account name", func() { - Ω(client.ResolveAccount(&account)).Should(Succeed()) - Ω(account.ID).ShouldNot(BeEmpty()) - }) - - It("can resolve a user from the domain path, account name, and user name", func() { - Ω(client.ResolveUser(&user)).Should(Succeed()) - Ω(user.ID).ShouldNot(BeEmpty()) - }) - - It("can get sub-domain user's credentials", func() { - Ω(client.ResolveUserKeys(&user)).Should(Succeed()) - - Ω(user.APIKey).ShouldNot(BeEmpty()) - Ω(user.SecretKey).ShouldNot(BeEmpty()) - }) - - It("can get an arbitrary user with keys from domain and account specifications alone", func() { - found, err := client.GetUserWithKeys(&user) - Ω(err).ShouldNot(HaveOccurred()) - Ω(found).Should(BeTrue()) - Ω(user.APIKey).ShouldNot(BeEmpty()) - }) - - It("can get create a new client as another user", func() { - found, err := client.GetUserWithKeys(&user) - Ω(err).ShouldNot(HaveOccurred()) - Ω(found).Should(BeTrue()) - Ω(user.APIKey).ShouldNot(BeEmpty()) - cfg := cloud.Config{APIKey: user.APIKey, SecretKey: user.SecretKey} - newClient, err := client.NewClientFromSpec(cfg) - Ω(err).ShouldNot(HaveOccurred()) - Ω(newClient).ShouldNot(BeNil()) - }) - }) -}) diff --git a/test/unit/cloud/zone_test.go b/test/unit/cloud/zone_test.go deleted file mode 100644 index 11fb4eed..00000000 --- a/test/unit/cloud/zone_test.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright 2022 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package cloud_test - -import ( - "fmt" - - csapi "github.com/apache/cloudstack-go/v2/cloudstack" - "github.com/aws/cluster-api-provider-cloudstack/pkg/cloud" - "github.com/aws/cluster-api-provider-cloudstack/test/dummies" - "github.com/golang/mock/gomock" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/pkg/errors" -) - -var _ = Describe("Cluster", func() { - var ( - client cloud.Client - mockCtrl *gomock.Controller - mockClient *csapi.CloudStackClient - zs *csapi.MockZoneServiceIface - ) - - BeforeEach(func() { - mockCtrl = gomock.NewController(GinkgoT()) - mockClient = csapi.NewMockClient(mockCtrl) - zs = mockClient.Zone.(*csapi.MockZoneServiceIface) - client = cloud.NewClientFromCSAPIClient(mockClient) - dummies.SetDummyVars() - dummies.SetDummyDomainAndAccount() - }) - - AfterEach(func() { - mockCtrl.Finish() - }) - - Context("an existing abstract dummies.CSCluster", func() { - It("handles zone not found.", func() { - expectedErr := fmt.Errorf("Not found") - zs.EXPECT().GetZoneID(dummies.Zone1.Name).Return("", -1, expectedErr) - zs.EXPECT().GetZoneByID(dummies.Zone1.ID).Return(nil, -1, expectedErr) - - err := client.ResolveZone(dummies.CSZone1) - Expect(errors.Cause(err)).To(MatchError(expectedErr)) - }) - - It("handles multiple zone IDs returned", func() { - zs.EXPECT().GetZoneID(dummies.Zone1.Name).Return(dummies.Zone1.ID, 2, nil) - zs.EXPECT().GetZoneByID(dummies.Zone1.ID).Return(nil, -1, fmt.Errorf("Not found")) - - Ω(client.ResolveZone(dummies.CSZone1)).Should(MatchError(And( - ContainSubstring("expected 1 Zone with name "+dummies.Zone1.Name+", but got 2"), - ContainSubstring("could not get Zone by ID "+dummies.Zone1.ID+": Not found")))) - }) - }) -})