Skip to content

Commit

Permalink
feat: AWS Terraform Provider (#619)
Browse files Browse the repository at this point in the history
Co-authored-by: Ryan Cartwright <[email protected]>
Co-authored-by: Jye Cusch <[email protected]>
  • Loading branch information
3 people authored Jun 5, 2024
1 parent f74db93 commit 39315ef
Show file tree
Hide file tree
Showing 177 changed files with 12,695 additions and 123 deletions.
2 changes: 2 additions & 0 deletions cloud/aws/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
dist/
deploy/runtime-aws
deploytf/runtime/runtime-aws
common/runtime/runtime-aws
4 changes: 3 additions & 1 deletion cloud/aws/.golangci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
run:
timeout: "5m"
skip-files:
- tools/tools.go
- tools/tools.go
go: 1.18

linters:
Expand All @@ -23,6 +23,8 @@ linters:
issues:
max-issues-per-linter: 0
max-same-issues: 0
exclude-dirs:
- deploytf/generated

linters-settings:
govet:
Expand Down
30 changes: 27 additions & 3 deletions cloud/aws/.goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ before:
- go work sync
- make predeploybin
builds:
- env:
# - GOWORK=on
- id: aws
env:
- CGO_ENABLED=0
id: aws
binary: aws
main: ./cmd/deploy
goos:
Expand All @@ -20,13 +19,38 @@ builds:
goarch:
- amd64
- arm64
- id: awstf
env:
- CGO_ENABLED=0
binary: aws
main: ./cmd/deploytf
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
archives:
- name_template: >-
{{ .ProjectName }}_
{{- tolower .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ tolower .Arch }}{{ end }}
builds:
- aws
format_overrides:
- goos: windows
format: zip
- name_template: >-
{{ .ProjectName }}tf_
{{- tolower .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ tolower .Arch }}{{ end }}
builds:
- awstf
format_overrides:
- goos: windows
format: zip
Expand Down
35 changes: 23 additions & 12 deletions cloud/aws/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,39 @@ GOLANGCI_LINT ?= GOLANGCI_LINT_CACHE=$(GOLANGCI_LINT_CACHE) go run github.com/go
binaries: deploybin

sec:
@touch deploy/runtime/runtime-aws
@touch common/runtime/runtime-aws
@go run github.com/securego/gosec/v2/cmd/gosec@latest -exclude-dir=tools ./...
@rm deploy/runtime/runtime-aws
@rm common/runtime/runtime-aws

# build runtime binary directly into the deploy director so it can be embedded directly into the deployment engine binary
# We only build a linux amd64 binary here to be packaged for cloud runtimes with docker
# More binaries can be distributed in future if required
.PHONY: runtimebin
runtimebin:
@echo Building AWS Runtime Server
@CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/runtime-aws -ldflags="-s -w -extldflags=-static" ./cmd/runtime

.PHONY: predeploybin
predeploybin: runtimebin
@cp bin/runtime-aws deploy/runtime/runtime-aws
@cp bin/runtime-aws common/runtime/runtime-aws

deploybin: predeploybin
@echo Building AWS Deployment Server
@CGO_ENABLED=0 go build -o bin/deploy-aws -ldflags="-s -w -extldflags=-static" -ldflags="-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=ignore" ./cmd/deploy
@rm deploy/runtime/runtime-aws

deploybintf: generate-terraform predeploybin
@echo Building AWS Terraform Deployment Server
@CGO_ENABLED=0 go build -o bin/deploy-awstf -ldflags="-s -w -extldflags=-static" -ldflags="-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=ignore" ./cmd/deploytf

.PHONY: install
install: deploybin
@echo installing aws deployment server to ${HOME}/.nitric/providers/nitric/aws-0.0.1
install: deploybin deploybintf
@mkdir -p ${HOME}/.nitric/providers/nitric/
@rm -f ${HOME}/.nitric/providers/nitric/aws-0.0.1
@echo installing aws deployment server to ${HOME}/.nitric/providers/nitric/aws-0.0.1
@cp bin/deploy-aws ${HOME}/.nitric/providers/nitric/aws-0.0.1
@echo installing aws terraform deployment server to ${HOME}/.nitric/providers/nitric/awstf-0.0.1
@cp bin/deploy-awstf ${HOME}/.nitric/providers/nitric/awstf-0.0.1


license-check: runtimebin
@echo Checking AWS Membrane OSS Licenses
Expand All @@ -41,16 +49,16 @@ license-check: runtimebin
sourcefiles := $(shell find . -type f -name "*.go" -o -name "*.dockerfile")

fmt:
@go run github.com/google/addlicense -c "Nitric Technologies Pty Ltd." -y "2021" $(sourcefiles)
@touch deploy/runtime/runtime-aws
@go run github.com/google/addlicense -ignore "./deploytf/generated/**" -c "Nitric Technologies Pty Ltd." -y "2021" $(sourcefiles)
@touch common/runtime/runtime-aws
$(GOLANGCI_LINT) run --fix
@rm deploy/runtime/runtime-aws
@rm common/runtime/runtime-aws

lint:
@go run github.com/google/addlicense -check -c "Nitric Technologies Pty Ltd." -y "2021" $(sourcefiles)
@touch deploy/runtime/runtime-aws
@go run github.com/google/addlicense -ignore "./deploytf/generated/**" -check -c "Nitric Technologies Pty Ltd." -y "2021" $(sourcefiles)
@touch common/runtime/runtime-aws
$(GOLANGCI_LINT) run
@rm deploy/runtime/runtime-aws
@rm common/runtime/runtime-aws

test: generate-mocks
@echo Running unit tests
Expand Down Expand Up @@ -81,4 +89,7 @@ generate-mocks: clean-mocks
@go run github.com/golang/mock/mockgen github.com/nitrictech/nitric/cloud/aws/ifaces/sqsiface SQSAPI > mocks/sqs/mock.go
@go run github.com/golang/mock/mockgen github.com/nitrictech/nitric/cloud/aws/runtime/resource AwsResourceProvider > mocks/provider/aws.go

generate-terraform:
@cd deploytf && cdktf get

generate-sources: generate-mocks
2 changes: 1 addition & 1 deletion cloud/aws/cmd/deploy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
package main

import (
"github.com/nitrictech/nitric/cloud/aws/common/runtime"
"github.com/nitrictech/nitric/cloud/aws/deploy"
"github.com/nitrictech/nitric/cloud/aws/deploy/runtime"
"github.com/nitrictech/nitric/cloud/common/deploy/provider"
)

Expand Down
35 changes: 35 additions & 0 deletions cloud/aws/cmd/deploytf/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright Nitric Pty Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 main

import (
"github.com/nitrictech/nitric/cloud/aws/common/runtime"
"github.com/nitrictech/nitric/cloud/aws/deploytf"
"github.com/nitrictech/nitric/cloud/common/deploy/provider"
)

// Start the deployment server
func main() {
// os.Setenv("JSII_SILENCE_WARNING_UNTESTED_NODE_VERSION", "true")
// os.Setenv("SYNTH_HCL_OUTPUT", "true")
awsStack := deploytf.NewNitricAwsProvider()

providerServer := provider.NewTerraformProviderServer(awsStack, runtime.NitricAwsRuntime)

// Start the terraform provider server
providerServer.Start()
}
123 changes: 123 additions & 0 deletions cloud/aws/common/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright Nitric Pty Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 common

import (
"github.com/imdario/mergo"
"github.com/mitchellh/mapstructure"
"github.com/nitrictech/nitric/cloud/common/deploy/config"
)

type ApiConfig struct {
Domains []string
}

type AwsImports struct {
// A map of nitric names to ARNs
Secrets map[string]string
}

type AwsConfig struct {
ScheduleTimezone string `mapstructure:"schedule-timezone,omitempty"`
Import AwsImports
Refresh bool
Apis map[string]*ApiConfig
config.AbstractConfig[*AwsConfigItem] `mapstructure:"config,squash"`
}

type AwsConfigItem struct {
Lambda *AwsLambdaConfig `mapstructure:",omitempty"`
Telemetry int
}

type AwsLambdaVpcConfig struct {
SubnetIds []string `mapstructure:"subnet-ids"`
SecurityGroupIds []string `mapstructure:"security-group-ids"`
}

type AwsLambdaConfig struct {
Memory int
Timeout int
ProvisionedConcurreny int `mapstructure:"provisioned-concurrency"`
Vpc *AwsLambdaVpcConfig `mapstructure:"vpc,omitempty"`
}

var defaultLambdaConfig = &AwsLambdaConfig{
Memory: 128,
Timeout: 15,
ProvisionedConcurreny: 0,
}

var defaultAwsConfigItem = AwsConfigItem{
Telemetry: 0,
}

// Return AwsConfig from stack attributes
func ConfigFromAttributes(attributes map[string]interface{}) (*AwsConfig, error) {
// get config attributes
err := config.ValidateRawConfigKeys(attributes, []string{"lambda"})
if err != nil {
return nil, err
}

awsConfig := &AwsConfig{}
err = mapstructure.Decode(attributes, awsConfig)
if err != nil {
return nil, err
}

// Default timezone if not specified
if awsConfig.ScheduleTimezone == "" {
// default to UTC
awsConfig.ScheduleTimezone = "UTC"
}

if awsConfig.Apis == nil {
awsConfig.Apis = map[string]*ApiConfig{}
}

if awsConfig.Config == nil {
awsConfig.Config = map[string]*AwsConfigItem{}
}

// if no default then set provider level defaults
if _, hasDefault := awsConfig.Config["default"]; !hasDefault {
awsConfig.Config["default"] = &defaultAwsConfigItem
awsConfig.Config["default"].Lambda = defaultLambdaConfig
}

for configName, configVal := range awsConfig.Config {
// Add omitted values from default configs where needed.
err := mergo.Merge(configVal, defaultAwsConfigItem)
if err != nil {
return nil, err
}

if configVal.Lambda == nil { // check if no runtime config provided, default to Lambda.
configVal.Lambda = defaultLambdaConfig
} else {
err := mergo.Merge(configVal.Lambda, defaultLambdaConfig)
if err != nil {
return nil, err
}
}

awsConfig.Config[configName] = configVal
}

return awsConfig, nil
}
File renamed without changes.
5 changes: 5 additions & 0 deletions cloud/aws/deploy/embeds/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package embeds

import (
_ "embed"
"fmt"

"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
Expand All @@ -40,3 +41,7 @@ var schedule_InputTemplate string
func GetScheduleInputDocument(scheduleName pulumi.StringInput) pulumi.StringOutput {
return pulumi.Sprintf(schedule_InputTemplate, scheduleName)
}

func GetScheduleInputDocumentString(scheduleName string) string {
return fmt.Sprintf(schedule_InputTemplate, scheduleName)
}
41 changes: 41 additions & 0 deletions cloud/aws/deploytf/.nitric/modules/api/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
resource "aws_apigatewayv2_api" "api_gateway" {
name = var.name
protocol_type = "HTTP"
body = var.spec
tags = {
"x-nitric-${var.stack_id}-name" = var.name,
"x-nitric-${var.stack_id}-type" = "api",
}
}

resource "aws_apigatewayv2_stage" "stage" {
api_id = aws_apigatewayv2_api.api_gateway.id
name = "$default"
auto_deploy = true
}

# deploy lambda permissions for execution
resource "aws_lambda_permission" "apigw_lambda" {
for_each = var.target_lambda_functions
action = "lambda:InvokeFunction"
function_name = each.value
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.api_gateway.execution_arn}/*/*/*"
}

# look up existing certificate for domains
data "aws_acm_certificate" "cert" {
for_each = var.domains
domain = each.value
}

# deploy custom domain names
resource "aws_apigatewayv2_domain_name" "domain" {
for_each = var.domains
domain_name = each.value
domain_name_configuration {
certificate_arn = data.aws_acm_certificate.cert[each.key].arn
endpoint_type = "REGIONAL"
security_policy = "TLS_1_2"
}
}
3 changes: 3 additions & 0 deletions cloud/aws/deploytf/.nitric/modules/api/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "endpoint" {
value = aws_apigatewayv2_api.api_gateway.api_endpoint
}
Loading

0 comments on commit 39315ef

Please sign in to comment.