diff --git a/README.md b/README.md index 32f526316..bb97d63b7 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ The application starts at `cmd/generate.go` 4. each generator (`react/generate.go`, `ci/generate.go` etc) further delegates and actually executes the templating based on the configs passed in. - `internal/templator/templator.go` is the base class and includes generic templating handling logic - it CI is required, it'll also call a CI generator and pass in the service specific CI configs + - TOOD: CI templates have to call separate templates based on the context - TODO: templator should be generic and not have any knowledge of the specific templating implementation (go, ci etc), move that logic upstream 5. Depending on the config (`deploy == true` for certain) it'll also run the `Execute` function and actually deploy the infrastructure diff --git a/cmd/generate.go b/cmd/generate.go index e1bb34a59..f16589181 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -71,11 +71,8 @@ var generateCmd = &cobra.Command{ kubernetes.Generate(t, cfg, &wg) } - // TODO we'll need to completely revamp the templating system eventually - if cfg.Infrastructure.AWS.Cognito.Deploy == true { - log.Println(aurora.Cyan(emoji.Sprintf("Generating Terraform"))) - terraform.Generate(t, cfg, &wg) - } + log.Println(aurora.Cyan(emoji.Sprintf("Generating Terraform"))) + terraform.Generate(t, cfg, &wg) // @TODO : This strucuture probably needs to be adjusted. Probably too generic. switch cfg.Frontend.Framework { diff --git a/internal/config/config.go b/internal/config/config.go index e309b35db..259aca533 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -77,7 +77,12 @@ type aws struct { AccountId string `yaml:"accountId"` Region string EKS eks - Cognito cognito + Cognito bool + Terraform terraform +} + +type terraform struct { + RemoteState bool } type eks struct { @@ -85,10 +90,6 @@ type eks struct { Deploy bool } -type cognito struct { - Deploy bool -} - func LoadConfig(filePath string) *Commit0Config { config := &Commit0Config{} data, err := ioutil.ReadFile(filePath) diff --git a/internal/generate/ci/generate.go b/internal/generate/ci/generate.go index bc0a44ddf..8c6758edf 100644 --- a/internal/generate/ci/generate.go +++ b/internal/generate/ci/generate.go @@ -26,7 +26,7 @@ func (e *CIGenerationError) Error() string { return fmt.Sprintf("Error: %s. Unable to Generate CI/CD Pipeline with config:\n%v\n", e.err, e.config) } -// TODO shouldn't have to pass in both ciConfig, should be able to +// TODO shouldn't have to pass in both ciConfig, and cfg, it's redundant. // Generate a CI configuration file based on your language and CI system func Generate(t *templator.CITemplator, cfg *config.Commit0Config, ciConfig config.CI, basePath string, wg *sync.WaitGroup) error { @@ -50,7 +50,7 @@ func Generate(t *templator.CITemplator, cfg *config.Commit0Config, ciConfig conf case "github": ciConfigPath = fmt.Sprintf("%s/%s", basePath, ".github/workflow/") ciFilename = "config.yml" - ciTemp = t.CircleCI + ciTemp = t.Github default: return &CIGenerationError{"Unsupported CI System", ciConfig} } diff --git a/internal/templator/templator.go b/internal/templator/templator.go index 099cb19e4..3cc849e16 100644 --- a/internal/templator/templator.go +++ b/internal/templator/templator.go @@ -63,7 +63,7 @@ func NewTemplator(box *packr.Box) *Templator { Readme: NewSingleFileTemplator(box, "util/README.tmpl"), Docker: NewDockerFileTemplator(box), React: NewEJSDirectoryTemplator(box, "react"), - Terraform: NewEJSDirectoryTemplator(box, "terraform"), + Terraform: NewDirectoryTemplator(box, "terraform"), Kubernetes: NewDirectoryTemplator(box, "kubernetes"), CI: NewCITemplator(box), } diff --git a/templates/terraform/environments/production.tfvars b/templates/terraform/environments/production.tfvars new file mode 100644 index 000000000..e69de29bb diff --git a/templates/terraform/environments/staging.tfvars b/templates/terraform/environments/staging.tfvars new file mode 100644 index 000000000..e69de29bb diff --git a/templates/terraform/global/remote-state/main.tf b/templates/terraform/global/remote-state/main.tf new file mode 100644 index 000000000..cea38fef4 --- /dev/null +++ b/templates/terraform/global/remote-state/main.tf @@ -0,0 +1,4 @@ +provider "aws" { + region = "${ var.region }" +} + diff --git a/templates/terraform/global/remote-state/terraform.tfvars b/templates/terraform/global/remote-state/terraform.tfvars new file mode 100644 index 000000000..bf85a742a --- /dev/null +++ b/templates/terraform/global/remote-state/terraform.tfvars @@ -0,0 +1 @@ +region = "{{ .Config.Infrastructure.AWS.Region }}" diff --git a/templates/terraform/global/remote-state/variables.tf b/templates/terraform/global/remote-state/variables.tf new file mode 100644 index 000000000..daef22220 --- /dev/null +++ b/templates/terraform/global/remote-state/variables.tf @@ -0,0 +1,11 @@ +variable "region" { + description = "The AWS region" +} + +variable "remote_state_s3_bucket" { + description = "Name of the S3 bucket to store the remote state" +} + +variable "remote_state_dynamo_table" { + description = "Dynamo DB Table to store the remote state locks" +} \ No newline at end of file diff --git a/templates/terraform/main.tf b/templates/terraform/main.tf index fefc78e58..2ad3d8af9 100644 --- a/templates/terraform/main.tf +++ b/templates/terraform/main.tf @@ -1,3 +1,64 @@ provider "aws" { + region = "${var.region}" +} -} \ No newline at end of file +# {{ if .Config.Infrastructure.AWS.Terraform.RemoteState }} +# Store remote state in S3 +resource "aws_s3_bucket" "terraform_remote_state" { + bucket = "${ var.remote_state_s3_bucket }" + acl = "private" + + versioning { + enabled = true + } +} + +resource "aws_dynamodb_table" "terraform_state_locks" { + name = "${ var.remote_state_dynamo_table }" + read_capacity = 2 + write_capacity = 2 + hash_key = "LockID" + + attribute { + name = "LockID" + type = "S" + } +} + +# Reference the remote state +terraform { + backend "s3" { + bucket = "${var.remote_state_s3_bucket}" + key = "infrastructure/terraform/shared" + encrypt = true + region = "${var.region}" + dynamodb_table = "${var.remote_state_dynamo_table}" + } +} +# {{- end}} +# {{ if .Config.Infrastructure.AWS.Cognito }} +# ref: https://github.com/squidfunk/terraform-aws-cognito-auth#usage + +# data "aws_acm_certificate" "wildcard_cert" { +# domain = "*.${var.public_dns_zone}" +# } + +module "cognito-auth" { + source = "squidfunk/cognito-auth/aws" + version = "0.4.2" + + namespace = "${var.auth_namespace}" + region = "${var.region}" + cognito_identity_pool_name = "${var.auth_pool_name}" + cognito_identity_pool_provider = "${var.auth_pool_provider}" + + # Optional: Default UI + # app_hosted_zone_id = "" + # app_certificate_arn = "${data.aws_acm_certificate.wildcard_cert.arn}" + # app_domain = "" + # app_origin = "" + + # Optional: Email delivery + # ses_sender_address = "" +} +# {{- end}} diff --git a/templates/terraform/variables.tf b/templates/terraform/variables.tf new file mode 100644 index 000000000..44136049a --- /dev/null +++ b/templates/terraform/variables.tf @@ -0,0 +1,27 @@ +variable "region" { + default = "{{ .Config.Infrastructure.AWS.Region }}" + description = "The AWS region" +} + +# {{ if .Config.Infrastructure.AWS.Terraform.RemoteState }} +variable "remote_state_s3_bucket" { + default = "project-{{ .Config.Name }}-terraform-state" + description = "Name of the S3 bucket to store the remote state" +} + +variable "remote_state_dynamo_table" { + default = "{{ .Config.Name }}-terraform-state-locks" + description = "Dynamo DB Table to store the remote state locks" +} +# {{- end}} +# {{ if .Config.Infrastructure.AWS.Cognito }} +variable "auth_namespace" { + default = "cognito_auth" +} +variable "auth_pool_name" { + description = "AWS Cognito pool name" +} +variable "auth_pool_provider" { + description = "AWS Cognito pool provider" +} +# {{- end}} diff --git a/templates/terraform/versions.tf b/templates/terraform/versions.tf new file mode 100644 index 000000000..ac97c6ac8 --- /dev/null +++ b/templates/terraform/versions.tf @@ -0,0 +1,4 @@ + +terraform { + required_version = ">= 0.12" +}