Skip to content

Commit

Permalink
fix(addon): Use default "All" mapping in aurora addons (#2357)
Browse files Browse the repository at this point in the history
* fix: add default mapping and integ tests for addons

* chore: remove hardcoded All, move comment

* chore: fix bad whitespace stripper

* chore: make integ-test essential for mergify

* chore: fix bad capitalization

* chore: go mod tidy
  • Loading branch information
bvtujo authored May 20, 2021
1 parent f004964 commit c8aa605
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .mergify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pull_request_rules:
- status-success=build (compile-windows)
- status-success=build (compile-darwin)
- status-success=test
- status-success=integ-test
- status-success=staticcheck
- status-success=license
- status-success=Semantic Pull Request
Expand All @@ -30,6 +31,7 @@ pull_request_rules:
- status-success=build (compile-windows)
- status-success=build (compile-darwin)
- status-success=test
- status-success=integ-test
- status-success=staticcheck
- status-success=license
- status-success=Semantic Pull Request
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
code.gitea.io/sdk/gitea v0.12.0 h1:hvDCz4wtFvo7rf5Ebj8tGd4aJ4wLPKX3BKFX9Dk1Pgs=
code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrLVhN+qmP8BTVvdH2YLs7Gl0=
Expand Down Expand Up @@ -505,6 +506,7 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
Expand Down
95 changes: 95 additions & 0 deletions internal/pkg/addon/addon_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// +build integration localintegration

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package addon_test

import (
"encoding"
"fmt"
"io/ioutil"
"path/filepath"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/copilot-cli/internal/pkg/addon"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)

func TestAddons(t *testing.T) {
testCases := map[string]struct {
addonMarshaler encoding.BinaryMarshaler
outFileName string
}{
"aurora": {
addonMarshaler: addon.NewRDS(addon.RDSProps{
ClusterName: "aurora",
Engine: "MySQL",
InitialDBName: "main",
Envs: []string{"test"},
}),
outFileName: "aurora.yml",
},
"ddb": {
addonMarshaler: addon.NewDynamoDB(&addon.DynamoDBProps{
StorageProps: &addon.StorageProps{
Name: "ddb",
},
Attributes: []addon.DDBAttribute{
{
Name: aws.String("primary"),
DataType: aws.String("S"),
},
{
Name: aws.String("sort"),
DataType: aws.String("N"),
},
{
Name: aws.String("othersort"),
DataType: aws.String("B"),
},
},
SortKey: aws.String("sort"),
PartitionKey: aws.String("primary"),
LSIs: []addon.DDBLocalSecondaryIndex{
{
Name: aws.String("othersort"),
PartitionKey: aws.String("primary"),
SortKey: aws.String("othersort"),
},
},
HasLSI: true,
}),
outFileName: "ddb.yml",
},
"s3": {
addonMarshaler: addon.NewS3(&addon.S3Props{
StorageProps: &addon.StorageProps{
Name: "bucket",
},
}),
outFileName: "bucket.yml",
},
}

for name, tc := range testCases {
testName := fmt.Sprintf("CF Template should be equal/%s", name)
t.Run(testName, func(t *testing.T) {

actualBytes, err := tc.addonMarshaler.MarshalBinary()
require.NoError(t, err, "cf should render")

cfActual := make(map[interface{}]interface{})
require.NoError(t, yaml.Unmarshal(actualBytes, cfActual))

expected, err := ioutil.ReadFile(filepath.Join("testdata", "storage", tc.outFileName))
require.NoError(t, err, "should be able to read expected bytes")
expectedBytes := []byte(expected)
mExpected := make(map[interface{}]interface{})
require.NoError(t, yaml.Unmarshal(expectedBytes, mExpected))
require.Equal(t, mExpected, cfActual)
})
}
}
120 changes: 120 additions & 0 deletions internal/pkg/addon/testdata/storage/aurora.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
Parameters:
App:
Type: String
Description: Your application's name.
Env:
Type: String
Description: The environment name your service, job, or workflow is being deployed to.
Name:
Type: String
Description: The name of the service, job, or workflow being deployed.
# Customize your Aurora Serverless cluster by setting the default value of the following parameters.
auroraDBName:
Type: String
Description: The name of the initial database to be created in the DB cluster.
Default: main
# Cannot have special characters
# Naming constraints: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints
auroraDBAutoPauseSeconds:
Type: Number
Description: The duration in seconds before the cluster pauses.
Default: 1000
Mappings:
auroraEnvScalingConfigurationMap:
test:
"DBMinCapacity": 1 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
"DBMaxCapacity": 8 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
All:
"DBMinCapacity": 1 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
"DBMaxCapacity": 8 # AllowedValues: [1, 2, 4, 8, 16, 32, 64, 128, 256]
Resources:
auroraDBSubnetGroup:
Type: 'AWS::RDS::DBSubnetGroup'
Properties:
DBSubnetGroupDescription: Group of Copilot private subnets for Aurora cluster.
SubnetIds:
!Split [',', { 'Fn::ImportValue': !Sub '${App}-${Env}-PrivateSubnets' }]
auroraSecurityGroup:
Metadata:
'aws:copilot:description': 'A security group for your workload to access the DB cluster aurora'
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: !Sub 'The Security Group for ${Name} to access DB cluster aurora.'
VpcId:
Fn::ImportValue:
!Sub '${App}-${Env}-VpcId'
Tags:
- Key: Name
Value: !Sub 'copilot-${App}-${Env}-${Name}-Aurora'
auroraDBClusterSecurityGroup:
Metadata:
"aws:copilot:description": A security group for your DB cluster aurora
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: The Security Group for the database cluster.
SecurityGroupIngress:
- ToPort: 3306
FromPort: 3306
IpProtocol: tcp
Description: !Sub 'From the Aurora Security Group of the workload ${Name}.'
SourceSecurityGroupId: !Ref auroraSecurityGroup
VpcId:
Fn::ImportValue:
!Sub '${App}-${Env}-VpcId'
auroraAuroraSecret:
Metadata:
'aws:copilot:description': A Secrets Manager secret to store your DB credentials
Type: AWS::SecretsManager::Secret
Properties:
Description: !Sub Aurora main user secret for ${AWS::StackName}
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: "password"
ExcludePunctuation: true
IncludeSpace: false
PasswordLength: 16
auroraDBClusterParameterGroup:
Metadata:
'aws:copilot:description': A DB parameter group for engine configuration values
Type: 'AWS::RDS::DBClusterParameterGroup'
Properties:
Description: !Ref 'AWS::StackName'
Family: 'aurora-mysql5.7'
Parameters:
character_set_client: 'utf8'
auroraDBCluster:
Metadata:
'aws:copilot:description': The aurora Aurora Serverless database cluster
Type: 'AWS::RDS::DBCluster'
Properties:
MasterUsername:
!Join [ "", [ '{{resolve:secretsmanager:', !Ref auroraAuroraSecret, ":SecretString:username}}" ]]
MasterUserPassword:
!Join [ "", [ '{{resolve:secretsmanager:', !Ref auroraAuroraSecret, ":SecretString:password}}" ]]
DatabaseName: !Ref auroraDBName
Engine: 'aurora-mysql'
EngineVersion: '5.7.mysql_aurora.2.07.1'
EngineMode: serverless
DBClusterParameterGroupName: !Ref auroraDBClusterParameterGroup
DBSubnetGroupName: !Ref auroraDBSubnetGroup
VpcSecurityGroupIds:
- !Ref auroraDBClusterSecurityGroup
ScalingConfiguration:
AutoPause: true
MinCapacity: !FindInMap [auroraEnvScalingConfigurationMap, All, DBMinCapacity]
MaxCapacity: !FindInMap [auroraEnvScalingConfigurationMap, All, DBMaxCapacity]
SecondsUntilAutoPause: !Ref auroraDBAutoPauseSeconds
auroraSecretAuroraClusterAttachment:
Type: AWS::SecretsManager::SecretTargetAttachment
Properties:
SecretId: !Ref auroraAuroraSecret
TargetId: !Ref auroraDBCluster
TargetType: AWS::RDS::DBCluster
Outputs:
auroraSecret: # injected as AURORA_SECRET environment variable by Copilot.
Description: "The JSON secret that holds the database username and password. Fields are 'host', 'port', 'dbname', 'username', 'password', 'dbClusterIdentifier' and 'engine'"
Value: !Ref auroraAuroraSecret
auroraSecurityGroup:
Description: "The security group to attach to the workload."
Value: !Ref auroraSecurityGroup

80 changes: 80 additions & 0 deletions internal/pkg/addon/testdata/storage/bucket.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
Parameters:
App:
Type: String
Description: Your application's name.
Env:
Type: String
Description: The environment name your service, job, or workflow is being deployed to.
Name:
Type: String
Description: The name of the service, job, or workflow being deployed.
Resources:
bucket:
Metadata:
'aws:copilot:description': 'An Amazon S3 bucket to store and retrieve objects for bucket'
Type: AWS::S3::Bucket
Properties:
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub '${App}-${Env}-${Name}-bucket'
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true

bucketBucketPolicy:
Metadata:
'aws:copilot:description': 'A bucket policy to deny unencrypted access to the bucket and its contents'
Type: AWS::S3::BucketPolicy
DeletionPolicy: Retain
Properties:
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: ForceHTTPS
Effect: Deny
Principal: '*'
Action: 's3:*'
Resource:
- !Sub ${ bucket.Arn}/*
- !Sub ${ bucket.Arn}
Condition:
Bool:
"aws:SecureTransport": false
Bucket: !Ref bucket

bucketAccessPolicy:
Metadata:
'aws:copilot:description': 'An IAM ManagedPolicy for your service to access the bucket bucket'
Type: AWS::IAM::ManagedPolicy
Properties:
Description: !Sub
- Grants CRUD access to the S3 bucket ${Bucket}
- { Bucket: !Ref bucket }
PolicyDocument:
Version: 2012-10-17
Statement:
- Sid: S3ObjectActions
Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
- s3:PutObjectACL
- s3:PutObjectTagging
- s3:DeleteObject
- s3:RestoreObject
Resource: !Sub ${ bucket.Arn}/*
- Sid: S3ListAction
Effect: Allow
Action: s3:ListBucket
Resource: !Sub ${ bucket.Arn}

Outputs:
bucketName:
Description: "The name of a user-defined bucket."
Value: !Ref bucket
bucketAccessPolicy:
Description: "The IAM::ManagedPolicy to attach to the task role"
Value: !Ref bucketAccessPolicy
Loading

0 comments on commit c8aa605

Please sign in to comment.