Skip to content

Commit

Permalink
Feature complete catch up with CloudFormation (#37)
Browse files Browse the repository at this point in the history
* Delete Golang Terraform code generator, to be replaced with native Terraform code.

* Generate regional code using native Terraform code

* Formatting fixes

* Update terraform-null-label to latest version

* Use Python 3.8 for the regional Lambda runtime

* Clean up unused variables of older null-label module

* Add example of deploying AutoSpotting

* Support parallel installations

* Add ManageASG, update main Lambda env vars and policies

* Improve logging of the regional event forwarder Lambda

* Sync forwarded regional events with CloudFormation

* Revert a few errors done while rebasing

* Add IAM policy for the regional event forwarder Lambda
  • Loading branch information
cristim committed Dec 1, 2020
1 parent 0594a68 commit 5c01e60
Show file tree
Hide file tree
Showing 23 changed files with 1,023 additions and 420 deletions.
36 changes: 0 additions & 36 deletions autospotting-policy.json

This file was deleted.

167 changes: 167 additions & 0 deletions context.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#
# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label
# All other instances of this file should be a copy of that one
#
#
# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf
# and then place it in your Terraform module to automatically get
# Cloud Posse's standard configuration inputs suitable for passing
# to Cloud Posse modules.
#
# Modules should access the whole context as `module.this.context`
# to get the input variables with nulls for defaults,
# for example `context = module.this.context`,
# and access individual variables as `module.this.<var>`,
# with final values filled in.
#
# For example, when using defaults, `module.this.context.delimiter`
# will be null, and `module.this.delimiter` will be `-` (hyphen).
#

module "this" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.21.0"

enabled = var.enabled
namespace = var.namespace
environment = var.environment
stage = var.stage
name = var.name
delimiter = var.delimiter
attributes = var.attributes
tags = var.tags
additional_tag_map = var.additional_tag_map
label_order = var.label_order
regex_replace_chars = var.regex_replace_chars
id_length_limit = var.id_length_limit

context = var.context
}

# Copy contents of cloudposse/terraform-null-label/variables.tf here

variable "context" {
type = object({
enabled = bool
namespace = string
environment = string
stage = string
name = string
delimiter = string
attributes = list(string)
tags = map(string)
additional_tag_map = map(string)
regex_replace_chars = string
label_order = list(string)
id_length_limit = number
})
default = {
enabled = true
namespace = null
environment = null
stage = null
name = null
delimiter = null
attributes = []
tags = {}
additional_tag_map = {}
regex_replace_chars = null
label_order = []
id_length_limit = null
}
description = <<-EOT
Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional_tag_map, which are merged.
EOT
}

variable "enabled" {
type = bool
default = null
description = "Set to false to prevent the module from creating any resources"
}

variable "namespace" {
type = string
default = null
description = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'"
}

variable "environment" {
type = string
default = null
description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'"
}

variable "stage" {
type = string
default = null
description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'"
}

variable "name" {
type = string
default = null
description = "Solution name, e.g. 'app' or 'jenkins'"
}

variable "delimiter" {
type = string
default = null
description = <<-EOT
Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all.
EOT
}

variable "attributes" {
type = list(string)
default = []
description = "Additional attributes (e.g. `1`)"
}

variable "tags" {
type = map(string)
default = {}
description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`"
}

variable "additional_tag_map" {
type = map(string)
default = {}
description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`."
}

variable "label_order" {
type = list(string)
default = null
description = <<-EOT
The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present.
EOT
}

variable "regex_replace_chars" {
type = string
default = null
description = <<-EOT
Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits.
EOT
}

variable "id_length_limit" {
type = number
default = null
description = <<-EOT
Limit `id` to this many characters.
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`.
EOT
}

#### End of copy of cloudposse/terraform-null-label/variables.tf
32 changes: 32 additions & 0 deletions examples/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
provider "aws" {
region = "us-east-1"
}

module "autospotting-test" {
source = "../"
name = "AutoSpotting"
environment = "test"
# when this is commented out AutoSpotting will install regional resources in
# all regions. After this value is changed, Terraform apply needs to be
# executed twice because of the way we generate some Terraform code from
# Terraform itself.
# autospotting_regions_enabled = ["us-east-1", "eu-west-1"]
}

# This can be used to install a second instance of AutoSpotting with different
# parameters.

# Be careful when destroying additional modules, you will need to restore
# modules/regional/providers.tf and modules/regional/regional.tf from git
# history, as they are deleted on destroy.

# module "autospotting-dev" {
# source = "../"
# name = "AutoSpotting"
# environment = "dev"
# autospotting_regions_enabled = ["us-east-1", "eu-west-1"]
# }

output "regions" {
value = module.autospotting-test.regions
}
13 changes: 0 additions & 13 deletions lambda-policy.json

This file was deleted.

100 changes: 51 additions & 49 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,55 +1,65 @@
module "label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=0.18.0"
context = var.label_context
namespace = var.label_namespace
environment = var.label_environment
stage = var.label_stage
name = var.label_name
attributes = var.label_attributes
tags = var.label_tags
delimiter = var.label_delimiter
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=0.21.0"
context = module.this
}

data "aws_regions" "current" {
all_regions = true
}

locals {
all_regions = data.aws_regions.current.names
unsupported_regions = ["ap-northeast-3"] # These regions currently throw an error when attempting to use them. This is also set in modules/regional/generate_regional_code.tf

all_usable_regions = setsubtract(local.all_regions, local.unsupported_regions)
regions = var.autospotting_regions_enabled == [] ? local.all_usable_regions : var.autospotting_regions_enabled
}

output "regions" {
value = local.regions
}

module "aws_lambda_function" {
source = "./modules/lambda"

label_context = module.label.context

lambda_zipname = var.lambda_zipname
lambda_s3_bucket = var.lambda_s3_bucket
lambda_s3_key = var.lambda_s3_key
lambda_role_arn = aws_iam_role.autospotting_role.arn
lambda_runtime = var.lambda_runtime
lambda_timeout = var.lambda_timeout
lambda_memory_size = var.lambda_memory_size
lambda_tags = var.lambda_tags

autospotting_allowed_instance_types = var.autospotting_allowed_instance_types
autospotting_disallowed_instance_types = var.autospotting_disallowed_instance_types
autospotting_instance_termination_method = var.autospotting_instance_termination_method
autospotting_min_on_demand_number = var.autospotting_min_on_demand_number
autospotting_min_on_demand_percentage = var.autospotting_min_on_demand_percentage
autospotting_on_demand_price_multiplier = var.autospotting_on_demand_price_multiplier
autospotting_spot_price_buffer_percentage = var.autospotting_spot_price_buffer_percentage
autospotting_spot_product_description = var.autospotting_spot_product_description
autospotting_bidding_policy = var.autospotting_bidding_policy
autospotting_regions_enabled = var.autospotting_regions_enabled
autospotting_tag_filters = var.autospotting_tag_filters
autospotting_tag_filtering_mode = var.autospotting_tag_filtering_mode
autospotting_license = var.autospotting_license
}
lambda_zipname = var.lambda_zipname
lambda_s3_bucket = var.lambda_s3_bucket
lambda_s3_key = var.lambda_s3_key
lambda_manage_asg_s3_key = var.lambda_manage_asg_s3_key
lambda_runtime = var.lambda_runtime
lambda_timeout = var.lambda_timeout
lambda_memory_size = var.lambda_memory_size
lambda_tags = var.lambda_tags

resource "aws_iam_role" "autospotting_role" {
name = module.label.id
path = "/lambda/"
assume_role_policy = file("${path.module}/lambda-policy.json")
force_detach_policies = true
autospotting_allowed_instance_types = var.autospotting_allowed_instance_types
autospotting_bidding_policy = var.autospotting_bidding_policy
autospotting_cron_schedule = var.autospotting_cron_schedule
autospotting_cron_schedule_state = var.autospotting_cron_schedule_state
autospotting_cron_timezone = var.autospotting_cron_timezone
autospotting_disallowed_instance_types = var.autospotting_disallowed_instance_types
autospotting_instance_termination_method = var.autospotting_instance_termination_method
autospotting_license = var.autospotting_license
autospotting_min_on_demand_number = var.autospotting_min_on_demand_number
autospotting_min_on_demand_percentage = var.autospotting_min_on_demand_percentage
autospotting_on_demand_price_multiplier = var.autospotting_on_demand_price_multiplier
autospotting_patch_beanswalk_userdata = var.autospotting_patch_beanswalk_userdata
autospotting_regions_enabled = var.autospotting_regions_enabled
autospotting_spot_price_buffer_percentage = var.autospotting_spot_price_buffer_percentage
autospotting_spot_product_description = var.autospotting_spot_product_description
autospotting_spot_product_premium = var.autospotting_spot_product_premium
autospotting_tag_filtering_mode = var.autospotting_tag_filtering_mode
autospotting_tag_filters = var.autospotting_tag_filters
autospotting_termination_notification_action = var.autospotting_termination_notification_action
}

resource "aws_iam_role_policy" "autospotting_policy" {
name = "policy_for_${module.label.id}"
role = aws_iam_role.autospotting_role.id
policy = file("${path.module}/autospotting-policy.json")
# Regional resources that trigger the main Lambda function
module "regional" {
source = "./modules/regional"
autospotting_lambda_arn = module.aws_lambda_function.arn
label_context = module.label.context
regions = local.regions
}

resource "aws_lambda_permission" "cloudwatch_events_permission" {
Expand Down Expand Up @@ -95,11 +105,3 @@ resource "aws_iam_policy" "beanstalk_policy" {
name = "elastic_beanstalk_iam_policy_for_${module.label.id}"
policy = data.aws_iam_policy_document.beanstalk.json
}

# Regional resources that trigger the main Lambda function

module "regional" {
source = "./modules/regional"
autospotting_lambda_arn = module.aws_lambda_function.arn
label_context = module.label.context
}
Loading

0 comments on commit 5c01e60

Please sign in to comment.