From 44766b0916be195f2b1cb24d945467156d7fc872 Mon Sep 17 00:00:00 2001 From: Andriy Knysh Date: Mon, 14 Oct 2019 21:57:08 -0400 Subject: [PATCH] Convert to TF 0.12. Add tests. Add Codefresh test pipeline (#49) * Convert to TF 0.12 * Convert to TF 0.12 * Convert to TF 0.12 * Convert to TF 0.12. Add tests. Add Codefresh test pipeline * Convert to TF 0.12. Add tests. Add Codefresh test pipeline * Convert to TF 0.12. Add tests. Add Codefresh test pipeline * Convert to TF 0.12. Add tests. Add Codefresh test pipeline * Convert to TF 0.12. Add tests. Add Codefresh test pipeline * Convert to TF 0.12. Add tests. Add Codefresh test pipeline * Convert to TF 0.12. Add tests. Add Codefresh test pipeline * Update tests * Update tests * Update tests * Update `terraform-aws-elastic-beanstalk-application` version --- .gitignore | 2 +- .travis.yml | 16 - LICENSE | 2 +- README.md | 408 ++++++++---------- README.yaml | 292 ++++--------- codefresh/test.yml | 74 ++++ docs/terraform.md | 104 +++-- examples/complete/fixtures.us-east-2.tfvars | 69 +++ examples/complete/main.tf | 79 ++++ examples/complete/outputs.tf | 229 ++++++++++ examples/complete/variables.tf | 188 ++++++++ examples/complete/versions.tf | 11 + .../existing_vpc_existing_subnets/main.tf | 25 +- examples/existing_vpc_new_subnets/main.tf | 31 +- examples/new_vpc_new_subnets/main.tf | 47 +- main.tf | 239 +++++----- outputs.tf | 218 ++++++++++ test/.gitignore | 1 + test/Makefile | 43 ++ test/Makefile.alpine | 5 + test/src/.gitignore | 2 + test/src/Gopkg.lock | 92 ++++ test/src/Gopkg.toml | 7 + test/src/Makefile | 50 +++ test/src/examples_complete_test.go | 116 +++++ variables.tf | 206 +++++---- versions.tf | 11 + 27 files changed, 1813 insertions(+), 754 deletions(-) delete mode 100644 .travis.yml create mode 100644 codefresh/test.yml create mode 100644 examples/complete/fixtures.us-east-2.tfvars create mode 100644 examples/complete/main.tf create mode 100644 examples/complete/outputs.tf create mode 100644 examples/complete/variables.tf create mode 100644 examples/complete/versions.tf create mode 100644 test/.gitignore create mode 100644 test/Makefile create mode 100644 test/Makefile.alpine create mode 100644 test/src/.gitignore create mode 100644 test/src/Gopkg.lock create mode 100644 test/src/Gopkg.toml create mode 100644 test/src/Makefile create mode 100644 test/src/examples_complete_test.go create mode 100644 versions.tf diff --git a/.gitignore b/.gitignore index 2d530ee..b6abc3c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ *.iml .build-harness -build-harness \ No newline at end of file +build-harness diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 241026e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -addons: - apt: - packages: - - git - - make - - curl - -install: - - make init - -script: - - make terraform/install - - make terraform/get-plugins - - make terraform/get-modules - - make terraform/lint - - make terraform/validate diff --git a/LICENSE b/LICENSE index 808ecf3..a6e3b3e 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2017-2018 Cloud Posse, LLC + Copyright 2017-2019 Cloud Posse, LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index c359a76..8b8ab1b 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,14 @@ [![Cloud Posse][logo]](https://cpco.io/homepage) -# terraform-aws-jenkins [![Build Status](https://travis-ci.org/cloudposse/terraform-aws-jenkins.svg?branch=master)](https://travis-ci.org/cloudposse/terraform-aws-jenkins) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-jenkins.svg)](https://github.com/cloudposse/terraform-aws-jenkins/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) +# terraform-aws-jenkins [![Codefresh Build Status](https://g.codefresh.io/api/badges/pipeline/cloudposse/terraform-modules%2Fterraform-aws-jenkins?type=cf-1)](https://g.codefresh.io/public/accounts/cloudposse/pipelines/5d9fea1192fba6201f04faca) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-jenkins.svg)](https://github.com/cloudposse/terraform-aws-jenkins/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) `terraform-aws-jenkins` is a Terraform module to build a Docker image with [Jenkins](https://jenkins.io/), save it to an [ECR](https://aws.amazon.com/ecr/) repo, and deploy to [Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/) running [Docker](https://www.docker.com/). This is an enterprise-ready, scalable and highly-available architecture and the CI/CD pattern to build and deploy Jenkins. + ## Features The module will create the following AWS resources: @@ -18,9 +19,8 @@ The module will create the following AWS resources: * Elastic Beanstalk Environment with Docker stack to run the Jenkins master * ECR repository to store the Jenkins Docker image * EFS filesystem to store Jenkins config and jobs (it will be mounted to a directory on the EC2 host, and then to the Docker container) + * AWS Backup stack to automatically backup the EFS * CodePipeline with CodeBuild to build and deploy Jenkins so even Jenkins itself follows the CI/CD pattern - * CloudFormation stack to run a DataPipeline to automatically backup the EFS to S3 - * CloudFormation stack for SNS notifications about the status of each backup After all of the AWS resources are created, @@ -34,15 +34,6 @@ __CodePipeline__ will: * Monitor the GitHub repo for changes and re-run the steps above if new commits are pushed -__DataPipeline__ will run on the specified schedule and will backup all Jenkins files to an S3 bucket by doing the following: - - * Spawn an EC2 instance - * Mount the EFS filesystem to a directory on the EC2 instance - * Backup the directory to an S3 bucket - * Notify about the status of the backup (Success or Failure) via email - * Destroy the EC2 instance - - ![jenkins build server architecture](https://user-images.githubusercontent.com/52489/30888694-d07d68c8-a2d6-11e7-90b2-d8275ef94f39.png) @@ -79,217 +70,99 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are ## Usage -For complete examples, see [examples](examples). +**IMPORTANT:** The `master` branch is used in `source` just as an example. In your code, do not pin to `master` because there may be breaking changes between releases. +Instead pin to the release tag (e.g. `?ref=tags/x.y.z`) of one of our [latest releases](https://github.com/cloudposse/terraform-aws-jenkins/releases). +For a complete example, see [examples/complete](examples/complete). -## Examples - -### Deploy Jenkins into an existing VPC with existing subnets +For automatic tests of the complete example, see [test](test). ```hcl -variable "max_availability_zones" { - default = "2" +provider "aws" { + region = var.region } -data "aws_availability_zones" "available" {} - -module "jenkins" { - source = "git::https://github.com/cloudposse/terraform-aws-jenkins.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - description = "Jenkins server as Docker container running on Elastic Beanstalk" - - master_instance_type = "t2.medium" - aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - vpc_id = "vpc-a22222ee" - zone_id = "ZXXXXXXXXXXX" - public_subnets = ["subnet-e63f82cb", "subnet-e66f44ab", "subnet-e88f42bd"] - private_subnets = ["subnet-e99d23eb", "subnet-e77e12bb", "subnet-e58a52bc"] - loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" - ssh_key_pair = "ssh-key-jenkins" - - github_oauth_token = "" - github_organization = "cloudposse" - github_repo_name = "jenkins" - github_branch = "master" - - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } - - env_vars = { - JENKINS_USER = "admin" - JENKINS_PASS = "123456" - JENKINS_NUM_EXECUTORS = 4 - } - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } +module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + tags = var.tags + delimiter = var.delimiter + cidr_block = "172.16.0.0/16" } -``` -### Deploy Jenkins into an existing VPC and new subnets - -```hcl -variable "max_availability_zones" { - default = "2" +module "subnets" { + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.0" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + tags = var.tags + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false } -data "aws_availability_zones" "available" {} - module "jenkins" { source = "git::https://github.com/cloudposse/terraform-aws-jenkins.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - description = "Jenkins server as Docker container running on Elastic Beanstalk" - - master_instance_type = "t2.medium" - aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - vpc_id = "vpc-a22222ee" - zone_id = "ZXXXXXXXXXXX" - public_subnets = "${module.subnets.public_subnet_ids}" - private_subnets = "${module.subnets.private_subnet_ids}" - loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" - ssh_key_pair = "ssh-key-jenkins" - - github_oauth_token = "" - github_organization = "cloudposse" - github_repo_name = "jenkins" - github_branch = "master" - - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } + namespace = var.namespace + stage = var.stage + name = var.name + description = var.description + + master_instance_type = var.master_instance_type + aws_account_id = var.aws_account_id + region = var.region + availability_zones = var.availability_zones + vpc_id = module.vpc.vpc_id + dns_zone_id = var.dns_zone_id + loadbalancer_subnets = module.subnets.public_subnet_ids + application_subnets = module.subnets.private_subnet_ids + + environment_type = var.environment_type + loadbalancer_type = var.loadbalancer_type + loadbalancer_certificate_arn = var.loadbalancer_certificate_arn + availability_zone_selector = var.availability_zone_selector + rolling_update_type = var.rolling_update_type + loadbalancer_logs_bucket_force_destroy = var.loadbalancer_logs_bucket_force_destroy + cicd_bucket_force_destroy = var.cicd_bucket_force_destroy + + github_oauth_token = var.github_oauth_token + github_organization = var.github_organization + github_repo_name = var.github_repo_name + github_branch = var.github_branch + + image_tag = var.image_tag + + healthcheck_url = var.healthcheck_url + + build_image = var.build_image + build_compute_type = var.build_compute_type + + efs_backup_schedule = var.efs_backup_schedule + efs_backup_start_window = var.efs_backup_start_window + efs_backup_completion_window = var.efs_backup_completion_window + efs_backup_cold_storage_after = var.efs_backup_cold_storage_after + efs_backup_delete_after = var.efs_backup_delete_after env_vars = { - JENKINS_USER = "admin" - JENKINS_PASS = "123456" - JENKINS_NUM_EXECUTORS = 4 - } - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } -} - -module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - namespace = "cp" - name = "jenkins" - stage = "prod" - region = "us-west-2" - vpc_id = "vpc-a22222ee" - igw_id = "igw-s32321vd" - cidr_block = "10.0.0.0/16" - nat_gateway_enabled = "true" - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" + "JENKINS_USER" = var.jenkins_username + "JENKINS_PASS" = var.jenkins_password + "JENKINS_NUM_EXECUTORS" = var.jenkins_num_executors } } ``` -### Deploy Jenkins into a new VPC and new subnets -```hcl -variable "max_availability_zones" { - default = "2" -} - -data "aws_availability_zones" "available" {} -module "jenkins" { - source = "git::https://github.com/cloudposse/terraform-aws-jenkins.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - description = "Jenkins server as Docker container running on Elastic Beanstalk" - - master_instance_type = "t2.medium" - aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - vpc_id = "${module.vpc.vpc_id}" - zone_id = "ZXXXXXXXXXXX" - public_subnets = "${module.subnets.public_subnet_ids}" - private_subnets = "${module.subnets.private_subnet_ids}" - loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" - ssh_key_pair = "ssh-key-jenkins" - - github_oauth_token = "" - github_organization = "cloudposse" - github_repo_name = "jenkins" - github_branch = "master" - - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } - - env_vars = { - JENKINS_USER = "admin" - JENKINS_PASS = "123456" - JENKINS_NUM_EXECUTORS = 4 - } - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } -} - -module "vpc" { - source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - cidr_block = "10.0.0.0/16" - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } -} - -module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - namespace = "cp" - name = "jenkins" - stage = "prod" - region = "us-west-2" - vpc_id = "${module.vpc.vpc_id}" - igw_id = "${module.vpc.igw_id}" - cidr_block = "${module.vpc.vpc_cidr_block}" - nat_gateway_enabled = "true" - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } -} -``` @@ -303,45 +176,99 @@ Available targets: lint Lint terraform code ``` - ## Inputs | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| -| attributes | Additional attributes (e.g. `policy` or `role`) | list | `` | no | -| availability_zones | List of Availability Zones for EFS | list | - | yes | +| allowed_security_groups | List of security groups to be allowed to connect to Jenkins master EC2 instances | list(string) | `` | no | +| application_subnets | List of subnets to place EC2 instances and EFS | list(string) | - | yes | +| attributes | Additional attributes (e.g. `1`) | list(string) | `` | no | +| availability_zone_selector | Availability Zone selector | string | `Any` | no | +| availability_zones | List of Availability Zones for EFS | list(string) | - | yes | | aws_account_id | AWS Account ID. Used as CodeBuild ENV variable $AWS_ACCOUNT_ID when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html | string | - | yes | -| aws_region | AWS region in which to provision the AWS resources | string | `us-west-2` | no | -| build_compute_type | CodeBuild compute type, e.g. 'BUILD_GENERAL1_SMALL'. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-compute-types | string | `BUILD_GENERAL1_SMALL` | no | -| build_image | CodeBuild build image, e.g. 'aws/codebuild/docker:1.12.1'. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-available | string | `aws/codebuild/docker:1.12.1` | no | -| datapipeline_config | DataPipeline configuration options | map | `` | no | -| delimiter | Delimiter to be used between `name`, `namespace`, `stage`, etc. | string | `-` | no | +| build_compute_type | CodeBuild compute type, e.g. 'BUILD_GENERAL1_SMALL'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html | string | `BUILD_GENERAL1_SMALL` | no | +| build_image | CodeBuild build image, e.g. 'aws/codebuild/amazonlinux2-x86_64-standard:1.0'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html | string | `aws/codebuild/docker:1.12.1` | no | +| cicd_bucket_force_destroy | Force destroy the CI/CD S3 bucket even if it's not empty | bool | `false` | no | +| delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | | description | Will be used as Elastic Beanstalk application description | string | `Jenkins server as Docker container running on Elastic Benastalk` | no | -| env_default_key | Default ENV variable key for Elastic Beanstalk `aws:elasticbeanstalk:application:environment` setting | string | `DEFAULT_ENV_%d` | no | -| env_default_value | Default ENV variable value for Elastic Beanstalk `aws:elasticbeanstalk:application:environment` setting | string | `UNSET` | no | -| env_vars | Map of custom ENV variables to be provided to the Jenkins application running on Elastic Beanstalk, e.g. env_vars = { JENKINS_USER = 'admin' JENKINS_PASS = 'xxxxxx' } | map | `` | no | +| dns_zone_id | Route53 parent zone ID. The module will create sub-domain DNS records in the parent zone for the EB environment and EFS | string | - | yes | +| efs_backup_cold_storage_after | Specifies the number of days after creation that a recovery point is moved to cold storage | number | `null` | no | +| efs_backup_completion_window | The amount of time AWS Backup attempts a backup before canceling the job and returning an error. Must be at least 60 minutes greater than `start_window` | number | `null` | no | +| efs_backup_delete_after | Specifies the number of days after creation that a recovery point is deleted. Must be 90 days greater than `cold_storage_after` | number | `null` | no | +| efs_backup_schedule | A CRON expression specifying when AWS Backup initiates a backup job | string | `null` | no | +| efs_backup_start_window | The amount of time in minutes before beginning a backup. Minimum value is 60 minutes | number | `null` | no | +| env_vars | Map of custom ENV variables to be provided to the Jenkins application running on Elastic Beanstalk, e.g. env_vars = { JENKINS_USER = 'admin' JENKINS_PASS = 'xxxxxx' } | map(string) | `` | no | +| environment_type | Environment type, e.g. 'LoadBalanced' or 'SingleInstance'. If setting to 'SingleInstance', `rolling_update_type` must be set to 'Time' or `Immutable`, and `loadbalancer_subnets` will be unused (it applies to the ELB, which does not exist in SingleInstance environments) | string | `LoadBalanced` | no | | github_branch | GitHub repository branch, e.g. 'master'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' master branch | string | `master` | no | -| github_oauth_token | GitHub Oauth Token for accessing private repositories. Leave it empty when deploying a public 'Jenkins' repository, e.g. https://github.com/cloudposse/jenkins | string | `` | no | +| github_oauth_token | GitHub Oauth Token | string | - | yes | | github_organization | GitHub organization, e.g. 'cloudposse'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository | string | `cloudposse` | no | | github_repo_name | GitHub repository name, e.g. 'jenkins'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository | string | `jenkins` | no | | healthcheck_url | Application Health Check URL. Elastic Beanstalk will call this URL to check the health of the application running on EC2 instances | string | `/login` | no | | image_tag | Docker image tag in the ECR repository, e.g. 'latest'. Used as CodeBuild ENV variable $IMAGE_TAG when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html | string | `latest` | no | -| loadbalancer_certificate_arn | Load Balancer SSL certificate ARN. The certificate must be present in AWS Certificate Manager | string | - | yes | +| loadbalancer_certificate_arn | Load Balancer SSL certificate ARN. The certificate must be present in AWS Certificate Manager | string | `` | no | +| loadbalancer_logs_bucket_force_destroy | Force destroy the S3 bucket for load balancer logs even if it's not empty | bool | `false` | no | +| loadbalancer_subnets | List of subnets to place Elastic Load Balancer | list(string) | - | yes | | loadbalancer_type | Load Balancer type, e.g. 'application' or 'classic' | string | `application` | no | | master_instance_type | EC2 instance type for Jenkins master, e.g. 't2.medium' | string | `t2.medium` | no | -| name | Solution name, e.g. 'app' or 'jenkins' | string | `jenkins` | no | -| namespace | Namespace, which could be your organization name, e.g. 'cp' or 'cloudposse' | string | - | yes | -| noncurrent_version_expiration_days | Backup S3 bucket noncurrent version expiration days | string | `35` | no | -| private_subnets | List of private subnets to place EC2 instances and EFS | list | - | yes | -| public_subnets | List of public subnets to place Elastic Load Balancer | list | - | yes | -| security_groups | List of security groups to be allowed to connect to the EC2 instances | list | `` | no | -| solution_stack_name | Elastic Beanstalk stack, e.g. Docker, Go, Node, Java, IIS. For more info: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html | string | `64bit Amazon Linux 2017.09 v2.8.4 running Docker 17.09.1-ce` | no | -| ssh_key_pair | Name of SSH key that will be deployed on Elastic Beanstalk and DataPipeline instance. The key should be present in AWS | string | `` | no | -| stage | Stage, e.g. 'prod', 'staging', 'dev', or 'test' | string | - | yes | -| tags | Additional tags (e.g. `map('BusinessUnit`,`XYZ`) | map | `` | no | -| use_efs_ip_address | | string | `false` | no | +| name | Solution name, e.g. 'app' or 'jenkins' | string | - | yes | +| namespace | Namespace, which could be your organization name, e.g. 'eg' or 'cp' | string | `` | no | +| region | AWS region in which to provision the AWS resources | string | - | yes | +| rolling_update_type | `Health`, `Time` or `Immutable`. Set it to `Immutable` to apply the configuration change to a fresh group of instances. For more details, see https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingupdatepolicyrollingupdate | string | `Health` | no | +| solution_stack_name | Elastic Beanstalk stack, e.g. Docker, Go, Node, Java, IIS. For more info: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html | string | `64bit Amazon Linux 2018.03 v2.12.17 running Docker 18.06.1-ce` | no | +| ssh_key_pair | Name of SSH key that will be deployed on Elastic Beanstalk instances. The key should be present in AWS | string | `` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', or 'test' | string | `` | no | +| tags | Additional tags (e.g. `map('BusinessUnit`,`XYZ`) | map(string) | `` | no | +| use_efs_ip_address | If set to `true`, will provide the EFS IP address instead of DNS name to Jenkins as ENV var | bool | `false` | no | | vpc_id | ID of the VPC in which to provision the AWS resources | string | - | yes | -| zone_id | Route53 parent zone ID. The module will create sub-domain DNS records in the parent zone for the EB environment and EFS | string | - | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| codebuild_badge_url | The URL of the build badge when badge_enabled is enabled | +| codebuild_cache_bucket_arn | CodeBuild cache S3 bucket ARN | +| codebuild_cache_bucket_name | CodeBuild cache S3 bucket name | +| codebuild_project_id | CodeBuild project ID | +| codebuild_project_name | CodeBuild project name | +| codebuild_role_arn | CodeBuild IAM Role ARN | +| codebuild_role_id | CodeBuild IAM Role ID | +| codepipeline_arn | CodePipeline ARN | +| codepipeline_id | CodePipeline ID | +| ecr_registry_id | Registry ID | +| ecr_registry_url | Registry URL | +| ecr_repository_name | Registry name | +| efs_arn | EFS ARN | +| efs_backup_plan_arn | Backup Plan ARN | +| efs_backup_plan_version | Unique, randomly generated, Unicode, UTF-8 encoded string that serves as the version ID of the backup plan | +| efs_backup_selection_id | Backup Selection ID | +| efs_backup_vault_arn | Backup Vault ARN | +| efs_backup_vault_id | Backup Vault ID | +| efs_backup_vault_recovery_points | Backup Vault recovery points | +| efs_dns_name | EFS DNS name | +| efs_host | Route53 DNS hostname for the EFS | +| efs_id | EFS ID | +| efs_mount_target_dns_names | List of EFS mount target DNS names | +| efs_mount_target_ids | List of EFS mount target IDs (one per Availability Zone) | +| efs_mount_target_ips | List of EFS mount target IPs (one per Availability Zone) | +| efs_network_interface_ids | List of mount target network interface IDs | +| elastic_beanstalk_application_name | Elastic Beanstalk Application name | +| elastic_beanstalk_environment_all_settings | List of all option settings configured in the environment. These are a combination of default settings and their overrides from setting in the configuration | +| elastic_beanstalk_environment_application | The Elastic Beanstalk Application specified for this environment | +| elastic_beanstalk_environment_autoscaling_groups | The autoscaling groups used by this environment | +| elastic_beanstalk_environment_ec2_instance_profile_role_name | Instance IAM role name | +| elastic_beanstalk_environment_elb_zone_id | ELB zone id | +| elastic_beanstalk_environment_endpoint | Fully qualified DNS name for the environment | +| elastic_beanstalk_environment_hostname | DNS hostname | +| elastic_beanstalk_environment_id | ID of the Elastic Beanstalk environment | +| elastic_beanstalk_environment_instances | Instances used by this environment | +| elastic_beanstalk_environment_launch_configurations | Launch configurations in use by this environment | +| elastic_beanstalk_environment_load_balancers | Elastic Load Balancers in use by this environment | +| elastic_beanstalk_environment_name | Name | +| elastic_beanstalk_environment_queues | SQS queues in use by this environment | +| elastic_beanstalk_environment_security_group_id | Security group id | +| elastic_beanstalk_environment_setting | Settings specifically set for this environment | +| elastic_beanstalk_environment_tier | The environment tier | +| elastic_beanstalk_environment_triggers | Autoscaling triggers in use by this environment | @@ -357,7 +284,7 @@ Are you using this project or any of our other projects? Consider [leaving a tes Check out these related projects. -- [terraform-aws-elastic-beanstalk-applicationl](https://github.com/cloudposse/terraform-aws-elastic-beanstalk-application) - Terraform module to provision AWS Elastic Beanstalk application +- [terraform-aws-elastic-beanstalk-application](https://github.com/cloudposse/terraform-aws-elastic-beanstalk-application) - Terraform module to provision AWS Elastic Beanstalk application - [terraform-aws-elastic-beanstalk-environment](https://github.com/cloudposse/terraform-aws-elastic-beanstalk-environment) - Terraform module to provision AWS Elastic Beanstalk environment - [terraform-aws-ecr](https://github.com/cloudposse/terraform-aws-ecr) - Terraform Module to manage Docker Container Registries on AWS ECR - [terraform-aws-efs](https://github.com/cloudposse/terraform-aws-efs) - Terraform Module to define an EFS Filesystem (aka NFS) @@ -429,7 +356,7 @@ In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. ## Copyright -Copyright © 2017-2018 [Cloud Posse, LLC](https://cpco.io/copyright) +Copyright © 2017-2019 [Cloud Posse, LLC](https://cpco.io/copyright) @@ -484,15 +411,24 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply ### Contributors -| [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]
[Andriy Knysh][aknysh_homepage] | [![Ivan Pinatti][ivan-pinatti_avatar]][ivan-pinatti_homepage]
[Ivan Pinatti][ivan-pinatti_homepage] | [![Sergey Vasilyev][s2504s_avatar]][s2504s_homepage]
[Sergey Vasilyev][s2504s_homepage] | -|---|---|---| +| [![Erik Osterman][osterman_avatar]][osterman_homepage]
[Erik Osterman][osterman_homepage] | [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]
[Andriy Knysh][aknysh_homepage] | [![Igor Rodionov][goruha_avatar]][goruha_homepage]
[Igor Rodionov][goruha_homepage] | [![Ivan Pinatti][ivan-pinatti_avatar]][ivan-pinatti_homepage]
[Ivan Pinatti][ivan-pinatti_homepage] | [![Sergey Vasilyev][s2504s_avatar]][s2504s_homepage]
[Sergey Vasilyev][s2504s_homepage] | +|---|---|---|---|---| + + + [osterman_homepage]: https://github.com/osterman + [osterman_avatar]: https://img.cloudposse.com/150x150/https://github.com/osterman.png + + [aknysh_homepage]: https://github.com/aknysh/ + [aknysh_avatar]: https://img.cloudposse.com/150x150/https://github.com/aknysh.png + + [goruha_homepage]: https://github.com/goruha/ + [goruha_avatar]: https://img.cloudposse.com/150x150/https://github.com/goruha.png + + [ivan-pinatti_homepage]: https://github.com/ivan-pinatti/ + [ivan-pinatti_avatar]: https://img.cloudposse.com/150x150/https://github.com/ivan-pinatti.png - [aknysh_homepage]: https://github.com/aknysh - [aknysh_avatar]: https://github.com/aknysh.png?size=150 - [ivan-pinatti_homepage]: https://github.com/ivan-pinatti - [ivan-pinatti_avatar]: https://github.com/ivan-pinatti.png?size=150 - [s2504s_homepage]: https://github.com/s2504s - [s2504s_avatar]: https://github.com/s2504s.png?size=150 + [s2504s_homepage]: https://github.com/s2504s/ + [s2504s_avatar]: https://img.cloudposse.com/150x150/https://github.com/s2504s.png diff --git a/README.yaml b/README.yaml index f469d46..35ebbe1 100644 --- a/README.yaml +++ b/README.yaml @@ -38,9 +38,9 @@ github_repo: cloudposse/terraform-aws-jenkins # Badges to display badges: - - name: "Build Status" - image: "https://travis-ci.org/cloudposse/terraform-aws-jenkins.svg?branch=master" - url: "https://travis-ci.org/cloudposse/terraform-aws-jenkins" + - name: "Codefresh Build Status" + image: "https://g.codefresh.io/api/badges/pipeline/cloudposse/terraform-modules%2Fterraform-aws-jenkins?type=cf-1" + url: "https://g.codefresh.io/public/accounts/cloudposse/pipelines/5d9fea1192fba6201f04faca" - name: "Latest Release" image: "https://img.shields.io/github/release/cloudposse/terraform-aws-jenkins.svg" url: "https://github.com/cloudposse/terraform-aws-jenkins/releases/latest" @@ -49,7 +49,7 @@ badges: url: "https://slack.cloudposse.com" related: - - name: "terraform-aws-elastic-beanstalk-applicationl" + - name: "terraform-aws-elastic-beanstalk-application" description: "Terraform module to provision AWS Elastic Beanstalk application" url: "https://github.com/cloudposse/terraform-aws-elastic-beanstalk-application" - name: "terraform-aws-elastic-beanstalk-environment" @@ -77,6 +77,7 @@ description: |- and deploy to [Elastic Beanstalk](https://aws.amazon.com/elasticbeanstalk/) running [Docker](https://www.docker.com/). This is an enterprise-ready, scalable and highly-available architecture and the CI/CD pattern to build and deploy Jenkins. + ## Features The module will create the following AWS resources: @@ -85,9 +86,8 @@ description: |- * Elastic Beanstalk Environment with Docker stack to run the Jenkins master * ECR repository to store the Jenkins Docker image * EFS filesystem to store Jenkins config and jobs (it will be mounted to a directory on the EC2 host, and then to the Docker container) + * AWS Backup stack to automatically backup the EFS * CodePipeline with CodeBuild to build and deploy Jenkins so even Jenkins itself follows the CI/CD pattern - * CloudFormation stack to run a DataPipeline to automatically backup the EFS to S3 - * CloudFormation stack for SNS notifications about the status of each backup After all of the AWS resources are created, @@ -101,225 +101,92 @@ description: |- * Monitor the GitHub repo for changes and re-run the steps above if new commits are pushed - __DataPipeline__ will run on the specified schedule and will backup all Jenkins files to an S3 bucket by doing the following: - - * Spawn an EC2 instance - * Mount the EFS filesystem to a directory on the EC2 instance - * Backup the directory to an S3 bucket - * Notify about the status of the backup (Success or Failure) via email - * Destroy the EC2 instance - - ![jenkins build server architecture](https://user-images.githubusercontent.com/52489/30888694-d07d68c8-a2d6-11e7-90b2-d8275ef94f39.png) # How to use this project usage: |- - For complete examples, see [examples](examples). + For a complete example, see [examples/complete](examples/complete). -# Example usage - -examples: |- - ### Deploy Jenkins into an existing VPC with existing subnets + For automatic tests of the complete example, see [test](test). ```hcl - variable "max_availability_zones" { - default = "2" + provider "aws" { + region = var.region } - data "aws_availability_zones" "available" {} - - module "jenkins" { - source = "git::https://github.com/cloudposse/terraform-aws-jenkins.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - description = "Jenkins server as Docker container running on Elastic Beanstalk" - - master_instance_type = "t2.medium" - aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - vpc_id = "vpc-a22222ee" - zone_id = "ZXXXXXXXXXXX" - public_subnets = ["subnet-e63f82cb", "subnet-e66f44ab", "subnet-e88f42bd"] - private_subnets = ["subnet-e99d23eb", "subnet-e77e12bb", "subnet-e58a52bc"] - loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" - ssh_key_pair = "ssh-key-jenkins" - - github_oauth_token = "" - github_organization = "cloudposse" - github_repo_name = "jenkins" - github_branch = "master" - - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } - - env_vars = { - JENKINS_USER = "admin" - JENKINS_PASS = "123456" - JENKINS_NUM_EXECUTORS = 4 - } - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } - } - ``` - - ### Deploy Jenkins into an existing VPC and new subnets - - ```hcl - variable "max_availability_zones" { - default = "2" - } - - data "aws_availability_zones" "available" {} - - module "jenkins" { - source = "git::https://github.com/cloudposse/terraform-aws-jenkins.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - description = "Jenkins server as Docker container running on Elastic Beanstalk" - - master_instance_type = "t2.medium" - aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - vpc_id = "vpc-a22222ee" - zone_id = "ZXXXXXXXXXXX" - public_subnets = "${module.subnets.public_subnet_ids}" - private_subnets = "${module.subnets.private_subnet_ids}" - loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" - ssh_key_pair = "ssh-key-jenkins" - - github_oauth_token = "" - github_organization = "cloudposse" - github_repo_name = "jenkins" - github_branch = "master" - - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } - - env_vars = { - JENKINS_USER = "admin" - JENKINS_PASS = "123456" - JENKINS_NUM_EXECUTORS = 4 - } - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } + module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + tags = var.tags + delimiter = var.delimiter + cidr_block = "172.16.0.0/16" } module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - namespace = "cp" - name = "jenkins" - stage = "prod" - region = "us-west-2" - vpc_id = "vpc-a22222ee" - igw_id = "igw-s32321vd" - cidr_block = "10.0.0.0/16" - nat_gateway_enabled = "true" - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } - } - ``` - - ### Deploy Jenkins into a new VPC and new subnets - - ```hcl - variable "max_availability_zones" { - default = "2" + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.0" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + tags = var.tags + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false } - data "aws_availability_zones" "available" {} - module "jenkins" { source = "git::https://github.com/cloudposse/terraform-aws-jenkins.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - description = "Jenkins server as Docker container running on Elastic Beanstalk" - - master_instance_type = "t2.medium" - aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - vpc_id = "${module.vpc.vpc_id}" - zone_id = "ZXXXXXXXXXXX" - public_subnets = "${module.subnets.public_subnet_ids}" - private_subnets = "${module.subnets.private_subnet_ids}" - loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" - ssh_key_pair = "ssh-key-jenkins" - - github_oauth_token = "" - github_organization = "cloudposse" - github_repo_name = "jenkins" - github_branch = "master" - - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } + namespace = var.namespace + stage = var.stage + name = var.name + description = var.description + + master_instance_type = var.master_instance_type + aws_account_id = var.aws_account_id + region = var.region + availability_zones = var.availability_zones + vpc_id = module.vpc.vpc_id + dns_zone_id = var.dns_zone_id + loadbalancer_subnets = module.subnets.public_subnet_ids + application_subnets = module.subnets.private_subnet_ids + + environment_type = var.environment_type + loadbalancer_type = var.loadbalancer_type + loadbalancer_certificate_arn = var.loadbalancer_certificate_arn + availability_zone_selector = var.availability_zone_selector + rolling_update_type = var.rolling_update_type + loadbalancer_logs_bucket_force_destroy = var.loadbalancer_logs_bucket_force_destroy + cicd_bucket_force_destroy = var.cicd_bucket_force_destroy + + github_oauth_token = var.github_oauth_token + github_organization = var.github_organization + github_repo_name = var.github_repo_name + github_branch = var.github_branch + + image_tag = var.image_tag + + healthcheck_url = var.healthcheck_url + + build_image = var.build_image + build_compute_type = var.build_compute_type + + efs_backup_schedule = var.efs_backup_schedule + efs_backup_start_window = var.efs_backup_start_window + efs_backup_completion_window = var.efs_backup_completion_window + efs_backup_cold_storage_after = var.efs_backup_cold_storage_after + efs_backup_delete_after = var.efs_backup_delete_after env_vars = { - JENKINS_USER = "admin" - JENKINS_PASS = "123456" - JENKINS_NUM_EXECUTORS = 4 - } - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } - } - - module "vpc" { - source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=master" - namespace = "cp" - name = "jenkins" - stage = "prod" - cidr_block = "10.0.0.0/16" - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" - } - } - - module "subnets" { - source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - namespace = "cp" - name = "jenkins" - stage = "prod" - region = "us-west-2" - vpc_id = "${module.vpc.vpc_id}" - igw_id = "${module.vpc.igw_id}" - cidr_block = "${module.vpc.vpc_cidr_block}" - nat_gateway_enabled = "true" - - tags = { - BusinessUnit = "ABC" - Department = "XYZ" + "JENKINS_USER" = var.jenkins_username + "JENKINS_PASS" = var.jenkins_password + "JENKINS_NUM_EXECUTORS" = var.jenkins_num_executors } } ``` @@ -335,9 +202,18 @@ include: # Contributors to this project contributors: + - name: "Erik Osterman" + homepage: "https://github.com/osterman" + github: "osterman" - name: "Andriy Knysh" + homepage: "https://github.com/aknysh/" github: "aknysh" + - name: "Igor Rodionov" + homepage: "https://github.com/goruha/" + github: "goruha" - name: "Ivan Pinatti" + homepage: "https://github.com/ivan-pinatti/" github: "ivan-pinatti" - name: "Sergey Vasilyev" - github: "s2504s" \ No newline at end of file + homepage: "https://github.com/s2504s/" + github: "s2504s" diff --git a/codefresh/test.yml b/codefresh/test.yml new file mode 100644 index 0000000..ed93ead --- /dev/null +++ b/codefresh/test.yml @@ -0,0 +1,74 @@ +version: '1.0' + +stages: + - Prepare + - Test + +steps: + wait: + title: Wait + stage: Prepare + image: codefresh/cli:latest + commands: + - codefresh get builds --pipeline=${{CF_REPO_NAME}} --status running --limit 1000 -o json | jq --arg id ${{CF_BUILD_ID}} -ser 'flatten|.[-1].id==$id' + retry: + maxAttempts: 10 + delay: 20 + exponentialFactor: 1.1 + + main_clone: + title: "Clone repository" + type: git-clone + stage: Prepare + description: "Initialize" + repo: ${{CF_REPO_OWNER}}/${{CF_REPO_NAME}} + git: github + revision: ${{CF_REVISION}} + + clean_init: + title: Prepare build-harness and test-harness + image: ${{TEST_IMAGE}} + stage: Prepare + commands: + - cf_export PATH="/usr/local/terraform/0.12/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + - make init + - git -C build-harness checkout master + - make -C test/ clean init TEST_HARNESS_BRANCH=master + - make -C test/src clean init + - find . -type d -name '.terraform' | xargs rm -rf + - find . -type f -name 'terraform.tfstate*' -exec rm -f {} \; + + test: + type: "parallel" + title: "Run tests" + description: "Run all tests in parallel" + stage: Test + steps: + test_readme_lint: + title: "Test README.md updated" + stage: "Test" + image: ${{TEST_IMAGE}} + description: Test "readme/lint" + commands: + - make readme/lint + + test_module: + title: Test module with bats + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/ module + + test_examples_complete: + title: Test "examples/complete" with bats + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/ examples/complete + + test_examples_complete_terratest: + title: Test "examples/complete" with terratest + image: ${{TEST_IMAGE}} + stage: Test + commands: + - make -C test/src diff --git a/docs/terraform.md b/docs/terraform.md index 1a9a222..d987611 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -1,40 +1,94 @@ - ## Inputs | Name | Description | Type | Default | Required | |------|-------------|:----:|:-----:|:-----:| -| attributes | Additional attributes (e.g. `policy` or `role`) | list | `` | no | -| availability_zones | List of Availability Zones for EFS | list | - | yes | +| allowed_security_groups | List of security groups to be allowed to connect to Jenkins master EC2 instances | list(string) | `` | no | +| application_subnets | List of subnets to place EC2 instances and EFS | list(string) | - | yes | +| attributes | Additional attributes (e.g. `1`) | list(string) | `` | no | +| availability_zone_selector | Availability Zone selector | string | `Any` | no | +| availability_zones | List of Availability Zones for EFS | list(string) | - | yes | | aws_account_id | AWS Account ID. Used as CodeBuild ENV variable $AWS_ACCOUNT_ID when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html | string | - | yes | -| aws_region | AWS region in which to provision the AWS resources | string | `us-west-2` | no | -| build_compute_type | CodeBuild compute type, e.g. 'BUILD_GENERAL1_SMALL'. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-compute-types | string | `BUILD_GENERAL1_SMALL` | no | -| build_image | CodeBuild build image, e.g. 'aws/codebuild/docker:1.12.1'. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-available | string | `aws/codebuild/docker:1.12.1` | no | -| datapipeline_config | DataPipeline configuration options | map | `` | no | -| delimiter | Delimiter to be used between `name`, `namespace`, `stage`, etc. | string | `-` | no | +| build_compute_type | CodeBuild compute type, e.g. 'BUILD_GENERAL1_SMALL'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html | string | `BUILD_GENERAL1_SMALL` | no | +| build_image | CodeBuild build image, e.g. 'aws/codebuild/amazonlinux2-x86_64-standard:1.0'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html | string | `aws/codebuild/docker:1.12.1` | no | +| cicd_bucket_force_destroy | Force destroy the CI/CD S3 bucket even if it's not empty | bool | `false` | no | +| delimiter | Delimiter to be used between `namespace`, `stage`, `name` and `attributes` | string | `-` | no | | description | Will be used as Elastic Beanstalk application description | string | `Jenkins server as Docker container running on Elastic Benastalk` | no | -| env_default_key | Default ENV variable key for Elastic Beanstalk `aws:elasticbeanstalk:application:environment` setting | string | `DEFAULT_ENV_%d` | no | -| env_default_value | Default ENV variable value for Elastic Beanstalk `aws:elasticbeanstalk:application:environment` setting | string | `UNSET` | no | -| env_vars | Map of custom ENV variables to be provided to the Jenkins application running on Elastic Beanstalk, e.g. env_vars = { JENKINS_USER = 'admin' JENKINS_PASS = 'xxxxxx' } | map | `` | no | +| dns_zone_id | Route53 parent zone ID. The module will create sub-domain DNS records in the parent zone for the EB environment and EFS | string | - | yes | +| efs_backup_cold_storage_after | Specifies the number of days after creation that a recovery point is moved to cold storage | number | `null` | no | +| efs_backup_completion_window | The amount of time AWS Backup attempts a backup before canceling the job and returning an error. Must be at least 60 minutes greater than `start_window` | number | `null` | no | +| efs_backup_delete_after | Specifies the number of days after creation that a recovery point is deleted. Must be 90 days greater than `cold_storage_after` | number | `null` | no | +| efs_backup_schedule | A CRON expression specifying when AWS Backup initiates a backup job | string | `null` | no | +| efs_backup_start_window | The amount of time in minutes before beginning a backup. Minimum value is 60 minutes | number | `null` | no | +| env_vars | Map of custom ENV variables to be provided to the Jenkins application running on Elastic Beanstalk, e.g. env_vars = { JENKINS_USER = 'admin' JENKINS_PASS = 'xxxxxx' } | map(string) | `` | no | +| environment_type | Environment type, e.g. 'LoadBalanced' or 'SingleInstance'. If setting to 'SingleInstance', `rolling_update_type` must be set to 'Time' or `Immutable`, and `loadbalancer_subnets` will be unused (it applies to the ELB, which does not exist in SingleInstance environments) | string | `LoadBalanced` | no | | github_branch | GitHub repository branch, e.g. 'master'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' master branch | string | `master` | no | -| github_oauth_token | GitHub Oauth Token for accessing private repositories. Leave it empty when deploying a public 'Jenkins' repository, e.g. https://github.com/cloudposse/jenkins | string | `` | no | +| github_oauth_token | GitHub Oauth Token | string | - | yes | | github_organization | GitHub organization, e.g. 'cloudposse'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository | string | `cloudposse` | no | | github_repo_name | GitHub repository name, e.g. 'jenkins'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository | string | `jenkins` | no | | healthcheck_url | Application Health Check URL. Elastic Beanstalk will call this URL to check the health of the application running on EC2 instances | string | `/login` | no | | image_tag | Docker image tag in the ECR repository, e.g. 'latest'. Used as CodeBuild ENV variable $IMAGE_TAG when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html | string | `latest` | no | -| loadbalancer_certificate_arn | Load Balancer SSL certificate ARN. The certificate must be present in AWS Certificate Manager | string | - | yes | +| loadbalancer_certificate_arn | Load Balancer SSL certificate ARN. The certificate must be present in AWS Certificate Manager | string | `` | no | +| loadbalancer_logs_bucket_force_destroy | Force destroy the S3 bucket for load balancer logs even if it's not empty | bool | `false` | no | +| loadbalancer_subnets | List of subnets to place Elastic Load Balancer | list(string) | - | yes | | loadbalancer_type | Load Balancer type, e.g. 'application' or 'classic' | string | `application` | no | | master_instance_type | EC2 instance type for Jenkins master, e.g. 't2.medium' | string | `t2.medium` | no | -| name | Solution name, e.g. 'app' or 'jenkins' | string | `jenkins` | no | -| namespace | Namespace, which could be your organization name, e.g. 'cp' or 'cloudposse' | string | - | yes | -| noncurrent_version_expiration_days | Backup S3 bucket noncurrent version expiration days | string | `35` | no | -| private_subnets | List of private subnets to place EC2 instances and EFS | list | - | yes | -| public_subnets | List of public subnets to place Elastic Load Balancer | list | - | yes | -| security_groups | List of security groups to be allowed to connect to the EC2 instances | list | `` | no | -| solution_stack_name | Elastic Beanstalk stack, e.g. Docker, Go, Node, Java, IIS. For more info: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html | string | `64bit Amazon Linux 2017.09 v2.8.4 running Docker 17.09.1-ce` | no | -| ssh_key_pair | Name of SSH key that will be deployed on Elastic Beanstalk and DataPipeline instance. The key should be present in AWS | string | `` | no | -| stage | Stage, e.g. 'prod', 'staging', 'dev', or 'test' | string | - | yes | -| tags | Additional tags (e.g. `map('BusinessUnit`,`XYZ`) | map | `` | no | -| use_efs_ip_address | | string | `false` | no | +| name | Solution name, e.g. 'app' or 'jenkins' | string | - | yes | +| namespace | Namespace, which could be your organization name, e.g. 'eg' or 'cp' | string | `` | no | +| region | AWS region in which to provision the AWS resources | string | - | yes | +| rolling_update_type | `Health`, `Time` or `Immutable`. Set it to `Immutable` to apply the configuration change to a fresh group of instances. For more details, see https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingupdatepolicyrollingupdate | string | `Health` | no | +| solution_stack_name | Elastic Beanstalk stack, e.g. Docker, Go, Node, Java, IIS. For more info: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html | string | `64bit Amazon Linux 2018.03 v2.12.17 running Docker 18.06.1-ce` | no | +| ssh_key_pair | Name of SSH key that will be deployed on Elastic Beanstalk instances. The key should be present in AWS | string | `` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', or 'test' | string | `` | no | +| tags | Additional tags (e.g. `map('BusinessUnit`,`XYZ`) | map(string) | `` | no | +| use_efs_ip_address | If set to `true`, will provide the EFS IP address instead of DNS name to Jenkins as ENV var | bool | `false` | no | | vpc_id | ID of the VPC in which to provision the AWS resources | string | - | yes | -| zone_id | Route53 parent zone ID. The module will create sub-domain DNS records in the parent zone for the EB environment and EFS | string | - | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| codebuild_badge_url | The URL of the build badge when badge_enabled is enabled | +| codebuild_cache_bucket_arn | CodeBuild cache S3 bucket ARN | +| codebuild_cache_bucket_name | CodeBuild cache S3 bucket name | +| codebuild_project_id | CodeBuild project ID | +| codebuild_project_name | CodeBuild project name | +| codebuild_role_arn | CodeBuild IAM Role ARN | +| codebuild_role_id | CodeBuild IAM Role ID | +| codepipeline_arn | CodePipeline ARN | +| codepipeline_id | CodePipeline ID | +| ecr_registry_id | Registry ID | +| ecr_registry_url | Registry URL | +| ecr_repository_name | Registry name | +| efs_arn | EFS ARN | +| efs_backup_plan_arn | Backup Plan ARN | +| efs_backup_plan_version | Unique, randomly generated, Unicode, UTF-8 encoded string that serves as the version ID of the backup plan | +| efs_backup_selection_id | Backup Selection ID | +| efs_backup_vault_arn | Backup Vault ARN | +| efs_backup_vault_id | Backup Vault ID | +| efs_backup_vault_recovery_points | Backup Vault recovery points | +| efs_dns_name | EFS DNS name | +| efs_host | Route53 DNS hostname for the EFS | +| efs_id | EFS ID | +| efs_mount_target_dns_names | List of EFS mount target DNS names | +| efs_mount_target_ids | List of EFS mount target IDs (one per Availability Zone) | +| efs_mount_target_ips | List of EFS mount target IPs (one per Availability Zone) | +| efs_network_interface_ids | List of mount target network interface IDs | +| elastic_beanstalk_application_name | Elastic Beanstalk Application name | +| elastic_beanstalk_environment_all_settings | List of all option settings configured in the environment. These are a combination of default settings and their overrides from setting in the configuration | +| elastic_beanstalk_environment_application | The Elastic Beanstalk Application specified for this environment | +| elastic_beanstalk_environment_autoscaling_groups | The autoscaling groups used by this environment | +| elastic_beanstalk_environment_ec2_instance_profile_role_name | Instance IAM role name | +| elastic_beanstalk_environment_elb_zone_id | ELB zone id | +| elastic_beanstalk_environment_endpoint | Fully qualified DNS name for the environment | +| elastic_beanstalk_environment_hostname | DNS hostname | +| elastic_beanstalk_environment_id | ID of the Elastic Beanstalk environment | +| elastic_beanstalk_environment_instances | Instances used by this environment | +| elastic_beanstalk_environment_launch_configurations | Launch configurations in use by this environment | +| elastic_beanstalk_environment_load_balancers | Elastic Load Balancers in use by this environment | +| elastic_beanstalk_environment_name | Name | +| elastic_beanstalk_environment_queues | SQS queues in use by this environment | +| elastic_beanstalk_environment_security_group_id | Security group id | +| elastic_beanstalk_environment_setting | Settings specifically set for this environment | +| elastic_beanstalk_environment_tier | The environment tier | +| elastic_beanstalk_environment_triggers | Autoscaling triggers in use by this environment | diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars new file mode 100644 index 0000000..3e2da69 --- /dev/null +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -0,0 +1,69 @@ +region = "us-east-2" + +availability_zones = ["us-east-2a", "us-east-2b"] + +aws_account_id = "126450723953" + +namespace = "eg" + +stage = "test" + +name = "jenkins" + +description = "Jenkins server as Docker container running on Elastic Benastalk" + +master_instance_type = "t2.medium" + +healthcheck_url = "/login" + +# https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html +# https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html#platforms-supported.docker +solution_stack_name = "64bit Amazon Linux 2018.03 v2.12.17 running Docker 18.06.1-ce" + +dns_zone_id = "Z3SO0TKDDQ0RGG" + +availability_zone_selector = "Any" + +environment_type = "LoadBalanced" + +loadbalancer_type = "application" + +loadbalancer_logs_bucket_force_destroy = true + +cicd_bucket_force_destroy = true + +rolling_update_type = "Health" + +# `github_oauth_token` is required for CodePipeline to download the Jenkins repo (https://github.com/cloudposse/jenkins) from GitHub +# Can be provided in `TF_VAR_github_oauth_token` environment variable +# github_oauth_token = "XXXXXXXXXXXXXX" + +github_organization = "cloudposse" + +github_repo_name = "jenkins" + +github_branch = "master" + +# https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html +build_image = "aws/codebuild/docker:1.12.1" + +# https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html +build_compute_type = "BUILD_GENERAL1_SMALL" + +image_tag = "latest" + +efs_backup_schedule = "cron(0 12 * * ? *)" + +efs_backup_start_window = 60 + +efs_backup_completion_window = 120 + +efs_backup_cold_storage_after = 30 + +efs_backup_delete_after = 180 + +jenkins_username = "admin" + +jenkins_password = "1234567" + +jenkins_num_executors = 2 diff --git a/examples/complete/main.tf b/examples/complete/main.tf new file mode 100644 index 0000000..1ef053d --- /dev/null +++ b/examples/complete/main.tf @@ -0,0 +1,79 @@ +provider "aws" { + region = var.region +} + +module "vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.0" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + tags = var.tags + delimiter = var.delimiter + cidr_block = "172.16.0.0/16" +} + +module "subnets" { + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.16.0" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + attributes = var.attributes + tags = var.tags + delimiter = var.delimiter + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false +} + +module "jenkins" { + source = "../../" + namespace = var.namespace + stage = var.stage + name = var.name + description = var.description + + master_instance_type = var.master_instance_type + aws_account_id = var.aws_account_id + region = var.region + availability_zones = var.availability_zones + vpc_id = module.vpc.vpc_id + dns_zone_id = var.dns_zone_id + loadbalancer_subnets = module.subnets.public_subnet_ids + application_subnets = module.subnets.private_subnet_ids + + environment_type = var.environment_type + loadbalancer_type = var.loadbalancer_type + loadbalancer_certificate_arn = var.loadbalancer_certificate_arn + availability_zone_selector = var.availability_zone_selector + rolling_update_type = var.rolling_update_type + loadbalancer_logs_bucket_force_destroy = var.loadbalancer_logs_bucket_force_destroy + cicd_bucket_force_destroy = var.cicd_bucket_force_destroy + + github_oauth_token = var.github_oauth_token + github_organization = var.github_organization + github_repo_name = var.github_repo_name + github_branch = var.github_branch + + image_tag = var.image_tag + + healthcheck_url = var.healthcheck_url + + build_image = var.build_image + build_compute_type = var.build_compute_type + + efs_backup_schedule = var.efs_backup_schedule + efs_backup_start_window = var.efs_backup_start_window + efs_backup_completion_window = var.efs_backup_completion_window + efs_backup_cold_storage_after = var.efs_backup_cold_storage_after + efs_backup_delete_after = var.efs_backup_delete_after + + env_vars = { + "JENKINS_USER" = var.jenkins_username + "JENKINS_PASS" = var.jenkins_password + "JENKINS_NUM_EXECUTORS" = var.jenkins_num_executors + } +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf new file mode 100644 index 0000000..7dba59f --- /dev/null +++ b/examples/complete/outputs.tf @@ -0,0 +1,229 @@ +output "public_subnet_cidrs" { + value = module.subnets.public_subnet_cidrs + description = "Public subnet CIDRs" +} + +output "private_subnet_cidrs" { + value = module.subnets.private_subnet_cidrs + description = "Private subnet CIDRs" +} + +output "vpc_cidr" { + value = module.vpc.vpc_cidr_block + description = "VPC ID" +} + +output "elastic_beanstalk_application_name" { + value = module.jenkins.elastic_beanstalk_application_name + description = "Elastic Beanstalk Application name" +} + +output "elastic_beanstalk_environment_hostname" { + value = module.jenkins.elastic_beanstalk_environment_hostname + description = "DNS hostname" +} + +output "elastic_beanstalk_environment_id" { + description = "ID of the Elastic Beanstalk environment" + value = module.jenkins.elastic_beanstalk_environment_id +} + +output "elastic_beanstalk_environment_name" { + value = module.jenkins.elastic_beanstalk_environment_name + description = "Name" +} + +output "elastic_beanstalk_environment_security_group_id" { + value = module.jenkins.elastic_beanstalk_environment_security_group_id + description = "Security group id" +} + +output "elastic_beanstalk_environment_elb_zone_id" { + value = module.jenkins.elastic_beanstalk_environment_elb_zone_id + description = "ELB zone id" +} + +output "elastic_beanstalk_environment_ec2_instance_profile_role_name" { + value = module.jenkins.elastic_beanstalk_environment_ec2_instance_profile_role_name + description = "Instance IAM role name" +} + +output "elastic_beanstalk_environment_tier" { + description = "The environment tier" + value = module.jenkins.elastic_beanstalk_environment_tier +} + +output "elastic_beanstalk_environment_setting" { + description = "Settings specifically set for this environment" + value = module.jenkins.elastic_beanstalk_environment_setting +} + +output "elastic_beanstalk_environment_all_settings" { + description = "List of all option settings configured in the environment. These are a combination of default settings and their overrides from setting in the configuration" + value = module.jenkins.elastic_beanstalk_environment_all_settings +} + +output "elastic_beanstalk_environment_endpoint" { + description = "Fully qualified DNS name for the environment" + value = module.jenkins.elastic_beanstalk_environment_endpoint +} + +output "elastic_beanstalk_environment_autoscaling_groups" { + description = "The autoscaling groups used by this environment" + value = module.jenkins.elastic_beanstalk_environment_autoscaling_groups +} + +output "elastic_beanstalk_environment_instances" { + description = "Instances used by this environment" + value = module.jenkins.elastic_beanstalk_environment_instances +} + +output "elastic_beanstalk_environment_launch_configurations" { + description = "Launch configurations in use by this environment" + value = module.jenkins.elastic_beanstalk_environment_launch_configurations +} + +output "elastic_beanstalk_environment_load_balancers" { + description = "Elastic Load Balancers in use by this environment" + value = module.jenkins.elastic_beanstalk_environment_load_balancers +} + +output "elastic_beanstalk_environment_queues" { + description = "SQS queues in use by this environment" + value = module.jenkins.elastic_beanstalk_environment_queues +} + +output "elastic_beanstalk_environment_triggers" { + description = "Autoscaling triggers in use by this environment" + value = module.jenkins.elastic_beanstalk_environment_triggers +} + +output "ecr_registry_id" { + value = module.jenkins.ecr_registry_id + description = "Registry ID" +} + +output "ecr_registry_url" { + value = module.jenkins.ecr_registry_url + description = "Registry URL" +} + +output "ecr_repository_name" { + value = module.jenkins.ecr_repository_name + description = "Registry name" +} + +output "efs_arn" { + value = module.jenkins.efs_arn + description = "EFS ARN" +} + +output "efs_id" { + value = module.jenkins.efs_id + description = "EFS ID" +} + +output "efs_host" { + value = module.jenkins.efs_host + description = "Route53 DNS hostname for the EFS" +} + +output "efs_dns_name" { + value = module.jenkins.efs_dns_name + description = "EFS DNS name" +} + +output "efs_mount_target_dns_names" { + value = module.jenkins.efs_mount_target_dns_names + description = "List of EFS mount target DNS names" +} + +output "efs_mount_target_ids" { + value = module.jenkins.efs_mount_target_ids + description = "List of EFS mount target IDs (one per Availability Zone)" +} + +output "efs_mount_target_ips" { + value = module.jenkins.efs_mount_target_ips + description = "List of EFS mount target IPs (one per Availability Zone)" +} + +output "efs_network_interface_ids" { + value = module.jenkins.efs_network_interface_ids + description = "List of mount target network interface IDs" +} + +output "codebuild_project_name" { + description = "CodeBuild project name" + value = module.jenkins.codebuild_project_name +} + +output "codebuild_project_id" { + description = "CodeBuild project ID" + value = module.jenkins.codebuild_project_id +} + +output "codebuild_role_id" { + description = "CodeBuild IAM Role ID" + value = module.jenkins.codebuild_role_id +} + +output "codebuild_role_arn" { + description = "CodeBuild IAM Role ARN" + value = module.jenkins.codebuild_role_arn +} + +output "codebuild_cache_bucket_name" { + description = "CodeBuild cache S3 bucket name" + value = module.jenkins.codebuild_cache_bucket_name +} + +output "codebuild_cache_bucket_arn" { + description = "CodeBuild cache S3 bucket ARN" + value = module.jenkins.codebuild_cache_bucket_arn +} + +output "codebuild_badge_url" { + description = "The URL of the build badge when badge_enabled is enabled" + value = module.jenkins.codebuild_badge_url +} + +output "codepipeline_id" { + description = "CodePipeline ID" + value = module.jenkins.codepipeline_id +} + +output "codepipeline_arn" { + description = "CodePipeline ARN" + value = module.jenkins.codepipeline_arn +} + +output "efs_backup_vault_id" { + value = module.jenkins.efs_backup_vault_id + description = "Backup Vault ID" +} + +output "efs_backup_vault_arn" { + value = module.jenkins.efs_backup_vault_arn + description = "Backup Vault ARN" +} + +output "efs_backup_vault_recovery_points" { + value = module.jenkins.efs_backup_vault_recovery_points + description = "Backup Vault recovery points" +} + +output "efs_backup_plan_arn" { + value = module.jenkins.efs_backup_plan_arn + description = "Backup Plan ARN" +} + +output "efs_backup_plan_version" { + value = module.jenkins.efs_backup_plan_version + description = "Unique, randomly generated, Unicode, UTF-8 encoded string that serves as the version ID of the backup plan" +} + +output "efs_backup_selection_id" { + value = module.jenkins.efs_backup_selection_id + description = "Backup Selection ID" +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf new file mode 100644 index 0000000..bfb2693 --- /dev/null +++ b/examples/complete/variables.tf @@ -0,0 +1,188 @@ +variable "region" { + type = string + description = "AWS region in which to provision the AWS resources" +} + +variable "availability_zones" { + type = list(string) + description = "List of Availability Zones for EFS" +} + +variable "namespace" { + type = string + description = "Namespace, which could be your organization name, e.g. 'eg' or 'cp'" +} + +variable "stage" { + type = string + description = "Stage, e.g. 'prod', 'staging', 'dev', or 'test'" +} + +variable "name" { + type = string + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = "-" + description = "Delimiter to be used between `namespace`, `stage`, `name` and `attributes`" +} + +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 "description" { + type = string + description = "Will be used as Elastic Beanstalk application description" +} + +// https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html +// https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html#platforms-supported.docker +variable "solution_stack_name" { + type = string + description = "Elastic Beanstalk stack, e.g. Docker, Go, Node, Java, IIS. For more info: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html" +} + +variable "master_instance_type" { + type = string + description = "EC2 instance type for Jenkins master, e.g. 't2.medium'" +} + +variable "healthcheck_url" { + type = string + description = "Application Health Check URL. Elastic Beanstalk will call this URL to check the health of the application running on EC2 instances" +} + +variable "loadbalancer_type" { + type = string + description = "Load Balancer type, e.g. 'application' or 'classic'" +} + +variable "loadbalancer_certificate_arn" { + type = string + description = "Load Balancer SSL certificate ARN. The certificate must be present in AWS Certificate Manager" + default = "" +} + +variable "availability_zone_selector" { + type = string + description = "Availability Zone selector" +} + +variable "environment_type" { + type = string + description = "Environment type, e.g. 'LoadBalanced' or 'SingleInstance'. If setting to 'SingleInstance', `rolling_update_type` must be set to 'Time' or `Immutable`, and `loadbalancer_subnets` will be unused (it applies to the ELB, which does not exist in SingleInstance environments)" +} + +# https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingupdatepolicyrollingupdate +variable "rolling_update_type" { + type = string + description = "`Health`, `Time` or `Immutable`. Set it to `Immutable` to apply the configuration change to a fresh group of instances. For more details, see https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingupdatepolicyrollingupdate" +} + +variable "dns_zone_id" { + type = string + description = "Route53 parent zone ID. The module will create sub-domain DNS records in the parent zone for the EB environment and EFS" +} + +variable "github_oauth_token" { + type = string + description = "GitHub Oauth Token" +} + +variable "github_organization" { + type = string + description = "GitHub organization, e.g. 'cloudposse'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository" +} + +variable "github_repo_name" { + type = string + description = "GitHub repository name, e.g. 'jenkins'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository" +} + +variable "github_branch" { + type = string + description = "GitHub repository branch, e.g. 'master'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' master branch" +} + +# https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html +variable "build_image" { + type = string + description = "CodeBuild build image, e.g. 'aws/codebuild/amazonlinux2-x86_64-standard:1.0'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html" +} + +# https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html +variable "build_compute_type" { + type = string + description = "CodeBuild compute type, e.g. 'BUILD_GENERAL1_SMALL'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html" +} + +variable "aws_account_id" { + type = string + description = "AWS Account ID. Used as CodeBuild ENV variable $AWS_ACCOUNT_ID when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html" +} + +variable "image_tag" { + type = string + description = "Docker image tag in the ECR repository, e.g. 'latest'. Used as CodeBuild ENV variable $IMAGE_TAG when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html" +} + +variable "efs_backup_schedule" { + type = string + description = "A CRON expression specifying when AWS Backup initiates a backup job" +} + +variable "efs_backup_start_window" { + type = number + description = "The amount of time in minutes before beginning a backup. Minimum value is 60 minutes" +} + +variable "efs_backup_completion_window" { + type = number + description = "The amount of time AWS Backup attempts a backup before canceling the job and returning an error. Must be at least 60 minutes greater than `start_window`" +} + +variable "efs_backup_cold_storage_after" { + type = number + description = "Specifies the number of days after creation that a recovery point is moved to cold storage" +} + +variable "efs_backup_delete_after" { + type = number + description = "Specifies the number of days after creation that a recovery point is deleted. Must be 90 days greater than `cold_storage_after`" +} + +variable "jenkins_username" { + type = string + description = "Jenkins username" +} + +variable "jenkins_password" { + type = string + description = "Jenkins password" +} + +variable "jenkins_num_executors" { + type = number + description = "Number of Jenkins executors (slave instances)" +} + +variable "loadbalancer_logs_bucket_force_destroy" { + type = bool + description = "Force destroy the S3 bucket for load balancer logs" +} + +variable "cicd_bucket_force_destroy" { + type = bool + description = "Force destroy the CI/CD S3 bucket even if it's not empty" +} diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf new file mode 100644 index 0000000..43b0c82 --- /dev/null +++ b/examples/complete/versions.tf @@ -0,0 +1,11 @@ +terraform { + required_version = "~> 0.12.0" + + required_providers { + aws = "~> 2.0" + local = "~> 1.2" + null = "~> 2.0" + random = "~> 2.0" + template = "~> 2.0" + } +} diff --git a/examples/existing_vpc_existing_subnets/main.tf b/examples/existing_vpc_existing_subnets/main.tf index 3219b86..e7f456f 100644 --- a/examples/existing_vpc_existing_subnets/main.tf +++ b/examples/existing_vpc_existing_subnets/main.tf @@ -1,28 +1,28 @@ provider "aws" { - region = "us-west-2" + region = "us-east-2" } variable "max_availability_zones" { - default = "2" + default = 2 } data "aws_availability_zones" "available" {} module "jenkins" { source = "../../" - namespace = "cp" + namespace = "eg" + stage = "test" name = "jenkins" - stage = "prod" description = "Jenkins server as Docker container running on Elastic Beanstalk" master_instance_type = "t2.medium" aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] + region = "us-west-2" + availability_zones = slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones) vpc_id = "vpc-a22222ee" - zone_id = "ZXXXXXXXXXXX" - public_subnets = ["subnet-e63f82cb", "subnet-e66f44ab", "subnet-e88f42bd"] - private_subnets = ["subnet-e99d23eb", "subnet-e77e12bb", "subnet-e58a52bc"] + dns_zone_id = "ZXXXXXXXXXXX" + loadbalancer_subnets = ["subnet-e63f82cb", "subnet-e66f44ab", "subnet-e88f42bd"] + application_subnets = ["subnet-e99d23eb", "subnet-e77e12bb", "subnet-e58a52bc"] loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" ssh_key_pair = "ssh-key-jenkins" @@ -31,13 +31,6 @@ module "jenkins" { github_repo_name = "jenkins" github_branch = "master" - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } - env_vars = { JENKINS_USER = "admin" JENKINS_PASS = "123456" diff --git a/examples/existing_vpc_new_subnets/main.tf b/examples/existing_vpc_new_subnets/main.tf index 4f5f044..0a5de4f 100644 --- a/examples/existing_vpc_new_subnets/main.tf +++ b/examples/existing_vpc_new_subnets/main.tf @@ -1,28 +1,28 @@ provider "aws" { - region = "us-west-2" + region = "us-east-2" } variable "max_availability_zones" { - default = "2" + default = 2 } data "aws_availability_zones" "available" {} module "jenkins" { source = "../../" - namespace = "cp" + namespace = "eg" + stage = "test" name = "jenkins" - stage = "prod" description = "Jenkins server as Docker container running on Elastic Beanstalk" master_instance_type = "t2.medium" aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] + region = "us-east-2" + availability_zones = slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones) vpc_id = "vpc-a22222ee" - zone_id = "ZXXXXXXXXXXX" - public_subnets = "${module.subnets.public_subnet_ids}" - private_subnets = "${module.subnets.private_subnet_ids}" + dns_zone_id = "ZXXXXXXXXXXX" + loadbalancer_subnets = module.subnets.public_subnet_ids + application_subnets = module.subnets.private_subnet_ids loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" ssh_key_pair = "ssh-key-jenkins" @@ -31,13 +31,6 @@ module "jenkins" { github_repo_name = "jenkins" github_branch = "master" - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } - env_vars = { JENKINS_USER = "admin" JENKINS_PASS = "123456" @@ -52,10 +45,10 @@ module "jenkins" { module "subnets" { source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - namespace = "cp" + availability_zones = slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones) + namespace = "eg" + stage = "test" name = "jenkins" - stage = "prod" region = "us-west-2" vpc_id = "vpc-a22222ee" igw_id = "igw-s32321vd" diff --git a/examples/new_vpc_new_subnets/main.tf b/examples/new_vpc_new_subnets/main.tf index 1cf6c27..9a74db0 100644 --- a/examples/new_vpc_new_subnets/main.tf +++ b/examples/new_vpc_new_subnets/main.tf @@ -1,28 +1,28 @@ provider "aws" { - region = "us-west-2" + region = "us-east-2" } variable "max_availability_zones" { - default = "2" + default = 2 } data "aws_availability_zones" "available" {} module "jenkins" { source = "../../" - namespace = "cp" + namespace = "eg" + stage = "test" name = "jenkins" - stage = "prod" description = "Jenkins server as Docker container running on Elastic Beanstalk" master_instance_type = "t2.medium" aws_account_id = "000111222333" - aws_region = "us-west-2" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - vpc_id = "${module.vpc.vpc_id}" - zone_id = "ZXXXXXXXXXXX" - public_subnets = "${module.subnets.public_subnet_ids}" - private_subnets = "${module.subnets.private_subnet_ids}" + region = "us-east-2" + availability_zones = slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones) + vpc_id = module.vpc.vpc_id + dns_zone_id = "ZXXXXXXXXXXX" + loadbalancer_subnets = module.subnets.public_subnet_ids + application_subnets = module.subnets.private_subnet_ids loadbalancer_certificate_arn = "XXXXXXXXXXXXXXXXX" ssh_key_pair = "ssh-key-jenkins" @@ -31,13 +31,6 @@ module "jenkins" { github_repo_name = "jenkins" github_branch = "master" - datapipeline_config = { - instance_type = "t2.medium" - email = "me@mycompany.com" - period = "12 hours" - timeout = "60 Minutes" - } - env_vars = { JENKINS_USER = "admin" JENKINS_PASS = "123456" @@ -52,9 +45,9 @@ module "jenkins" { module "vpc" { source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=master" - namespace = "cp" + namespace = "eg" + stage = "test" name = "jenkins" - stage = "prod" cidr_block = "10.0.0.0/16" tags = { @@ -65,15 +58,15 @@ module "vpc" { module "subnets" { source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=master" - availability_zones = ["${slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones)}"] - namespace = "cp" + availability_zones = slice(data.aws_availability_zones.available.names, 0, var.max_availability_zones) + namespace = "eg" + stage = "test" name = "jenkins" - stage = "prod" - region = "us-west-2" - vpc_id = "${module.vpc.vpc_id}" - igw_id = "${module.vpc.igw_id}" - cidr_block = "${module.vpc.vpc_cidr_block}" - nat_gateway_enabled = "true" + region = "us-east-2" + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = true tags = { BusinessUnit = "ABC" diff --git a/main.tf b/main.tf index 8cd987d..0a574be 100644 --- a/main.tf +++ b/main.tf @@ -1,24 +1,36 @@ # Elastic Beanstalk Application module "elastic_beanstalk_application" { - source = "git::https://github.com/cloudposse/terraform-aws-elastic-beanstalk-application.git?ref=tags/0.1.6" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - description = "${var.description}" - delimiter = "${var.delimiter}" - attributes = ["${compact(concat(var.attributes, list("eb-app")))}"] - tags = "${var.tags}" + source = "git::https://github.com/cloudposse/terraform-aws-elastic-beanstalk-application.git?ref=tags/0.4.0" + namespace = var.namespace + name = var.name + stage = var.stage + description = var.description + delimiter = var.delimiter + attributes = compact(concat(var.attributes, ["app"])) + tags = var.tags } # Elastic Beanstalk Environment module "elastic_beanstalk_environment" { - source = "git::https://github.com/cloudposse/terraform-aws-elastic-beanstalk-environment.git?ref=tags/0.11.0" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - zone_id = "${var.zone_id}" - app = "${module.elastic_beanstalk_application.app_name}" - instance_type = "${var.master_instance_type}" + source = "git::https://github.com/cloudposse/terraform-aws-elastic-beanstalk-environment.git?ref=tags/0.16.0" + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = compact(concat(var.attributes, ["env"])) + tags = var.tags + + region = var.region + dns_zone_id = var.dns_zone_id + elastic_beanstalk_application_name = module.elastic_beanstalk_application.elastic_beanstalk_application_name + instance_type = var.master_instance_type + + tier = "WebServer" + environment_type = var.environment_type + loadbalancer_type = var.loadbalancer_type + loadbalancer_certificate_arn = var.loadbalancer_certificate_arn + availability_zone_selector = var.availability_zone_selector + rolling_update_type = var.rolling_update_type # Set `min` and `max` number of running EC2 instances to `1` since we want only one Jenkins master running at any time autoscale_min = 1 @@ -26,140 +38,129 @@ module "elastic_beanstalk_environment" { # Since we set `autoscale_min = autoscale_max`, we need to set `updating_min_in_service` to 0 for the AutoScaling Group to work. # Elastic Beanstalk will terminate the master instance and replace it with a new one in case of any issues with it. - # But it's OK since we store all Jenkins state (settings, jobs, etc.) on the EFS. - # If the instance gets replaced or rebooted, Jenkins will find all the data on EFS after restart. + # It's OK since we store all Jenkins state (settings, jobs, etc.) on the EFS. + # If the instance gets replaced or rebooted, Jenkins will find all the data on the EFS after restart. updating_min_in_service = 0 updating_max_batch = 1 - healthcheck_url = "${var.healthcheck_url}" - loadbalancer_type = "${var.loadbalancer_type}" - loadbalancer_certificate_arn = "${var.loadbalancer_certificate_arn}" - vpc_id = "${var.vpc_id}" - public_subnets = "${var.public_subnets}" - private_subnets = "${var.private_subnets}" - security_groups = "${var.security_groups}" - keypair = "${var.ssh_key_pair}" - solution_stack_name = "${var.solution_stack_name}" - env_default_key = "${var.env_default_key}" - env_default_value = "${var.env_default_value}" + healthcheck_url = var.healthcheck_url + vpc_id = var.vpc_id + loadbalancer_subnets = var.loadbalancer_subnets + application_subnets = var.application_subnets + allowed_security_groups = var.allowed_security_groups + keypair = var.ssh_key_pair + solution_stack_name = var.solution_stack_name + force_destroy = var.loadbalancer_logs_bucket_force_destroy # Provide EFS DNS name to EB in the `EFS_HOST` ENV var. EC2 instance will mount to the EFS filesystem and use it to store Jenkins state # Add slaves Security Group `JENKINS_SLAVE_SECURITY_GROUPS` (comma-separated if more than one). Will be used by Jenkins to init the EC2 plugin to launch slaves inside the Security Group - env_vars = "${ - merge( - map( - "EFS_HOST", "${var.use_efs_ip_address ? module.efs.mount_target_ips[0] : module.efs.dns_name}", - "USE_EFS_IP", "${var.use_efs_ip_address}", - "JENKINS_SLAVE_SECURITY_GROUPS", "${aws_security_group.slaves.id}" - ), var.env_vars - ) - }" - - delimiter = "${var.delimiter}" - attributes = ["${compact(concat(var.attributes, list("eb-env")))}"] - tags = "${var.tags}" + env_vars = merge( + { + "EFS_HOST" = var.use_efs_ip_address ? module.efs.mount_target_ips[0] : module.efs.dns_name + "USE_EFS_IP" = var.use_efs_ip_address + "JENKINS_SLAVE_SECURITY_GROUPS" = aws_security_group.slaves.id + }, + var.env_vars + ) } # Elastic Container Registry Docker Repository module "ecr" { - source = "git::https://github.com/cloudposse/terraform-aws-ecr.git?ref=tags/0.6.0" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - delimiter = "${var.delimiter}" - attributes = ["${compact(concat(var.attributes, list("ecr")))}"] - tags = "${var.tags}" + source = "git::https://github.com/cloudposse/terraform-aws-ecr.git?ref=tags/0.7.0" + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags } # EFS to store Jenkins state (settings, jobs, etc.) module "efs" { - source = "git::https://github.com/cloudposse/terraform-aws-efs.git?ref=tags/0.9.0" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - aws_region = "${var.aws_region}" - vpc_id = "${var.vpc_id}" - subnets = "${var.private_subnets}" - availability_zones = "${var.availability_zones}" - zone_id = "${var.zone_id}" - - # EC2 instances (from `elastic_beanstalk_environment`) and DataPipeline instances (from `efs_backup`) are allowed to connect to the EFS - security_groups = ["${module.elastic_beanstalk_environment.security_group_id}", "${module.efs_backup.security_group_id}"] - - delimiter = "${var.delimiter}" - attributes = ["${compact(concat(var.attributes, list("efs")))}"] - tags = "${var.tags}" + source = "git::https://github.com/cloudposse/terraform-aws-efs.git?ref=tags/0.11.0" + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = compact(concat(var.attributes, ["efs"])) + tags = var.tags + region = var.region + vpc_id = var.vpc_id + subnets = var.application_subnets + zone_id = var.dns_zone_id + + # EC2 instances (from `elastic_beanstalk_environment`) are allowed to connect to the EFS + security_groups = [module.elastic_beanstalk_environment.security_group_id] } -# EFS backup to S3 +# EFS backup module "efs_backup" { - source = "git::https://github.com/cloudposse/terraform-aws-efs-backup.git?ref=tags/0.9.0" - name = "${var.name}" - stage = "${var.stage}" - namespace = "${var.namespace}" - region = "${var.aws_region}" - vpc_id = "${var.vpc_id}" - efs_mount_target_id = "${element(module.efs.mount_target_ids, 0)}" - use_ip_address = "${var.use_efs_ip_address}" - noncurrent_version_expiration_days = "${var.noncurrent_version_expiration_days}" - ssh_key_pair = "${var.ssh_key_pair}" - modify_security_group = "false" - datapipeline_config = "${var.datapipeline_config}" - delimiter = "${var.delimiter}" - attributes = ["${compact(concat(var.attributes, list("efs-backup")))}"] - tags = "${var.tags}" + source = "git::https://github.com/cloudposse/terraform-aws-backup.git?ref=tags/0.1.1" + namespace = var.namespace + stage = var.stage + name = var.name + attributes = compact(concat(var.attributes, ["efs"])) + tags = var.tags + delimiter = var.delimiter + backup_resources = [module.efs.arn] + schedule = var.efs_backup_schedule + start_window = var.efs_backup_start_window + completion_window = var.efs_backup_completion_window + cold_storage_after = var.efs_backup_cold_storage_after + delete_after = var.efs_backup_delete_after } # CodePipeline/CodeBuild to build Jenkins Docker image, store it to a ECR repo, and deploy it to Elastic Beanstalk running Docker stack module "cicd" { - source = "git::https://github.com/cloudposse/terraform-aws-cicd.git?ref=tags/0.6.0" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - app = "${module.elastic_beanstalk_application.app_name}" - env = "${module.elastic_beanstalk_environment.name}" - enabled = "true" - github_oauth_token = "${var.github_oauth_token}" - repo_owner = "${var.github_organization}" - repo_name = "${var.github_repo_name}" - branch = "${var.github_branch}" - build_image = "${var.build_image}" - build_compute_type = "${var.build_compute_type}" - privileged_mode = "true" - aws_region = "${var.aws_region}" - aws_account_id = "${var.aws_account_id}" - image_repo_name = "${module.ecr.repository_name}" - image_tag = "${var.image_tag}" - poll_source_changes = "true" - delimiter = "${var.delimiter}" - attributes = ["${compact(concat(var.attributes, list("cicd")))}"] - tags = "${var.tags}" + source = "git::https://github.com/cloudposse/terraform-aws-cicd.git?ref=tags/0.8.0" + namespace = var.namespace + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = compact(concat(var.attributes, ["cicd"])) + tags = var.tags + elastic_beanstalk_application_name = module.elastic_beanstalk_application.elastic_beanstalk_application_name + elastic_beanstalk_environment_name = module.elastic_beanstalk_environment.name + enabled = true + github_oauth_token = var.github_oauth_token + repo_owner = var.github_organization + repo_name = var.github_repo_name + branch = var.github_branch + build_image = var.build_image + build_compute_type = var.build_compute_type + privileged_mode = true + region = var.region + aws_account_id = var.aws_account_id + image_repo_name = module.ecr.repository_name + image_tag = var.image_tag + poll_source_changes = true + force_destroy = var.cicd_bucket_force_destroy } # Label for EC2 slaves module "label_slaves" { - source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.7.0" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - delimiter = "${var.delimiter}" - attributes = ["${compact(concat(var.attributes, list("slaves")))}"] - tags = "${var.tags}" + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.15.0" + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = compact(concat(var.attributes, ["slaves"])) + tags = var.tags } # Security Group for EC2 slaves resource "aws_security_group" "slaves" { - name = "${module.label_slaves.id}" + name = module.label_slaves.id description = "Security Group for Jenkins EC2 slaves" - vpc_id = "${var.vpc_id}" + vpc_id = var.vpc_id # Allow the provided Security Groups to connect to Jenkins slave instances ingress { from_port = 0 to_port = 0 protocol = -1 - security_groups = ["${var.security_groups}"] + security_groups = var.allowed_security_groups } # Allow Jenkins master instance to communicate with Jenkins slave instances on SSH port 22 @@ -167,7 +168,7 @@ resource "aws_security_group" "slaves" { from_port = 22 to_port = 22 protocol = "tcp" - security_groups = ["${module.elastic_beanstalk_environment.security_group_id}"] + security_groups = [module.elastic_beanstalk_environment.security_group_id] } egress { @@ -177,7 +178,7 @@ resource "aws_security_group" "slaves" { cidr_blocks = ["0.0.0.0/0"] } - tags = "${module.label_slaves.tags}" + tags = module.label_slaves.tags } # Policy document with permissions to launch new EC2 instances @@ -204,7 +205,7 @@ data "aws_iam_policy_document" "slaves" { "ec2:DescribeAvailabilityZones", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", - "iam:PassRole", + "iam:PassRole" ] resources = ["*"] @@ -214,14 +215,14 @@ data "aws_iam_policy_document" "slaves" { # Policy for the EB EC2 instance profile to allow launching Jenkins slaves resource "aws_iam_policy" "slaves" { - name = "${module.label_slaves.id}" + name = module.label_slaves.id path = "/" description = "Policy for EC2 instance profile to allow launching Jenkins slaves" - policy = "${data.aws_iam_policy_document.slaves.json}" + policy = data.aws_iam_policy_document.slaves.json } # Attach Policy to the EC2 instance profile to allow Jenkins master to launch and control slave EC2 instances resource "aws_iam_role_policy_attachment" "slaves" { - role = "${module.elastic_beanstalk_environment.ec2_instance_profile_role_name}" - policy_arn = "${aws_iam_policy.slaves.arn}" + role = module.elastic_beanstalk_environment.ec2_instance_profile_role_name + policy_arn = aws_iam_policy.slaves.arn } diff --git a/outputs.tf b/outputs.tf index 8b13789..1ee4775 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1 +1,219 @@ +output "elastic_beanstalk_application_name" { + value = module.elastic_beanstalk_application.elastic_beanstalk_application_name + description = "Elastic Beanstalk Application name" +} +output "elastic_beanstalk_environment_hostname" { + value = module.elastic_beanstalk_environment.hostname + description = "DNS hostname" +} + +output "elastic_beanstalk_environment_id" { + description = "ID of the Elastic Beanstalk environment" + value = module.elastic_beanstalk_environment.id +} + +output "elastic_beanstalk_environment_name" { + value = module.elastic_beanstalk_environment.name + description = "Name" +} + +output "elastic_beanstalk_environment_security_group_id" { + value = module.elastic_beanstalk_environment.security_group_id + description = "Security group id" +} + +output "elastic_beanstalk_environment_elb_zone_id" { + value = module.elastic_beanstalk_environment.elb_zone_id + description = "ELB zone id" +} + +output "elastic_beanstalk_environment_ec2_instance_profile_role_name" { + value = module.elastic_beanstalk_environment.ec2_instance_profile_role_name + description = "Instance IAM role name" +} + +output "elastic_beanstalk_environment_tier" { + description = "The environment tier" + value = module.elastic_beanstalk_environment.tier +} + +output "elastic_beanstalk_environment_application" { + description = "The Elastic Beanstalk Application specified for this environment" + value = module.elastic_beanstalk_environment.application +} + +output "elastic_beanstalk_environment_setting" { + description = "Settings specifically set for this environment" + value = module.elastic_beanstalk_environment.setting +} + +output "elastic_beanstalk_environment_all_settings" { + description = "List of all option settings configured in the environment. These are a combination of default settings and their overrides from setting in the configuration" + value = module.elastic_beanstalk_environment.all_settings +} + +output "elastic_beanstalk_environment_endpoint" { + description = "Fully qualified DNS name for the environment" + value = module.elastic_beanstalk_environment.endpoint +} + +output "elastic_beanstalk_environment_autoscaling_groups" { + description = "The autoscaling groups used by this environment" + value = module.elastic_beanstalk_environment.autoscaling_groups +} + +output "elastic_beanstalk_environment_instances" { + description = "Instances used by this environment" + value = module.elastic_beanstalk_environment.instances +} + +output "elastic_beanstalk_environment_launch_configurations" { + description = "Launch configurations in use by this environment" + value = module.elastic_beanstalk_environment.launch_configurations +} + +output "elastic_beanstalk_environment_load_balancers" { + description = "Elastic Load Balancers in use by this environment" + value = module.elastic_beanstalk_environment.load_balancers +} + +output "elastic_beanstalk_environment_queues" { + description = "SQS queues in use by this environment" + value = module.elastic_beanstalk_environment.queues +} + +output "elastic_beanstalk_environment_triggers" { + description = "Autoscaling triggers in use by this environment" + value = module.elastic_beanstalk_environment.triggers +} + +output "ecr_registry_id" { + value = module.ecr.registry_id + description = "Registry ID" +} + +output "ecr_registry_url" { + value = module.ecr.registry_url + description = "Registry URL" +} + +output "ecr_repository_name" { + value = module.ecr.repository_name + description = "Registry name" +} + +output "efs_arn" { + value = module.efs.arn + description = "EFS ARN" +} + +output "efs_id" { + value = module.efs.id + description = "EFS ID" +} + +output "efs_host" { + value = module.efs.host + description = "Route53 DNS hostname for the EFS" +} + +output "efs_dns_name" { + value = module.efs.dns_name + description = "EFS DNS name" +} + +output "efs_mount_target_dns_names" { + value = module.efs.mount_target_dns_names + description = "List of EFS mount target DNS names" +} + +output "efs_mount_target_ids" { + value = module.efs.mount_target_ids + description = "List of EFS mount target IDs (one per Availability Zone)" +} + +output "efs_mount_target_ips" { + value = module.efs.mount_target_ips + description = "List of EFS mount target IPs (one per Availability Zone)" +} + +output "efs_network_interface_ids" { + value = module.efs.network_interface_ids + description = "List of mount target network interface IDs" +} + +output "codebuild_project_name" { + description = "CodeBuild project name" + value = module.cicd.codebuild_project_name +} + +output "codebuild_project_id" { + description = "CodeBuild project ID" + value = module.cicd.codebuild_project_id +} + +output "codebuild_role_id" { + description = "CodeBuild IAM Role ID" + value = module.cicd.codebuild_role_id +} + +output "codebuild_role_arn" { + description = "CodeBuild IAM Role ARN" + value = module.cicd.codebuild_role_arn +} + +output "codebuild_cache_bucket_name" { + description = "CodeBuild cache S3 bucket name" + value = module.cicd.codebuild_cache_bucket_name +} + +output "codebuild_cache_bucket_arn" { + description = "CodeBuild cache S3 bucket ARN" + value = module.cicd.codebuild_cache_bucket_arn +} + +output "codebuild_badge_url" { + description = "The URL of the build badge when badge_enabled is enabled" + value = module.cicd.codebuild_badge_url +} + +output "codepipeline_id" { + description = "CodePipeline ID" + value = module.cicd.codepipeline_id +} + +output "codepipeline_arn" { + description = "CodePipeline ARN" + value = module.cicd.codepipeline_arn +} + +output "efs_backup_vault_id" { + value = module.efs_backup.backup_vault_id + description = "Backup Vault ID" +} + +output "efs_backup_vault_arn" { + value = module.efs_backup.backup_vault_arn + description = "Backup Vault ARN" +} + +output "efs_backup_vault_recovery_points" { + value = module.efs_backup.backup_vault_recovery_points + description = "Backup Vault recovery points" +} + +output "efs_backup_plan_arn" { + value = module.efs_backup.backup_plan_arn + description = "Backup Plan ARN" +} + +output "efs_backup_plan_version" { + value = module.efs_backup.backup_plan_version + description = "Unique, randomly generated, Unicode, UTF-8 encoded string that serves as the version ID of the backup plan" +} + +output "efs_backup_selection_id" { + value = module.efs_backup.backup_selection_id + description = "Backup Selection ID" +} diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..4cd30cb --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +.test-harness \ No newline at end of file diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..17b2fe7 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,43 @@ +TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git +TEST_HARNESS_BRANCH ?= master +TEST_HARNESS_PATH = $(realpath .test-harness) +BATS_ARGS ?= --tap +BATS_LOG ?= test.log + +# Define a macro to run the tests +define RUN_TESTS +@echo "Running tests in $(1)" +@cd $(1) && bats $(BATS_ARGS) $(addsuffix .bats,$(addprefix $(TEST_HARNESS_PATH)/test/terraform/,$(TESTS))) +endef + +default: all + +-include Makefile.* + +## Provision the test-harnesss +.test-harness: + [ -d $@ ] || git clone --depth=1 -b $(TEST_HARNESS_BRANCH) $(TEST_HARNESS) $@ + +## Initialize the tests +init: .test-harness + +## Install all dependencies (OS specific) +deps:: + @exit 0 + +## Clean up the test harness +clean: + [ "$(TEST_HARNESS_PATH)" == "/" ] || rm -rf $(TEST_HARNESS_PATH) + +## Run all tests +all: module examples/complete + +## Run basic sanity checks against the module itself +module: export TESTS ?= installed lint get-modules module-pinning get-plugins provider-pinning validate terraform-docs input-descriptions output-descriptions +module: deps + $(call RUN_TESTS, ../) + +## Run tests against example +examples/complete: export TESTS ?= installed lint get-modules get-plugins validate +examples/complete: deps + $(call RUN_TESTS, ../$@) diff --git a/test/Makefile.alpine b/test/Makefile.alpine new file mode 100644 index 0000000..7925b18 --- /dev/null +++ b/test/Makefile.alpine @@ -0,0 +1,5 @@ +ifneq (,$(wildcard /sbin/apk)) +## Install all dependencies for alpine +deps:: init + @apk add --update terraform-docs@cloudposse json2hcl@cloudposse +endif diff --git a/test/src/.gitignore b/test/src/.gitignore new file mode 100644 index 0000000..a7c7c18 --- /dev/null +++ b/test/src/.gitignore @@ -0,0 +1,2 @@ +.gopath +vendor/ \ No newline at end of file diff --git a/test/src/Gopkg.lock b/test/src/Gopkg.lock new file mode 100644 index 0000000..87bb6bd --- /dev/null +++ b/test/src/Gopkg.lock @@ -0,0 +1,92 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" + +[[projects]] + digest = "1:75d6042fc66aebc974cc49b0c6c7cc3b9adb5f8130fbfa0dbec0820d990afa25" + name = "github.com/gruntwork-io/terratest" + packages = [ + "modules/collections", + "modules/customerrors", + "modules/files", + "modules/logger", + "modules/retry", + "modules/shell", + "modules/ssh", + "modules/terraform", + ] + pruneopts = "UT" + revision = "892abb2c35878d0808101bbfe6559e931dc2d354" + version = "v0.16.0" + +[[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + pruneopts = "UT" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + digest = "1:5da8ce674952566deae4dbc23d07c85caafc6cfa815b0b3e03e41979cedb8750" + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require", + ] + pruneopts = "UT" + revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053" + version = "v1.3.0" + +[[projects]] + branch = "master" + digest = "1:831470c2758c8b733941144f2803a0ccad0632c5a767415b777ebd296b5f463e" + name = "golang.org/x/crypto" + packages = [ + "curve25519", + "ed25519", + "ed25519/internal/edwards25519", + "internal/chacha20", + "internal/subtle", + "poly1305", + "ssh", + "ssh/agent", + ] + pruneopts = "UT" + revision = "22d7a77e9e5f409e934ed268692e56707cd169e5" + +[[projects]] + branch = "master" + digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70" + name = "golang.org/x/net" + packages = ["context"] + pruneopts = "UT" + revision = "f3200d17e092c607f615320ecaad13d87ad9a2b3" + +[[projects]] + branch = "master" + digest = "1:181f3fd33e620b958b5ab77da177cf775cdcccd7db82963607875fbd09ae995e" + name = "golang.org/x/sys" + packages = [ + "cpu", + "unix", + ] + pruneopts = "UT" + revision = "9cd6430ef91e39e1a0ec0470cf1321a33ef1b887" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/gruntwork-io/terratest/modules/terraform", + "github.com/stretchr/testify/assert", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/test/src/Gopkg.toml b/test/src/Gopkg.toml new file mode 100644 index 0000000..995bac5 --- /dev/null +++ b/test/src/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.2" + +[prune] + go-tests = true + unused-packages = true diff --git a/test/src/Makefile b/test/src/Makefile new file mode 100644 index 0000000..179da56 --- /dev/null +++ b/test/src/Makefile @@ -0,0 +1,50 @@ +PACKAGE = terraform-aws-jenkins +GOEXE ?= /usr/bin/go +GOPATH = $(CURDIR)/.gopath +GOBIN = $(GOPATH)/bin +BASE = $(GOPATH)/src/$(PACKAGE) +PATH := $(PATH):$(GOBIN) + +export TF_DATA_DIR ?= $(CURDIR)/.terraform +export TF_CLI_ARGS_init ?= -get-plugins=true +export GOPATH + +.PHONY: all +## Default target +all: test + +ifneq (,$(wildcard /sbin/apk)) +## Install go, if not installed +$(GOEXE): + apk add --update go +endif + +ifeq ($(shell uname -s),Linux) +## Install all `dep`, if not installed +$(GOBIN)/dep: + @mkdir -p $(GOBIN) + @curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh +endif + +## Prepare the GOPATH +$(BASE): $(GOEXE) + @mkdir -p $(dir $@) + @ln -sf $(CURDIR) $@ + +## Download vendor dependencies to vendor/ +$(BASE)/vendor: $(BASE) $(GOBIN)/dep + cd $(BASE) && dep ensure + +.PHONY : init +## Initialize tests +init: $(BASE)/vendor + +.PHONY : test +## Run tests +test: init + cd $(BASE) && go test -v -timeout 30m -run TestExamplesComplete + +.PHONY : clean +## Clean up files +clean: + rm -rf .gopath/ vendor/ $(TF_DATA_DIR) diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go new file mode 100644 index 0000000..c0774b7 --- /dev/null +++ b/test/src/examples_complete_test.go @@ -0,0 +1,116 @@ +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +// Test the Terraform module in examples/complete using Terratest. +func TestExamplesComplete(t *testing.T) { + t.Parallel() + + terraformOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/complete", + Upgrade: true, + // Variables to pass to our Terraform code using -var-file options + VarFiles: []string{"fixtures.us-east-2.tfvars"}, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` + _, err := terraform.InitAndApplyE(t, terraformOptions) + + /* + We need to apply twice because of the current bug with `dynamic` blocks in terraform `aws` provider: + + Error: Provider produced inconsistent final plan + When expanding the plan for + module.jenkins.module.elastic_beanstalk_environment.aws_elastic_beanstalk_environment.default + to include new values learned so far during apply, provider "aws" produced an + invalid new value for .setting: block set length changed from 72 to 77. + This is a bug in the provider, which should be reported in the provider's own issue tracker. + + https://github.com/terraform-providers/terraform-provider-aws/issues/10297 + https://github.com/terraform-providers/terraform-provider-aws/issues/7987 + https://github.com/hashicorp/terraform/issues/20517 + */ + + if err != nil { + terraform.Apply(t, terraformOptions) + } + + // Run `terraform output` to get the value of an output variable + vpcCidr := terraform.Output(t, terraformOptions, "vpc_cidr") + // Verify we're getting back the outputs we expect + assert.Equal(t, "172.16.0.0/16", vpcCidr) + + // Run `terraform output` to get the value of an output variable + privateSubnetCidrs := terraform.OutputList(t, terraformOptions, "private_subnet_cidrs") + // Verify we're getting back the outputs we expect + assert.Equal(t, []string{"172.16.0.0/19", "172.16.32.0/19"}, privateSubnetCidrs) + + // Run `terraform output` to get the value of an output variable + publicSubnetCidrs := terraform.OutputList(t, terraformOptions, "public_subnet_cidrs") + // Verify we're getting back the outputs we expect + assert.Equal(t, []string{"172.16.96.0/19", "172.16.128.0/19"}, publicSubnetCidrs) + + // Run `terraform output` to get the value of an output variable + elasticBeanstalkApplicationName := terraform.Output(t, terraformOptions, "elastic_beanstalk_application_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-jenkins-app", elasticBeanstalkApplicationName) + + // Run `terraform output` to get the value of an output variable + elasticBeanstalkEnvironmentName := terraform.Output(t, terraformOptions, "elastic_beanstalk_environment_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-jenkins-env", elasticBeanstalkEnvironmentName) + + // Run `terraform output` to get the value of an output variable + elasticBeanstalkEnvironmentHostname := terraform.Output(t, terraformOptions, "elastic_beanstalk_environment_hostname") + // Verify we're getting back the outputs we expect + assert.Equal(t, "jenkins.testing.cloudposse.co", elasticBeanstalkEnvironmentHostname) + + // Run `terraform output` to get the value of an output variable + ecrRepositoryName := terraform.Output(t, terraformOptions, "ecr_repository_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-jenkins", ecrRepositoryName) + + // Run `terraform output` to get the value of an output variable + codebuildProjectName := terraform.Output(t, terraformOptions, "codebuild_project_name") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-jenkins-cicd-build", codebuildProjectName) + + // Run `terraform output` to get the value of an output variable + codebuildCacheBucketName := terraform.Output(t, terraformOptions, "codebuild_cache_bucket_name") + // Verify we're getting back the outputs we expect + assert.Contains(t, codebuildCacheBucketName, "eg-test-jenkins-cicd-build") + + // Run `terraform output` to get the value of an output variable + codepipelineId := terraform.Output(t, terraformOptions, "codepipeline_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-jenkins-cicd", codepipelineId) + + // Run `terraform output` to get the value of an output variable + efsArn := terraform.Output(t, terraformOptions, "efs_arn") + // Verify we're getting back the outputs we expect + assert.Contains(t, efsArn, "arn:aws:elasticfilesystem:us-east-2:126450723953:file-system") + + // Run `terraform output` to get the value of an output variable + efsBackupPlanArn := terraform.Output(t, terraformOptions, "efs_backup_plan_arn") + // Verify we're getting back the outputs we expect + assert.Contains(t, efsBackupPlanArn, "arn:aws:backup:us-east-2:126450723953:backup-plan") + + // Run `terraform output` to get the value of an output variable + efsBackupVaultArn := terraform.Output(t, terraformOptions, "efs_backup_vault_arn") + // Verify we're getting back the outputs we expect + assert.Equal(t, "arn:aws:backup:us-east-2:126450723953:backup-vault:eg-test-jenkins-efs", efsBackupVaultArn) + + // Run `terraform output` to get the value of an output variable + efsBackupVaultId := terraform.Output(t, terraformOptions, "efs_backup_vault_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-jenkins-efs", efsBackupVaultId) +} diff --git a/variables.tf b/variables.tf index e04a5c6..2ecbac5 100644 --- a/variables.tf +++ b/variables.tf @@ -1,201 +1,235 @@ -variable "aws_region" { - type = "string" - default = "us-west-2" +variable "region" { + type = string description = "AWS region in which to provision the AWS resources" } variable "namespace" { - type = "string" - description = "Namespace, which could be your organization name, e.g. 'cp' or 'cloudposse'" + type = string + description = "Namespace, which could be your organization name, e.g. 'eg' or 'cp'" + default = "" +} + +variable "stage" { + type = string + description = "Stage, e.g. 'prod', 'staging', 'dev', or 'test'" + default = "" } variable "name" { - type = "string" + type = string description = "Solution name, e.g. 'app' or 'jenkins'" - default = "jenkins" } -variable "stage" { - type = "string" - description = "Stage, e.g. 'prod', 'staging', 'dev', or 'test'" +variable "delimiter" { + type = string + default = "-" + description = "Delimiter to be used between `namespace`, `stage`, `name` and `attributes`" +} + +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 "description" { - type = "string" + type = string default = "Jenkins server as Docker container running on Elastic Benastalk" description = "Will be used as Elastic Beanstalk application description" } -# http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html#concepts.platforms.docker +// https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html +// https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platforms-supported.html#platforms-supported.docker variable "solution_stack_name" { - type = "string" - default = "64bit Amazon Linux 2017.09 v2.8.4 running Docker 17.09.1-ce" + type = string + default = "64bit Amazon Linux 2018.03 v2.12.17 running Docker 18.06.1-ce" description = "Elastic Beanstalk stack, e.g. Docker, Go, Node, Java, IIS. For more info: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/concepts.platforms.html" } variable "master_instance_type" { - type = "string" + type = string default = "t2.medium" description = "EC2 instance type for Jenkins master, e.g. 't2.medium'" } variable "vpc_id" { - type = "string" + type = string description = "ID of the VPC in which to provision the AWS resources" } variable "availability_zones" { - type = "list" + type = list(string) description = "List of Availability Zones for EFS" } variable "healthcheck_url" { - type = "string" + type = string default = "/login" description = "Application Health Check URL. Elastic Beanstalk will call this URL to check the health of the application running on EC2 instances" } variable "loadbalancer_type" { - type = "string" + type = string default = "application" description = "Load Balancer type, e.g. 'application' or 'classic'" } variable "loadbalancer_certificate_arn" { - type = "string" + type = string description = "Load Balancer SSL certificate ARN. The certificate must be present in AWS Certificate Manager" + default = "" } -variable "public_subnets" { - type = "list" - description = "List of public subnets to place Elastic Load Balancer" +variable "loadbalancer_subnets" { + type = list(string) + description = "List of subnets to place Elastic Load Balancer" } -variable "private_subnets" { - type = "list" - description = "List of private subnets to place EC2 instances and EFS" +variable "application_subnets" { + type = list(string) + description = "List of subnets to place EC2 instances and EFS" } -variable "zone_id" { - type = "string" +variable "dns_zone_id" { + type = string description = "Route53 parent zone ID. The module will create sub-domain DNS records in the parent zone for the EB environment and EFS" } -variable "security_groups" { - type = "list" +variable "allowed_security_groups" { + type = list(string) default = [] - description = "List of security groups to be allowed to connect to the EC2 instances" + description = "List of security groups to be allowed to connect to Jenkins master EC2 instances" } variable "ssh_key_pair" { - type = "string" + type = string default = "" - description = "Name of SSH key that will be deployed on Elastic Beanstalk and DataPipeline instance. The key should be present in AWS" + description = "Name of SSH key that will be deployed on Elastic Beanstalk instances. The key should be present in AWS" } variable "github_oauth_token" { - type = "string" - default = "" - description = "GitHub Oauth Token for accessing private repositories. Leave it empty when deploying a public 'Jenkins' repository, e.g. https://github.com/cloudposse/jenkins" + type = string + description = "GitHub Oauth Token" } variable "github_organization" { - type = "string" + type = string default = "cloudposse" description = "GitHub organization, e.g. 'cloudposse'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository" } variable "github_repo_name" { - type = "string" + type = string default = "jenkins" description = "GitHub repository name, e.g. 'jenkins'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' repository" } variable "github_branch" { - type = "string" + type = string default = "master" description = "GitHub repository branch, e.g. 'master'. By default, this module will deploy 'https://github.com/cloudposse/jenkins' master branch" } -# http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-available +# https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html variable "build_image" { - type = "string" + type = string default = "aws/codebuild/docker:1.12.1" - description = "CodeBuild build image, e.g. 'aws/codebuild/docker:1.12.1'. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-available" + description = "CodeBuild build image, e.g. 'aws/codebuild/amazonlinux2-x86_64-standard:1.0'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html" } -# http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-compute-types +# https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html variable "build_compute_type" { - type = "string" + type = string default = "BUILD_GENERAL1_SMALL" - description = "CodeBuild compute type, e.g. 'BUILD_GENERAL1_SMALL'. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref.html#build-env-ref-compute-types" + description = "CodeBuild compute type, e.g. 'BUILD_GENERAL1_SMALL'. For more info: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html" } variable "aws_account_id" { - type = "string" + type = string description = "AWS Account ID. Used as CodeBuild ENV variable $AWS_ACCOUNT_ID when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html" } -variable "image_tag" { - type = "string" - description = "Docker image tag in the ECR repository, e.g. 'latest'. Used as CodeBuild ENV variable $IMAGE_TAG when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html" - default = "latest" +variable "availability_zone_selector" { + type = string + default = "Any" + description = "Availability Zone selector" } -variable "env_default_key" { - type = "string" - default = "DEFAULT_ENV_%d" - description = "Default ENV variable key for Elastic Beanstalk `aws:elasticbeanstalk:application:environment` setting" +variable "environment_type" { + type = string + default = "LoadBalanced" + description = "Environment type, e.g. 'LoadBalanced' or 'SingleInstance'. If setting to 'SingleInstance', `rolling_update_type` must be set to 'Time' or `Immutable`, and `loadbalancer_subnets` will be unused (it applies to the ELB, which does not exist in SingleInstance environments)" } -variable "env_default_value" { - type = "string" - default = "UNSET" - description = "Default ENV variable value for Elastic Beanstalk `aws:elasticbeanstalk:application:environment` setting" +# https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingupdatepolicyrollingupdate +variable "rolling_update_type" { + type = string + default = "Health" + description = "`Health`, `Time` or `Immutable`. Set it to `Immutable` to apply the configuration change to a fresh group of instances. For more details, see https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-autoscalingupdatepolicyrollingupdate" +} + +variable "image_tag" { + type = string + description = "Docker image tag in the ECR repository, e.g. 'latest'. Used as CodeBuild ENV variable $IMAGE_TAG when building Docker images. For more info: http://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html" + default = "latest" } variable "env_vars" { - type = "map" + type = map(string) default = {} description = "Map of custom ENV variables to be provided to the Jenkins application running on Elastic Beanstalk, e.g. env_vars = { JENKINS_USER = 'admin' JENKINS_PASS = 'xxxxxx' }" } -variable "noncurrent_version_expiration_days" { - type = "string" - default = "35" - description = "Backup S3 bucket noncurrent version expiration days" +variable "use_efs_ip_address" { + type = bool + default = false + description = "If set to `true`, will provide the EFS IP address instead of DNS name to Jenkins as ENV var" } -variable "delimiter" { - type = "string" - default = "-" - description = "Delimiter to be used between `name`, `namespace`, `stage`, etc." +variable "efs_backup_schedule" { + type = string + description = "A CRON expression specifying when AWS Backup initiates a backup job" + default = null } -variable "attributes" { - type = "list" - default = [] - description = "Additional attributes (e.g. `policy` or `role`)" +variable "efs_backup_start_window" { + type = number + description = "The amount of time in minutes before beginning a backup. Minimum value is 60 minutes" + default = null } -variable "tags" { - type = "map" - default = {} - description = "Additional tags (e.g. `map('BusinessUnit`,`XYZ`)" +variable "efs_backup_completion_window" { + type = number + description = "The amount of time AWS Backup attempts a backup before canceling the job and returning an error. Must be at least 60 minutes greater than `start_window`" + default = null } -variable "datapipeline_config" { - type = "map" - description = "DataPipeline configuration options" +variable "efs_backup_cold_storage_after" { + type = number + description = "Specifies the number of days after creation that a recovery point is moved to cold storage" + default = null +} - default = { - instance_type = "t2.small" - email = "" - period = "24 hours" - timeout = "60 Minutes" - } +variable "efs_backup_delete_after" { + type = number + description = "Specifies the number of days after creation that a recovery point is deleted. Must be 90 days greater than `cold_storage_after`" + default = null } -variable "use_efs_ip_address" { - default = "false" +variable "loadbalancer_logs_bucket_force_destroy" { + type = bool + default = false + description = "Force destroy the S3 bucket for load balancer logs even if it's not empty" +} + +variable "cicd_bucket_force_destroy" { + type = bool + default = false + description = "Force destroy the CI/CD S3 bucket even if it's not empty" } diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..43b0c82 --- /dev/null +++ b/versions.tf @@ -0,0 +1,11 @@ +terraform { + required_version = "~> 0.12.0" + + required_providers { + aws = "~> 2.0" + local = "~> 1.2" + null = "~> 2.0" + random = "~> 2.0" + template = "~> 2.0" + } +}