Skip to content

Commit

Permalink
Add network peering contract tests
Browse files Browse the repository at this point in the history
Signed-off-by: jose.vazquez <[email protected]>
  • Loading branch information
josvazg committed Nov 12, 2024
1 parent 41fd4b1 commit 863fb09
Show file tree
Hide file tree
Showing 5 changed files with 529 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/test-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,14 @@ jobs:
MCLI_ORG_ID: ${{ secrets.ATLAS_ORG_ID }}
MCLI_PUBLIC_API_KEY: ${{ secrets.ATLAS_PUBLIC_KEY }}
MCLI_PRIVATE_API_KEY: ${{ secrets.ATLAS_PRIVATE_KEY }}
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets. AZURE_CLIENT_SECRET }}
GOOGLE_PROJECT_ID: ${{ secrets.GOOGLE_PROJECT_ID }}
GCP_SA_CRED: ${{ secrets.GCP_SA_CRED}}
USE_KIND: "false" # Avoid launching a kind cluster yet again
run: devbox run -- 'make contract-tests'
68 changes: 68 additions & 0 deletions test/contract/networkpeering/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package networkpeering

import (
"fmt"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
)

func createAWSTestVPC(name, cidr, region string) (string, error) {
awsSession, err := newAWSSession(region)
if err != nil {
return "", fmt.Errorf("failed to create an AWS session: %w", err)
}
ec2Client := ec2.New(awsSession)
result, err := ec2Client.CreateVpc(&ec2.CreateVpcInput{
AmazonProvidedIpv6CidrBlock: aws.Bool(false),
CidrBlock: aws.String(cidr),
TagSpecifications: []*ec2.TagSpecification{{
ResourceType: aws.String(ec2.ResourceTypeVpc),
Tags: []*ec2.Tag{
{Key: aws.String("Name"), Value: aws.String(name)},
},
}},
})
if err != nil {
return "", fmt.Errorf("failed to create an AWS VPC: %w", err)
}

_, err = ec2Client.ModifyVpcAttribute(&ec2.ModifyVpcAttributeInput{
EnableDnsHostnames: &ec2.AttributeBooleanValue{
Value: aws.Bool(true),
},
VpcId: result.Vpc.VpcId,
})
if err != nil {
return "", fmt.Errorf("failed to configure AWS VPC: %w", err)
}

return *result.Vpc.VpcId, nil
}

func deleteAWSTestVPC(vpcID, region string) error {
awsSession, err := newAWSSession(region)
if err != nil {
return fmt.Errorf("failed to create an AWS session: %w", err)
}
ec2Client := ec2.New(awsSession)
_, err = ec2Client.DeleteVpc(&ec2.DeleteVpcInput{
DryRun: aws.Bool(false),
VpcId: aws.String(vpcID),
})
return err
}

func newAWSSession(region string) (*session.Session, error) {
awsSession, err := session.NewSession(aws.NewConfig().WithRegion(region))
if err != nil {
return nil, err
}
return awsSession, nil
}

func awsRegionCode(region string) string {
return strings.ReplaceAll(strings.ToLower(region), "_", "-")
}
117 changes: 117 additions & 0 deletions test/contract/networkpeering/azure.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package networkpeering

import (
"context"
"errors"
"fmt"
"os"

"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2"

"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/pointer"
)

const (
azureTestResourceGroupName = "svet-test"
)

type azureConnection struct {
resourceGroupName string
credentials *azidentity.DefaultAzureCredential
networkResourceFactory *armnetwork.ClientFactory
}

func createAzureTestVpc(ctx context.Context, vpcName, cidr, region string) (string, error) {
azr, err := newAzureClient(azureTestResourceGroupName)
if err != nil {
return "", fmt.Errorf("failed to create azure client: %w", err)
}
vpcClient := azr.networkResourceFactory.NewVirtualNetworksClient()

op, err := vpcClient.BeginCreateOrUpdate(
ctx,
azr.resourceGroupName,
vpcName,
armnetwork.VirtualNetwork{
Location: pointer.MakePtr(region),
Properties: &armnetwork.VirtualNetworkPropertiesFormat{
AddressSpace: &armnetwork.AddressSpace{
AddressPrefixes: []*string{
pointer.MakePtr(cidr),
},
},
},
Tags: map[string]*string{
"Name": pointer.MakePtr(vpcName),
},
},
nil,
)
if err != nil {
return "", fmt.Errorf("failed to begin create azure VPC: %w", err)
}

vpc, err := op.PollUntilDone(ctx, nil)
if err != nil {
return "", fmt.Errorf("creation process of VPC failed: %w", err)
}
if vpc.Name == nil {
return "", errors.New("VPC created without a name")
}
return *vpc.Name, nil
}

func deleteAzureTestVpc(ctx context.Context, vpcName string) error {
azr, err := newAzureClient(azureTestResourceGroupName)
if err != nil {
return fmt.Errorf("failed to create azure client: %w", err)
}
vpcClient := azr.networkResourceFactory.NewVirtualNetworksClient()

op, err := vpcClient.BeginDelete(
ctx,
azr.resourceGroupName,
vpcName,
nil,
)
if err != nil {
return err
}

_, err = op.PollUntilDone(ctx, nil)

return err
}

func newAzureClient(resourceGroupName string) (*azureConnection, error) {
subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID")
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
return nil, err
}

networkFactory, err := armnetwork.NewClientFactory(subscriptionID, cred, nil)
if err != nil {
return nil, err
}

return &azureConnection{
resourceGroupName: resourceGroupName,
networkResourceFactory: networkFactory,
credentials: cred,
}, err
}

func azureRegionCode(region string) string {
region2azure := map[string]string{
"US_CENTRAL": "us_central",
"US_EAST": "eastus",
"US_EAST_2": "eastus2",
}
azureRegion, ok := region2azure[region]
if !ok {
return fmt.Sprintf("unsupported region %q", region)
}
return azureRegion
}
98 changes: 98 additions & 0 deletions test/contract/networkpeering/google.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package networkpeering

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"

compute "cloud.google.com/go/compute/apiv1"
"cloud.google.com/go/compute/apiv1/computepb"

"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/pointer"
)

type googleConnection struct {
projectID string

networkClient *compute.NetworksClient
}

func createGoogleTestVPC(ctx context.Context, vpcName string) error {
gce, err := newGoogleConnection(ctx, os.Getenv("GOOGLE_PROJECT_ID"))
if err != nil {
return fmt.Errorf("failed to get Google Cloud connection: %w", err)
}

op, err := gce.networkClient.Insert(ctx, &computepb.InsertNetworkRequest{
Project: gce.projectID,
NetworkResource: &computepb.Network{
Name: pointer.MakePtr(vpcName),
Description: pointer.MakePtr("Atlas Kubernetes Operator E2E Tests VPC"),
AutoCreateSubnetworks: pointer.MakePtr(false),
},
})
if err != nil {
return fmt.Errorf("failed to request creation of Google VPC: %w", err)
}

err = op.Wait(ctx)
if err != nil {
return fmt.Errorf("failed to create Google VPC: %w", err)
}

return nil
}

func deleteGoogleTestVPC(ctx context.Context, vpcName string) error {
gce, err := newGoogleConnection(ctx, os.Getenv("GOOGLE_PROJECT_ID"))
if err != nil {
return fmt.Errorf("failed to get Google Cloud connection: %w", err)
}
op, err := gce.networkClient.Delete(ctx, &computepb.DeleteNetworkRequest{
Project: gce.projectID,
Network: vpcName,
})
if err != nil {
return fmt.Errorf("failed to request deletion of Google VPC: %w", err)
}
err = op.Wait(ctx)
if err != nil {
return fmt.Errorf("failed to delete Google VPC: %w", err)
}

return nil
}

func newGoogleConnection(ctx context.Context, projectID string) (*googleConnection, error) {
if err := ensureCredentials(); err != nil {
return nil, fmt.Errorf("failed to prepare credentials")
}

networkClient, err := compute.NewNetworksRESTClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to setup network rest client")
}

return &googleConnection{
projectID: projectID,
networkClient: networkClient,
}, nil
}

func ensureCredentials() error {
if os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") != "" {
return nil
}
credsFilename := os.Getenv("GCP_SA_CRED")
if credsFilename == "" {
return errors.New("GOOGLE_APPLICATION_CREDENTIALS and GCP_SA_CRED are unset, cant setup Google credentials")
}
credsContents, err := os.ReadFile(filepath.Clean(credsFilename))
if err != nil {
return fmt.Errorf("failed to read credentials from filename %s pointed by GCP_SA_CRED: %w", credsFilename, err)
}
os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", string(credsContents))
return nil
}
Loading

0 comments on commit 863fb09

Please sign in to comment.