From ae9904f127c7885810b39c7b47643ce5d7711a8e Mon Sep 17 00:00:00 2001 From: "jose.vazquez" Date: Fri, 7 Feb 2025 18:23:32 +0100 Subject: [PATCH] try fix controller --- .../atlasnetworkpeering_controller.go | 240 +------------ .../atlasnetworkpeering/container.go | 103 ------ .../atlasnetworkpeering/container_test.go | 63 ---- .../controller/atlasnetworkpeering/state.go | 91 +++++ .../atlasnetworkpeering/transition.go | 149 ++++++++ internal/controller/workflow/reason.go | 14 +- .../translation/atlas_deployments_service.go | 2 +- .../mocks/translation/atlas_users_service.go | 3 +- .../mocks/translation/custom_role_service.go | 3 +- .../translation/data_federation_service.go | 3 +- ...datafederation_private_endpoint_service.go | 3 +- internal/mocks/translation/deployment.go | 58 +++- .../mocks/translation/deployment_service.go | 3 +- .../translation/encryption_at_rest_service.go | 3 +- .../mocks/translation/endpoint_service.go | 3 +- .../translation/ip_access_list_service.go | 3 +- .../translation/maintenance_window_service.go | 3 +- .../translation/network_container_service.go | 3 +- .../translation/network_peering_service.go | 318 +++--------------- .../translation/private_endpoint_service.go | 3 +- .../translation/project_referrer_object.go | 3 +- internal/mocks/translation/project_service.go | 3 +- .../translation/team_projects_service.go | 3 +- .../mocks/translation/team_roles_service.go | 3 +- .../mocks/translation/team_users_service.go | 3 +- internal/mocks/translation/teams_service.go | 3 +- .../translation/networkpeering/conversion.go | 188 +---------- .../networkpeering/conversion_test.go | 52 +-- .../networkpeering/networkpeering.go | 86 +---- .../networkpeering/networkpeering_test.go | 182 ++++------ test/e2e/network_peering_controller_test.go | 227 +++++++------ 31 files changed, 599 insertions(+), 1225 deletions(-) delete mode 100644 internal/controller/atlasnetworkpeering/container.go delete mode 100644 internal/controller/atlasnetworkpeering/container_test.go create mode 100644 internal/controller/atlasnetworkpeering/state.go create mode 100644 internal/controller/atlasnetworkpeering/transition.go diff --git a/internal/controller/atlasnetworkpeering/atlasnetworkpeering_controller.go b/internal/controller/atlasnetworkpeering/atlasnetworkpeering_controller.go index 379a814377..de74ad9ba9 100644 --- a/internal/controller/atlasnetworkpeering/atlasnetworkpeering_controller.go +++ b/internal/controller/atlasnetworkpeering/atlasnetworkpeering_controller.go @@ -20,7 +20,6 @@ limitations under the License. import ( "context" "errors" - "fmt" "reflect" "time" @@ -41,8 +40,6 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/provider" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/status" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/atlas" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/customresource" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/reconciler" @@ -50,6 +47,7 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/workflow" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/indexer" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/pointer" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkcontainer" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkpeering" ) @@ -86,13 +84,6 @@ func NewAtlasNetworkPeeringsReconciler( } } -type reconcileRequest struct { - workflowCtx *workflow.Context - service networkpeering.NetworkPeeringService - projectID string - networkPeering *akov2.AtlasNetworkPeering -} - //+kubebuilder:rbac:groups=atlas.mongodb.com,resources=atlasnetworkpeerings,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=atlas.mongodb.com,resources=atlasnetworkpeerings/status,verbs=get;update;patch //+kubebuilder:rbac:groups=atlas.mongodb.com,resources=atlasnetworkpeerings/finalizers,verbs=update @@ -137,237 +128,22 @@ func (r *AtlasNetworkPeeringReconciler) Reconcile(ctx context.Context, req ctrl. if err != nil { return r.terminate(workflowCtx, &akoNetworkPeering, workflow.AtlasAPIAccessNotConfigured, err), nil } - sdkClient, orgID, err := r.AtlasProvider.SdkClient(ctx, credentials, r.Log) + sdkClientSet, orgID, err := r.AtlasProvider.SdkClientSet(ctx, credentials, r.Log) if err != nil { return r.terminate(workflowCtx, &akoNetworkPeering, workflow.AtlasAPIAccessNotConfigured, err), nil } - project, err := r.ResolveProject(ctx, sdkClient, &akoNetworkPeering, orgID) + project, err := r.ResolveProject(ctx, sdkClientSet.SdkClient20231115008, &akoNetworkPeering, orgID) if err != nil { return r.terminate(workflowCtx, &akoNetworkPeering, workflow.AtlasAPIAccessNotConfigured, err), nil } - return r.handle(&reconcileRequest{ - workflowCtx: workflowCtx, - service: networkpeering.NewNetworkPeeringService(sdkClient.NetworkPeeringApi), - projectID: project.ID, - networkPeering: &akoNetworkPeering, + return r.handle(workflowCtx, &reconcileRequest{ + service: networkpeering.NewNetworkPeeringServiceFromClientSet(sdkClientSet), + containerService: networkcontainer.NewNetworkContainerServiceFromClientSet(sdkClientSet), + projectID: project.ID, + networkPeering: &akoNetworkPeering, }), nil } -func (r *AtlasNetworkPeeringReconciler) handle(req *reconcileRequest) ctrl.Result { - r.Log.Infow("handling network peering reconcile request", - "service set", (req.service != nil), "projectID", req.projectID, "networkPeering", req.networkPeering) - var atlasPeer *networkpeering.NetworkPeer - if req.networkPeering.Status.ID != "" { - peer, err := req.service.GetPeer(req.workflowCtx.Context, req.projectID, req.networkPeering.Status.ID) - if err != nil && !errors.Is(err, networkpeering.ErrNotFound) { - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, err) - } - atlasPeer = peer - } - inAtlas := atlasPeer != nil - deleted := req.networkPeering.DeletionTimestamp != nil - - switch { - case !deleted && !inAtlas: - return r.create(req) - case !deleted && inAtlas: - return r.sync(req, atlasPeer) - case deleted && inAtlas: - return r.delete(req, atlasPeer) - default: - return r.unmanage(req) // deleted && !inAtlas - } -} - -func (r *AtlasNetworkPeeringReconciler) create(req *reconcileRequest) ctrl.Result { - container, err := r.handleContainer(req) - if err != nil { - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, err) - } - req.workflowCtx.EnsureStatusOption(updateContainerStatusOption(container)) - specPeer := networkpeering.NewNetworkPeeringSpec(&req.networkPeering.Spec.AtlasNetworkPeeringConfig) - specPeer.ContainerID = container.ID - newPeer, err := req.service.CreatePeer(req.workflowCtx.Context, req.projectID, specPeer) - if err != nil { - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, err) - } - req.workflowCtx.EnsureStatusOption(updatePeeringStatusOption(newPeer)) - return workflow.InProgress( - workflow.NetworkPeeringConnectionCreating, - fmt.Sprintf("Network Peering Connection %s is %s", - req.networkPeering.Status.ID, req.networkPeering.Status.Status), - ).ReconcileResult() -} - -func (r *AtlasNetworkPeeringReconciler) sync(req *reconcileRequest, atlasPeer *networkpeering.NetworkPeer) ctrl.Result { - container, err := r.handleContainer(req) - if err != nil { - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, err) - } - req.workflowCtx.EnsureStatusOption(updateContainerStatusOption(container)) - switch { - case atlasPeer.Failed(): - err := fmt.Errorf("peer connection failed: %s", atlasPeer.ErrorMessage) - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, err) - case !atlasPeer.Available(): - return r.inProgress(req, atlasPeer) - } - return r.ready(req, atlasPeer) -} - -func (r *AtlasNetworkPeeringReconciler) delete(req *reconcileRequest, atlasPeer *networkpeering.NetworkPeer) ctrl.Result { - id := req.networkPeering.Status.ID - peer := atlasPeer - if id != "" && !atlasPeer.Closing() { - if err := req.service.DeletePeer(req.workflowCtx.Context, req.projectID, id); err != nil { - wrappedErr := fmt.Errorf("failed to delete peer connection %s: %w", id, err) - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, wrappedErr) - } - closingPeer, err := req.service.GetPeer(req.workflowCtx.Context, req.projectID, id) - if err != nil { - wrappedErr := fmt.Errorf("failed to get closing peer connection %s: %w", id, err) - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, wrappedErr) - } - peer = closingPeer - } - return r.inProgress(req, peer) -} - -func (r *AtlasNetworkPeeringReconciler) unmanage(req *reconcileRequest) ctrl.Result { - req.workflowCtx.EnsureStatusOption(clearPeeringStatusOption()) - if _, err := r.handleContainer(req); err != nil { - containerID := containerID(req.networkPeering) - if !errors.Is(err, networkpeering.ErrContainerInUse) { - wrappedErr := fmt.Errorf("failed to clear container %s: %w", containerID, err) - return r.terminate(req.workflowCtx, req.networkPeering, workflow.Internal, wrappedErr) - } - } - req.workflowCtx.EnsureStatusOption(clearContainerStatusOption()) - if err := customresource.ManageFinalizer(req.workflowCtx.Context, r.Client, req.networkPeering, customresource.UnsetFinalizer); err != nil { - return r.terminate(req.workflowCtx, req.networkPeering, workflow.AtlasFinalizerNotRemoved, err) - } - - return workflow.Deleted().ReconcileResult() -} - -func (r *AtlasNetworkPeeringReconciler) inProgress(req *reconcileRequest, peer *networkpeering.NetworkPeer) ctrl.Result { - req.workflowCtx.EnsureStatusOption(updatePeeringStatusOption(peer)) - - return workflow.InProgress( - workflow.NetworkPeeringConnectionPending, - fmt.Sprintf("Network Peering Connection %s is %s", peer.ID, peer.Status), - ).ReconcileResult() -} - -func (r *AtlasNetworkPeeringReconciler) ready(req *reconcileRequest, peer *networkpeering.NetworkPeer) ctrl.Result { - if err := customresource.ManageFinalizer(req.workflowCtx.Context, r.Client, req.networkPeering, customresource.SetFinalizer); err != nil { - return r.terminate(req.workflowCtx, req.networkPeering, workflow.AtlasFinalizerNotSet, err) - } - - req.workflowCtx.EnsureStatusOption(updatePeeringStatusOption(peer)) - req.workflowCtx.SetConditionTrue(api.ReadyType) - - if req.networkPeering.Spec.ExternalProjectRef != nil { - return workflow.Requeue(r.independentSyncPeriod).ReconcileResult() - } - - return workflow.OK().ReconcileResult() -} - -func (r *AtlasNetworkPeeringReconciler) terminate( - ctx *workflow.Context, - resource api.AtlasCustomResource, - reason workflow.ConditionReason, - err error, -) ctrl.Result { - condition := api.ReadyType - r.Log.Errorf("resource %T(%s/%s) failed on condition %s: %s", - resource, resource.GetNamespace(), resource.GetName(), condition, err) - result := workflow.Terminate(reason, err) - ctx.SetConditionFalse(api.ReadyType).SetConditionFromResult(condition, result) - - return result.ReconcileResult() -} - -func updateContainerStatusOption(container *networkpeering.ProviderContainer) status.AtlasNetworkPeeringStatusOption { - return func(peeringStatus *status.AtlasNetworkPeeringStatus) { - applyContainerStatus(peeringStatus, container) - } -} - -func applyContainerStatus(peeringStatus *status.AtlasNetworkPeeringStatus, container *networkpeering.ProviderContainer) { - peeringStatus.ContainerID = container.ID - peeringStatus.ContainerProvisioned = container.Provisioned - providerName := provider.ProviderName(container.Provider) - switch { - case providerName == provider.ProviderAWS && container.AWSStatus != nil: - if peeringStatus.AWSStatus == nil { - peeringStatus.AWSStatus = &status.AWSStatus{} - } - peeringStatus.AWSStatus.ContainerVpcID = container.AWSStatus.VpcID - case providerName == provider.ProviderAzure && container.AzureStatus != nil: - if peeringStatus.AzureStatus == nil { - peeringStatus.AzureStatus = &status.AzureStatus{} - } - peeringStatus.AzureStatus.AzureSubscriptionID = container.AzureStatus.AzureSubscriptionID - peeringStatus.AzureStatus.VnetName = container.AzureStatus.VnetName - case providerName == provider.ProviderGCP && container.GoogleStatus != nil: - if peeringStatus.GoogleStatus == nil { - peeringStatus.GoogleStatus = &status.GoogleStatus{} - } - peeringStatus.GoogleStatus.GCPProjectID = container.GoogleStatus.GCPProjectID - peeringStatus.GoogleStatus.NetworkName = container.GoogleStatus.NetworkName - } -} - -func updatePeeringStatusOption(peer *networkpeering.NetworkPeer) status.AtlasNetworkPeeringStatusOption { - return func(peeringStatus *status.AtlasNetworkPeeringStatus) { - applyPeeringStatus(peeringStatus, peer) - } -} - -func applyPeeringStatus(peeringStatus *status.AtlasNetworkPeeringStatus, peer *networkpeering.NetworkPeer) { - peeringStatus.ID = peer.ID - peeringStatus.Status = peer.Status - peeringStatus.Error = peer.ErrorMessage - providerName := provider.ProviderName(peer.Provider) - if providerName == provider.ProviderAWS && peer.AWSStatus != nil { - if peeringStatus.AWSStatus == nil { - peeringStatus.AWSStatus = &status.AWSStatus{} - } - peeringStatus.AWSStatus.ConnectionID = peer.AWSStatus.ConnectionID - } -} - -func clearPeeringStatusOption() status.AtlasNetworkPeeringStatusOption { - return func(peeringStatus *status.AtlasNetworkPeeringStatus) { - clearPeeringStatus(peeringStatus) - } -} - -func clearPeeringStatus(peeringStatus *status.AtlasNetworkPeeringStatus) { - peeringStatus.ID = "" - peeringStatus.Status = "" - peeringStatus.Error = "" - if peeringStatus.AWSStatus != nil { - peeringStatus.AWSStatus.ConnectionID = "" - } -} - -func clearContainerStatusOption() status.AtlasNetworkPeeringStatusOption { - return func(peeringStatus *status.AtlasNetworkPeeringStatus) { - clearContainerStatus(peeringStatus) - } -} - -func clearContainerStatus(peeringStatus *status.AtlasNetworkPeeringStatus) { - peeringStatus.ContainerID = "" - peeringStatus.ContainerProvisioned = false - peeringStatus.AWSStatus = nil - peeringStatus.AzureStatus = nil - peeringStatus.GoogleStatus = nil -} - // SetupWithManager sets up the controller with the Manager. func (r *AtlasNetworkPeeringReconciler) SetupWithManager(mgr ctrl.Manager, skipNameValidation bool) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/internal/controller/atlasnetworkpeering/container.go b/internal/controller/atlasnetworkpeering/container.go deleted file mode 100644 index 909ece079c..0000000000 --- a/internal/controller/atlasnetworkpeering/container.go +++ /dev/null @@ -1,103 +0,0 @@ -package atlasnetworkpeering - -import ( - "errors" - "fmt" - - akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/provider" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkpeering" -) - -func (r *AtlasNetworkPeeringReconciler) handleContainer(req *reconcileRequest) (*networkpeering.ProviderContainer, error) { - atlasContainer, err := discoverContainer(req) - if err != nil && !errors.Is(err, networkpeering.ErrNotFound) { - return nil, fmt.Errorf("failed to discover container: %w", err) - } - inAtlas := atlasContainer != nil - deleted := req.networkPeering.DeletionTimestamp != nil - switch { - case !deleted && !inAtlas: - return r.createContainer(req) - case !deleted && inAtlas: - return atlasContainer, nil - case deleted && inAtlas: - return r.deleteContainer(req) - default: - return r.unmanageContainer() - } -} - -func discoverContainer(req *reconcileRequest) (*networkpeering.ProviderContainer, error) { - containerID := containerID(req.networkPeering) - if containerID != "" { - container, err := req.service.GetContainer(req.workflowCtx.Context, req.projectID, containerID) - if err != nil { - return nil, fmt.Errorf("failed to get container from project %s and container %s: %w", - req.projectID, containerID, err) - } - return container, nil - } - container, err := req.service.FindContainer( - req.workflowCtx.Context, - req.projectID, - req.networkPeering.Spec.Provider, - req.networkPeering.Spec.AtlasCIDRBlock, - ) - if errors.Is(err, networkpeering.ErrNotFound) { - return nil, nil // no existing container - } - if err != nil { - return nil, fmt.Errorf("failed to get find container with CIDR %q for provider %s at project %s: %w", - req.networkPeering.Spec.AtlasCIDRBlock, - req.networkPeering.Spec.Provider, - req.projectID, - err, - ) - } - return container, nil -} - -func (r *AtlasNetworkPeeringReconciler) createContainer(req *reconcileRequest) (*networkpeering.ProviderContainer, error) { - specContainer := networkpeering.NewProviderContainer( - "", - req.networkPeering.Spec.Provider, - &req.networkPeering.Spec.AtlasProviderContainerConfig, - ) - fixContainerRegion(specContainer, req) - createdContainer, err := - req.service.CreateContainer(req.workflowCtx.Context, req.projectID, specContainer) - if err != nil { - return nil, fmt.Errorf("failed to create container: %w", err) - } - return createdContainer, nil -} - -func fixContainerRegion(specContainer *networkpeering.ProviderContainer, req *reconcileRequest) { - // in AWS it is assumed not specifying the reagion means it is the same as the accepter region - if req.networkPeering.Spec.Provider == string(provider.ProviderAWS) && - specContainer.ContainerRegion == "" && - req.networkPeering.Spec.AWSConfiguration != nil { - specContainer.ContainerRegion = req.networkPeering.Spec.AWSConfiguration.AccepterRegionName - } -} - -func (r *AtlasNetworkPeeringReconciler) deleteContainer(req *reconcileRequest) (*networkpeering.ProviderContainer, error) { - containerID := containerID(req.networkPeering) - err := req.service.DeleteContainer(req.workflowCtx.Context, req.projectID, containerID) - if err == nil || errors.Is(err, networkpeering.ErrNotFound) { - return r.unmanageContainer() - } - return nil, fmt.Errorf("failed to delete container %s: %w", containerID, err) -} - -func (r *AtlasNetworkPeeringReconciler) unmanageContainer() (*networkpeering.ProviderContainer, error) { - return nil, nil -} - -func containerID(peer *akov2.AtlasNetworkPeering) string { - if peer.Spec.ContainerID != "" { - return peer.Spec.ContainerID - } - return peer.Status.ContainerID -} diff --git a/internal/controller/atlasnetworkpeering/container_test.go b/internal/controller/atlasnetworkpeering/container_test.go deleted file mode 100644 index 23edac85dc..0000000000 --- a/internal/controller/atlasnetworkpeering/container_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package atlasnetworkpeering - -import ( - "errors" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - - v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/provider" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/workflow" - peeringMock "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/mocks/translation" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkpeering" -) - -const ( - sampleProjectID = "fake-632842834" - - sampleContainerID = "container-id" -) - -var errFakeFailure = errors.New("failure") - -func TestHandleContainer(t *testing.T) { - for _, tc := range []struct { - title string - req *reconcileRequest - expectedContainer *networkpeering.ProviderContainer - expectedError error - }{ - { - title: "fail to create container", - req: &reconcileRequest{ - workflowCtx: &workflow.Context{}, - service: func() networkpeering.NetworkPeeringService { - netpeeringService := peeringMock.NewNetworkPeeringServiceMock(t) - netpeeringService.EXPECT().GetContainer(mock.Anything, sampleProjectID, sampleContainerID).Return(nil, nil) - netpeeringService.EXPECT().CreateContainer(mock.Anything, sampleProjectID, mock.Anything).Return(nil, errFakeFailure) - return netpeeringService - }(), - projectID: sampleProjectID, - networkPeering: &v1.AtlasNetworkPeering{ - Spec: v1.AtlasNetworkPeeringSpec{ - AtlasNetworkPeeringConfig: v1.AtlasNetworkPeeringConfig{ - Provider: string(provider.ProviderAWS), - ContainerID: sampleContainerID, - }, - AtlasProviderContainerConfig: v1.AtlasProviderContainerConfig{}, - }, - }, - }, - expectedError: errFakeFailure, - }, - } { - t.Run(tc.title, func(t *testing.T) { - r := &AtlasNetworkPeeringReconciler{} - container, err := r.handleContainer(tc.req) - assert.Equal(t, tc.expectedContainer, container) - assert.ErrorIs(t, err, tc.expectedError) - }) - } -} diff --git a/internal/controller/atlasnetworkpeering/state.go b/internal/controller/atlasnetworkpeering/state.go new file mode 100644 index 0000000000..5f4149a0dd --- /dev/null +++ b/internal/controller/atlasnetworkpeering/state.go @@ -0,0 +1,91 @@ +package atlasnetworkpeering + +import ( + "context" + "errors" + "fmt" + + akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/workflow" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkcontainer" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkpeering" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type reconcileRequest struct { + service networkpeering.NetworkPeeringService + containerService networkcontainer.NetworkContainerService + projectID string + networkPeering *akov2.AtlasNetworkPeering +} + +func (r *AtlasNetworkPeeringReconciler) handle(workflowCtx *workflow.Context, req *reconcileRequest) ctrl.Result { + r.Log.Infow("handling network peering reconcile request", + "service set", (req.service != nil), "projectID", req.projectID, "networkPeering", req.networkPeering) + container, err := r.getContainer(workflowCtx.Context, req) + if err != nil { + return r.terminate(workflowCtx, req.networkPeering, workflow.Internal, err) + } + if container == nil { + err := fmt.Errorf("container not found for reference %v", req.networkPeering.Spec.ContainerRef) + return r.terminate(workflowCtx, req.networkPeering, workflow.NetworkPeeringMissingContainer, err) + } + var atlasPeer *networkpeering.NetworkPeer + if req.networkPeering.Status.ID != "" { + peer, err := req.service.Get(workflowCtx.Context, req.projectID, req.networkPeering.Status.ID) + if err != nil && !errors.Is(err, networkpeering.ErrNotFound) { + return r.terminate(workflowCtx, req.networkPeering, workflow.Internal, err) + } + atlasPeer = peer + } + inAtlas := atlasPeer != nil + deleted := req.networkPeering.DeletionTimestamp != nil + + switch { + case !deleted && !inAtlas: + return r.create(workflowCtx, req, container) + case !deleted && inAtlas: + return r.sync(workflowCtx, req, atlasPeer) + case deleted && inAtlas: + return r.delete(workflowCtx, req, atlasPeer) + default: // deleted && !inAtlas + return r.unmanage(workflowCtx, req) + } +} + +func (r *AtlasNetworkPeeringReconciler) getContainer(ctx context.Context, req *reconcileRequest) (*networkcontainer.NetworkContainer, error) { + id := req.networkPeering.Spec.ContainerRef.ID + if req.networkPeering.Spec.ContainerRef.ID == "" { // Name should be non nil instead + id, err := getContainerIDFromKubernetes(ctx, r.Client, req.networkPeering) + if err != nil { + return nil, fmt.Errorf("failed to solve Network Container id from Kubernetes: %w", err) + } + if id == "" { + return nil, fmt.Errorf("container %s has no id, is it still to be created?", + req.networkPeering.Spec.ContainerRef.Name) + } + } + container, err := req.containerService.Get(ctx, req.projectID, id) + if err != nil { + return nil, fmt.Errorf("failed to fetch Network Container %s from Atlas by id: %w", id, err) + } + return container, nil +} + +func getContainerIDFromKubernetes(ctx context.Context, k8sClient client.Client, networkPeering *akov2.AtlasNetworkPeering) (string, error) { + k8sContainer := akov2.AtlasNetworkContainer{} + key := client.ObjectKey{ + Name: networkPeering.Spec.ContainerRef.Name, + Namespace: networkPeering.Namespace, + } + err := k8sClient.Get(ctx, key, &k8sContainer) + if err != nil { + return "", fmt.Errorf("failed to fetch the Kubernetes Network Container %s info: %w", key.Name, err) + } + id := k8sContainer.Spec.ID + if id == "" { + id = k8sContainer.Status.ID + } + return id, nil +} diff --git a/internal/controller/atlasnetworkpeering/transition.go b/internal/controller/atlasnetworkpeering/transition.go new file mode 100644 index 0000000000..3c84a9d861 --- /dev/null +++ b/internal/controller/atlasnetworkpeering/transition.go @@ -0,0 +1,149 @@ +package atlasnetworkpeering + +import ( + "fmt" + "reflect" + + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/provider" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/status" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/customresource" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/workflow" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkcontainer" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkpeering" + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *AtlasNetworkPeeringReconciler) create(workflowCtx *workflow.Context, req *reconcileRequest, container *networkcontainer.NetworkContainer) ctrl.Result { + newPeer, err := req.service.Create( + workflowCtx.Context, + req.projectID, + container.ID, + &req.networkPeering.Spec.AtlasNetworkPeeringConfig, + ) + if err != nil { + return r.terminate(workflowCtx, req.networkPeering, workflow.Internal, err) + } + workflowCtx.EnsureStatusOption(updatePeeringStatusOption(newPeer)) + return workflow.InProgress( + workflow.NetworkPeeringConnectionCreating, + fmt.Sprintf("Network Peering Connection %s is %s", + req.networkPeering.Status.ID, req.networkPeering.Status.Status), + ).ReconcileResult() +} + +func (r *AtlasNetworkPeeringReconciler) sync(workflowCtx *workflow.Context, req *reconcileRequest, atlasPeer *networkpeering.NetworkPeer) ctrl.Result { + switch { + case atlasPeer.Failed(): + err := fmt.Errorf("peer connection failed: %s", atlasPeer.ErrorMessage) + return r.terminate(workflowCtx, req.networkPeering, workflow.Internal, err) + case !atlasPeer.Available(): + return r.inProgress(workflowCtx, atlasPeer) + } + if !reflect.DeepEqual(atlasPeer.AtlasNetworkPeeringConfig, &req.networkPeering.Spec.AtlasNetworkPeeringConfig) { + return r.update(workflowCtx, req, atlasPeer) + } + return r.ready(workflowCtx, req, atlasPeer) +} + +func (r *AtlasNetworkPeeringReconciler) update(workflowCtx *workflow.Context, req *reconcileRequest, atlasPeer *networkpeering.NetworkPeer) ctrl.Result { + req.service. +} + +func (r *AtlasNetworkPeeringReconciler) delete(workflowCtx *workflow.Context, req *reconcileRequest, atlasPeer *networkpeering.NetworkPeer) ctrl.Result { + id := req.networkPeering.Status.ID + peer := atlasPeer + if id != "" && !atlasPeer.Closing() { + if err := req.service.Delete(workflowCtx.Context, req.projectID, id); err != nil { + wrappedErr := fmt.Errorf("failed to delete peer connection %s: %w", id, err) + return r.terminate(workflowCtx, req.networkPeering, workflow.Internal, wrappedErr) + } + closingPeer, err := req.service.Get(workflowCtx.Context, req.projectID, id) + if err != nil { + wrappedErr := fmt.Errorf("failed to get closing peer connection %s: %w", id, err) + return r.terminate(workflowCtx, req.networkPeering, workflow.Internal, wrappedErr) + } + peer = closingPeer + } + return r.inProgress(workflowCtx, peer) +} + +func (r *AtlasNetworkPeeringReconciler) unmanage(workflowCtx *workflow.Context, req *reconcileRequest) ctrl.Result { + workflowCtx.EnsureStatusOption(clearPeeringStatusOption()) + if err := customresource.ManageFinalizer(workflowCtx.Context, r.Client, req.networkPeering, customresource.UnsetFinalizer); err != nil { + return r.terminate(workflowCtx, req.networkPeering, workflow.AtlasFinalizerNotRemoved, err) + } + + return workflow.Deleted().ReconcileResult() +} + +func (r *AtlasNetworkPeeringReconciler) inProgress(workflowCtx *workflow.Context, peer *networkpeering.NetworkPeer) ctrl.Result { + workflowCtx.EnsureStatusOption(updatePeeringStatusOption(peer)) + + return workflow.InProgress( + workflow.NetworkPeeringConnectionPending, + fmt.Sprintf("Network Peering Connection %s is %s", peer.ID, peer.Status), + ).ReconcileResult() +} + +func (r *AtlasNetworkPeeringReconciler) ready(workflowCtx *workflow.Context, req *reconcileRequest, peer *networkpeering.NetworkPeer) ctrl.Result { + if err := customresource.ManageFinalizer(workflowCtx.Context, r.Client, req.networkPeering, customresource.SetFinalizer); err != nil { + return r.terminate(workflowCtx, req.networkPeering, workflow.AtlasFinalizerNotSet, err) + } + + workflowCtx.EnsureStatusOption(updatePeeringStatusOption(peer)) + workflowCtx.SetConditionTrue(api.ReadyType) + + if req.networkPeering.Spec.ExternalProjectRef != nil { + return workflow.Requeue(r.independentSyncPeriod).ReconcileResult() + } + + return workflow.OK().ReconcileResult() +} + +func (r *AtlasNetworkPeeringReconciler) terminate( + ctx *workflow.Context, + resource api.AtlasCustomResource, + reason workflow.ConditionReason, + err error, +) ctrl.Result { + condition := api.ReadyType + r.Log.Errorf("resource %T(%s/%s) failed on condition %s: %s", + resource, resource.GetNamespace(), resource.GetName(), condition, err) + result := workflow.Terminate(reason, err) + ctx.SetConditionFalse(api.ReadyType).SetConditionFromResult(condition, result) + + return result.ReconcileResult() +} + +func updatePeeringStatusOption(peer *networkpeering.NetworkPeer) status.AtlasNetworkPeeringStatusOption { + return func(peeringStatus *status.AtlasNetworkPeeringStatus) { + applyPeeringStatus(peeringStatus, peer) + } +} + +func applyPeeringStatus(peeringStatus *status.AtlasNetworkPeeringStatus, peer *networkpeering.NetworkPeer) { + peeringStatus.ID = peer.ID + peeringStatus.Status = peer.Status + providerName := provider.ProviderName(peer.Provider) + if providerName == provider.ProviderAWS && peer.AWSStatus != nil { + if peeringStatus.AWSStatus == nil { + peeringStatus.AWSStatus = &status.AWSStatus{} + } + peeringStatus.AWSStatus.ConnectionID = peer.AWSStatus.ConnectionID + } +} + +func clearPeeringStatusOption() status.AtlasNetworkPeeringStatusOption { + return func(peeringStatus *status.AtlasNetworkPeeringStatus) { + clearPeeringStatus(peeringStatus) + } +} + +func clearPeeringStatus(peeringStatus *status.AtlasNetworkPeeringStatus) { + peeringStatus.ID = "" + peeringStatus.Status = "" + if peeringStatus.AWSStatus != nil { + peeringStatus.AWSStatus.ConnectionID = "" + } +} diff --git a/internal/controller/workflow/reason.go b/internal/controller/workflow/reason.go index acba5a311d..57831de626 100644 --- a/internal/controller/workflow/reason.go +++ b/internal/controller/workflow/reason.go @@ -161,16 +161,16 @@ const ( IPAccessListPending ConditionReason = "IPAccessListPending" ) -// Atlas Network Peering reasons -const ( - NetworkPeeringConnectionCreating ConditionReason = "NetworkPeeringConnectionCreating" - NetworkPeeringConnectionPending ConditionReason = "NetworkPeeringConnectionPending" - NetworkPeeringRemovingContainer ConditionReason = "NetworkPeeringRemovingContainer" -) - // Atlas Network Container reasons const ( NetworkContainerNotConfigured ConditionReason = "NetworkContainerNotConfigured" NetworkContainerCreated ConditionReason = "NetworkContainerCreated" NetworkContainerNotDeleted ConditionReason = "NetworkContainerNotDeleted" ) + +// Atlas Network Peering reasons +const ( + NetworkPeeringMissingContainer ConditionReason = "NetworkPeeringMissingContainer" + NetworkPeeringConnectionCreating ConditionReason = "NetworkPeeringConnectionCreating" + NetworkPeeringConnectionPending ConditionReason = "NetworkPeeringConnectionPending" +) diff --git a/internal/mocks/translation/atlas_deployments_service.go b/internal/mocks/translation/atlas_deployments_service.go index b79f3bc8d6..aad95e5565 100644 --- a/internal/mocks/translation/atlas_deployments_service.go +++ b/internal/mocks/translation/atlas_deployments_service.go @@ -5,10 +5,10 @@ package translation import ( context "context" + deployment "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/deployment" mock "github.com/stretchr/testify/mock" v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" - deployment "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/deployment" ) // AtlasDeploymentsServiceMock is an autogenerated mock type for the AtlasDeploymentsService type diff --git a/internal/mocks/translation/atlas_users_service.go b/internal/mocks/translation/atlas_users_service.go index 83e42f07b3..b806b67aa9 100644 --- a/internal/mocks/translation/atlas_users_service.go +++ b/internal/mocks/translation/atlas_users_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - dbuser "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/dbuser" + mock "github.com/stretchr/testify/mock" ) // AtlasUsersServiceMock is an autogenerated mock type for the AtlasUsersService type diff --git a/internal/mocks/translation/custom_role_service.go b/internal/mocks/translation/custom_role_service.go index a1b118c856..7abfdb075b 100644 --- a/internal/mocks/translation/custom_role_service.go +++ b/internal/mocks/translation/custom_role_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - customroles "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/customroles" + mock "github.com/stretchr/testify/mock" ) // CustomRoleServiceMock is an autogenerated mock type for the CustomRoleService type diff --git a/internal/mocks/translation/data_federation_service.go b/internal/mocks/translation/data_federation_service.go index ccda3410fb..ec83348ca9 100644 --- a/internal/mocks/translation/data_federation_service.go +++ b/internal/mocks/translation/data_federation_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - datafederation "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/datafederation" + mock "github.com/stretchr/testify/mock" ) // DataFederationServiceMock is an autogenerated mock type for the DataFederationService type diff --git a/internal/mocks/translation/datafederation_private_endpoint_service.go b/internal/mocks/translation/datafederation_private_endpoint_service.go index c00af20b12..5f94b5e2d9 100644 --- a/internal/mocks/translation/datafederation_private_endpoint_service.go +++ b/internal/mocks/translation/datafederation_private_endpoint_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - datafederation "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/datafederation" + mock "github.com/stretchr/testify/mock" ) // DatafederationPrivateEndpointServiceMock is an autogenerated mock type for the DatafederationPrivateEndpointService type diff --git a/internal/mocks/translation/deployment.go b/internal/mocks/translation/deployment.go index 9647094a8f..4ced596960 100644 --- a/internal/mocks/translation/deployment.go +++ b/internal/mocks/translation/deployment.go @@ -3,10 +3,9 @@ package translation import ( - mock "github.com/stretchr/testify/mock" - v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" status "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/status" + mock "github.com/stretchr/testify/mock" ) // DeploymentMock is an autogenerated mock type for the Deployment type @@ -22,6 +21,61 @@ func (_m *DeploymentMock) EXPECT() *DeploymentMock_Expecter { return &DeploymentMock_Expecter{mock: &_m.Mock} } +// Deprecated provides a mock function with no fields +func (_m *DeploymentMock) Deprecated() (bool, string) { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Deprecated") + } + + var r0 bool + var r1 string + if rf, ok := ret.Get(0).(func() (bool, string)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func() string); ok { + r1 = rf() + } else { + r1 = ret.Get(1).(string) + } + + return r0, r1 +} + +// DeploymentMock_Deprecated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Deprecated' +type DeploymentMock_Deprecated_Call struct { + *mock.Call +} + +// Deprecated is a helper method to define mock.On call +func (_e *DeploymentMock_Expecter) Deprecated() *DeploymentMock_Deprecated_Call { + return &DeploymentMock_Deprecated_Call{Call: _e.mock.On("Deprecated")} +} + +func (_c *DeploymentMock_Deprecated_Call) Run(run func()) *DeploymentMock_Deprecated_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *DeploymentMock_Deprecated_Call) Return(_a0 bool, _a1 string) *DeploymentMock_Deprecated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *DeploymentMock_Deprecated_Call) RunAndReturn(run func() (bool, string)) *DeploymentMock_Deprecated_Call { + _c.Call.Return(run) + return _c +} + // GetConnection provides a mock function with no fields func (_m *DeploymentMock) GetConnection() *status.ConnectionStrings { ret := _m.Called() diff --git a/internal/mocks/translation/deployment_service.go b/internal/mocks/translation/deployment_service.go index 06756db53a..a0f7b4c0d8 100644 --- a/internal/mocks/translation/deployment_service.go +++ b/internal/mocks/translation/deployment_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - deployment "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/deployment" + mock "github.com/stretchr/testify/mock" v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" ) diff --git a/internal/mocks/translation/encryption_at_rest_service.go b/internal/mocks/translation/encryption_at_rest_service.go index 9b49603dff..80358f169b 100644 --- a/internal/mocks/translation/encryption_at_rest_service.go +++ b/internal/mocks/translation/encryption_at_rest_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - encryptionatrest "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/encryptionatrest" + mock "github.com/stretchr/testify/mock" ) // EncryptionAtRestServiceMock is an autogenerated mock type for the EncryptionAtRestService type diff --git a/internal/mocks/translation/endpoint_service.go b/internal/mocks/translation/endpoint_service.go index 5dfff04caa..ad68d33b26 100644 --- a/internal/mocks/translation/endpoint_service.go +++ b/internal/mocks/translation/endpoint_service.go @@ -3,9 +3,8 @@ package translation import ( - mock "github.com/stretchr/testify/mock" - privateendpoint "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/privateendpoint" + mock "github.com/stretchr/testify/mock" ) // EndpointServiceMock is an autogenerated mock type for the EndpointService type diff --git a/internal/mocks/translation/ip_access_list_service.go b/internal/mocks/translation/ip_access_list_service.go index a33d0fa506..a728838a71 100644 --- a/internal/mocks/translation/ip_access_list_service.go +++ b/internal/mocks/translation/ip_access_list_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - ipaccesslist "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/ipaccesslist" + mock "github.com/stretchr/testify/mock" ) // IPAccessListServiceMock is an autogenerated mock type for the IPAccessListService type diff --git a/internal/mocks/translation/maintenance_window_service.go b/internal/mocks/translation/maintenance_window_service.go index e0d058ce5e..79b4d5f82f 100644 --- a/internal/mocks/translation/maintenance_window_service.go +++ b/internal/mocks/translation/maintenance_window_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - maintenancewindow "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/maintenancewindow" + mock "github.com/stretchr/testify/mock" ) // MaintenanceWindowServiceMock is an autogenerated mock type for the MaintenanceWindowService type diff --git a/internal/mocks/translation/network_container_service.go b/internal/mocks/translation/network_container_service.go index 915c0260d7..a813ed39c1 100644 --- a/internal/mocks/translation/network_container_service.go +++ b/internal/mocks/translation/network_container_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - networkcontainer "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkcontainer" + mock "github.com/stretchr/testify/mock" ) // NetworkContainerServiceMock is an autogenerated mock type for the NetworkContainerService type diff --git a/internal/mocks/translation/network_peering_service.go b/internal/mocks/translation/network_peering_service.go index ad45329f7a..587ae08c36 100644 --- a/internal/mocks/translation/network_peering_service.go +++ b/internal/mocks/translation/network_peering_service.go @@ -5,9 +5,9 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - + v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" networkpeering "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkpeering" + mock "github.com/stretchr/testify/mock" ) // NetworkPeeringServiceMock is an autogenerated mock type for the NetworkPeeringService type @@ -23,89 +23,29 @@ func (_m *NetworkPeeringServiceMock) EXPECT() *NetworkPeeringServiceMock_Expecte return &NetworkPeeringServiceMock_Expecter{mock: &_m.Mock} } -// CreateContainer provides a mock function with given fields: ctx, projectID, container -func (_m *NetworkPeeringServiceMock) CreateContainer(ctx context.Context, projectID string, container *networkpeering.ProviderContainer) (*networkpeering.ProviderContainer, error) { - ret := _m.Called(ctx, projectID, container) - - if len(ret) == 0 { - panic("no return value specified for CreateContainer") - } - - var r0 *networkpeering.ProviderContainer - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, *networkpeering.ProviderContainer) (*networkpeering.ProviderContainer, error)); ok { - return rf(ctx, projectID, container) - } - if rf, ok := ret.Get(0).(func(context.Context, string, *networkpeering.ProviderContainer) *networkpeering.ProviderContainer); ok { - r0 = rf(ctx, projectID, container) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*networkpeering.ProviderContainer) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, *networkpeering.ProviderContainer) error); ok { - r1 = rf(ctx, projectID, container) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NetworkPeeringServiceMock_CreateContainer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateContainer' -type NetworkPeeringServiceMock_CreateContainer_Call struct { - *mock.Call -} - -// CreateContainer is a helper method to define mock.On call -// - ctx context.Context -// - projectID string -// - container *networkpeering.ProviderContainer -func (_e *NetworkPeeringServiceMock_Expecter) CreateContainer(ctx interface{}, projectID interface{}, container interface{}) *NetworkPeeringServiceMock_CreateContainer_Call { - return &NetworkPeeringServiceMock_CreateContainer_Call{Call: _e.mock.On("CreateContainer", ctx, projectID, container)} -} - -func (_c *NetworkPeeringServiceMock_CreateContainer_Call) Run(run func(ctx context.Context, projectID string, container *networkpeering.ProviderContainer)) *NetworkPeeringServiceMock_CreateContainer_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(*networkpeering.ProviderContainer)) - }) - return _c -} - -func (_c *NetworkPeeringServiceMock_CreateContainer_Call) Return(_a0 *networkpeering.ProviderContainer, _a1 error) *NetworkPeeringServiceMock_CreateContainer_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *NetworkPeeringServiceMock_CreateContainer_Call) RunAndReturn(run func(context.Context, string, *networkpeering.ProviderContainer) (*networkpeering.ProviderContainer, error)) *NetworkPeeringServiceMock_CreateContainer_Call { - _c.Call.Return(run) - return _c -} - -// CreatePeer provides a mock function with given fields: ctx, projectID, conn -func (_m *NetworkPeeringServiceMock) CreatePeer(ctx context.Context, projectID string, conn *networkpeering.NetworkPeer) (*networkpeering.NetworkPeer, error) { - ret := _m.Called(ctx, projectID, conn) +// Create provides a mock function with given fields: ctx, projectID, containerID, cfg +func (_m *NetworkPeeringServiceMock) Create(ctx context.Context, projectID string, containerID string, cfg *v1.AtlasNetworkPeeringConfig) (*networkpeering.NetworkPeer, error) { + ret := _m.Called(ctx, projectID, containerID, cfg) if len(ret) == 0 { - panic("no return value specified for CreatePeer") + panic("no return value specified for Create") } var r0 *networkpeering.NetworkPeer var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, *networkpeering.NetworkPeer) (*networkpeering.NetworkPeer, error)); ok { - return rf(ctx, projectID, conn) + if rf, ok := ret.Get(0).(func(context.Context, string, string, *v1.AtlasNetworkPeeringConfig) (*networkpeering.NetworkPeer, error)); ok { + return rf(ctx, projectID, containerID, cfg) } - if rf, ok := ret.Get(0).(func(context.Context, string, *networkpeering.NetworkPeer) *networkpeering.NetworkPeer); ok { - r0 = rf(ctx, projectID, conn) + if rf, ok := ret.Get(0).(func(context.Context, string, string, *v1.AtlasNetworkPeeringConfig) *networkpeering.NetworkPeer); ok { + r0 = rf(ctx, projectID, containerID, cfg) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*networkpeering.NetworkPeer) } } - if rf, ok := ret.Get(1).(func(context.Context, string, *networkpeering.NetworkPeer) error); ok { - r1 = rf(ctx, projectID, conn) + if rf, ok := ret.Get(1).(func(context.Context, string, string, *v1.AtlasNetworkPeeringConfig) error); ok { + r1 = rf(ctx, projectID, containerID, cfg) } else { r1 = ret.Error(1) } @@ -113,90 +53,43 @@ func (_m *NetworkPeeringServiceMock) CreatePeer(ctx context.Context, projectID s return r0, r1 } -// NetworkPeeringServiceMock_CreatePeer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePeer' -type NetworkPeeringServiceMock_CreatePeer_Call struct { +// NetworkPeeringServiceMock_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type NetworkPeeringServiceMock_Create_Call struct { *mock.Call } -// CreatePeer is a helper method to define mock.On call -// - ctx context.Context -// - projectID string -// - conn *networkpeering.NetworkPeer -func (_e *NetworkPeeringServiceMock_Expecter) CreatePeer(ctx interface{}, projectID interface{}, conn interface{}) *NetworkPeeringServiceMock_CreatePeer_Call { - return &NetworkPeeringServiceMock_CreatePeer_Call{Call: _e.mock.On("CreatePeer", ctx, projectID, conn)} -} - -func (_c *NetworkPeeringServiceMock_CreatePeer_Call) Run(run func(ctx context.Context, projectID string, conn *networkpeering.NetworkPeer)) *NetworkPeeringServiceMock_CreatePeer_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(*networkpeering.NetworkPeer)) - }) - return _c -} - -func (_c *NetworkPeeringServiceMock_CreatePeer_Call) Return(_a0 *networkpeering.NetworkPeer, _a1 error) *NetworkPeeringServiceMock_CreatePeer_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *NetworkPeeringServiceMock_CreatePeer_Call) RunAndReturn(run func(context.Context, string, *networkpeering.NetworkPeer) (*networkpeering.NetworkPeer, error)) *NetworkPeeringServiceMock_CreatePeer_Call { - _c.Call.Return(run) - return _c -} - -// DeleteContainer provides a mock function with given fields: ctx, projectID, containerID -func (_m *NetworkPeeringServiceMock) DeleteContainer(ctx context.Context, projectID string, containerID string) error { - ret := _m.Called(ctx, projectID, containerID) - - if len(ret) == 0 { - panic("no return value specified for DeleteContainer") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, projectID, containerID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// NetworkPeeringServiceMock_DeleteContainer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteContainer' -type NetworkPeeringServiceMock_DeleteContainer_Call struct { - *mock.Call -} - -// DeleteContainer is a helper method to define mock.On call +// Create is a helper method to define mock.On call // - ctx context.Context // - projectID string // - containerID string -func (_e *NetworkPeeringServiceMock_Expecter) DeleteContainer(ctx interface{}, projectID interface{}, containerID interface{}) *NetworkPeeringServiceMock_DeleteContainer_Call { - return &NetworkPeeringServiceMock_DeleteContainer_Call{Call: _e.mock.On("DeleteContainer", ctx, projectID, containerID)} +// - cfg *v1.AtlasNetworkPeeringConfig +func (_e *NetworkPeeringServiceMock_Expecter) Create(ctx interface{}, projectID interface{}, containerID interface{}, cfg interface{}) *NetworkPeeringServiceMock_Create_Call { + return &NetworkPeeringServiceMock_Create_Call{Call: _e.mock.On("Create", ctx, projectID, containerID, cfg)} } -func (_c *NetworkPeeringServiceMock_DeleteContainer_Call) Run(run func(ctx context.Context, projectID string, containerID string)) *NetworkPeeringServiceMock_DeleteContainer_Call { +func (_c *NetworkPeeringServiceMock_Create_Call) Run(run func(ctx context.Context, projectID string, containerID string, cfg *v1.AtlasNetworkPeeringConfig)) *NetworkPeeringServiceMock_Create_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string)) + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(*v1.AtlasNetworkPeeringConfig)) }) return _c } -func (_c *NetworkPeeringServiceMock_DeleteContainer_Call) Return(_a0 error) *NetworkPeeringServiceMock_DeleteContainer_Call { - _c.Call.Return(_a0) +func (_c *NetworkPeeringServiceMock_Create_Call) Return(_a0 *networkpeering.NetworkPeer, _a1 error) *NetworkPeeringServiceMock_Create_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *NetworkPeeringServiceMock_DeleteContainer_Call) RunAndReturn(run func(context.Context, string, string) error) *NetworkPeeringServiceMock_DeleteContainer_Call { +func (_c *NetworkPeeringServiceMock_Create_Call) RunAndReturn(run func(context.Context, string, string, *v1.AtlasNetworkPeeringConfig) (*networkpeering.NetworkPeer, error)) *NetworkPeeringServiceMock_Create_Call { _c.Call.Return(run) return _c } -// DeletePeer provides a mock function with given fields: ctx, projectID, containerID -func (_m *NetworkPeeringServiceMock) DeletePeer(ctx context.Context, projectID string, containerID string) error { +// Delete provides a mock function with given fields: ctx, projectID, containerID +func (_m *NetworkPeeringServiceMock) Delete(ctx context.Context, projectID string, containerID string) error { ret := _m.Called(ctx, projectID, containerID) if len(ret) == 0 { - panic("no return value specified for DeletePeer") + panic("no return value specified for Delete") } var r0 error @@ -209,163 +102,42 @@ func (_m *NetworkPeeringServiceMock) DeletePeer(ctx context.Context, projectID s return r0 } -// NetworkPeeringServiceMock_DeletePeer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeletePeer' -type NetworkPeeringServiceMock_DeletePeer_Call struct { +// NetworkPeeringServiceMock_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type NetworkPeeringServiceMock_Delete_Call struct { *mock.Call } -// DeletePeer is a helper method to define mock.On call +// Delete is a helper method to define mock.On call // - ctx context.Context // - projectID string // - containerID string -func (_e *NetworkPeeringServiceMock_Expecter) DeletePeer(ctx interface{}, projectID interface{}, containerID interface{}) *NetworkPeeringServiceMock_DeletePeer_Call { - return &NetworkPeeringServiceMock_DeletePeer_Call{Call: _e.mock.On("DeletePeer", ctx, projectID, containerID)} +func (_e *NetworkPeeringServiceMock_Expecter) Delete(ctx interface{}, projectID interface{}, containerID interface{}) *NetworkPeeringServiceMock_Delete_Call { + return &NetworkPeeringServiceMock_Delete_Call{Call: _e.mock.On("Delete", ctx, projectID, containerID)} } -func (_c *NetworkPeeringServiceMock_DeletePeer_Call) Run(run func(ctx context.Context, projectID string, containerID string)) *NetworkPeeringServiceMock_DeletePeer_Call { +func (_c *NetworkPeeringServiceMock_Delete_Call) Run(run func(ctx context.Context, projectID string, containerID string)) *NetworkPeeringServiceMock_Delete_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(string), args[2].(string)) }) return _c } -func (_c *NetworkPeeringServiceMock_DeletePeer_Call) Return(_a0 error) *NetworkPeeringServiceMock_DeletePeer_Call { +func (_c *NetworkPeeringServiceMock_Delete_Call) Return(_a0 error) *NetworkPeeringServiceMock_Delete_Call { _c.Call.Return(_a0) return _c } -func (_c *NetworkPeeringServiceMock_DeletePeer_Call) RunAndReturn(run func(context.Context, string, string) error) *NetworkPeeringServiceMock_DeletePeer_Call { - _c.Call.Return(run) - return _c -} - -// FindContainer provides a mock function with given fields: ctx, projectID, provider, cidrBlock -func (_m *NetworkPeeringServiceMock) FindContainer(ctx context.Context, projectID string, provider string, cidrBlock string) (*networkpeering.ProviderContainer, error) { - ret := _m.Called(ctx, projectID, provider, cidrBlock) - - if len(ret) == 0 { - panic("no return value specified for FindContainer") - } - - var r0 *networkpeering.ProviderContainer - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, string) (*networkpeering.ProviderContainer, error)); ok { - return rf(ctx, projectID, provider, cidrBlock) - } - if rf, ok := ret.Get(0).(func(context.Context, string, string, string) *networkpeering.ProviderContainer); ok { - r0 = rf(ctx, projectID, provider, cidrBlock) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*networkpeering.ProviderContainer) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok { - r1 = rf(ctx, projectID, provider, cidrBlock) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NetworkPeeringServiceMock_FindContainer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindContainer' -type NetworkPeeringServiceMock_FindContainer_Call struct { - *mock.Call -} - -// FindContainer is a helper method to define mock.On call -// - ctx context.Context -// - projectID string -// - provider string -// - cidrBlock string -func (_e *NetworkPeeringServiceMock_Expecter) FindContainer(ctx interface{}, projectID interface{}, provider interface{}, cidrBlock interface{}) *NetworkPeeringServiceMock_FindContainer_Call { - return &NetworkPeeringServiceMock_FindContainer_Call{Call: _e.mock.On("FindContainer", ctx, projectID, provider, cidrBlock)} -} - -func (_c *NetworkPeeringServiceMock_FindContainer_Call) Run(run func(ctx context.Context, projectID string, provider string, cidrBlock string)) *NetworkPeeringServiceMock_FindContainer_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *NetworkPeeringServiceMock_FindContainer_Call) Return(_a0 *networkpeering.ProviderContainer, _a1 error) *NetworkPeeringServiceMock_FindContainer_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *NetworkPeeringServiceMock_FindContainer_Call) RunAndReturn(run func(context.Context, string, string, string) (*networkpeering.ProviderContainer, error)) *NetworkPeeringServiceMock_FindContainer_Call { - _c.Call.Return(run) - return _c -} - -// GetContainer provides a mock function with given fields: ctx, projectID, containerID -func (_m *NetworkPeeringServiceMock) GetContainer(ctx context.Context, projectID string, containerID string) (*networkpeering.ProviderContainer, error) { - ret := _m.Called(ctx, projectID, containerID) - - if len(ret) == 0 { - panic("no return value specified for GetContainer") - } - - var r0 *networkpeering.ProviderContainer - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) (*networkpeering.ProviderContainer, error)); ok { - return rf(ctx, projectID, containerID) - } - if rf, ok := ret.Get(0).(func(context.Context, string, string) *networkpeering.ProviderContainer); ok { - r0 = rf(ctx, projectID, containerID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*networkpeering.ProviderContainer) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { - r1 = rf(ctx, projectID, containerID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NetworkPeeringServiceMock_GetContainer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetContainer' -type NetworkPeeringServiceMock_GetContainer_Call struct { - *mock.Call -} - -// GetContainer is a helper method to define mock.On call -// - ctx context.Context -// - projectID string -// - containerID string -func (_e *NetworkPeeringServiceMock_Expecter) GetContainer(ctx interface{}, projectID interface{}, containerID interface{}) *NetworkPeeringServiceMock_GetContainer_Call { - return &NetworkPeeringServiceMock_GetContainer_Call{Call: _e.mock.On("GetContainer", ctx, projectID, containerID)} -} - -func (_c *NetworkPeeringServiceMock_GetContainer_Call) Run(run func(ctx context.Context, projectID string, containerID string)) *NetworkPeeringServiceMock_GetContainer_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *NetworkPeeringServiceMock_GetContainer_Call) Return(_a0 *networkpeering.ProviderContainer, _a1 error) *NetworkPeeringServiceMock_GetContainer_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *NetworkPeeringServiceMock_GetContainer_Call) RunAndReturn(run func(context.Context, string, string) (*networkpeering.ProviderContainer, error)) *NetworkPeeringServiceMock_GetContainer_Call { +func (_c *NetworkPeeringServiceMock_Delete_Call) RunAndReturn(run func(context.Context, string, string) error) *NetworkPeeringServiceMock_Delete_Call { _c.Call.Return(run) return _c } -// GetPeer provides a mock function with given fields: ctx, projectID, containerID -func (_m *NetworkPeeringServiceMock) GetPeer(ctx context.Context, projectID string, containerID string) (*networkpeering.NetworkPeer, error) { +// Get provides a mock function with given fields: ctx, projectID, containerID +func (_m *NetworkPeeringServiceMock) Get(ctx context.Context, projectID string, containerID string) (*networkpeering.NetworkPeer, error) { ret := _m.Called(ctx, projectID, containerID) if len(ret) == 0 { - panic("no return value specified for GetPeer") + panic("no return value specified for Get") } var r0 *networkpeering.NetworkPeer @@ -390,32 +162,32 @@ func (_m *NetworkPeeringServiceMock) GetPeer(ctx context.Context, projectID stri return r0, r1 } -// NetworkPeeringServiceMock_GetPeer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPeer' -type NetworkPeeringServiceMock_GetPeer_Call struct { +// NetworkPeeringServiceMock_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type NetworkPeeringServiceMock_Get_Call struct { *mock.Call } -// GetPeer is a helper method to define mock.On call +// Get is a helper method to define mock.On call // - ctx context.Context // - projectID string // - containerID string -func (_e *NetworkPeeringServiceMock_Expecter) GetPeer(ctx interface{}, projectID interface{}, containerID interface{}) *NetworkPeeringServiceMock_GetPeer_Call { - return &NetworkPeeringServiceMock_GetPeer_Call{Call: _e.mock.On("GetPeer", ctx, projectID, containerID)} +func (_e *NetworkPeeringServiceMock_Expecter) Get(ctx interface{}, projectID interface{}, containerID interface{}) *NetworkPeeringServiceMock_Get_Call { + return &NetworkPeeringServiceMock_Get_Call{Call: _e.mock.On("Get", ctx, projectID, containerID)} } -func (_c *NetworkPeeringServiceMock_GetPeer_Call) Run(run func(ctx context.Context, projectID string, containerID string)) *NetworkPeeringServiceMock_GetPeer_Call { +func (_c *NetworkPeeringServiceMock_Get_Call) Run(run func(ctx context.Context, projectID string, containerID string)) *NetworkPeeringServiceMock_Get_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(string), args[2].(string)) }) return _c } -func (_c *NetworkPeeringServiceMock_GetPeer_Call) Return(_a0 *networkpeering.NetworkPeer, _a1 error) *NetworkPeeringServiceMock_GetPeer_Call { +func (_c *NetworkPeeringServiceMock_Get_Call) Return(_a0 *networkpeering.NetworkPeer, _a1 error) *NetworkPeeringServiceMock_Get_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *NetworkPeeringServiceMock_GetPeer_Call) RunAndReturn(run func(context.Context, string, string) (*networkpeering.NetworkPeer, error)) *NetworkPeeringServiceMock_GetPeer_Call { +func (_c *NetworkPeeringServiceMock_Get_Call) RunAndReturn(run func(context.Context, string, string) (*networkpeering.NetworkPeer, error)) *NetworkPeeringServiceMock_Get_Call { _c.Call.Return(run) return _c } diff --git a/internal/mocks/translation/private_endpoint_service.go b/internal/mocks/translation/private_endpoint_service.go index 29d4d676de..1cc7c5e0db 100644 --- a/internal/mocks/translation/private_endpoint_service.go +++ b/internal/mocks/translation/private_endpoint_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - privateendpoint "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/privateendpoint" + mock "github.com/stretchr/testify/mock" ) // PrivateEndpointServiceMock is an autogenerated mock type for the PrivateEndpointService type diff --git a/internal/mocks/translation/project_referrer_object.go b/internal/mocks/translation/project_referrer_object.go index 6d40c06736..2442a4612d 100644 --- a/internal/mocks/translation/project_referrer_object.go +++ b/internal/mocks/translation/project_referrer_object.go @@ -3,9 +3,8 @@ package translation import ( - mock "github.com/stretchr/testify/mock" - apiv1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" + mock "github.com/stretchr/testify/mock" runtime "k8s.io/apimachinery/pkg/runtime" diff --git a/internal/mocks/translation/project_service.go b/internal/mocks/translation/project_service.go index b416d46584..972d838f49 100644 --- a/internal/mocks/translation/project_service.go +++ b/internal/mocks/translation/project_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - project "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/project" + mock "github.com/stretchr/testify/mock" ) // ProjectServiceMock is an autogenerated mock type for the ProjectService type diff --git a/internal/mocks/translation/team_projects_service.go b/internal/mocks/translation/team_projects_service.go index b2cbe5f2a9..d17924bd18 100644 --- a/internal/mocks/translation/team_projects_service.go +++ b/internal/mocks/translation/team_projects_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - teams "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/teams" + mock "github.com/stretchr/testify/mock" ) // TeamProjectsServiceMock is an autogenerated mock type for the TeamProjectsService type diff --git a/internal/mocks/translation/team_roles_service.go b/internal/mocks/translation/team_roles_service.go index f14875d151..231ffb9a14 100644 --- a/internal/mocks/translation/team_roles_service.go +++ b/internal/mocks/translation/team_roles_service.go @@ -5,10 +5,9 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" teams "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/teams" + mock "github.com/stretchr/testify/mock" ) // TeamRolesServiceMock is an autogenerated mock type for the TeamRolesService type diff --git a/internal/mocks/translation/team_users_service.go b/internal/mocks/translation/team_users_service.go index 8abd345d97..8a7ba49029 100644 --- a/internal/mocks/translation/team_users_service.go +++ b/internal/mocks/translation/team_users_service.go @@ -5,9 +5,8 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - teams "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/teams" + mock "github.com/stretchr/testify/mock" ) // TeamUsersServiceMock is an autogenerated mock type for the TeamUsersService type diff --git a/internal/mocks/translation/teams_service.go b/internal/mocks/translation/teams_service.go index a71a195def..f69683f56c 100644 --- a/internal/mocks/translation/teams_service.go +++ b/internal/mocks/translation/teams_service.go @@ -5,10 +5,9 @@ package translation import ( context "context" - mock "github.com/stretchr/testify/mock" - v1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" teams "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/teams" + mock "github.com/stretchr/testify/mock" ) // TeamsServiceMock is an autogenerated mock type for the TeamsService type diff --git a/internal/translation/networkpeering/conversion.go b/internal/translation/networkpeering/conversion.go index 67a41e3d74..64acf69ae6 100644 --- a/internal/translation/networkpeering/conversion.go +++ b/internal/translation/networkpeering/conversion.go @@ -17,6 +17,7 @@ type AWSStatus struct { type NetworkPeer struct { akov2.AtlasNetworkPeeringConfig ID string + ContainerID string Status string ErrorMessage string AWSStatus *AWSStatus @@ -98,87 +99,7 @@ func NewNetworkPeer(id string, cfg *akov2.AtlasNetworkPeeringConfig) *NetworkPee } } -// NewNetworkPeeringSpec creates an spec for network peering from the given config -func NewNetworkPeeringSpec(cfg *akov2.AtlasNetworkPeeringConfig) *NetworkPeer { - return NewNetworkPeer("", cfg) -} - -type ProviderContainer struct { - akov2.AtlasProviderContainerConfig - ID string - Provider string - Provisioned bool - AWSStatus *AWSContainerStatus - AzureStatus *AzureContainerStatus - GoogleStatus *GoogleContainerStatus -} - -type AWSContainerStatus struct { - VpcID string -} - -type AzureContainerStatus struct { - AzureSubscriptionID string - VnetName string -} - -type GoogleContainerStatus struct { - GCPProjectID string - NetworkName string -} - -func NewProviderContainer(id string, provider string, cfg *akov2.AtlasProviderContainerConfig) *ProviderContainer { - return &ProviderContainer{ - AtlasProviderContainerConfig: *cfg, - ID: id, - Provider: provider, - } -} - -func (pc *ProviderContainer) UpdateStatus(atlas *ProviderContainer) { - pc.ID = atlas.ID - pc.Provisioned = atlas.Provisioned - switch provider.ProviderName(pc.Provider) { - case provider.ProviderAWS: - pc.AWSStatus = atlas.AWSStatus - case provider.ProviderAzure: - pc.AzureStatus = atlas.AzureStatus - case provider.ProviderGCP: - pc.GoogleStatus = atlas.GoogleStatus - } -} - -func (pc *ProviderContainer) String() string { - return fmt.Sprintf("ProviderContainer for %s ID=%s\nConfig:%v\nStatus:%v", - pc.Provider, pc.ID, pc.configString(), pc.statusString()) -} - -func (pc *ProviderContainer) configString() string { - return fmt.Sprintf("{ ContainerRegion=%s AtlasCIDRBlock=%s }", pc.ContainerRegion, pc.AtlasCIDRBlock) -} - -func (pc *ProviderContainer) statusString() string { - aws := "" - if pc.AWSStatus != nil { - status := pc.AWSStatus - aws = fmt.Sprintf("AWSStatus:{ VpcID=%s } ", status.VpcID) - } - azure := "" - if pc.AzureStatus != nil { - status := pc.AzureStatus - azure = fmt.Sprintf("AzureStatus:{ AzureSubscriptionID=%s VnetName=%s } ", - status.AzureSubscriptionID, status.VnetName) - } - google := "" - if pc.GoogleStatus != nil { - status := pc.GoogleStatus - google = fmt.Sprintf("GoogleStatus:{GCPProjectID=%s NetworkName=%s } ", - status.GCPProjectID, status.NetworkName) - } - return fmt.Sprintf("{ Provisioned=%v %s%s%s}", pc.Provisioned, aws, azure, google) -} - -func toAtlasConnection(peer *NetworkPeer) (*admin.BaseNetworkPeeringConnectionSettings, error) { +func toAtlas(peer *NetworkPeer) (*admin.BaseNetworkPeeringConnectionSettings, error) { switch peer.Provider { case string(provider.ProviderAWS): if peer.AWSConfiguration == nil { @@ -219,7 +140,7 @@ func toAtlasConnection(peer *NetworkPeer) (*admin.BaseNetworkPeeringConnectionSe } } -func fromAtlasConnection(conn *admin.BaseNetworkPeeringConnectionSettings) (*NetworkPeer, error) { +func fromAtlas(conn *admin.BaseNetworkPeeringConnectionSettings) (*NetworkPeer, error) { networkPeer, err := fromAtlasConnectionNoStatus(conn) if err != nil { return nil, fmt.Errorf("failed to convert BaseNetworkPeeringConnectionSettings to NetworkPeer: %w", err) @@ -254,10 +175,10 @@ func fromAtlasConnectionNoStatus(conn *admin.BaseNetworkPeeringConnectionSetting switch provider.ProviderName(conn.GetProviderName()) { case provider.ProviderAWS: return &NetworkPeer{ - ID: conn.GetId(), + ID: conn.GetId(), + ContainerID: conn.GetContainerId(), AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ - ContainerID: conn.GetContainerId(), - Provider: conn.GetProviderName(), + Provider: conn.GetProviderName(), AWSConfiguration: &akov2.AWSNetworkPeeringConfiguration{ AccepterRegionName: conn.GetAccepterRegionName(), AWSAccountID: conn.GetAwsAccountId(), @@ -268,10 +189,10 @@ func fromAtlasConnectionNoStatus(conn *admin.BaseNetworkPeeringConnectionSetting }, nil case provider.ProviderGCP: return &NetworkPeer{ - ID: conn.GetId(), + ID: conn.GetId(), + ContainerID: conn.GetContainerId(), AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ - ContainerID: conn.GetContainerId(), - Provider: conn.GetProviderName(), + Provider: conn.GetProviderName(), GCPConfiguration: &akov2.GCPNetworkPeeringConfiguration{ GCPProjectID: conn.GetGcpProjectId(), NetworkName: conn.GetNetworkName(), @@ -280,10 +201,10 @@ func fromAtlasConnectionNoStatus(conn *admin.BaseNetworkPeeringConnectionSetting }, nil case provider.ProviderAzure: return &NetworkPeer{ - ID: conn.GetId(), + ID: conn.GetId(), + ContainerID: conn.GetContainerId(), AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ - ContainerID: conn.GetContainerId(), - Provider: conn.GetProviderName(), + Provider: conn.GetProviderName(), AzureConfiguration: &akov2.AzureNetworkPeeringConfiguration{ AzureDirectoryID: conn.GetAzureDirectoryId(), AzureSubscriptionID: conn.GetAzureSubscriptionId(), @@ -303,7 +224,7 @@ func fromAtlasConnectionList(list []admin.BaseNetworkPeeringConnectionSettings) } peers := make([]NetworkPeer, 0, len(list)) for i, conn := range list { - c, err := fromAtlasConnection(&conn) + c, err := fromAtlas(&conn) if err != nil { return nil, fmt.Errorf("failed to convert connection list item %d: %w", i, err) } @@ -311,86 +232,3 @@ func fromAtlasConnectionList(list []admin.BaseNetworkPeeringConnectionSettings) } return peers, nil } - -func toAtlasContainer(container *ProviderContainer) *admin.CloudProviderContainer { - cpc := &admin.CloudProviderContainer{ - Id: pointer.SetOrNil(container.ID, ""), - ProviderName: pointer.SetOrNil(container.Provider, ""), - AtlasCidrBlock: pointer.SetOrNil(container.AtlasCIDRBlock, ""), - } - if cpc.GetProviderName() == string(provider.ProviderAWS) { - cpc.RegionName = pointer.SetOrNil(container.ContainerRegion, "") - } else { - cpc.Region = pointer.SetOrNil(container.ContainerRegion, "") - } - return cpc -} - -func fromAtlasContainer(container *admin.CloudProviderContainer) *ProviderContainer { - pc := fromAtlasContainerNoStatus(container) - pc.Provisioned = container.GetProvisioned() - switch provider.ProviderName(pc.Provider) { - case provider.ProviderAWS: - pc.AWSStatus = fromAtlasAWSContainerStatus(container) - case provider.ProviderAzure: - pc.AzureStatus = fromAtlasAzureContainerStatus(container) - case provider.ProviderGCP: - pc.GoogleStatus = fromAtlasGoogleContainerStatus(container) - } - return pc -} - -func fromAtlasAWSContainerStatus(container *admin.CloudProviderContainer) *AWSContainerStatus { - if container.VpcId == nil { - return nil - } - return &AWSContainerStatus{ - VpcID: container.GetVpcId(), - } -} - -func fromAtlasAzureContainerStatus(container *admin.CloudProviderContainer) *AzureContainerStatus { - if container.AzureSubscriptionId == nil && container.VnetName == nil { - return nil - } - return &AzureContainerStatus{ - AzureSubscriptionID: container.GetAzureSubscriptionId(), - VnetName: container.GetVnetName(), - } -} - -func fromAtlasGoogleContainerStatus(container *admin.CloudProviderContainer) *GoogleContainerStatus { - if container.GcpProjectId == nil && container.NetworkName == nil { - return nil - } - return &GoogleContainerStatus{ - GCPProjectID: container.GetGcpProjectId(), - NetworkName: container.GetNetworkName(), - } -} - -func fromAtlasContainerNoStatus(container *admin.CloudProviderContainer) *ProviderContainer { - region := container.GetRegion() - if container.GetProviderName() == string(provider.ProviderAWS) { - region = container.GetRegionName() - } - return &ProviderContainer{ - ID: container.GetId(), - Provider: container.GetProviderName(), - AtlasProviderContainerConfig: akov2.AtlasProviderContainerConfig{ - AtlasCIDRBlock: container.GetAtlasCidrBlock(), - ContainerRegion: region, - }, - } -} - -func fromAtlasContainerList(list []admin.CloudProviderContainer) []ProviderContainer { - if list == nil { - return nil - } - containers := make([]ProviderContainer, 0, len(list)) - for _, container := range list { - containers = append(containers, *fromAtlasContainer(&container)) - } - return containers -} diff --git a/internal/translation/networkpeering/conversion_test.go b/internal/translation/networkpeering/conversion_test.go index b255fd7462..7e261e59df 100644 --- a/internal/translation/networkpeering/conversion_test.go +++ b/internal/translation/networkpeering/conversion_test.go @@ -29,9 +29,9 @@ func FuzzConvertConnection(f *testing.F) { gofuzz.NewFromGoFuzz(data).Fuzz(&peerData) peerData.Provider = providerNames[index%3] cleanupPeer(&peerData) - atlasConn, err := toAtlasConnection(&peerData) + atlasConn, err := toAtlas(&peerData) require.NoError(t, err) - result, err := fromAtlasConnection(atlasConn) + result, err := fromAtlas(atlasConn) require.NoError(t, err) assert.Equal(t, &peerData, result, "failed for index=%d", index) }) @@ -49,12 +49,12 @@ func FuzzConvertListOfConnections(f *testing.F) { gofuzz.NewFromGoFuzz(data).Fuzz(&peerData) peerData.Provider = providerNames[index%3] cleanupPeer(&peerData) - atlasConn, err := toAtlasConnection(&peerData) + atlasConn, err := toAtlas(&peerData) require.NoError(t, err) - expectedConn, err := fromAtlasConnection(atlasConn) + expectedConn, err := fromAtlas(atlasConn) require.NoError(t, err) expected = append(expected, *expectedConn) - atlasConnItem, err := toAtlasConnection(&peerData) + atlasConnItem, err := toAtlas(&peerData) require.NoError(t, err) conns = append(conns, *atlasConnItem) } @@ -64,41 +64,6 @@ func FuzzConvertListOfConnections(f *testing.F) { }) } -func FuzzConvertContainer(f *testing.F) { - for i := uint(0); i < fuzzIterations; i++ { - f.Add(([]byte)(fmt.Sprintf("seed sample %x", i)), i) - } - f.Fuzz(func(t *testing.T, data []byte, index uint) { - containerData := ProviderContainer{} - gofuzz.NewFromGoFuzz(data).Fuzz(&containerData) - containerData.Provider = providerNames[index%3] - cleanupContainer(&containerData) - result := fromAtlasContainer(toAtlasContainer(&containerData)) - assert.Equal(t, &containerData, result, "failed for index=%d", index) - }) -} - -func FuzzConvertListOfContainers(f *testing.F) { - for i := uint(0); i < fuzzIterations; i++ { - f.Add(([]byte)(fmt.Sprintf("seed sample %x", i)), i, (i % 5)) - } - f.Fuzz(func(t *testing.T, data []byte, index uint, size uint) { - containers := []admin.CloudProviderContainer{} - expected := []ProviderContainer{} - for i := uint(0); i < size; i++ { - containerData := ProviderContainer{} - gofuzz.NewFromGoFuzz(data).Fuzz(&containerData) - containerData.Provider = providerNames[index%3] - cleanupContainer(&containerData) - expectedContainer := fromAtlasContainer(toAtlasContainer(&containerData)) - expected = append(expected, *expectedContainer) - containers = append(containers, *toAtlasContainer(&containerData)) - } - result := fromAtlasContainerList(containers) - assert.Equal(t, expected, result) - }) -} - func cleanupPeer(peer *NetworkPeer) { peer.ID = "" if peer.Provider != string(provider.ProviderAWS) { @@ -115,10 +80,3 @@ func cleanupPeer(peer *NetworkPeer) { peer.ErrorMessage = "" peer.AWSStatus = nil } - -func cleanupContainer(container *ProviderContainer) { - // status fields are only populated from Atlas they do not complete a roundtrip - container.AWSStatus = nil - container.AzureStatus = nil - container.GoogleStatus = nil -} diff --git a/internal/translation/networkpeering/networkpeering.go b/internal/translation/networkpeering/networkpeering.go index 1ed80c7160..705c8cc829 100644 --- a/internal/translation/networkpeering/networkpeering.go +++ b/internal/translation/networkpeering/networkpeering.go @@ -4,12 +4,11 @@ import ( "context" "errors" "fmt" - "net/http" "go.mongodb.org/atlas-sdk/v20231115008/admin" + akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/controller/atlas" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/paging" ) var ( @@ -20,22 +19,10 @@ var ( ErrContainerInUse = errors.New("container still in use") ) -type PeerConnectionsService interface { - CreatePeer(ctx context.Context, projectID string, conn *NetworkPeer) (*NetworkPeer, error) - GetPeer(ctx context.Context, projectID, containerID string) (*NetworkPeer, error) - DeletePeer(ctx context.Context, projectID, containerID string) error -} - -type PeeringContainerService interface { - CreateContainer(ctx context.Context, projectID string, container *ProviderContainer) (*ProviderContainer, error) - GetContainer(ctx context.Context, projectID, containerID string) (*ProviderContainer, error) - FindContainer(ctx context.Context, projectID, provider, cidrBlock string) (*ProviderContainer, error) - DeleteContainer(ctx context.Context, projectID, containerID string) error -} - type NetworkPeeringService interface { - PeerConnectionsService - PeeringContainerService + Create(ctx context.Context, projectID, containerID string, cfg *akov2.AtlasNetworkPeeringConfig) (*NetworkPeer, error) + Get(ctx context.Context, projectID, containerID string) (*NetworkPeer, error) + Delete(ctx context.Context, projectID, containerID string) error } type networkPeeringService struct { @@ -50,23 +37,26 @@ func NewNetworkPeeringService(peeringAPI admin.NetworkPeeringApi) NetworkPeering return &networkPeeringService{peeringAPI: peeringAPI} } -func (np *networkPeeringService) CreatePeer(ctx context.Context, projectID string, conn *NetworkPeer) (*NetworkPeer, error) { - atlasConnRequest, err := toAtlasConnection(conn) +func (np *networkPeeringService) Create(ctx context.Context, projectID, containerID string, cfg *akov2.AtlasNetworkPeeringConfig) (*NetworkPeer, error) { + atlasConnRequest, err := toAtlas(&NetworkPeer{ + AtlasNetworkPeeringConfig: *cfg, + ContainerID: containerID, + }) if err != nil { return nil, fmt.Errorf("failed to convert peer to Atlas: %w", err) } newAtlasConn, _, err := np.peeringAPI.CreatePeeringConnection(ctx, projectID, atlasConnRequest).Execute() if err != nil { - return nil, fmt.Errorf("failed to create network peer %v: %w", conn, err) + return nil, fmt.Errorf("failed to create network peer from config %v: %w", cfg, err) } - newPeer, err := fromAtlasConnection(newAtlasConn) + newPeer, err := fromAtlas(newAtlasConn) if err != nil { return nil, fmt.Errorf("failed to convert peer from Atlas: %w", err) } return newPeer, nil } -func (np *networkPeeringService) GetPeer(ctx context.Context, projectID, peerID string) (*NetworkPeer, error) { +func (np *networkPeeringService) Get(ctx context.Context, projectID, peerID string) (*NetworkPeer, error) { atlasConn, _, err := np.peeringAPI.GetPeeringConnection(ctx, projectID, peerID).Execute() if err != nil { if admin.IsErrorCode(err, "PEER_NOT_FOUND") { @@ -74,14 +64,14 @@ func (np *networkPeeringService) GetPeer(ctx context.Context, projectID, peerID } return nil, fmt.Errorf("failed to get network peer for peer id %v: %w", peerID, err) } - peer, err := fromAtlasConnection(atlasConn) + peer, err := fromAtlas(atlasConn) if err != nil { return nil, fmt.Errorf("failed to convert peer from Atlas: %w", err) } return peer, nil } -func (np *networkPeeringService) DeletePeer(ctx context.Context, projectID, peerID string) error { +func (np *networkPeeringService) Delete(ctx context.Context, projectID, peerID string) error { _, _, err := np.peeringAPI.DeletePeeringConnection(ctx, projectID, peerID).Execute() if admin.IsErrorCode(err, "PEER_ALREADY_REQUESTED_DELETION") || admin.IsErrorCode(err, "PEER_NOT_FOUND") { return nil // if it was already removed or being removed it is also fine @@ -91,51 +81,3 @@ func (np *networkPeeringService) DeletePeer(ctx context.Context, projectID, peer } return nil } - -func (np *networkPeeringService) CreateContainer(ctx context.Context, projectID string, container *ProviderContainer) (*ProviderContainer, error) { - newContainer, _, err := np.peeringAPI.CreatePeeringContainer(ctx, projectID, toAtlasContainer(container)).Execute() - if err != nil { - return nil, fmt.Errorf("failed to create peering container %s: %w", container.ID, err) - } - return fromAtlasContainer(newContainer), nil -} - -func (np *networkPeeringService) GetContainer(ctx context.Context, projectID, containerID string) (*ProviderContainer, error) { - container, _, err := np.peeringAPI.GetPeeringContainer(ctx, projectID, containerID).Execute() - if admin.IsErrorCode(err, "CLOUD_PROVIDER_CONTAINER_NOT_FOUND") { - return nil, ErrNotFound - } - if err != nil { - return nil, fmt.Errorf("failed to get container %s: %w", containerID, err) - } - return fromAtlasContainer(container), nil -} - -func (np *networkPeeringService) FindContainer(ctx context.Context, projectID, provider, cidrBlock string) (*ProviderContainer, error) { - containers, err := paging.ListAll(ctx, func(ctx context.Context, pageNum int) (paging.Response[admin.CloudProviderContainer], *http.Response, error) { - return np.peeringAPI.ListPeeringContainerByCloudProvider(ctx, projectID).ProviderName(provider).PageNum(pageNum).Execute() - }) - if err != nil { - return nil, fmt.Errorf("failed to list containers at project %s: %w", projectID, err) - } - for _, container := range containers { - if container.GetAtlasCidrBlock() == cidrBlock { - return fromAtlasContainer(&container), nil - } - } - return nil, ErrNotFound -} - -func (np *networkPeeringService) DeleteContainer(ctx context.Context, projectID, containerID string) error { - _, _, err := np.peeringAPI.DeletePeeringContainer(ctx, projectID, containerID).Execute() - if admin.IsErrorCode(err, "CLOUD_PROVIDER_CONTAINER_NOT_FOUND") { - return ErrNotFound - } - if admin.IsErrorCode(err, "CONTAINERS_IN_USE") { - return fmt.Errorf("failed to remove container %s as it is still in use: %w", containerID, ErrContainerInUse) - } - if err != nil { - return fmt.Errorf("failed to delete container: %w", err) - } - return nil -} diff --git a/test/contract/networkpeering/networkpeering_test.go b/test/contract/networkpeering/networkpeering_test.go index 5462a4bd42..5835618588 100644 --- a/test/contract/networkpeering/networkpeering_test.go +++ b/test/contract/networkpeering/networkpeering_test.go @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/require" akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/provider" + "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkcontainer" "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/translation/networkpeering" "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/cloud/aws" "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/cloud/azure" @@ -24,59 +26,6 @@ const ( testVPCName = "ako-test-network-peering-vpc" ) -func TestPeerContainerServiceCRUD(t *testing.T) { - ctx := context.Background() - contract.RunGoContractTest(ctx, t, "test container CRUD", func(ch contract.ContractHelper) { - projectName := utils.RandomName("peer-container-crud-project") - require.NoError(t, ch.AddResources(ctx, 5*time.Minute, contract.DefaultAtlasProject(projectName))) - testProjectID, err := ch.ProjectID(ctx, projectName) - require.NoError(t, err) - nps := networkpeering.NewNetworkPeeringService(ch.AtlasClient().NetworkPeeringApi) - cs := nps.(networkpeering.PeeringContainerService) - for _, tc := range []struct { - provider string - container *networkpeering.ProviderContainer - }{ - { - provider: "AWS", - container: testAWSPeeringContainer("10.1.0.0/21"), - }, - { - provider: "Azure", - container: testAzurePeeringContainer("10.2.0.0/21"), - }, - { - provider: "Google", - container: testGooglePeeringContainer("10.3.0.0/18"), // .../21 is not allowed in GCP - }, - } { - createdContainer := &networkpeering.ProviderContainer{} - t.Run(fmt.Sprintf("create %s container", tc.provider), func(t *testing.T) { - newContainer, err := cs.CreateContainer(ctx, testProjectID, tc.container) - require.NoError(t, err) - assert.NotEmpty(t, newContainer.ID) - createdContainer = newContainer - }) - - t.Run(fmt.Sprintf("get %s container", tc.provider), func(t *testing.T) { - container, err := cs.GetContainer(ctx, testProjectID, createdContainer.ID) - require.NoError(t, err) - assert.NotEmpty(t, container) - assert.Equal(t, createdContainer.ID, container.ID) - assert.Equal(t, tc.container.ContainerRegion, container.ContainerRegion) - assert.Equal(t, tc.container.AtlasCIDRBlock, container.AtlasCIDRBlock) - }) - - t.Run(fmt.Sprintf("delete %s container", tc.provider), func(t *testing.T) { - time.Sleep(time.Second) // Atlas may reject removal if it happened within a second of creation - assert.NoErrorf(t, cs.DeleteContainer(ctx, testProjectID, createdContainer.ID), - "failed cleanup for provider %s Atlas project ID %s and container id %s", - tc.provider, testProjectID, createdContainer.ID) - }) - } - }) -} - func TestPeerServiceCRUD(t *testing.T) { ctx := context.Background() contract.RunGoContractTest(ctx, t, "test peer CRUD", func(ch contract.ContractHelper) { @@ -84,154 +33,145 @@ func TestPeerServiceCRUD(t *testing.T) { require.NoError(t, ch.AddResources(ctx, time.Minute, contract.DefaultAtlasProject(projectName))) testProjectID, err := ch.ProjectID(ctx, projectName) require.NoError(t, err) + ncs := networkcontainer.NewNetworkContainerService(ch.AtlasClient().NetworkPeeringApi) nps := networkpeering.NewNetworkPeeringService(ch.AtlasClient().NetworkPeeringApi) - ps := nps.(networkpeering.PeerConnectionsService) createdPeer := &networkpeering.NetworkPeer{} for _, tc := range []struct { provider string - preparedCloudTest func(func(peerRequest *networkpeering.NetworkPeer)) + preparedCloudTest func(func(containerID string, cfg *akov2.AtlasNetworkPeeringConfig)) }{ { - provider: "AWS", - preparedCloudTest: func(performTest func(*networkpeering.NetworkPeer)) { + provider: string(provider.ProviderAWS), + preparedCloudTest: func(performTest func(string, *akov2.AtlasNetworkPeeringConfig)) { testContainer := testAWSPeeringContainer("10.10.0.0/21") - awsRegionName := aws.RegionCode(testContainer.ContainerRegion) + awsRegionName := aws.RegionCode(testContainer.Region) vpcCIDR := "10.11.0.0/21" awsVPCid, err := aws.CreateVPC(utils.RandomName(testVPCName), vpcCIDR, awsRegionName) require.NoError(t, err) - newContainer, err := nps.CreateContainer(ctx, testProjectID, testContainer) + newContainer, err := ncs.Create(ctx, testProjectID, testContainer) require.NoError(t, err) assert.NotEmpty(t, newContainer.ID) defer func() { require.NoError(t, aws.DeleteVPC(awsVPCid, awsRegionName)) }() - performTest(testAWSPeerConnection(t, newContainer.ID, vpcCIDR, awsVPCid)) + performTest(newContainer.ID, testAWSPeerConnection(t, vpcCIDR, awsVPCid)) }, }, { - provider: "AZURE", - preparedCloudTest: func(performTest func(*networkpeering.NetworkPeer)) { + provider: string(provider.ProviderAzure), + preparedCloudTest: func(performTest func(string, *akov2.AtlasNetworkPeeringConfig)) { testContainer := testAzurePeeringContainer("10.20.0.0/21") - azureRegionName := azure.RegionCode(testContainer.ContainerRegion) + azureRegionName := azure.RegionCode(testContainer.Region) vpcCIDR := "10.21.0.0/21" azureVPC, err := azure.CreateVPC(ctx, utils.RandomName(testVPCName), vpcCIDR, azureRegionName) require.NoError(t, err) - newContainer, err := nps.CreateContainer(ctx, testProjectID, testContainer) + newContainer, err := ncs.Create(ctx, testProjectID, testContainer) require.NoError(t, err) assert.NotEmpty(t, newContainer.ID) defer func() { require.NoError(t, azure.DeleteVPC(ctx, azureVPC)) }() - performTest(testAzurePeerConnection(t, newContainer.ID, azureVPC)) + performTest(newContainer.ID, testAzurePeerConnection(t, azureVPC)) }, }, { - provider: "GOOGLE", - preparedCloudTest: func(performTest func(*networkpeering.NetworkPeer)) { + provider: string(provider.ProviderGCP), + preparedCloudTest: func(performTest func(string, *akov2.AtlasNetworkPeeringConfig)) { testContainer := testGooglePeeringContainer("10.30.0.0/18") vpcName := utils.RandomName(testVPCName) require.NoError(t, google.CreateVPC(ctx, vpcName)) - newContainer, err := nps.CreateContainer(ctx, testProjectID, testContainer) + newContainer, err := ncs.Create(ctx, testProjectID, testContainer) require.NoError(t, err) assert.NotEmpty(t, newContainer.ID) defer func() { require.NoError(t, google.DeleteVPC(ctx, vpcName)) }() - performTest(testGooglePeerConnection(t, newContainer.ID, vpcName)) + performTest(newContainer.ID, testGooglePeerConnection(t, vpcName)) }, }, } { - tc.preparedCloudTest(func(peerRequest *networkpeering.NetworkPeer) { + tc.preparedCloudTest(func(containerID string, cfg *akov2.AtlasNetworkPeeringConfig) { t.Run(fmt.Sprintf("create %s peer connection", tc.provider), func(t *testing.T) { - newPeer, err := ps.CreatePeer(ctx, testProjectID, peerRequest) + newPeer, err := nps.Create(ctx, testProjectID, containerID, cfg) require.NoError(t, err) assert.NotEmpty(t, newPeer) createdPeer = newPeer }) t.Run(fmt.Sprintf("get %s peer connection", tc.provider), func(t *testing.T) { - peer, err := ps.GetPeer(ctx, testProjectID, createdPeer.ID) + peer, err := nps.Get(ctx, testProjectID, createdPeer.ID) require.NoError(t, err) assert.Equal(t, createdPeer, peer) }) t.Run(fmt.Sprintf("delete %s peer connection", tc.provider), func(t *testing.T) { - assert.NoError(t, ps.DeletePeer(ctx, testProjectID, createdPeer.ID)) + assert.NoError(t, nps.Delete(ctx, testProjectID, createdPeer.ID)) }) }) } }) } -func testAWSPeeringContainer(cidr string) *networkpeering.ProviderContainer { - return &networkpeering.ProviderContainer{ - Provider: "AWS", - AtlasProviderContainerConfig: akov2.AtlasProviderContainerConfig{ - ContainerRegion: "US_EAST_1", - AtlasCIDRBlock: cidr, +func testAWSPeeringContainer(cidr string) *networkcontainer.NetworkContainerConfig { + return &networkcontainer.NetworkContainerConfig{ + Provider: string(provider.ProviderAWS), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + Region: "US_EAST_1", + CIDRBlock: cidr, }, } } -func testAzurePeeringContainer(cidr string) *networkpeering.ProviderContainer { - return &networkpeering.ProviderContainer{ - Provider: "AZURE", - AtlasProviderContainerConfig: akov2.AtlasProviderContainerConfig{ - ContainerRegion: "US_EAST_2", - AtlasCIDRBlock: cidr, +func testAzurePeeringContainer(cidr string) *networkcontainer.NetworkContainerConfig { + return &networkcontainer.NetworkContainerConfig{ + Provider: string(provider.ProviderAzure), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + Region: "US_EAST_2", + CIDRBlock: cidr, }, } } -func testGooglePeeringContainer(cidr string) *networkpeering.ProviderContainer { - return &networkpeering.ProviderContainer{ - Provider: "GCP", - AtlasProviderContainerConfig: akov2.AtlasProviderContainerConfig{ - AtlasCIDRBlock: cidr, +func testGooglePeeringContainer(cidr string) *networkcontainer.NetworkContainerConfig { + return &networkcontainer.NetworkContainerConfig{ + Provider: string(provider.ProviderGCP), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + CIDRBlock: cidr, }, } } -func testAWSPeerConnection(t *testing.T, containerID string, vpcCIDR, vpcID string) *networkpeering.NetworkPeer { - return &networkpeering.NetworkPeer{ - AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ - Provider: "AWS", - ContainerID: containerID, - AWSConfiguration: &akov2.AWSNetworkPeeringConfiguration{ - AWSAccountID: mustHaveEnvVar(t, "AWS_ACCOUNT_ID"), - AccepterRegionName: "us-east-1", - RouteTableCIDRBlock: vpcCIDR, - VpcID: vpcID, - }, +func testAWSPeerConnection(t *testing.T, vpcCIDR, vpcID string) *akov2.AtlasNetworkPeeringConfig { + return &akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderAWS), + AWSConfiguration: &akov2.AWSNetworkPeeringConfiguration{ + AWSAccountID: mustHaveEnvVar(t, "AWS_ACCOUNT_ID"), + AccepterRegionName: "us-east-1", + RouteTableCIDRBlock: vpcCIDR, + VpcID: vpcID, }, } } -func testAzurePeerConnection(t *testing.T, containerID string, vpcName string) *networkpeering.NetworkPeer { - return &networkpeering.NetworkPeer{ - AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ - Provider: "AZURE", - ContainerID: containerID, - AzureConfiguration: &akov2.AzureNetworkPeeringConfiguration{ - AzureDirectoryID: mustHaveEnvVar(t, "AZURE_TENANT_ID"), - AzureSubscriptionID: mustHaveEnvVar(t, "AZURE_SUBSCRIPTION_ID"), - ResourceGroupName: azure.TestResourceGroupName(), - VNetName: vpcName, - }, +func testAzurePeerConnection(t *testing.T, vpcName string) *akov2.AtlasNetworkPeeringConfig { + return &akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderAzure), + AzureConfiguration: &akov2.AzureNetworkPeeringConfiguration{ + AzureDirectoryID: mustHaveEnvVar(t, "AZURE_TENANT_ID"), + AzureSubscriptionID: mustHaveEnvVar(t, "AZURE_SUBSCRIPTION_ID"), + ResourceGroupName: azure.TestResourceGroupName(), + VNetName: vpcName, }, } } -func testGooglePeerConnection(t *testing.T, containerID string, vpcName string) *networkpeering.NetworkPeer { - return &networkpeering.NetworkPeer{ - AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ - Provider: "GCP", - ContainerID: containerID, - GCPConfiguration: &akov2.GCPNetworkPeeringConfiguration{ - GCPProjectID: mustHaveEnvVar(t, "GOOGLE_PROJECT_ID"), - NetworkName: vpcName, - }, +func testGooglePeerConnection(t *testing.T, vpcName string) *akov2.AtlasNetworkPeeringConfig { + return &akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderGCP), + GCPConfiguration: &akov2.GCPNetworkPeeringConfiguration{ + GCPProjectID: mustHaveEnvVar(t, "GOOGLE_PROJECT_ID"), + NetworkName: vpcName, }, } } diff --git a/test/e2e/network_peering_controller_test.go b/test/e2e/network_peering_controller_test.go index 2210abbf05..26e3fe64e9 100644 --- a/test/e2e/network_peering_controller_test.go +++ b/test/e2e/network_peering_controller_test.go @@ -13,7 +13,6 @@ import ( "github.com/mongodb/mongodb-atlas-kubernetes/v2/api" akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1" - "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/common" "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1/provider" "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/e2e/actions" "github.com/mongodb/mongodb-atlas-kubernetes/v2/test/helper/e2e/actions/cloud" @@ -35,12 +34,9 @@ func newRandomName(base string) string { return fmt.Sprintf("%s-%s", base, randomSuffix) } -type netPeerTestCase struct { - ProviderName provider.ProviderName - AWS *akov2.AWSNetworkPeeringConfiguration - Azure *akov2.AzureNetworkPeeringConfiguration - GCP *akov2.GCPNetworkPeeringConfiguration - Container akov2.AtlasProviderContainerConfig +type containerAndPeering struct { + container *akov2.AtlasNetworkContainer + peering *akov2.AtlasNetworkPeering } var _ = Describe("NetworkPeeringController", Label("networkpeering-controller"), func() { @@ -82,19 +78,30 @@ var _ = Describe("NetworkPeeringController", Label("networkpeering-controller"), 40000, []func(*model.TestDataProvider){}, ).WithProject(data.DefaultProject()), - []*akov2.AtlasNetworkPeering{ - newPeeringTestCase(netPeerTestCase{ - ProviderName: provider.ProviderAWS, - Container: akov2.AtlasProviderContainerConfig{ - ContainerRegion: "US_EAST_1", - AtlasCIDRBlock: "10.8.0.0/22", + []containerAndPeering{ + { + container: &akov2.AtlasNetworkContainer{ + Spec: akov2.AtlasNetworkContainerSpec{ + Provider: string(provider.ProviderAWS), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + Region: "US_EAST_1", + CIDRBlock: "10.8.0.0/22", + }, + }, }, - AWS: &akov2.AWSNetworkPeeringConfiguration{ - AccepterRegionName: "us-east-1", // AccepterRegionName uses AWS region names - AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), - RouteTableCIDRBlock: "10.0.0.0/24", + peering: &akov2.AtlasNetworkPeering{ + Spec: akov2.AtlasNetworkPeeringSpec{ + AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderAWS), + AWSConfiguration: &akov2.AWSNetworkPeeringConfiguration{ + AccepterRegionName: "us-east-1", // AccepterRegionName uses AWS region names + AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), + RouteTableCIDRBlock: "10.0.0.0/24", + }, + }, + }, }, - }), + }, }, ), Entry("Test[networkpeering-aws-2]: AWS Network Peering CR between different regions and without existent Atlas Container", @@ -105,19 +112,30 @@ var _ = Describe("NetworkPeeringController", Label("networkpeering-controller"), 40000, []func(*model.TestDataProvider){}, ).WithProject(data.DefaultProject()), - []*akov2.AtlasNetworkPeering{ - newPeeringTestCase(netPeerTestCase{ - ProviderName: provider.ProviderAWS, - Container: akov2.AtlasProviderContainerConfig{ - ContainerRegion: "US_EAST_1", - AtlasCIDRBlock: "10.8.0.0/22", + []containerAndPeering{ + { + container: &akov2.AtlasNetworkContainer{ + Spec: akov2.AtlasNetworkContainerSpec{ + Provider: string(provider.ProviderAWS), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + Region: "US_EAST_1", + CIDRBlock: "10.8.0.0/22", + }, + }, }, - AWS: &akov2.AWSNetworkPeeringConfiguration{ - AccepterRegionName: "eu-west-2", - AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), - RouteTableCIDRBlock: "10.0.0.0/24", + peering: &akov2.AtlasNetworkPeering{ + Spec: akov2.AtlasNetworkPeeringSpec{ + AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderAWS), + AWSConfiguration: &akov2.AWSNetworkPeeringConfiguration{ + AccepterRegionName: "eu-west-2", + AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), + RouteTableCIDRBlock: "10.0.0.0/24", + }, + }, + }, }, - }), + }, }, ), Entry("Test[networkpeering-aws-3]: AWS Network Peering CRs between different regions and without container region specified", @@ -128,30 +146,52 @@ var _ = Describe("NetworkPeeringController", Label("networkpeering-controller"), 40000, []func(*model.TestDataProvider){}, ).WithProject(data.DefaultProject()), - []*akov2.AtlasNetworkPeering{ - newPeeringTestCase(netPeerTestCase{ - ProviderName: provider.ProviderAWS, - Container: akov2.AtlasProviderContainerConfig{ - ContainerRegion: "US_EAST_1", - AtlasCIDRBlock: "10.8.0.0/22", + []containerAndPeering{ + { + container: &akov2.AtlasNetworkContainer{ + Spec: akov2.AtlasNetworkContainerSpec{ + Provider: string(provider.ProviderAWS), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + Region: "US_EAST_1", + CIDRBlock: "10.8.0.0/22", + }, + }, }, - AWS: &akov2.AWSNetworkPeeringConfiguration{ - AccepterRegionName: "eu-west-1", - AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), - RouteTableCIDRBlock: "192.168.0.0/16", + peering: &akov2.AtlasNetworkPeering{ + Spec: akov2.AtlasNetworkPeeringSpec{ + AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderAWS), + AWSConfiguration: &akov2.AWSNetworkPeeringConfiguration{ + AccepterRegionName: "eu-west-1", + AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), + RouteTableCIDRBlock: "192.168.0.0/16", + }, + }, + }, }, - }), - newPeeringTestCase(netPeerTestCase{ - ProviderName: provider.ProviderAWS, - Container: akov2.AtlasProviderContainerConfig{ - AtlasCIDRBlock: "10.8.0.0/22", + }, + { + container: &akov2.AtlasNetworkContainer{ + Spec: akov2.AtlasNetworkContainerSpec{ + Provider: string(provider.ProviderAWS), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + CIDRBlock: "10.8.0.0/22", + }, + }, }, - AWS: &akov2.AWSNetworkPeeringConfiguration{ - AccepterRegionName: "us-east-1", - AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), - RouteTableCIDRBlock: "10.0.0.0/24", + peering: &akov2.AtlasNetworkPeering{ + Spec: akov2.AtlasNetworkPeeringSpec{ + AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderAWS), + AWSConfiguration: &akov2.AWSNetworkPeeringConfiguration{ + AccepterRegionName: "us-east-1", + AWSAccountID: os.Getenv("AWS_ACCOUNT_ID"), + RouteTableCIDRBlock: "10.0.0.0/24", + }, + }, + }, }, - }), + }, }, ), Entry("Test[networkpeering-gcp-1]: GCP Network Peering CR", @@ -162,17 +202,28 @@ var _ = Describe("NetworkPeeringController", Label("networkpeering-controller"), 40000, []func(*model.TestDataProvider){}, ).WithProject(data.DefaultProject()), - []*akov2.AtlasNetworkPeering{ - newPeeringTestCase(netPeerTestCase{ - ProviderName: provider.ProviderGCP, - Container: akov2.AtlasProviderContainerConfig{ - AtlasCIDRBlock: "10.8.0.0/18", + []containerAndPeering{ + { + container: &akov2.AtlasNetworkContainer{ + Spec: akov2.AtlasNetworkContainerSpec{ + Provider: string(provider.ProviderGCP), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + CIDRBlock: "10.8.0.0/18", + }, + }, }, - GCP: &akov2.GCPNetworkPeeringConfiguration{ - GCPProjectID: cloud.GoogleProjectID, - NetworkName: newRandomName(GCPVPCName), + peering: &akov2.AtlasNetworkPeering{ + Spec: akov2.AtlasNetworkPeeringSpec{ + AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderGCP), + GCPConfiguration: &akov2.GCPNetworkPeeringConfiguration{ + GCPProjectID: cloud.GoogleProjectID, + NetworkName: newRandomName(GCPVPCName), + }, + }, + }, }, - }), + }, }, ), Entry("Test[networkpeering-azure-1]: User has project which was updated with Azure PrivateEndpoint", @@ -183,20 +234,31 @@ var _ = Describe("NetworkPeeringController", Label("networkpeering-controller"), 40000, []func(*model.TestDataProvider){}, ).WithProject(data.DefaultProject()), - []*akov2.AtlasNetworkPeering{ - newPeeringTestCase(netPeerTestCase{ - ProviderName: provider.ProviderAzure, - Container: akov2.AtlasProviderContainerConfig{ - AtlasCIDRBlock: "192.168.248.0/21", - ContainerRegion: "US_EAST_2", + []containerAndPeering{ + { + container: &akov2.AtlasNetworkContainer{ + Spec: akov2.AtlasNetworkContainerSpec{ + Provider: string(provider.ProviderAzure), + AtlasNetworkContainerConfig: akov2.AtlasNetworkContainerConfig{ + CIDRBlock: "192.168.248.0/21", + Region: "US_EAST_2", + }, + }, }, - Azure: &akov2.AzureNetworkPeeringConfiguration{ - AzureDirectoryID: os.Getenv(DirectoryID), - AzureSubscriptionID: os.Getenv(SubscriptionID), - ResourceGroupName: cloud.ResourceGroupName, - VNetName: newRandomName(AzureVPCName), + peering: &akov2.AtlasNetworkPeering{ + Spec: akov2.AtlasNetworkPeeringSpec{ + AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ + Provider: string(provider.ProviderAzure), + AzureConfiguration: &akov2.AzureNetworkPeeringConfiguration{ + AzureDirectoryID: os.Getenv(DirectoryID), + AzureSubscriptionID: os.Getenv(SubscriptionID), + ResourceGroupName: cloud.ResourceGroupName, + VNetName: newRandomName(AzureVPCName), + }, + }, + }, }, - }), + }, }, ), ) @@ -310,31 +372,6 @@ func EnsurePeersReadyToConnect(g Gomega, userData *model.TestDataProvider, peers return true } -func newPeeringTestCase(tc netPeerTestCase) *akov2.AtlasNetworkPeering { - np := &akov2.AtlasNetworkPeering{ - Spec: akov2.AtlasNetworkPeeringSpec{ - ProjectDualReference: akov2.ProjectDualReference{ - ProjectRef: &common.ResourceRefNamespaced{ - Name: data.ProjectName, - }, - }, - AtlasNetworkPeeringConfig: akov2.AtlasNetworkPeeringConfig{ - Provider: string(tc.ProviderName), - }, - AtlasProviderContainerConfig: tc.Container, - }, - } - switch tc.ProviderName { - case provider.ProviderAWS: - np.Spec.AWSConfiguration = tc.AWS - case provider.ProviderAzure: - np.Spec.AzureConfiguration = tc.Azure - case provider.ProviderGCP: - np.Spec.GCPConfiguration = tc.GCP - } - return np -} - func networkPeeringReady(peer *akov2.AtlasNetworkPeering) bool { for _, condition := range peer.Status.Conditions { GinkgoWriter.Printf("TODO: REMOVE LOG peer %s condition type=%s status=%s",