Skip to content

Commit

Permalink
feat: AWS RDS Support (#613)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjholm authored Jun 11, 2024
1 parent c6f17ec commit f4727d2
Show file tree
Hide file tree
Showing 39 changed files with 2,188 additions and 590 deletions.
2 changes: 2 additions & 0 deletions cloud/aws/cmd/runtime/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
sqs_service "github.com/nitrictech/nitric/cloud/aws/runtime/queue"
"github.com/nitrictech/nitric/cloud/aws/runtime/resource"
secrets_manager_secret_service "github.com/nitrictech/nitric/cloud/aws/runtime/secret"
sql_service "github.com/nitrictech/nitric/cloud/aws/runtime/sql"
s3_service "github.com/nitrictech/nitric/cloud/aws/runtime/storage"
sns_service "github.com/nitrictech/nitric/cloud/aws/runtime/topic"
"github.com/nitrictech/nitric/cloud/aws/runtime/websocket"
Expand Down Expand Up @@ -67,6 +68,7 @@ func main() {
membraneOpts.ResourcesPlugin = provider
membraneOpts.WebsocketPlugin, _ = websocket.NewAwsApiGatewayWebsocket(provider)
membraneOpts.QueuesPlugin, _ = sqs_service.New(provider)
membraneOpts.SqlPlugin = sql_service.NewRdsSqlService()

m, err := membrane.New(membraneOpts)
if err != nil {
Expand Down
84 changes: 60 additions & 24 deletions cloud/aws/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,24 @@ import (
"github.com/nitrictech/nitric/cloud/common/deploy/provider"
"github.com/nitrictech/nitric/cloud/common/deploy/pulumix"
"github.com/nitrictech/nitric/cloud/common/deploy/tags"
resourcespb "github.com/nitrictech/nitric/core/pkg/proto/resources/v1"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/apigatewayv2"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/dynamodb"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/ecr"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/iam"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/lambda"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/rds"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/resourcegroups"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/s3"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/secretsmanager"
"github.com/pulumi/pulumi-aws/sdk/v5/go/aws/sqs"
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/codebuild"
awsec2 "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ec2"
"github.com/pulumi/pulumi-awsx/sdk/go/awsx/ec2"
"github.com/pulumi/pulumi-random/sdk/v4/go/random"
"github.com/pulumi/pulumi/sdk/v3/go/auto"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/samber/lo"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
Expand All @@ -54,18 +60,29 @@ type NitricAwsPulumiProvider struct {
StackId string
AwsConfig *AwsConfig

EcrAuthToken *ecr.GetAuthorizationTokenResult
Lambdas map[string]*lambda.Function
LambdaRoles map[string]*iam.Role
HttpProxies map[string]*apigatewayv2.Api
Apis map[string]*apigatewayv2.Api
Secrets map[string]*secretsmanager.Secret
Buckets map[string]*s3.Bucket
BucketNotifications map[string]*s3.BucketNotification
Topics map[string]*topic
Queues map[string]*sqs.Queue
Websockets map[string]*apigatewayv2.Api
KeyValueStores map[string]*dynamodb.Table
Vpc *ec2.Vpc
VpcAzs []string
VpcSecurityGroup *awsec2.SecurityGroup
// A codebuild job for creating the requested databases for a single database cluster
DbMasterPassword *random.RandomPassword
CreateDatabaseProject *codebuild.Project
CodeBuildRole *iam.Role
// A map of unique image keys to database migration codebuild projects
DatabaseMigrationJobs map[string]*codebuild.Project
DatabaseCluster *rds.Cluster
RdsPrxoy *rds.Proxy
EcrAuthToken *ecr.GetAuthorizationTokenResult
Lambdas map[string]*lambda.Function
LambdaRoles map[string]*iam.Role
HttpProxies map[string]*apigatewayv2.Api
Apis map[string]*apigatewayv2.Api
Secrets map[string]*secretsmanager.Secret
Buckets map[string]*s3.Bucket
BucketNotifications map[string]*s3.BucketNotification
Topics map[string]*topic
Queues map[string]*sqs.Queue
Websockets map[string]*apigatewayv2.Api
KeyValueStores map[string]*dynamodb.Table

provider.NitricDefaultOrder

Expand Down Expand Up @@ -147,6 +164,24 @@ func (a *NitricAwsPulumiProvider) Pre(ctx *pulumi.Context, resources []*pulumix.
},
})

databases := lo.Filter(resources, func(item *pulumix.NitricPulumiResource[any], idx int) bool {
return item.Id.Type == resourcespb.ResourceType_SqlDatabase
})
// Create a shared database cluster if we have more than one database
if len(databases) > 0 {
// deploy a VPC and security groups for this database cluster
err := a.vpc(ctx)
if err != nil {
return err
}

// deploy the RDS cluster
err = a.rds(ctx)
if err != nil {
return err
}
}

return err
}

Expand Down Expand Up @@ -197,24 +232,25 @@ func (a *NitricAwsPulumiProvider) Result(ctx *pulumi.Context) (pulumi.StringOutp
}).(pulumi.StringOutput)

if !ok {
return pulumi.StringOutput{}, fmt.Errorf("Failed to generate pulumi output")
return pulumi.StringOutput{}, fmt.Errorf("failed to generate pulumi output")
}

return output, nil
}

func NewNitricAwsProvider() *NitricAwsPulumiProvider {
return &NitricAwsPulumiProvider{
Lambdas: make(map[string]*lambda.Function),
LambdaRoles: make(map[string]*iam.Role),
Apis: make(map[string]*apigatewayv2.Api),
HttpProxies: make(map[string]*apigatewayv2.Api),
Secrets: make(map[string]*secretsmanager.Secret),
Buckets: make(map[string]*s3.Bucket),
BucketNotifications: make(map[string]*s3.BucketNotification),
Websockets: make(map[string]*apigatewayv2.Api),
Topics: make(map[string]*topic),
Queues: make(map[string]*sqs.Queue),
KeyValueStores: make(map[string]*dynamodb.Table),
Lambdas: make(map[string]*lambda.Function),
LambdaRoles: make(map[string]*iam.Role),
Apis: make(map[string]*apigatewayv2.Api),
HttpProxies: make(map[string]*apigatewayv2.Api),
Secrets: make(map[string]*secretsmanager.Secret),
Buckets: make(map[string]*s3.Bucket),
BucketNotifications: make(map[string]*s3.BucketNotification),
Websockets: make(map[string]*apigatewayv2.Api),
Topics: make(map[string]*topic),
Queues: make(map[string]*sqs.Queue),
KeyValueStores: make(map[string]*dynamodb.Table),
DatabaseMigrationJobs: make(map[string]*codebuild.Project),
}
}
7 changes: 7 additions & 0 deletions cloud/aws/deploy/embeds/codebuild-create-db.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: 0.2
phases:
build:
commands:
- echo "Creating database ${DB_NAME}"
- export PGPASSWORD=${DB_MASTER_PASSWORD}
- psql -h ${DB_CLUSTER_ENDPOINT} -U ${DB_MASTER_USERNAME} -d nitric -c "CREATE DATABASE ${DB_NAME}" || echo "database ${DB_NAME} already exists"
6 changes: 6 additions & 0 deletions cloud/aws/deploy/embeds/codebuild-migrate-db.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 0.2
phases:
build:
commands:
- cd %s
- %s
35 changes: 35 additions & 0 deletions cloud/aws/deploy/embeds/codebuild.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2021 Nitric Technologies Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package embeds

import (
_ "embed"

"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

//go:embed codebuild-create-db.yaml
var codebuild_CreateDatabaseTemplate string

//go:embed codebuild-migrate-db.yaml
var codebuild_MigrateDatabaseTemplate string

func GetCodeBuildCreateDatabaseConfig() pulumi.StringInput {
return pulumi.String(codebuild_CreateDatabaseTemplate)
}

func GetCodeBuildMigrateDatabaseConfig(workdir string, cmd string) pulumi.StringInput {
return pulumi.Sprintf(codebuild_MigrateDatabaseTemplate, workdir, cmd)
}
18 changes: 18 additions & 0 deletions cloud/aws/deploy/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,31 @@ func (a *NitricAwsPulumiProvider) Service(ctx *pulumi.Context, parent pulumi.Res
envVars[k] = v
}

if a.DatabaseCluster != nil {
// Include the base database cluster URI for the runtime to resolve databases based on their name
envVars["NITRIC_DATABASE_BASE_URL"] = pulumi.Sprintf("postgres://%s:%s@%s:%s", "nitric", a.DbMasterPassword.Result,
a.DatabaseCluster.Endpoint, "5432")
}

var vpcConfig *awslambda.FunctionVpcConfigArgs = nil
if typeConfig.Lambda.Vpc != nil {
if a.Vpc != nil {
return fmt.Errorf("this stack has configuration that requires its own VPC configuration and cannot accept custom lambda VPC configurations")
}

vpcConfig = &awslambda.FunctionVpcConfigArgs{
SubnetIds: pulumi.ToStringArray(typeConfig.Lambda.Vpc.SubnetIds),
SecurityGroupIds: pulumi.ToStringArray(typeConfig.Lambda.Vpc.SecurityGroupIds),
}
} else if a.Vpc != nil {
vpcConfig = &awslambda.FunctionVpcConfigArgs{
SubnetIds: a.Vpc.PrivateSubnetIds,
SecurityGroupIds: pulumi.StringArray{a.VpcSecurityGroup.ID()},
// VpcId: a.Vpc.VpcId,
}
}

if vpcConfig != nil {
// Create a policy attachment for VPC access
_, err = iam.NewRolePolicyAttachment(ctx, name+"VPCAccessExecutionRole", &iam.RolePolicyAttachmentArgs{
PolicyArn: iam.ManagedPolicyAWSLambdaVPCAccessExecutionRole,
Expand Down
Loading

0 comments on commit f4727d2

Please sign in to comment.