From da30c74685ee95e0c833242eccacefaa376344b9 Mon Sep 17 00:00:00 2001 From: clayton Date: Mon, 1 Jul 2019 13:37:45 -0400 Subject: [PATCH 01/14] hotfix/v0.2.6 --- README.md | 8 ++--- examples/tf-s3-consumer/pom.xml | 4 +-- examples/tf-s3/pom.xml | 10 ++++-- tf-build-tools/pom.xml | 41 ++++++++++++++++++++----- tf-build-tools/tf-cmd-api/pom.xml | 2 +- tf-build-tools/tf-maven-plugin/pom.xml | 2 +- tf-build-tools/tf-maven-starter/pom.xml | 2 +- 7 files changed, 50 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index d1c1905f..5207a0cd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.2.1/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.2.1/jar -[tf-maven-starter]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-starter/0.2.1/pom -[maven-badge]:https://img.shields.io/badge/maven%20central-0.2.1-green.svg +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.2.6/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.2.6/jar +[tf-maven-starter]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-starter/0.2.6/pom +[maven-badge]:https://img.shields.io/badge/maven%20central-0.2.6-green.svg ![terraform-maven](.docs/MavenTerraform.png) diff --git a/examples/tf-s3-consumer/pom.xml b/examples/tf-s3-consumer/pom.xml index 63790df8..c8e8d52e 100644 --- a/examples/tf-s3-consumer/pom.xml +++ b/examples/tf-s3-consumer/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-maven-starter - 0.2.1 + 0.2.6 tf-s3-consumer com.deliveredtechnologies.example.maven.tf @@ -27,7 +27,7 @@ com.deliveredtechnologies tf-maven-starter - 0.2-SNAPSHOT + 0.2.6 pom diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index d233976e..b3b02ee5 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-maven-starter - 0.2.1 + 0.2.6 tf-s3 com.deliveredtechnologies.example.maven.tf @@ -17,11 +17,17 @@ https://oss.sonatype.org/content/repositories/snapshots/ + + + sonatype + https://oss.sonatype.org/content/repositories/snapshots/ + + com.deliveredtechnologies tf-maven-starter - 0.2 + 0.2.6 pom diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index 187dac57..f67e7396 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -2,11 +2,12 @@ - 4.0.0 - com.deliveredtechnologies - tf-build-tools + 4.0.0 + com.deliveredtechnologies + tf-build-tools pom - 0.2.1 + 0.2.6 + Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api tf-maven-plugin @@ -71,9 +72,6 @@ release https://oss.sonatype.org/ - true - true - true true @@ -153,7 +151,7 @@ ${nexus.server.id} ${nexus.server.url} - true + false @@ -162,6 +160,33 @@ + + org.codehaus.mojo + flatten-maven-plugin + 1.1.0 + + true + minimum + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index cca09a54..2a7d9f37 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.2.1 + 0.2.6 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 334a3609..3cec9fc2 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.2.1 + 0.2.6 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-maven-starter/pom.xml b/tf-build-tools/tf-maven-starter/pom.xml index 95962a47..bd77f8a9 100644 --- a/tf-build-tools/tf-maven-starter/pom.xml +++ b/tf-build-tools/tf-maven-starter/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.2.1 + 0.2.6 4.0.0 tf-maven-starter From 5927256073ec825c58ef48a799f5ece00c4dbc7a Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Sun, 14 Jul 2019 22:12:47 -0400 Subject: [PATCH 02/14] v0.3 released * integrated unit test support (issue #70) * Fixed S3 Backend Bug (issue #76) --- README.md | 38 +++--- examples/tf-s3-consumer/pom.xml | 4 +- examples/tf-s3/pom.xml | 53 +++++++- examples/tf-s3/src/main/tf/s3/inputs.tf | 11 -- examples/tf-s3/src/main/tf/s3/main.tf | 95 +-------------- examples/tf-s3/src/main/tf/s3/outputs.tf | 11 +- .../tf/s3/policies/replication-policy.json | 33 ----- .../tf-s3/src/main/tf/s3/tfvars/test.tfvars | 2 + .../src/main/tf/s3_replicated_src/inputs.tf | 27 +++++ .../src/main/tf/s3_replicated_src/main.tf | 86 +++++++++++++ .../src/main/tf/s3_replicated_src/outputs.tf | 9 ++ .../policies/assume-role-policy.json | 0 .../policies/replication-policy.json | 65 ++++++++++ .../tf/s3_replicated_src/tfvars/dev.tfvars | 2 + .../tf/s3_replicated_src/tfvars/test.tfvars | 2 + .../tf-s3/src/test/groovy/tf/s3/S3Spec.groovy | 113 ++++++++++++++++++ tf-build-tools/pom.xml | 2 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- .../terraform/TerraformCommand.java | 2 +- .../TerraformCommandLineDecorator.java | 10 ++ .../terraform/api/TerraformApply.java | 13 +- .../terraform/api/TerraformDestroy.java | 20 ++-- .../terraform/api/TerraformInit.java | 30 +++-- .../terraform/api/TerraformOutput.java | 48 ++++++++ .../terraform/api/TerraformPlan.java | 13 +- .../terraform/TerraformUtilsTest.java | 18 +++ .../terraform/api/TerraformApplyTest.java | 36 +----- .../terraform/api/TerraformDestroyTest.java | 7 +- .../terraform/api/TerraformInitTest.java | 16 +-- .../terraform/api/TerraformOutputTest.java | 58 +++++++++ .../terraform/api/TerraformPlanTest.java | 7 +- tf-build-tools/tf-maven-plugin/pom.xml | 2 +- .../maven/terraform/TerraformGet.java | 6 +- .../maven/terraform/mojo/Apply.java | 9 +- .../maven/terraform/mojo/Destroy.java | 10 +- .../maven/terraform/mojo/Init.java | 11 +- .../maven/terraform/mojo/Plan.java | 9 +- tf-build-tools/tf-maven-starter/pom.xml | 2 +- 38 files changed, 613 insertions(+), 269 deletions(-) delete mode 100644 examples/tf-s3/src/main/tf/s3/policies/replication-policy.json create mode 100644 examples/tf-s3/src/main/tf/s3_replicated_src/inputs.tf create mode 100644 examples/tf-s3/src/main/tf/s3_replicated_src/main.tf create mode 100644 examples/tf-s3/src/main/tf/s3_replicated_src/outputs.tf rename examples/tf-s3/src/main/tf/{s3 => s3_replicated_src}/policies/assume-role-policy.json (100%) create mode 100644 examples/tf-s3/src/main/tf/s3_replicated_src/policies/replication-policy.json create mode 100644 examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/dev.tfvars create mode 100644 examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/test.tfvars create mode 100644 examples/tf-s3/src/test/groovy/tf/s3/S3Spec.groovy create mode 100644 tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java create mode 100644 tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java diff --git a/README.md b/README.md index 5207a0cd..fb79505f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.2.6/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.2.6/jar -[tf-maven-starter]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-starter/0.2.6/pom -[maven-badge]:https://img.shields.io/badge/maven%20central-0.2.6-green.svg +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.3/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.3/jar +[tf-maven-starter]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-starter/0.3/pom +[tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ +[tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ +[tf-maven-starter-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-starter/ +[maven-badge]:https://img.shields.io/badge/maven%20central-0.3-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.3-green.svg ![terraform-maven](.docs/MavenTerraform.png) @@ -9,7 +13,7 @@ ![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg) [![Build Status](https://travis-ci.org/deliveredtechnologies/terraform-maven.svg?branch=develop&maxAge=600&service=github)](https://travis-ci.org/deliveredtechnologies/terraform-maven) -[![Coverage Status](https://coveralls.io/repos/github/deliveredtechnologies/terraform-maven/badge.svg?branch=develop&maxAge=600&service=github)](https://coveralls.io/github/deliveredtechnologies/terraform-maven?branch=develop) +[![Coverage Status](https://coveralls.io/repos/github/deliveredtechnologies/terraform-maven/badge.svg?branch=develop)](https://coveralls.io/github/deliveredtechnologies/terraform-maven?branch=develop) [![Maven Central][maven-badge]][tf-maven-plugin] # Terraform Maven Plugin @@ -36,11 +40,11 @@ Now, all of that Maven goodness can be used with Terraform. ### Artifacts in This Repository -| Artifact Name | Version | Description | -|------------------|---------------------------------------------------|-----------------------------| -| tf-maven-plugin | [![Maven Central][maven-badge]][tf-maven-plugin] | Terraform Maven Plugin | -| tf-cmd-api | [![Maven Central][maven-badge]][tf-cmd-api] | Terraform Command API | -| tf-maven-starter | [![Maven Central][maven-badge]][tf-maven-starter] | Terraform Maven starter POM | +| Artifact Name | Version | Latest Snapshot | Description | +|------------------|---------------------------------------------------|----------------------------------------------------------------------|-----------------------------| +| tf-maven-plugin | [![Maven Central][maven-badge]][tf-maven-plugin] | [![Maven Snapshot][maven-snapshot-badge]][tf-maven-plugin-snapshot] | Terraform Maven Plugin | +| tf-cmd-api | [![Maven Central][maven-badge]][tf-cmd-api] | [![Maven Snapshot][maven-snapshot-badge]][tf-cmd-api-snapshot] | Terraform Command API | +| tf-maven-starter | [![Maven Central][maven-badge]][tf-maven-starter] | [![Maven Snapshot][maven-snapshot-badge]][tf-maven-starter-snapshot] | Terraform Maven starter POM | ### Benefits of the Terraform Maven Plugin * Dependency Management @@ -98,12 +102,13 @@ _Note: tf:init depends on tf:get; so tf:get is always executed when tf:init is s Optional Parameters: -| Name | Type | Description | -| ------------- | ------- | ------------------------------------------------------------------------------------------------------------------- | -| tfRootDir | String | The root module directory location where terraform will be initialized; defaults to `src/main/tf/{first dir found}` | -| pluginDir | String | Skips plugin installation and loads plugins only from the specified directory | -| getPlugins | Boolean | Skips plugin installation | -| verifyPlugins | Boolean | Skips release signature validation when installing downloaded plugins (not recommended) | +| Name | Type | Description | +| ------------- | ------- | -------------------------------------------------------------------------------------------------------------------------- | +| tfRootDir | String | The root module directory location where terraform will be initialized; defaults to `src/main/tf/{first dir found}` | +| pluginDir | String | Skips plugin installation and loads plugins only from the specified directory | +| getPlugins | Boolean | Skips plugin installation | +| backendConfig | String | A comma delimited string of optional backend config (e.g. backendConfig="region=us-east-1,bucket=mybucket,key=/some/path") | +| verifyPlugins | Boolean | Skips release signature validation when installing downloaded plugins (not recommended) | --- @@ -164,6 +169,7 @@ Optional Parameters: | Name | Type | Description | | ----------- | ------ | ---------------------------------------------------------------------------------------------- | | lockTimeout | Number | Duration to retry a state lock | +| tfVars | String | A comma delimited string of tfvars (e.g. -var 'name=value') | | target | Number | A resource address to target | | noColor | Any | If this property exists, the -no-color flag is set | | tfRootDir | String | A terraform config directory to destroy; defaults to current directory | diff --git a/examples/tf-s3-consumer/pom.xml b/examples/tf-s3-consumer/pom.xml index c8e8d52e..4ec02e47 100644 --- a/examples/tf-s3-consumer/pom.xml +++ b/examples/tf-s3-consumer/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-maven-starter - 0.2.6 + 0.3 tf-s3-consumer com.deliveredtechnologies.example.maven.tf @@ -27,7 +27,7 @@ com.deliveredtechnologies tf-maven-starter - 0.2.6 + 0.3 pom diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index b3b02ee5..9b6d37c8 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-maven-starter - 0.2.6 + 0.3 tf-s3 com.deliveredtechnologies.example.maven.tf @@ -27,9 +27,32 @@ com.deliveredtechnologies tf-maven-starter - 0.2.6 + 0.3 pom + + com.deliveredtechnologies + tf-cmd-api + 0.3- + + + org.codehaus.groovy + groovy-all + 2.4.7 + test + + + org.spockframework + spock-core + 1.3-groovy-2.4 + test + + + com.amazonaws + aws-java-sdk + 1.11.584 + test + @@ -58,6 +81,32 @@ org.codehaus.mojo flatten-maven-plugin + + org.codehaus.gmavenplus + gmavenplus-plugin + 1.7.0 + + + + addTestSources + compileTests + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*Spec.java + + + diff --git a/examples/tf-s3/src/main/tf/s3/inputs.tf b/examples/tf-s3/src/main/tf/s3/inputs.tf index 8c67cd8c..2d6f8d5f 100644 --- a/examples/tf-s3/src/main/tf/s3/inputs.tf +++ b/examples/tf-s3/src/main/tf/s3/inputs.tf @@ -4,12 +4,6 @@ variable "region" { default = "us-east-1" } -variable "replication_region" { - description = "region where the bucket will be repliced to (destination), if applicable; defaults to us-west-1" - type = "string" - default = "us-west-1" -} - variable "bucket_name" { description = "name of the bucket; defaults to a 'bucket-{random id}'" type = "string" @@ -28,8 +22,3 @@ variable "is_versioned" { default = false } -variable "is_replicated" { - description = "true if replication is to be enabled, otherwise false; defaults to false" - type = "string" - default = false -} diff --git a/examples/tf-s3/src/main/tf/s3/main.tf b/examples/tf-s3/src/main/tf/s3/main.tf index d6ffc12b..bec8edb3 100644 --- a/examples/tf-s3/src/main/tf/s3/main.tf +++ b/examples/tf-s3/src/main/tf/s3/main.tf @@ -2,11 +2,6 @@ provider "aws" { region = "${var.region}" } -provider "aws" { - alias = "destination" - region = "${var.replication_region}" -} - resource "random_id" "bucket_name" { prefix = "bucket-" byte_length = 8 @@ -16,101 +11,15 @@ locals { bucket_name = "${length(var.bucket_name) == 0 ? random_id.bucket_name.hex : var.bucket_name}" } -data "template_file" "assume_role_policy" { - template = "${file("${path.module}/policies/assume-role-policy.json")}" -} - -data "template_file" "replication_policy" { - template = "${file("${path.module}/policies/replication-policy.json")}" - vars { - source_bucket_arn = "${var.is_replicated ? join("", aws_s3_bucket.source_bucket.*.arn) : join("", aws_s3_bucket.bucket.*.arn)}" - destination_bucket_arn = "${var.is_replicated ? join("", aws_s3_bucket.destination_bucket.*.arn) : join("", aws_s3_bucket.bucket.*.arn)}" - } -} - -resource "aws_iam_role" "replication" { - count = "${var.is_replicated ? 1 : 0}" - provider = "aws.destination" - name = "tf-iam-role-${local.bucket_name}-replication" - assume_role_policy = "${data.template_file.assume_role_policy.rendered}" -} - -resource "aws_iam_policy" "replication" { - count = "${var.is_replicated ? 1 : 0}" - provider = "aws.destination" - name = "tf-iam-role-policy-${local.bucket_name}-replication" - policy = "${data.template_file.replication_policy.rendered}" -} - -resource "aws_iam_policy_attachment" "replication" { - count = "${var.is_replicated ? 1 : 0}" - provider = "aws.destination" - name = "tf-iam-role-attachment-${local.bucket_name}-replication" - roles = ["${aws_iam_role.replication.name}"] - policy_arn = "${aws_iam_policy.replication.arn}" -} - resource "aws_kms_key" "kmskey" { description = "This key is used to encrypt bucket objects" deletion_window_in_days = 10 } -resource "aws_kms_key" "destination_kmskey" { - count = "${var.is_replicated ? 1 : 0}" - provider = "aws.destination" - description = "This key is used to encrypt replicated bucket objects" - deletion_window_in_days = 10 -} - -resource "aws_s3_bucket" "destination_bucket" { - count = "${var.is_replicated ? 1 : 0}" - provider = "aws.destination" - bucket = "replica-${local.bucket_name}" - region = "${var.replication_region}" - - versioning { - enabled = true - } - - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - kms_master_key_id = "${aws_kms_key.destination_kmskey.arn}" - sse_algorithm = "aws:kms" - } - } - } -} - -resource "aws_s3_bucket" "source_bucket" { - count = "${var.is_replicated ? 1 : 0}" - region = "${var.region}" - bucket = "${local.bucket_name}" - acl = "private" - - versioning { - enabled = true - } - - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - kms_master_key_id = "${aws_kms_key.kmskey.arn}" - sse_algorithm = "aws:kms" - } - } - } - - tags = { - Environment = "${var.environment}" - } -} - resource "aws_s3_bucket" "bucket" { - count = "${var.is_replicated ? 0 : 1}" - region = "${var.region}" bucket = "${local.bucket_name}" acl = "private" + force_destroy = "true" versioning { enabled = "${var.is_versioned}" @@ -126,6 +35,6 @@ resource "aws_s3_bucket" "bucket" { } tags = { - Environment = "${var.environment}" + environment = "${var.environment}" } } diff --git a/examples/tf-s3/src/main/tf/s3/outputs.tf b/examples/tf-s3/src/main/tf/s3/outputs.tf index 0b29d9bf..ca7abf22 100644 --- a/examples/tf-s3/src/main/tf/s3/outputs.tf +++ b/examples/tf-s3/src/main/tf/s3/outputs.tf @@ -1,4 +1,9 @@ -output "bucket_arns" { - description = "a list of bucket arns: [bucket_arn] for non-replicated; [source_arn, destination_arn] for replicated" - value = "${var.is_replicated ? "${join("", aws_s3_bucket.source_bucket.*.arn)},${join("", aws_s3_bucket.destination_bucket.*.arn)}" : join("", aws_s3_bucket.bucket.*.arn)}" +output "bucket_arn" { + description = "bucket arn" + value = "${aws_s3_bucket.bucket.arn}" +} + +output "kms_key_arn" { + description = "kms key arn for the bucket encryption" + value = "${aws_kms_key.kmskey.arn}" } diff --git a/examples/tf-s3/src/main/tf/s3/policies/replication-policy.json b/examples/tf-s3/src/main/tf/s3/policies/replication-policy.json deleted file mode 100644 index 87810277..00000000 --- a/examples/tf-s3/src/main/tf/s3/policies/replication-policy.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "Version": "2012-10-17", - "Statement": [ - { - "Action": [ - "s3:GetReplicationConfiguration", - "s3:ListBucket" - ], - "Effect": "Allow", - "Resource": [ - "${source_bucket_arn}" - ] - }, - { - "Action": [ - "s3:GetObjectVersion", - "s3:GetObjectVersionAcl" - ], - "Effect": "Allow", - "Resource": [ - "${source_bucket_arn}/*" - ] - }, - { - "Action": [ - "s3:ReplicateObject", - "s3:ReplicateDelete" - ], - "Effect": "Allow", - "Resource": "${destination_bucket_arn}/*" - } - ] -} diff --git a/examples/tf-s3/src/main/tf/s3/tfvars/test.tfvars b/examples/tf-s3/src/main/tf/s3/tfvars/test.tfvars index e69de29b..3c3bd5f5 100644 --- a/examples/tf-s3/src/main/tf/s3/tfvars/test.tfvars +++ b/examples/tf-s3/src/main/tf/s3/tfvars/test.tfvars @@ -0,0 +1,2 @@ +region = "us-east-2" +environment = "test" diff --git a/examples/tf-s3/src/main/tf/s3_replicated_src/inputs.tf b/examples/tf-s3/src/main/tf/s3_replicated_src/inputs.tf new file mode 100644 index 00000000..41a53e16 --- /dev/null +++ b/examples/tf-s3/src/main/tf/s3_replicated_src/inputs.tf @@ -0,0 +1,27 @@ +variable "region" { + description = "region where the bucket will be created or the source region; defaults to us-east-1" + type = "string" + default = "us-east-1" +} + +variable "bucket_name" { + description = "name of the bucket; defaults to a 'bucket-{random id}'" + type = "string" + default = "" +} + +variable "environment" { + description = "value of the 'Environment' tag" + type = "string" + default = "dev" +} + +variable "destination_bucket_arn" { + description = "arn of the destination bucket for replication" + type = "string" +} + +variable "destination_kms_key_arn" { + description = "arn of the destination kms key" + type = "string" +} diff --git a/examples/tf-s3/src/main/tf/s3_replicated_src/main.tf b/examples/tf-s3/src/main/tf/s3_replicated_src/main.tf new file mode 100644 index 00000000..535b9863 --- /dev/null +++ b/examples/tf-s3/src/main/tf/s3_replicated_src/main.tf @@ -0,0 +1,86 @@ +provider "aws" { + region = "${var.region}" +} + +resource "random_id" "bucket_name" { + prefix = "bucket-" + byte_length = 8 +} + +locals { + bucket_name = "${length(var.bucket_name) == 0 ? random_id.bucket_name.hex : var.bucket_name}" +} + +data "template_file" "assume_role_policy" { + template = "${file("${path.module}/policies/assume-role-policy.json")}" +} + +data "template_file" "replication_policy" { + template = "${file("${path.module}/policies/replication-policy.json")}" + vars { + source_bucket_arn = "${aws_s3_bucket.source_bucket.arn}" + destination_bucket_arn = "${var.destination_bucket_arn}" + source_kms_key_arn = "${aws_kms_key.kmskey.arn}" + destination_kms_key_arn = "${var.destination_kms_key_arn}" + } +} + +resource "aws_iam_role" "replication" { + name = "tf-iam-role-${local.bucket_name}-replication" + assume_role_policy = "${data.template_file.assume_role_policy.rendered}" +} + +resource "aws_iam_policy" "replication" { + name = "tf-iam-role-policy-${local.bucket_name}-replication" + policy = "${data.template_file.replication_policy.rendered}" +} + +resource "aws_iam_policy_attachment" "replication" { + name = "tf-iam-role-attachment-${local.bucket_name}-replication" + roles = ["${aws_iam_role.replication.name}"] + policy_arn = "${aws_iam_policy.replication.arn}" +} + +resource "aws_kms_key" "kmskey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +resource "aws_s3_bucket" "source_bucket" { + region = "${var.region}" + bucket = "${local.bucket_name}" + acl = "private" + + versioning { + enabled = true + } + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = "${aws_kms_key.kmskey.arn}" + sse_algorithm = "aws:kms" + } + } + } + + replication_configuration { + role = "${aws_iam_role.replication.arn}" + "rules" { + "destination" { + bucket = "${var.destination_bucket_arn}" + replica_kms_key_id = "${var.destination_kms_key_arn}" + } + "source_selection_criteria" { + sse_kms_encrypted_objects { + enabled = true + } + } + status = "Enabled" + } + } + + tags = { + Environment = "${var.environment}" + } +} diff --git a/examples/tf-s3/src/main/tf/s3_replicated_src/outputs.tf b/examples/tf-s3/src/main/tf/s3_replicated_src/outputs.tf new file mode 100644 index 00000000..529feb02 --- /dev/null +++ b/examples/tf-s3/src/main/tf/s3_replicated_src/outputs.tf @@ -0,0 +1,9 @@ +output "bucket_arn" { + description = "bucket arn" + value = "${aws_s3_bucket.source_bucket.arn}" +} + +output "kms_key_arn" { + description = "kms key arn for the bucket encryption" + value = "${aws_kms_key.kmskey.arn}" +} diff --git a/examples/tf-s3/src/main/tf/s3/policies/assume-role-policy.json b/examples/tf-s3/src/main/tf/s3_replicated_src/policies/assume-role-policy.json similarity index 100% rename from examples/tf-s3/src/main/tf/s3/policies/assume-role-policy.json rename to examples/tf-s3/src/main/tf/s3_replicated_src/policies/assume-role-policy.json diff --git a/examples/tf-s3/src/main/tf/s3_replicated_src/policies/replication-policy.json b/examples/tf-s3/src/main/tf/s3_replicated_src/policies/replication-policy.json new file mode 100644 index 00000000..a6a10ef0 --- /dev/null +++ b/examples/tf-s3/src/main/tf/s3_replicated_src/policies/replication-policy.json @@ -0,0 +1,65 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "s3:ListBucket", + "s3:Get", + "s3:DeleteBucket" + ], + "Effect": "Allow", + "Resource": [ + "${source_bucket_arn}", + "${destination_bucket_arn}" + ] + }, + { + "Action": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket", + "s3:Get" + ], + "Effect": "Allow", + "Resource": [ + "${source_bucket_arn}", + "${source_bucket_arn}/*" + ] + }, + { + "Action": [ + "s3:GetObjectVersion", + "s3:GetObjectVersionAcl" + ], + "Effect": "Allow", + "Resource": [ + "${source_bucket_arn}/*" + ] + }, + { + "Action": [ + "s3:ListBucket", + "s3:Get", + "s3:ReplicateObject", + "s3:ReplicateDelete", + "s3:ReplicateTags", + "s3:GetObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": "${destination_bucket_arn}/*" + }, + { + "Effect": "Allow", + "Action": [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ], + "Resource": [ + "${source_kms_key_arn}", + "${destination_kms_key_arn}" + ] + } + ] +} diff --git a/examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/dev.tfvars b/examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/dev.tfvars new file mode 100644 index 00000000..44843ce3 --- /dev/null +++ b/examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/dev.tfvars @@ -0,0 +1,2 @@ +region = "us-east-2" +environment = "dev" diff --git a/examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/test.tfvars b/examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/test.tfvars new file mode 100644 index 00000000..3c3bd5f5 --- /dev/null +++ b/examples/tf-s3/src/main/tf/s3_replicated_src/tfvars/test.tfvars @@ -0,0 +1,2 @@ +region = "us-east-2" +environment = "test" diff --git a/examples/tf-s3/src/test/groovy/tf/s3/S3Spec.groovy b/examples/tf-s3/src/test/groovy/tf/s3/S3Spec.groovy new file mode 100644 index 00000000..72bdc8cd --- /dev/null +++ b/examples/tf-s3/src/test/groovy/tf/s3/S3Spec.groovy @@ -0,0 +1,113 @@ +package tf.s3 + +import com.amazonaws.services.s3.AmazonS3 +import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.deliveredtechnologies.terraform.api.TerraformApply +import com.deliveredtechnologies.terraform.api.TerraformDestroy +import com.deliveredtechnologies.terraform.api.TerraformInit +import com.deliveredtechnologies.terraform.api.TerraformOutput +import com.deliveredtechnologies.terraform.api.TerraformPlan +import groovy.json.JsonSlurper +import spock.lang.Specification + +class S3Spec extends Specification { + + def "S3 module provisions a bucket in AWS"() { + given: + Properties tfProperties = new Properties() + + String region = 'us-east-1' + String environment = 'dev' + String stackName = 's3' + + TerraformInit init = new TerraformInit(stackName) + TerraformApply apply = new TerraformApply(stackName) + + AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion("us-east-1").build() + + tfProperties.put('tfRootDir', stackName) + tfProperties.put('tfVars', "region=${region},environment=${environment}".toString()) + + when: + init.execute(tfProperties) + apply.execute(tfProperties) + def jsonOutput = getTerraformOutput(stackName) + String bucketName = jsonOutput.bucket_arn.value[(jsonOutput.bucket_arn.value.lastIndexOf(":") + 1)..-1] + + then: + s3.doesBucketExistV2 bucketName + s3.getBucketTaggingConfiguration(bucketName).getTagSet().getTag('environment') == environment + + cleanup: + TerraformDestroy destroy = new TerraformDestroy(stackName) + destroy.execute(tfProperties) + } + + def "Replicated bucket replicates S3 objects from east to west"() { + given: + Properties tfSrcProperties = new Properties() + Properties tfDestProperties = new Properties() + + String srcRegion = 'us-east-1' + String destRegion = 'us-west-1' + String environment = 'dev' + String srcStackName = 's3_replicated_src' + String destStackName = 's3' + String s3ObjectName = 'test.txt' + + TerraformInit initDest = new TerraformInit(destStackName) + TerraformPlan planDest = new TerraformPlan(destStackName) + TerraformApply applyDest = new TerraformApply(destStackName) + TerraformInit initSrc = new TerraformInit(srcStackName) + TerraformApply applySrc = new TerraformApply(srcStackName) + + AmazonS3 sourceS3 = AmazonS3ClientBuilder.standard().withRegion(srcRegion).build() + AmazonS3 destS3 = AmazonS3ClientBuilder.standard().withRegion(destRegion).build() + + when: + //provision destination bucket + tfDestProperties.put('tfVars', "region=${destRegion},environment=${environment},is_versioned=true".toString()) + + initDest.execute(tfDestProperties) + applyDest.execute(tfDestProperties) + def destJsonOutput = getTerraformOutput(destStackName) + String destBucketArn = destJsonOutput.bucket_arn.value + String destKmsKeyArn = destJsonOutput.kms_key_arn.value + String destBucketName = destBucketArn[(destBucketArn.lastIndexOf(":") + 1)..-1] + + //provision source bucket with replication to destination bucket + tfSrcProperties.put('tfVars', "region=${srcRegion},environment=${environment},destination_bucket_arn=${destBucketArn},destination_kms_key_arn=${destKmsKeyArn}".toString()) + + initSrc.execute(tfSrcProperties) + applySrc.execute(tfSrcProperties) + + def srcJsonOutput = getTerraformOutput(destStackName) + String srcBucketArn = srcJsonOutput.bucket_arn.value + String srcBucketName = srcBucketArn[(srcBucketArn.lastIndexOf(":") + 1)..-1] + + //upload a file to the source region + sourceS3.putObject(srcBucketName, s3ObjectName, "This is a test!") + + //give a little time to replicate + sleep(5000) + + then: + sourceS3.getBucketTaggingConfiguration(srcBucketName).getTagSet().getTag('environment') == environment + destS3.getBucketTaggingConfiguration(destBucketName).getTagSet().getTag('environment') == environment + destS3.doesObjectExist(destBucketName, s3ObjectName) + + cleanup: + TerraformDestroy destroySrc = new TerraformDestroy(srcStackName) + TerraformDestroy destroyDest = new TerraformDestroy(destStackName) + + destroySrc.execute(tfSrcProperties) + destroyDest.execute(tfDestProperties) + } + + private def getTerraformOutput(String stackName) { + TerraformOutput output = new TerraformOutput(stackName) + String tfOutput = output.execute(new Properties()) + JsonSlurper slurper = new JsonSlurper() + slurper.parseText(tfOutput) + } +} diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index f67e7396..d3c3d3e3 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.2.6 + 0.3 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 2a7d9f37..0f8fa9e6 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.2.6 + 0.3 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java index b9a893c5..dae51d0e 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java @@ -1,7 +1,7 @@ package com.deliveredtechnologies.terraform; public enum TerraformCommand { - INIT("init"), PLAN("plan"), APPLY("apply"), DESTROY("destroy"), OUT("out"); + INIT("init"), PLAN("plan"), APPLY("apply"), DESTROY("destroy"), OUTPUT("output"); private String value; diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java index 3a1aba05..ce82db61 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java @@ -34,6 +34,16 @@ public TerraformCommandLineDecorator(TerraformCommand cmd) throws IOException { this(cmd, new CommandLine(TerraformUtils.getDefaultTerraformRootModuleDir())); } + /** + * Instantiates TerraformCommandLineDecorator using TerraformCommand.
+ * The directory where commands are executed is based on {tfRootDir}. + * @param cmd the Terraform command to be executed + * @throws IOException + */ + public TerraformCommandLineDecorator(TerraformCommand cmd, String tfRootDir) throws IOException, TerraformException { + this(cmd, new CommandLine(tfRootDir == null ? TerraformUtils.getDefaultTerraformRootModuleDir() : TerraformUtils.getTerraformRootModuleDir(tfRootDir))); + } + @Override public String execute(String command, int timeout) throws IOException, InterruptedException { return commandLine.execute(getTerraformCommand(command), timeout); diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java index b26ad849..22478968 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import java.io.IOException; import java.util.Optional; @@ -22,7 +21,6 @@ enum TerraformApplyParam { lockTimeout("lock-timeout"), target("target"), plan("plan"), - tfRootDir("dir"), noColor("no-color"), timeout("timeout"); @@ -48,6 +46,10 @@ public TerraformApply() throws IOException { this(new TerraformCommandLineDecorator(TerraformCommand.APPLY)); } + public TerraformApply(String tfRootDir) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.APPLY, tfRootDir)); + } + /** * Executes terraform apply. *

@@ -57,7 +59,6 @@ public TerraformApply() throws IOException { * lockTimeout - state file lock timeout
* target - resource target
* autoApprove - approve without prompt
- * tfRootDir - the directory in which to run the apply command * plan - the plan file to run the apply against
* noColor - remove color encoding from output
* timeout - how long in milliseconds the terraform apply command can run
@@ -90,7 +91,6 @@ public String execute(Properties properties) throws TerraformException { break; case timeout: case plan: - case tfRootDir: break; default: options.append(String.format("-%1$s=%2$s ", param, properties.getProperty(param.property))); @@ -103,11 +103,6 @@ public String execute(Properties properties) throws TerraformException { try { if (properties.containsKey(TerraformApplyParam.plan.property)) { options.append(properties.getProperty(TerraformApplyParam.plan.property)); - } else { - String tfModuleDir = TerraformUtils.getTerraformRootModuleDir( - properties.getProperty(TerraformApplyParam.tfRootDir.property, - TerraformUtils.getDefaultTerraformRootModuleDir().toString())).toAbsolutePath().toString(); - options.append(tfModuleDir); } if (properties.containsKey("timeout")) { diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java index 5a2ab23e..6236d878 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import java.io.IOException; import java.util.Optional; @@ -20,7 +19,7 @@ public class TerraformDestroy implements TerraformOperation { enum TerraformDestroyParam { lockTimeout("lock-timeout"), target("target"), - tfRootDir("dir"), + tfVars("var"), noColor("no-color"), timeout("timeout"); @@ -46,6 +45,10 @@ public TerraformDestroy() throws IOException { this(new TerraformCommandLineDecorator(TerraformCommand.DESTROY)); } + public TerraformDestroy(String tfRootDir) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.DESTROY, tfRootDir)); + } + /** * Executes terraform destroy.
*

@@ -53,7 +56,6 @@ public TerraformDestroy() throws IOException { * lockTimeout - state file lock timeout
* target - resource target
* autoApprove - approve without prompt
- * tfRootDir - the directory in which to run the apply command * noColor - remove color encoding from output
* timeout - how long in milliseconds the terraform apply command can run
*

@@ -67,6 +69,13 @@ public String execute(Properties properties) throws TerraformException { for (TerraformDestroyParam param : TerraformDestroyParam.values()) { if (!properties.containsKey(param.property)) continue; + if (param == TerraformDestroyParam.tfVars) { + for (String var : ((String)properties.get(param.property)).split(",")) { + options.append(String.format("-%1$s '%2$s' ", param, var.trim())); + } + continue; + } + switch (param) { case lockTimeout: case target: @@ -82,11 +91,6 @@ public String execute(Properties properties) throws TerraformException { options.append("-auto-approve "); try { - String tfModuleDir = TerraformUtils.getTerraformRootModuleDir( - properties.getProperty(TerraformDestroyParam.tfRootDir.property, - TerraformUtils.getDefaultTerraformRootModuleDir().toString())).toAbsolutePath().toString(); - options.append(tfModuleDir); - if (properties.containsKey(TerraformDestroyParam.timeout.property)) { return terraform.execute(options.toString(), Integer.parseInt(properties.getProperty(TerraformDestroyParam.timeout.property))); } else { diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java index 1338dab0..291c688e 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,9 +23,9 @@ public class TerraformInit implements TerraformOperation { enum TerraformInitParam { pluginDir("plugin-dir"), - tfRootDir("tfRootDir"), verifyPlugins("verify-plugins"), - getPlugins("get-plugins"); + getPlugins("get-plugins"), + backendConfig("backend-config"); Optional name = Optional.empty(); String property; @@ -46,10 +45,18 @@ public TerraformInit() throws IOException { this(LoggerFactory.getLogger(TerraformInit.class), new TerraformCommandLineDecorator(TerraformCommand.INIT)); } + public TerraformInit(String tfRootDir) throws IOException, TerraformException { + this(LoggerFactory.getLogger(TerraformInit.class), new TerraformCommandLineDecorator(TerraformCommand.INIT, tfRootDir)); + } + public TerraformInit(Logger log) throws IOException { this(log, new TerraformCommandLineDecorator(TerraformCommand.INIT)); } + public TerraformInit(Logger log, String tfRootDir) throws IOException, TerraformException { + this(log, new TerraformCommandLineDecorator(TerraformCommand.INIT, tfRootDir)); + } + TerraformInit(Executable terraform) { this(LoggerFactory.getLogger(TerraformInit.class), terraform); } @@ -63,7 +70,9 @@ public TerraformInit(Logger log) throws IOException { * Executes terraform init.
*

* Valid Properties:
- * tfRootDir - the directory where terraform init is called + * pluginDir - skips plugin installation and loads plugins only from the specified directory
+ * verifyPlugins - skips release signature validation when installing downloaded plugins (not recommended)
+ * getPlugins - skips plugin installation when false
*

* @param properties paramter options and properties for terraform init * @return the output of terraform init @@ -73,13 +82,16 @@ public TerraformInit(Logger log) throws IOException { public String execute(Properties properties) throws TerraformException { try { StringBuilder options = new StringBuilder(); - String workingDir = TerraformUtils.getTerraformRootModuleDir( - properties.getProperty(TerraformInitParam.tfRootDir.toString(), - TerraformUtils.getDefaultTerraformRootModuleDir().toString())).toAbsolutePath().toString(); - log.info(String.format("*** Terraform root module directory is '%1$s' ***", workingDir)); for (TerraformInitParam param : TerraformInitParam.values()) { if (properties.containsKey(param.property)) { + + if (param == TerraformInitParam.backendConfig) { + for (String file : (properties.getProperty(param.property)).split(",")) { + options.append(String.format("-%1$s=\"%2$s\" ", param, file.trim())); + } + } + switch (param) { case pluginDir: case getPlugins: @@ -92,7 +104,7 @@ public String execute(Properties properties) throws TerraformException { } } - options.append(String.format("-no-color %1$s", workingDir)); + options.append("-no-color "); return terraform.execute(options.toString()); } catch (InterruptedException | IOException e) { throw new TerraformException(e); diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java new file mode 100644 index 00000000..99a92b95 --- /dev/null +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java @@ -0,0 +1,48 @@ +package com.deliveredtechnologies.terraform.api; + +import com.deliveredtechnologies.io.Executable; +import com.deliveredtechnologies.terraform.TerraformCommand; +import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; +import com.deliveredtechnologies.terraform.TerraformException; + +import java.io.IOException; +import java.util.Properties; + +public class TerraformOutput implements TerraformOperation { + private Executable terraform; + + TerraformOutput(Executable terraform) { + this.terraform = terraform; + } + + public TerraformOutput() throws IOException { + this(new TerraformCommandLineDecorator(TerraformCommand.OUTPUT)); + } + + public TerraformOutput(String tfRootDir) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.OUTPUT, tfRootDir)); + } + + /** + * Executes `terraform output -json -module={tfRootDir}`. + * + * @param properties parameter options for terraform output (currently, only tfRootDir) + * @return the output from terraform output -json + * @throws TerraformException + */ + @Override + public String execute(Properties properties) throws TerraformException { + try { + + String options = "-json"; + + if (properties.containsKey("timeout")) { + return terraform.execute(options, Integer.parseInt(properties.getProperty("timeout"))); + } else { + return terraform.execute(options); + } + } catch (InterruptedException | IOException e) { + throw new TerraformException(e.getMessage(), e); + } + } +} diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java index b3d42c66..4e472216 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import java.io.IOException; import java.util.Optional; @@ -23,7 +22,6 @@ enum TerraformPlanParam { lockTimeout("lock-timeout"), target("target"), planOutputFile("out"), - tfRootDir("dir"), planInput("input"), refreshState("refresh"), tfState("state"), @@ -53,6 +51,10 @@ public TerraformPlan() throws IOException { this(new TerraformCommandLineDecorator(TerraformCommand.PLAN)); } + public TerraformPlan(String tfRootDir) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.PLAN, tfRootDir)); + } + /** * Executes terraform plan. *

@@ -62,7 +64,6 @@ public TerraformPlan() throws IOException { * lockTimeout - state file lock timeout
* target - resource target
* planInput - ask for input for variables not directly set
- * tfRootDir - the directory in which to run the apply command * planOutputFile - path to save the generated execution plan
* refreshState - if true then refresh the state prior to running plan
* tfState - path to the state file; defaults to "terraform.tfstate"
@@ -96,7 +97,6 @@ public String execute(Properties properties) throws TerraformException { case noColor: options.append(String.format("-%1$s ", param)); break; - case tfRootDir: case timeout: break; default: @@ -110,11 +110,6 @@ public String execute(Properties properties) throws TerraformException { } try { - String tfModuleDir = TerraformUtils.getTerraformRootModuleDir( - properties.getProperty(TerraformPlanParam.tfRootDir.property, - TerraformUtils.getDefaultTerraformRootModuleDir().toString())).toAbsolutePath().toString(); - options.append(tfModuleDir); - if (properties.containsKey("timeout")) { return terraform.execute(options.toString(), Integer.parseInt(properties.getProperty("timeout"))); } else { diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java index 6953729e..e912d6f5 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java @@ -1,5 +1,6 @@ package com.deliveredtechnologies.terraform; +import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.Test; @@ -7,6 +8,9 @@ import java.nio.file.Path; import java.nio.file.Paths; +/** + * Tests for TerraformUtils. + */ public class TerraformUtilsTest { @Test @@ -20,4 +24,18 @@ public void getTerraformRootModuleDirReturnsTheDefaultDirWhenTheTfSourceDirIsNot Path tfRootModulePath = TerraformUtils.getDefaultTerraformRootModuleDir(); Assert.assertEquals(Paths.get("."), tfRootModulePath); } + + @Test + public void getTerraformRootModuleDirReturnsTheRootModuleDirRelativeToTheSourceDir() throws IOException, TerraformException { + try { + FileUtils.copyDirectory( + Paths.get("src", "test", "resources", "tf_initialized", "root").toFile(), + Paths.get("src", "main", "tf", "test").toFile() + ); + Path tfRootModulePath = TerraformUtils.getTerraformRootModuleDir("test"); + Assert.assertEquals(Paths.get("src", "main", "tf", "test"), tfRootModulePath); + } finally { + FileUtils.forceDelete(Paths.get("src", "main", "tf").toFile()); + } + } } diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java index 568427e5..be4aa26a 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import com.deliveredtechnologies.terraform.api.TerraformApply.TerraformApplyParam; import org.apache.commons.io.FileUtils; @@ -62,46 +61,13 @@ public void terraformApplyExecutesWhenAllPossiblePropertiesArePassed() throws IO @Test public void terraformApplyExecutesWhenNoPropertiesArePassed() throws IOException, InterruptedException, TerraformException { TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.APPLY, this.executable); - Mockito.when(this.executable.execute(String.format("terraform apply -auto-approve %1$s", TerraformUtils.getDefaultTerraformRootModuleDir().toAbsolutePath()))).thenReturn("Success!"); + Mockito.when(this.executable.execute("terraform apply -auto-approve ")).thenReturn("Success!"); TerraformApply terraformApply = new TerraformApply(terraformDecorator); Assert.assertEquals("Success!", terraformApply.execute(new Properties())); Mockito.verify(this.executable, Mockito.times(1)).execute(Mockito.anyString()); } - @Test - public void terraformApplyResolvesTheRootModuleDir() throws IOException, InterruptedException, TerraformException { - TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.APPLY, this.executable); - Mockito.when(this.executable.execute(String.format("terraform apply -auto-approve %1$s", TerraformUtils.getTerraformRootModuleDir(tfRootModule).toAbsolutePath().toString()))).thenReturn("Success!"); - TerraformApply terraformApply = new TerraformApply(terraformDecorator); - this.properties.put(TerraformApplyParam.tfRootDir.property, tfRootModule); - - Assert.assertEquals("Success!", terraformApply.execute(properties)); - Mockito.verify(this.executable, Mockito.times(1)).execute(Mockito.anyString()); - } - - @Test - public void terraformApplyAutoResolvesTheRootModuleDirWhenNoneIsSpecified() throws IOException, InterruptedException, TerraformException { - TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.APPLY, this.executable); - Mockito.when(this.executable.execute(String.format("terraform apply -auto-approve %1$s", TerraformUtils.getDefaultTerraformRootModuleDir().toAbsolutePath().toString()))).thenReturn("Success!"); - TerraformApply terraformApply = new TerraformApply(terraformDecorator); - - Assert.assertEquals("Success!", terraformApply.execute(properties)); - Mockito.verify(this.executable, Mockito.times(1)).execute(Mockito.anyString()); - } - - @Test - public void terraformApplyUsesPlanWhenBothPlanAndTfRootDirAreSpecified() throws IOException, InterruptedException, TerraformException { - TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.APPLY, this.executable); - Mockito.when(this.executable.execute("terraform apply -auto-approve someplan.tfplan")).thenReturn("Success!"); - TerraformApply terraformApply = new TerraformApply(terraformDecorator); - this.properties.put(TerraformApplyParam.plan.property, "someplan.tfplan"); - this.properties.put(TerraformApplyParam.tfRootDir.property, "/somedir"); - - Assert.assertEquals("Success!", terraformApply.execute(properties)); - Mockito.verify(this.executable, Mockito.times(1)).execute(Mockito.anyString()); - } - @Test(expected = TerraformException.class) public void terraformApplyThrowsTerraformExceptionOnError() throws IOException, InterruptedException, TerraformException { Mockito.when(this.executable.execute(Mockito.anyString())).thenThrow(new IOException("boom!")); diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java index efef1931..c9d0bae1 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.Assert; @@ -42,7 +41,7 @@ public void setup() throws IOException { public void terraformDestroyExecutesWhenAllPossiblePropertiesArePassed() throws IOException, InterruptedException, TerraformException { TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.DESTROY, this.executable); Mockito.when(this.executable.execute( - String.format("terraform destroy -lock-timeout=1000 -target=module1.module2 -no-color -auto-approve %1$s", TerraformUtils.getTerraformRootModuleDir(tfRootModule).toAbsolutePath().toString()), + "terraform destroy -lock-timeout=1000 -target=module1.module2 -var 'var1=one' -var 'var2=two' -no-color -auto-approve ", 1111)) .thenReturn("Success!"); TerraformDestroy terraformDestroy = new TerraformDestroy(terraformDecorator); @@ -51,7 +50,7 @@ public void terraformDestroyExecutesWhenAllPossiblePropertiesArePassed() throws this.properties.put(TerraformDestroy.TerraformDestroyParam.target.property, "module1.module2"); this.properties.put(TerraformDestroy.TerraformDestroyParam.noColor.property, "true"); this.properties.put(TerraformDestroy.TerraformDestroyParam.timeout.property, "1111"); - this.properties.put(TerraformDestroy.TerraformDestroyParam.tfRootDir.property, tfRootModule); + this.properties.put(TerraformDestroy.TerraformDestroyParam.tfVars.property, "var1=one,var2=two"); Assert.assertEquals("Success!", terraformDestroy.execute(properties)); Mockito.verify(this.executable, Mockito.times(1)).execute(Mockito.anyString(), Mockito.anyInt()); @@ -60,7 +59,7 @@ public void terraformDestroyExecutesWhenAllPossiblePropertiesArePassed() throws @Test public void terraformDestroyExecutesWhenNoPropertiesArePassed() throws IOException, InterruptedException, TerraformException { TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.DESTROY, this.executable); - Mockito.when(this.executable.execute(String.format("terraform destroy -auto-approve %1$s", TerraformUtils.getDefaultTerraformRootModuleDir().toAbsolutePath()))).thenReturn("Success!"); + Mockito.when(this.executable.execute("terraform destroy -auto-approve ")).thenReturn("Success!"); TerraformDestroy terraformDestroy = new TerraformDestroy(terraformDecorator); Assert.assertEquals("Success!", terraformDestroy.execute(new Properties())); diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java index 79eb491b..a02b3a0c 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import com.deliveredtechnologies.terraform.api.TerraformInit.TerraformInitParam; import org.apache.commons.io.FileUtils; @@ -46,16 +45,7 @@ public void executeCallsTerraformInitCommandWithNoOptions() throws IOException, String response = terraformInit.execute(new Properties()); Assert.assertEquals(successMessage, response); - Mockito.verify(commandLine, Mockito.times(1)).execute("terraform init -no-color " + TerraformUtils.getDefaultTerraformRootModuleDir().toAbsolutePath().toString()); - - //and now with a tfRootDir specified - String tfRootDir = Paths.get("src", "test", "resources", "tf_initialized", "root").toAbsolutePath().toString(); - Properties properties = new Properties(); - properties.put(TerraformInitParam.tfRootDir.toString(), tfRootDir); - response = terraformInit.execute(properties); - - Assert.assertEquals(successMessage, response); - Mockito.verify(commandLine, Mockito.times(1)).execute(String.format("terraform init -no-color %1$s", TerraformUtils.getTerraformRootModuleDir(tfRootDir))); + Mockito.verify(commandLine, Mockito.times(1)).execute("terraform init -no-color "); } @Test @@ -69,14 +59,14 @@ public void executeCallsTerraformInitCommandWithAllOptions() throws IOException, String tfRootDir = "test"; String pluginDir = "somepluginpath"; Properties properties = new Properties(); - properties.put(TerraformInitParam.tfRootDir.property, tfRootDir); properties.put(TerraformInitParam.getPlugins.property, "false"); properties.put(TerraformInitParam.pluginDir.property, pluginDir); properties.put(TerraformInitParam.verifyPlugins.property, "false"); + properties.put(TerraformInitParam.backendConfig.property, "bucket=mybucket,key=/path/to/my/key,region=us-east-1"); String response = terraformInit.execute(properties); Assert.assertEquals(successMessage, response); - Mockito.verify(commandLine, Mockito.times(1)).execute(String.format("terraform init -plugin-dir=%1$s -verify-plugins=false -get-plugins=false -no-color %2$s", pluginDir, Paths.get("src", "main", "tf", tfRootDir).toAbsolutePath().toString())); + Mockito.verify(commandLine, Mockito.times(1)).execute(String.format("terraform init -plugin-dir=somepluginpath -verify-plugins=false -get-plugins=false -backend-config=\"bucket=mybucket\" -backend-config=\"key=/path/to/my/key\" -backend-config=\"region=us-east-1\" -no-color ", pluginDir)); } @Test(expected = TerraformException.class) diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java new file mode 100644 index 00000000..ae7ac6b6 --- /dev/null +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java @@ -0,0 +1,58 @@ +package com.deliveredtechnologies.terraform.api; + +import com.deliveredtechnologies.io.Executable; +import com.deliveredtechnologies.terraform.TerraformCommand; +import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; +import com.deliveredtechnologies.terraform.TerraformException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.IOException; +import java.util.Properties; + +/** + * Tests for {@link TerraformOutput}. + */ +public class TerraformOutputTest { + + private final String successResponse = "Success!"; + private Executable commandLine; + private Properties properties; + private Executable terraform; + + /** + * Sets up mocks and properties. + * @throws IOException + * @throws InterruptedException + */ + @Before + public void setup() throws IOException, InterruptedException { + commandLine = Mockito.mock(Executable.class); + properties = new Properties(); + terraform = new TerraformCommandLineDecorator(TerraformCommand.OUTPUT, commandLine); + + } + + @Test + public void terraformOutputCallsOutputCommand() throws InterruptedException, IOException, TerraformException { + Mockito.when(commandLine.execute("terraform output -json")).thenReturn(successResponse); + + TerraformOutput terraformOutput = new TerraformOutput(terraform); + Assert.assertEquals(successResponse, terraformOutput.execute(properties)); + Mockito.verify(commandLine, Mockito.times(1)).execute(Mockito.anyString()); + } + + @Test + public void terraformOutputCallsOutputCommandWithTimeout() throws InterruptedException, IOException, TerraformException { + String timeout = "1000"; + properties.put("timeout", timeout); + + Mockito.when(commandLine.execute("terraform output -json", Integer.parseInt(timeout))).thenReturn(successResponse); + + TerraformOutput terraformOutput = new TerraformOutput(terraform); + Assert.assertEquals(successResponse, terraformOutput.execute(properties)); + Mockito.verify(commandLine, Mockito.times(1)).execute(Mockito.anyString(), Mockito.anyInt()); + } +} diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java index 3fdae8c8..4b16aa3e 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java @@ -4,7 +4,6 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; -import com.deliveredtechnologies.terraform.TerraformUtils; import org.apache.commons.io.FileUtils; import org.junit.After; @@ -44,7 +43,7 @@ public void terraformPlanExecutesWhenAllPossiblePropertiesArePassed() throws IOE Path tfRootDir = Paths.get("src", "test", "resources", "tf_initialized", "root").toAbsolutePath(); TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.PLAN, this.executable); Mockito.when(this.executable.execute( - "terraform plan -var 'key1=value1' -var 'key2=value2' -var_file=test1.txt -var_file=test2.txt -lock-timeout=1000 -target=module1.module2 -out=destroy.plan -input=true -refresh=true -state=my.tfstate -no-color -destroy " + tfRootDir.toString(), + "terraform plan -var 'key1=value1' -var 'key2=value2' -var_file=test1.txt -var_file=test2.txt -lock-timeout=1000 -target=module1.module2 -out=destroy.plan -input=true -refresh=true -state=my.tfstate -no-color -destroy ", 1111)) .thenReturn("Success!"); TerraformPlan terraformPlan = new TerraformPlan(terraformDecorator); @@ -60,7 +59,6 @@ public void terraformPlanExecutesWhenAllPossiblePropertiesArePassed() throws IOE this.properties.put(TerraformPlan.TerraformPlanParam.tfState.property, "my.tfstate"); this.properties.put(TerraformPlan.TerraformPlanParam.noColor.property, "true"); this.properties.put(TerraformPlan.TerraformPlanParam.timeout.property, "1111"); - this.properties.put(TerraformPlan.TerraformPlanParam.tfRootDir.property, tfRootDir.toString()); Assert.assertEquals("Success!", terraformPlan.execute(properties)); Mockito.verify(this.executable, Mockito.times(1)).execute(Mockito.anyString(), Mockito.anyInt()); @@ -68,9 +66,8 @@ public void terraformPlanExecutesWhenAllPossiblePropertiesArePassed() throws IOE @Test public void terraformPlanExecutesWhenNoPropertiesArePassed() throws IOException, InterruptedException, TerraformException { - Path tfRootDir = TerraformUtils.getDefaultTerraformRootModuleDir().toAbsolutePath(); TerraformCommandLineDecorator terraformDecorator = new TerraformCommandLineDecorator(TerraformCommand.PLAN, this.executable); - Mockito.when(this.executable.execute(String.format("terraform plan -input=false %1$s", tfRootDir))).thenReturn("Success!"); + Mockito.when(this.executable.execute("terraform plan -input=false ")).thenReturn("Success!"); TerraformPlan terraformPlan = new TerraformPlan(terraformDecorator); Assert.assertEquals("Success!", terraformPlan.execute(new Properties())); diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 3cec9fc2..89068d13 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.2.6 + 0.3 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java index 58d23af8..8abea338 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java @@ -4,8 +4,8 @@ import com.deliveredtechnologies.maven.logs.Slf4jMavenAdapter; import com.deliveredtechnologies.terraform.TerraformException; +import com.deliveredtechnologies.terraform.TerraformUtils; import com.deliveredtechnologies.terraform.api.TerraformOperation; -import org.apache.commons.lang.StringUtils; import org.apache.maven.plugin.logging.Log; import org.apache.maven.shared.invoker.DefaultInvocationRequest; import org.apache.maven.shared.invoker.DefaultInvoker; @@ -18,7 +18,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -41,8 +40,7 @@ public class TerraformGet implements TerraformOperation> { * @param tfModules the common modules directory; if null, it's defaulted to src/main/.tfmodules */ public TerraformGet(Log log, String tfModules) throws IOException { - //TODO: Use TerraformUtils to determine the tfModules directory instead of reimplementing it here. - this(log, StringUtils.isEmpty(tfModules) ? Paths.get("src", "main", ".tfmodules") : Paths.get(tfModules)); + this(log, TerraformUtils.getDefaultTfModulesDir()); } protected TerraformGet(Log log, Path tfModules) throws IOException { diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java index 63840b48..f10f993a 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java @@ -1,9 +1,11 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformApply; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; import java.io.IOException; @@ -14,11 +16,14 @@ */ @Mojo(name = "apply") public class Apply extends TerraformMojo { + @Parameter(property = "tfRootDir") + String tfRootDir; + @Override public void execute() throws MojoExecutionException, MojoFailureException { try { - execute(new TerraformApply(), System.getProperties()); - } catch (IOException e) { + execute(new TerraformApply(tfRootDir), System.getProperties()); + } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } } diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java index 3fd72099..bf82fd11 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java @@ -1,9 +1,11 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformDestroy; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; import java.io.IOException; @@ -14,11 +16,15 @@ */ @Mojo(name = "destroy") public class Destroy extends TerraformMojo { + @Parameter(property = "tfRootDir") + String tfRootDir; + @Override public void execute() throws MojoExecutionException, MojoFailureException { try { - execute(new TerraformDestroy(), System.getProperties()); - } catch (IOException e) { + getLog().info("tfRootDir is " + tfRootDir); + execute(new TerraformDestroy(tfRootDir), System.getProperties()); + } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } } diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java index 2379ded8..a1f9695f 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java @@ -1,11 +1,15 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformInit; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Execute; import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; + +import java.io.IOException; /** * Mojo terraform init goal. @@ -15,11 +19,14 @@ @Execute(goal = "get") @Mojo(name = "init") public class Init extends TerraformMojo { + @Parameter(property = "tfRootDir") + String tfRootDir; + @Override public void execute() throws MojoExecutionException, MojoFailureException { try { - execute(new TerraformInit(), System.getProperties()); - } catch (Exception e) { + execute(new TerraformInit(tfRootDir), System.getProperties()); + } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } } diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java index 786ba1e4..2607e82a 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java @@ -1,9 +1,11 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformPlan; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; import java.io.IOException; @@ -14,11 +16,14 @@ */ @Mojo(name = "plan") public class Plan extends TerraformMojo { + @Parameter(property = "tfRootDir") + String tfRootDir; + @Override public void execute() throws MojoExecutionException, MojoFailureException { try { - execute(new TerraformPlan(), System.getProperties()); - } catch (IOException e) { + execute(new TerraformPlan(tfRootDir), System.getProperties()); + } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } } diff --git a/tf-build-tools/tf-maven-starter/pom.xml b/tf-build-tools/tf-maven-starter/pom.xml index bd77f8a9..7fddf528 100644 --- a/tf-build-tools/tf-maven-starter/pom.xml +++ b/tf-build-tools/tf-maven-starter/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.2.6 + 0.3 4.0.0 tf-maven-starter From eb64a473bd6916452e95ac5968b9c4a5fb8bc478 Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Sun, 28 Jul 2019 23:30:53 -0400 Subject: [PATCH 03/14] v0.4 released * fixed/removed starter pom (issue #80) * fixed README.md type-o varFiles => tfVarFiles * added skipTfGet property that can be used to skip tf:get on tf:init * fixed dependency filter to only copy type=zip into .tfmodules * added tf-examples path (issue #83) * tf-examples path can be used by setting tfRootModule="tf-examples/" * added skipTfGet property that when set to true will skip tf:get as part of tf:init --- README.md | 201 ++++++++++++------ examples/tf-s3-consumer/pom.xml | 90 ++++++-- examples/tf-s3/pom.xml | 90 ++++++-- tf-build-tools/pom.xml | 3 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- .../terraform/TerraformUtils.java | 5 +- .../terraform/TerraformUtilsTest.java | 14 ++ tf-build-tools/tf-maven-plugin/pom.xml | 2 +- .../maven/terraform/TerraformGet.java | 5 +- .../maven/terraform/TerraformPackage.java | 38 +++- .../maven/terraform/mojo/Package.java | 2 +- .../maven/terraform/TerraformGetTest.java | 2 +- .../maven/terraform/TerraformPackageTest.java | 32 +++ tf-build-tools/tf-maven-starter/pom.xml | 138 ------------ 14 files changed, 379 insertions(+), 245 deletions(-) delete mode 100644 tf-build-tools/tf-maven-starter/pom.xml diff --git a/README.md b/README.md index fb79505f..86f62426 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.3/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.3/jar -[tf-maven-starter]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-starter/0.3/pom +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.4/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.4/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ -[tf-maven-starter-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-starter/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.3-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.3-green.svg +[maven-badge]:https://img.shields.io/badge/maven%20central-0.4-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.4-green.svg ![terraform-maven](.docs/MavenTerraform.png) @@ -18,13 +16,14 @@ # Terraform Maven Plugin -The Terraform Maven Plugin brings Terraform into Maven and greatly enhances the Terraform code management -lifecycle and management experience. Maven in some form has been the standard for Java project management for over a decade. -Now, all of that Maven goodness can be used with Terraform. +The Terraform Maven Plugin brings Maven to Terraform, which greatly enhances Terraform’s project lifecycle and dependency management capability. Maven in some form has been the standard for Java project management for over a decade. Now, all of that Maven goodness can be used with Terraform! + +


### Contents * [Artifacts in This Repository](#artifacts-in-this-repository) +* [Repository Directory Structure](#repo-directory-structure) * [Benefits of the Terraform Maven Plugin](#benefits-of-the-terraform-maven-plugin) * [Maven Goals](#maven-goals) * [tf:get](#tfget) @@ -37,6 +36,11 @@ Now, all of that Maven goodness can be used with Terraform. * [tf:clean](#tfclean) * [Setting Up a Terraform Maven Project](#setting-up-a-terraform-maven-project) * [How to Use Terraform Maven Projects](#how-to-use-terraform-maven-projects) +* [Articles](#articles) + +Not finding what you are looking for? [Try the Wiki!](https://github.com/deliveredtechnologies/terraform-maven/wiki) + +
### Artifacts in This Repository @@ -44,7 +48,14 @@ Now, all of that Maven goodness can be used with Terraform. |------------------|---------------------------------------------------|----------------------------------------------------------------------|-----------------------------| | tf-maven-plugin | [![Maven Central][maven-badge]][tf-maven-plugin] | [![Maven Snapshot][maven-snapshot-badge]][tf-maven-plugin-snapshot] | Terraform Maven Plugin | | tf-cmd-api | [![Maven Central][maven-badge]][tf-cmd-api] | [![Maven Snapshot][maven-snapshot-badge]][tf-cmd-api-snapshot] | Terraform Command API | -| tf-maven-starter | [![Maven Central][maven-badge]][tf-maven-starter] | [![Maven Snapshot][maven-snapshot-badge]][tf-maven-starter-snapshot] | Terraform Maven starter POM | + +### Repository Directory Structure +* examples - Terraform Maven example projects + * tf-s3 - A Terraform Maven s3 example project + * tf-s3-consumer - An example project that consumes the tf-s3 project as a dependency +* tf-build-tools - The parent project of the tf-maven-plugin and tf-cmd-api projects + * tf-maven-plugin - The Terraform Maven Plugin project + * tf-cmd-api - A Java API for Terraform project ### Benefits of the Terraform Maven Plugin * Dependency Management @@ -63,6 +74,9 @@ Now, all of that Maven goodness can be used with Terraform. * By default the [deploy goal](#tfdeploy) deploys a zip artifact packaged by the [package goal](#tfpackage) to a Maven repo along with the POM of the current Maven Terraform project. But if you want to point to a differnt POM or a different artifact for deployment, it can do that too. Easy peasy. +* Terraform support for Java testing frameworks + * The tf-cmd-api artifact provides Java support for Terraform, which can be used to easily integrate + mature Java testing frameworks, like Spock or JUnit. One example of this is the [[tf-s3 example in this repo]](examples/tf-s3). * Simple Integration with CI Tools * Get rid of hundreds of lines of untested code in your CI tool and replace it with tested build lifecycle management using Maven! Most CI tools either have Maven included or have a Maven plugin available. Less Terraform build logic @@ -109,6 +123,7 @@ Optional Parameters: | getPlugins | Boolean | Skips plugin installation | | backendConfig | String | A comma delimited string of optional backend config (e.g. backendConfig="region=us-east-1,bucket=mybucket,key=/some/path") | | verifyPlugins | Boolean | Skips release signature validation when installing downloaded plugins (not recommended) | +| skipTfGet | Boolean | If set to true, tf:init is done without running tf:get | --- @@ -122,7 +137,7 @@ Optional Parameters: | Name | Type | Description | | -------------- | ------- | ---------------------------------------------------------------------------------------------------------- | -| varFiles | String | A comma delimited string of tfvars files (e.g. -var-file=foo) | +| tfVarFiles | String | A comma delimited string of tfvars files (e.g. -var-file=foo) | | tfVars | String | A comma delimited string of tfvars (e.g. -var 'name=value') | | lockTimeout | Number | Duration to retry a state lock | | target | Number | A resource address to target | @@ -147,7 +162,7 @@ Optional Parameters: | Name | Type | Description | | ----------- | ------ | ---------------------------------------------------------------------------------------------------------- | -| varFiles | String | A comma delimited string of tfvars files (e.g. -var-file=foo) | +| tfVarFiles | String | A comma delimited string of tfvars files (e.g. -var-file=foo) | | tfVars | String | A comma delimited string of tfvars (e.g. -var 'name=value') | | lockTimeout | Number | Duration to retry a state lock | | target | Number | A resource address to target | @@ -187,11 +202,11 @@ Optionally, a fat compressed package can be created instead, which also includes _Note: Within the fat compressed package, module source paths are updated accordingly so that the pacakge is a wholly contained working module that can be consumed as a module, extracted, initialized and applied as-is or submitted to Terraform Enterprise._ -| Name | Type | Description | -| ------------ | ------- | -----------------------------------------------------------------------------------------------------| -| tfRootDir | String | The terraform root module directory location; defaults to src/main/tf/{first directory found} | -| tfModulesDir | String | The directory that contains the Terraform module depenencies; defaults to src/main/.tfmodules | -| fatTar | Boolean | Set to true if a fat compressed tar.gz package should be created, otherwise false; defaults to false | +| Name | Type | Description | +| ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------| +| tfRootDir | String | The terraform root module directory location; defaults to src/main/tf/{first directory found} or src/main/tf if there are multiple source modules | +| tfModulesDir | String | The directory that contains the Terraform module depenencies; defaults to src/main/.tfmodules | +| fatTar | Boolean | Set to true if a fat compressed tar.gz package should be created, otherwise false; defaults to false | --- @@ -204,7 +219,7 @@ Deploys a packaged Terraform zip artifact ([see tf:package](#tfpackage)) with a | Name | Type | Description | | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------- | | file | String | The name of the Terraform zip file to deploy; defaults to target/{artifactId}-{version}.zip | -| url | String | The url of the Maven repo to which the zip file artifact will be deployed | +| url | String | The url of the Maven repo to which the zip file artifact will be deployed; defaults to {HOME}/.m2/repository | | pomFile | String | The path to the pom.xml file to attach to the artifact; defaults to .flattened-pom.xml in the root of the project | | generatePom | String | If set to "true" then a POM will be generated and attached to the deployment | | groupId | String | The groupId for the generated POM (only used if generatePom=true | @@ -228,71 +243,127 @@ Deletes all 'terraform' files from terraform configurations along with the Terra 1. Create a generic Maven project. [see Maven Getting Started Guide](https://maven.apache.org/guides/getting-started/index.html) 2. Add a _src/main/tf_ directory, under which one or more Terraform root module will reside. -3. Add the Terraform Maven Starter POM as the parent project by adding the following to the POM under the _project_ tag. +3. Add a paramater to the POM that specifies the version of the Terraform Maven Plugin ```xml - - com.deliveredtechnologies - tf-maven-starter - 0.2.1 - + + 0.4 + ``` -4. Add the Terraform Maven starter POM as a dependency as follows. - -```xml - - - com.deliveredtechnologies - tf-maven-starter - 0.2.1 - pom - - -``` - -5. Configure the build plugins with the Terraform Maven Starter POM. +4. Configure the build plugins for the Terraform Maven Plugin (see the [tf-s3 example](examples/tf-s3) for reference). ```xml - - org.apache.maven.plugins - maven-install-plugin - - - default-install - never - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - com.deliveredtechnologies - tf-maven-plugin - - - org.codehaus.mojo - flatten-maven-plugin - + + org.apache.maven.plugins + maven-install-plugin + + + default-install + never + + + + + + maven-jar-plugin + + + default-jar + never + + unwanted + unwanted + + + + + + com.deliveredtechnologies + tf-maven-plugin + ${tf-maven-version} + + + terraform-clean + clean + + clean + + + + terraform-install + install + + deploy + + + + terraform-package + package + + package + + + + terraform-deploy + deploy + + deploy + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.codehaus.mojo + flatten-maven-plugin + 1.1.0 + + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + + ``` +_**Note: An archetype that creates new Terraform Maven projects is a planned enhancement._ + ### How to Use Terraform Maven Projects -If you used the Starter POM, the following Terraform Maven goals are mapped to the project's Maven phases. +If you used the above configuration, the following Terraform Maven goals are mapped to the project's Maven phases. | Maven Phase | Terraform Maven Goals | |-------------|-----------------------| | install | deploy | -| validate | init, plan | | clean | clean | | package | package | | deploy | deploy | + +### Articles + +* [Unit Testing Terraform](https://medium.com/@claytonlong_34858/unit-testing-terraform-e592a5c3777f) diff --git a/examples/tf-s3-consumer/pom.xml b/examples/tf-s3-consumer/pom.xml index 4ec02e47..74f849d7 100644 --- a/examples/tf-s3-consumer/pom.xml +++ b/examples/tf-s3-consumer/pom.xml @@ -3,11 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - com.deliveredtechnologies - tf-maven-starter - 0.3 - + + 0.4 + tf-s3-consumer com.deliveredtechnologies.example.maven.tf 1.0-SNAPSHOT @@ -24,11 +22,11 @@ + - com.deliveredtechnologies - tf-maven-starter - 0.3 - pom + org.apache.commons + commons-lang3 + 3.9 com.deliveredtechnologies.example.maven.tf @@ -49,6 +47,55 @@ + + + maven-jar-plugin + + + default-jar + never + + unwanted + unwanted + + + + + + com.deliveredtechnologies + tf-maven-plugin + ${tf-maven-version} + + + terraform-clean + clean + + clean + + + + terraform-install + install + + deploy + + + + terraform-package + package + + package + + + + terraform-deploy + deploy + + deploy + + + + org.apache.maven.plugins maven-deploy-plugin @@ -56,13 +103,30 @@ true - - com.deliveredtechnologies - tf-maven-plugin - org.codehaus.mojo flatten-maven-plugin + 1.1.0 + + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index 9b6d37c8..8f41b02e 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -3,11 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - com.deliveredtechnologies - tf-maven-starter - 0.3 - + + 0.4 + tf-s3 com.deliveredtechnologies.example.maven.tf 1.0-SNAPSHOT @@ -24,16 +22,10 @@ - - com.deliveredtechnologies - tf-maven-starter - 0.3 - pom - com.deliveredtechnologies tf-cmd-api - 0.3- + ${tf-maven-version} org.codehaus.groovy @@ -66,6 +58,55 @@ + + + maven-jar-plugin + + + default-jar + never + + unwanted + unwanted + + + + + + com.deliveredtechnologies + tf-maven-plugin + ${tf-maven-version} + + + terraform-clean + clean + + clean + + + + terraform-install + install + + deploy + + + + terraform-package + package + + package + + + + terraform-deploy + deploy + + deploy + + + + org.apache.maven.plugins maven-deploy-plugin @@ -73,13 +114,30 @@ true - - com.deliveredtechnologies - tf-maven-plugin - org.codehaus.mojo flatten-maven-plugin + 1.1.0 + + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + org.codehaus.gmavenplus diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index d3c3d3e3..f7af4947 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,12 +6,11 @@ com.deliveredtechnologies tf-build-tools pom - 0.3 + 0.4 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api tf-maven-plugin - tf-maven-starter 1.8 diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 0f8fa9e6..559dd501 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.3 + 0.4 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java index 33e868f4..b9227472 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java @@ -2,6 +2,7 @@ import com.deliveredtechnologies.terraform.TerraformException; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -39,7 +40,9 @@ public static Path getDefaultTerraformRootModuleDir() throws IOException { */ public static Path getTerraformRootModuleDir(String tfmodule) throws IOException, TerraformException { Path path; - if (tfmodule.contains("/")) { //relative or absolute path + if (tfmodule.startsWith("tf-examples")) { + path = Paths.get("src", "main", tfmodule); + } else if (tfmodule.contains(File.separator)) { //relative or absolute path path = Paths.get(tfmodule); } else { path = Paths.get("src", "main", "tf", tfmodule); diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java index e912d6f5..e584c6c5 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java @@ -38,4 +38,18 @@ public void getTerraformRootModuleDirReturnsTheRootModuleDirRelativeToTheSourceD FileUtils.forceDelete(Paths.get("src", "main", "tf").toFile()); } } + + @Test + public void getTerraformExampleModuleDirReturnsTheRootModuleDirRelativeToTheTfExamplesDir() throws IOException, TerraformException { + try { + FileUtils.copyDirectory( + Paths.get("src", "test", "resources", "tf_initialized", "root").toFile(), + Paths.get("src", "main", "tf-examples", "test").toFile() + ); + Path tfRootModulePath = TerraformUtils.getTerraformRootModuleDir("tf-examples/test"); + Assert.assertEquals(Paths.get("src", "main", "tf-examples", "test"), tfRootModulePath); + } finally { + FileUtils.forceDelete(Paths.get("src", "main", "tf-examples").toFile()); + } + } } diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 89068d13..e57231cb 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.3 + 0.4 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java index 8abea338..e0c9a3f0 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformGet.java @@ -68,6 +68,9 @@ public TerraformGet() throws IOException { @Override public List execute(Properties properties) throws TerraformException { + if (Boolean.valueOf(properties.getProperty("skipTfGet", "false"))) { + return new ArrayList(); + } getDependenciesFromMavenRepo(new DefaultInvoker(), new DefaultInvocationRequest()); return expandMavenArtifacts(tfModules); } @@ -84,7 +87,7 @@ final void getDependenciesFromMavenRepo(Invoker invoker, InvocationRequest reque //TODO: clean up magic strings Properties properties = new Properties(); properties.setProperty("outputDirectory", tfModules.toAbsolutePath().toString()); - properties.setProperty("type", PACKAGING); + properties.setProperty("includeTypes", PACKAGING); request.setGoals(Arrays.asList("dependency:copy-dependencies")); request.setProperties(properties); diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformPackage.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformPackage.java index af9e4876..768c117f 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformPackage.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/TerraformPackage.java @@ -3,16 +3,22 @@ import com.deliveredtechnologies.maven.io.Compressable; import com.deliveredtechnologies.maven.io.CompressableGZipTarFile; import com.deliveredtechnologies.maven.io.CompressableZipFile; +import com.deliveredtechnologies.maven.logs.MavenSlf4jAdapter; import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.TerraformUtils; import com.deliveredtechnologies.terraform.api.TerraformOperation; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; +import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.File; +import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -33,9 +39,9 @@ public class TerraformPackage implements TerraformOperation { static final String targetDir = "target"; static final String targetTfRootDir = "tf-root-module"; - static final List excludedFiles = Arrays.asList(new String[] {".terraform"}); - + static final List excludedFiles = Arrays.asList(new String[] {".terraform", "terraform.tfstate", "terraform.tfstate.backup", ".terraform.tfstate.lock.info"}); + private Logger logger; private MavenProject project; //TODO: Consider using intsance variables instead. @@ -45,10 +51,19 @@ enum TerraformPackageParams { fatTar; } - public TerraformPackage(MavenProject project) { + public TerraformPackage(MavenProject project, Logger logger) { + this.logger = logger; this.project = project; } + public TerraformPackage(MavenProject project, Log log) { + this(project, new MavenSlf4jAdapter(log)); + } + + public TerraformPackage(MavenProject project) { + this(project, LoggerFactory.getLogger(TerraformPackage.class)); + } + /** * Packages a Terraform config as a zip file. *

@@ -73,7 +88,15 @@ public String execute(Properties properties) throws TerraformException { Path tfModulesPath = !StringUtils.isEmpty(tfModulesDir) ? Paths.get(tfModulesDir) : TerraformUtils.getDefaultTfModulesDir(); - Path tfRootPath = !StringUtils.isEmpty(tfRootDir) ? Paths.get(tfRootDir) : TerraformUtils.getDefaultTerraformRootModuleDir(); + logger.debug(String.format("tfModulesPath is %1$s", tfModulesPath.toAbsolutePath().toString())); + + File tfSourceFile = Paths.get("src", "main", "tf").toFile(); + Path tfRootPath = !StringUtils.isEmpty(tfRootDir) + ? TerraformUtils.getTerraformRootModuleDir(tfRootDir) + : (tfSourceFile.exists() && tfSourceFile.isDirectory() && tfSourceFile.listFiles().length > 1 + ? tfSourceFile.toPath() + : TerraformUtils.getDefaultTerraformRootModuleDir()); + logger.debug(String.format("tfRootPath is %1$s", tfRootPath.toAbsolutePath().toString())); //copy tfRoot directory to target if (targetTfRootPath.toFile().exists()) FileUtils.forceDelete(targetTfRootPath.toFile()); @@ -85,7 +108,12 @@ public String execute(Properties properties) throws TerraformException { for (Path file : tfRootDirFiles.stream().filter(f -> !excludedFiles.contains(f.getFileName().toString())).collect(Collectors.toList())) { if (file.toFile().isDirectory()) { - FileUtils.copyDirectory(file.toFile(), targetTfRootPath.resolve(file.getFileName().toString()).toFile()); + FileUtils.copyDirectory(file.toFile(), targetTfRootPath.resolve(file.getFileName().toString()).toFile(), new FileFilter() { + @Override + public boolean accept(File pathname) { + return excludedFiles.stream().noneMatch(excludedFile -> pathname.getName().endsWith(excludedFile)); + } + }); } else { Files.copy(file, targetTfRootPath.resolve(file.getFileName().toString())); } diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Package.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Package.java index 160b5026..34dadd7d 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Package.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Package.java @@ -19,6 +19,6 @@ public class Package extends TerraformMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { - execute(new TerraformPackage(project), System.getProperties()); + execute(new TerraformPackage(project, getLog()), System.getProperties()); } } diff --git a/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformGetTest.java b/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformGetTest.java index 6e4b55db..54c66414 100644 --- a/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformGetTest.java +++ b/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformGetTest.java @@ -64,7 +64,7 @@ public void getDependenciesFromMavenRepoGetsDependenciesIntoModulesDirectory() t TerraformGet terraformGet = new TerraformGet(log, tfModules); Properties properties = new Properties(); properties.setProperty("outputDirectory", tfModules.toAbsolutePath().toString()); - properties.setProperty("type", "zip"); + properties.setProperty("includeTypes", "zip"); terraformGet.getDependenciesFromMavenRepo(invoker, request); diff --git a/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformPackageTest.java b/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformPackageTest.java index 2fc4951c..66fa49a9 100644 --- a/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformPackageTest.java +++ b/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/terraform/TerraformPackageTest.java @@ -6,6 +6,7 @@ import com.deliveredtechnologies.terraform.TerraformException; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.io.FileUtils; import org.apache.maven.project.MavenProject; import org.junit.Assert; import org.junit.Before; @@ -19,6 +20,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.HashSet; import java.util.Properties; import java.util.Set; @@ -124,4 +126,34 @@ public void packageGoalWithNoFatZipPackagesOnlyTfRootContentsInTheTargetDir() th Assert.assertTrue(zipEntryNames.contains("main.tf")); } } + + @Test + public void packageGoalWithNoFatZipAndMultipleModulesPackagesBothTfSourceModulesInTheTargetDir() throws TerraformException, IOException, URISyntaxException { + properties.remove(TerraformPackageParams.tfRootDir.toString()); + this.tfRoot = Paths.get(this.getClass().getResource("/tf_initialized").toURI()); + FileUtils.copyDirectory(this.tfRoot.toFile(), Paths.get("src", "main", "tf").toFile()); + Path zipFilePath = Paths.get(TerraformPackage.targetDir) + .resolve(String.format("%1$s-%2$s.zip", project.getArtifactId(), project.getVersion())); + String response = this.terraformPackage.execute(properties); + + Assert.assertEquals(response, String.format("Created zip file '%1$s'", zipFilePath.toString())); + Assert.assertEquals(2, this.targetTfRootModule.toFile().listFiles().length); + Assert.assertTrue(Arrays.stream(this.targetTfRootModule.toFile().listFiles()).anyMatch(file -> file.getName().equals("root"))); + Assert.assertTrue(Arrays.stream(this.targetTfRootModule.toFile().listFiles()).anyMatch(file -> file.getName().equals("other"))); + + try (IterableZipInputStream zipStream = new IterableZipInputStream(new FileInputStream(zipFilePath.toFile()))) { + int count = 0; + Set zipEntryNames = new HashSet<>(); + for (ZipEntry entry : zipStream) { + count++; + zipEntryNames.add(entry.getName()); + } + + Assert.assertEquals(4, count); + Assert.assertTrue(zipEntryNames.contains("root/")); + Assert.assertTrue(zipEntryNames.contains("other/")); + Assert.assertTrue(zipEntryNames.contains("root/main.tf")); + Assert.assertTrue(zipEntryNames.contains("other/main.tf")); + } + } } diff --git a/tf-build-tools/tf-maven-starter/pom.xml b/tf-build-tools/tf-maven-starter/pom.xml deleted file mode 100644 index 7fddf528..00000000 --- a/tf-build-tools/tf-maven-starter/pom.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - tf-build-tools - com.deliveredtechnologies - 0.3 - - 4.0.0 - tf-maven-starter - pom - tf-maven-starter - Terraform Maven Starter POM :: Simplifying the configuration of the Terraform Maven Plugin - - false - false - false - false - - - - dev - - true - - - ${project.build.sourceDirectory}/../tf/tfvars/dev.tfvars - - - - test - - ${project.build.sourceDirectory}/../tf/tfvars/test.tfvars - - - - stage - - ${project.build.sourceDirectory}/../tf/tfvars/stage.tfvars - - - - prod - - ${project.build.sourceDirectory}/../tf/tfvars/prod.tfvars - - - - - - - - - maven-jar-plugin - - - default-jar - never - - unwanted - unwanted - - - - - - com.deliveredtechnologies - tf-maven-plugin - ${project.parent.version} - - - terraform-install - install - - deploy - - - - terraform-plan - validate - - init - plan - - - - terraform-clean - clean - - clean - - - - terraform-package - package - - package - - - - terraform-deploy - deploy - - deploy - - - - - - org.codehaus.mojo - flatten-maven-plugin - 1.1.0 - - - - - - flatten - process-resources - - flatten - - - - - flatten.clean - clean - - clean - - - - - - - - From ca4421c85b81210e30ff6c1c44a87b9051cd5205 Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Wed, 31 Jul 2019 13:12:40 -0400 Subject: [PATCH 04/14] v0.5 released * added Synk security scans (issue #58) * added tf-s3-archetype (issue #69) * resolved critical maven dependency vulnerabilities --- .DS_Store | Bin 0 -> 6148 bytes README.md | 45 ++++- examples/tf-s3-consumer/pom.xml | 6 +- examples/tf-s3/pom.xml | 4 +- pom.xml | 14 ++ tf-build-tools/pom.xml | 14 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- tf-build-tools/tf-maven-plugin/pom.xml | 13 +- tf-build-tools/tf-s3-archetype/pom.xml | 32 ++++ .../META-INF/maven/archetype-metadata.xml | 21 +++ .../resources/archetype-resources/pom.xml | 167 ++++++++++++++++++ .../src/main/tf/s3/inputs.tf | 24 +++ .../src/main/tf/s3/main.tf | 40 +++++ .../src/main/tf/s3/outputs.tf | 9 + .../src/main/tf/s3/tfvars/dev.tfvars | 2 + .../src/main/tf/s3/tfvars/test.tfvars | 2 + .../src/main/tf/s3_replicated_src/inputs.tf | 27 +++ .../src/main/tf/s3_replicated_src/main.tf | 86 +++++++++ .../src/main/tf/s3_replicated_src/outputs.tf | 9 + .../policies/assume-role-policy.json | 13 ++ .../policies/replication-policy.json | 65 +++++++ .../tf/s3_replicated_src/tfvars/dev.tfvars | 2 + .../tf/s3_replicated_src/tfvars/test.tfvars | 2 + .../src/test/groovy/S3Spec.groovy | 116 ++++++++++++ .../projects/basic/archetype.properties | 5 + .../test/resources/projects/basic/goal.txt | 0 26 files changed, 703 insertions(+), 17 deletions(-) create mode 100644 .DS_Store create mode 100644 pom.xml create mode 100644 tf-build-tools/tf-s3-archetype/pom.xml create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/inputs.tf create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/main.tf create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/outputs.tf create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/dev.tfvars create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/test.tfvars create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/inputs.tf create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/main.tf create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/outputs.tf create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/assume-role-policy.json create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/replication-policy.json create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/dev.tfvars create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/test.tfvars create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy create mode 100644 tf-build-tools/tf-s3-archetype/src/test/resources/projects/basic/archetype.properties create mode 100644 tf-build-tools/tf-s3-archetype/src/test/resources/projects/basic/goal.txt diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..bd5b85acde8e374699d397f37caf84dfb4a20447 GIT binary patch literal 6148 zcmeHKF-`+P3>-s>Aexkv`vrcmioy%>0U&n~MNkj{iFDWTZN~Nji7sg=&{(o(*K2#V zQ=HELZ2sQe0y6+psv|z#jK$AgM{?0Tjutg~ykUU$TJIXxZbV1-^0^YBKn#chF(3xcG2qRWGQCce6$4^G4E!+Q--kkV ztPO|6_;k?32tb_B9l~|Y62#&TVr@7i(nGOKC1$F%5yLW_{?g)V!yz%#VR19-w41F> zC>FQVUm_e<6J^DK7&vC&GPg7D|98|g^Z#*@c49yb{3`}*vRE$Wd{XPJqsMu#E!2DJ qw=g!sX`&SqqZM=Gt@!33uK1egwc(H$>GVfBQ9lCCi$o0k1p{ANTpN)9 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 86f62426..ec33fea7 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,21 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.4/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.4/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.4-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.4-green.svg +[tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ +[maven-badge]:https://img.shields.io/badge/maven%20central-0.5-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5-green.svg +[tf-maven-plugin-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml +[tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml +[tf-cmd-api-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml +[tf-cmd-api-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml ![terraform-maven](.docs/MavenTerraform.png) --- + ![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg) [![Build Status](https://travis-ci.org/deliveredtechnologies/terraform-maven.svg?branch=develop&maxAge=600&service=github)](https://travis-ci.org/deliveredtechnologies/terraform-maven) [![Coverage Status](https://coveralls.io/repos/github/deliveredtechnologies/terraform-maven/badge.svg?branch=develop)](https://coveralls.io/github/deliveredtechnologies/terraform-maven?branch=develop) @@ -35,6 +42,7 @@ The Terraform Maven Plugin brings Maven to Terraform, which greatly enhances Ter * [tf:deploy](#tfdeploy) * [tf:clean](#tfclean) * [Setting Up a Terraform Maven Project](#setting-up-a-terraform-maven-project) +* [Setting Up a Terraform Maven Project Using an ArcheType](#setting-up-a-terraform-maven-project-using-an-archetype) * [How to Use Terraform Maven Projects](#how-to-use-terraform-maven-projects) * [Articles](#articles) @@ -44,10 +52,11 @@ Not finding what you are looking for? [Try the Wiki!](https://github.com/deliver ### Artifacts in This Repository -| Artifact Name | Version | Latest Snapshot | Description | -|------------------|---------------------------------------------------|----------------------------------------------------------------------|-----------------------------| -| tf-maven-plugin | [![Maven Central][maven-badge]][tf-maven-plugin] | [![Maven Snapshot][maven-snapshot-badge]][tf-maven-plugin-snapshot] | Terraform Maven Plugin | -| tf-cmd-api | [![Maven Central][maven-badge]][tf-cmd-api] | [![Maven Snapshot][maven-snapshot-badge]][tf-cmd-api-snapshot] | Terraform Command API | +| Artifact Name | Version | Latest Snapshot | Security Scan Results | Description | +|------------------|---------|-----------------|-----------------------|-------------| +| tf-maven-plugin | [![Maven Central][maven-badge]][tf-maven-plugin] | [![Maven Snapshot][maven-snapshot-badge]][tf-maven-plugin-snapshot] | [![tf-maven-plugin vulnerabilities][tf-maven-plugin-synk-badge]][tf-maven-plugin-synk] | Terraform Maven Plugin | +| tf-cmd-api | [![Maven Central][maven-badge]][tf-cmd-api] | [![Maven Snapshot][maven-snapshot-badge]][tf-cmd-api-snapshot] | [![tf-cmd-api vulnerabilities][tf-cmd-api-synk-badge]][tf-cmd-api-synk] | Terraform Command API | +| tf-s3-archetype | [![Maven Central][maven-badge]][tf-s3-archetype] | [![Maven Snapshot][maven-snapshot-badge]][tf-s3-archetype-snapshot] | N/A | Maven Terraform S3 Archetype | ### Repository Directory Structure * examples - Terraform Maven example projects @@ -351,7 +360,25 @@ Deletes all 'terraform' files from terraform configurations along with the Terra ``` -_**Note: An archetype that creates new Terraform Maven projects is a planned enhancement._ +### Setting Up a Terraform Maven Project Using an ArcheType + +Instead of doing all the above steps you can simply build the module/project by running the [Maven Archetype Plugin](https://maven.apache.org/guides/mini/guide-creating-archetypes.html) which creates project from an archetype. + +An example on how to generate the project using an archetype is shown below. + +```bash +mvn -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DgroupId= -DartifactId= +``` + +Maven Non-Interactive mode creates a project with the name that you passed in under . + +or + +```bash +mvn -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" +``` + +After running the above command mvn interactive console prompts for the required arguments (ex: groupId and artifactId) and creates the project accordingly. ### How to Use Terraform Maven Projects diff --git a/examples/tf-s3-consumer/pom.xml b/examples/tf-s3-consumer/pom.xml index 74f849d7..17906e31 100644 --- a/examples/tf-s3-consumer/pom.xml +++ b/examples/tf-s3-consumer/pom.xml @@ -4,11 +4,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.4 + 0.5 tf-s3-consumer com.deliveredtechnologies.example.maven.tf - 1.0-SNAPSHOT + 1.0 local @@ -31,7 +31,7 @@ com.deliveredtechnologies.example.maven.tf tf-s3 - 1.0-SNAPSHOT + 1.0 zip diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index 8f41b02e..59791e06 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,11 +4,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.4 + 0.5 tf-s3 com.deliveredtechnologies.example.maven.tf - 1.0-SNAPSHOT + 1.0 sonatype diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..2777f3e0 --- /dev/null +++ b/pom.xml @@ -0,0 +1,14 @@ + + + 4.0.0 + com.deliveredtechnologies + tf-maven-parent + pom + 1.0 + Parent project of tf-build-tools; used to enable synk security scans + + tf-build-tools + + diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index f7af4947..e7661015 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,11 +6,12 @@ com.deliveredtechnologies tf-build-tools pom - 0.4 + 0.5 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api tf-maven-plugin + tf-s3-archetype 1.8 @@ -41,6 +42,7 @@ Clayton Long https://github.com/Clayton7510 + architect developer America/New_York @@ -55,6 +57,16 @@ America/New_York + + + Sai Chaitanya + https://github.com/s1234a6i + + developer + + America/New_York + + snapshot diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 559dd501..219d01f4 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.4 + 0.5 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index e57231cb..f5ae8061 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.4 + 0.5 tf-maven-plugin maven-plugin @@ -112,6 +112,17 @@ org.apache.maven.plugins maven-dependency-plugin 3.1.1 + + + org.apache.struts + struts-core + + + + + org.apache.maven.doxia + doxia-core + 1.9 org.apache.maven.plugins diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml new file mode 100644 index 00000000..a4abc1eb --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + com.deliveredtechnologies + tf-build-tools + 0.5 + + tf-s3-archetype + pom + + tf-s3-archetype + + + + + org.apache.maven.archetype + archetype-packaging + 2.4 + + + + + + + maven-archetype-plugin + 2.4 + + + + + diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml new file mode 100644 index 00000000..f694c5ec --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml @@ -0,0 +1,21 @@ + + + + + src/main/tf + + **/*.tf + **/*.tfvars + **/*.json + + + + src/test/groovy + + **/*.groovy + + + + diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml new file mode 100644 index 00000000..a66c8a0b --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -0,0 +1,167 @@ + + + 4.0.0 + + 0.4-SNAPSHOT + + ${artifactId} + ${groupId} + ${version} + + + sonatype + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + sonatype + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + com.deliveredtechnologies + tf-cmd-api + ${tf-maven-version} + + + org.codehaus.groovy + groovy-all + 2.4.7 + test + + + org.spockframework + spock-core + 1.3-groovy-2.4 + test + + + com.amazonaws + aws-java-sdk + 1.11.584 + test + + + + + + org.apache.maven.plugins + maven-install-plugin + + + default-install + never + + + + + + maven-jar-plugin + + + default-jar + never + + unwanted + unwanted + + + + + + com.deliveredtechnologies + tf-maven-plugin + ${tf-maven-version} + + + terraform-clean + clean + + clean + + + + terraform-install + install + + deploy + + + + terraform-package + package + + package + + + + terraform-deploy + deploy + + deploy + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.codehaus.mojo + flatten-maven-plugin + 1.1.0 + + + + + flatten + process-resources + + flatten + + + + + flatten.clean + clean + + clean + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 1.7.0 + + + + addTestSources + compileTests + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*Spec.java + + + + + + diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/inputs.tf b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/inputs.tf new file mode 100644 index 00000000..2d6f8d5f --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/inputs.tf @@ -0,0 +1,24 @@ +variable "region" { + description = "region where the bucket will be created or the source region; defaults to us-east-1" + type = "string" + default = "us-east-1" +} + +variable "bucket_name" { + description = "name of the bucket; defaults to a 'bucket-{random id}'" + type = "string" + default = "" +} + +variable "environment" { + description = "value of the 'Environment' tag" + type = "string" + default = "dev" +} + +variable "is_versioned" { + description = "true if versioning is to be enabled, otherwise false; defaults to false" + type = "string" + default = false +} + diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/main.tf b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/main.tf new file mode 100644 index 00000000..bec8edb3 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/main.tf @@ -0,0 +1,40 @@ +provider "aws" { + region = "${var.region}" +} + +resource "random_id" "bucket_name" { + prefix = "bucket-" + byte_length = 8 +} + +locals { + bucket_name = "${length(var.bucket_name) == 0 ? random_id.bucket_name.hex : var.bucket_name}" +} + +resource "aws_kms_key" "kmskey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +resource "aws_s3_bucket" "bucket" { + bucket = "${local.bucket_name}" + acl = "private" + force_destroy = "true" + + versioning { + enabled = "${var.is_versioned}" + } + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = "${aws_kms_key.kmskey.arn}" + sse_algorithm = "aws:kms" + } + } + } + + tags = { + environment = "${var.environment}" + } +} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/outputs.tf b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/outputs.tf new file mode 100644 index 00000000..ca7abf22 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/outputs.tf @@ -0,0 +1,9 @@ +output "bucket_arn" { + description = "bucket arn" + value = "${aws_s3_bucket.bucket.arn}" +} + +output "kms_key_arn" { + description = "kms key arn for the bucket encryption" + value = "${aws_kms_key.kmskey.arn}" +} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/dev.tfvars b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/dev.tfvars new file mode 100644 index 00000000..44843ce3 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/dev.tfvars @@ -0,0 +1,2 @@ +region = "us-east-2" +environment = "dev" diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/test.tfvars b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/test.tfvars new file mode 100644 index 00000000..3c3bd5f5 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3/tfvars/test.tfvars @@ -0,0 +1,2 @@ +region = "us-east-2" +environment = "test" diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/inputs.tf b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/inputs.tf new file mode 100644 index 00000000..41a53e16 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/inputs.tf @@ -0,0 +1,27 @@ +variable "region" { + description = "region where the bucket will be created or the source region; defaults to us-east-1" + type = "string" + default = "us-east-1" +} + +variable "bucket_name" { + description = "name of the bucket; defaults to a 'bucket-{random id}'" + type = "string" + default = "" +} + +variable "environment" { + description = "value of the 'Environment' tag" + type = "string" + default = "dev" +} + +variable "destination_bucket_arn" { + description = "arn of the destination bucket for replication" + type = "string" +} + +variable "destination_kms_key_arn" { + description = "arn of the destination kms key" + type = "string" +} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/main.tf b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/main.tf new file mode 100644 index 00000000..535b9863 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/main.tf @@ -0,0 +1,86 @@ +provider "aws" { + region = "${var.region}" +} + +resource "random_id" "bucket_name" { + prefix = "bucket-" + byte_length = 8 +} + +locals { + bucket_name = "${length(var.bucket_name) == 0 ? random_id.bucket_name.hex : var.bucket_name}" +} + +data "template_file" "assume_role_policy" { + template = "${file("${path.module}/policies/assume-role-policy.json")}" +} + +data "template_file" "replication_policy" { + template = "${file("${path.module}/policies/replication-policy.json")}" + vars { + source_bucket_arn = "${aws_s3_bucket.source_bucket.arn}" + destination_bucket_arn = "${var.destination_bucket_arn}" + source_kms_key_arn = "${aws_kms_key.kmskey.arn}" + destination_kms_key_arn = "${var.destination_kms_key_arn}" + } +} + +resource "aws_iam_role" "replication" { + name = "tf-iam-role-${local.bucket_name}-replication" + assume_role_policy = "${data.template_file.assume_role_policy.rendered}" +} + +resource "aws_iam_policy" "replication" { + name = "tf-iam-role-policy-${local.bucket_name}-replication" + policy = "${data.template_file.replication_policy.rendered}" +} + +resource "aws_iam_policy_attachment" "replication" { + name = "tf-iam-role-attachment-${local.bucket_name}-replication" + roles = ["${aws_iam_role.replication.name}"] + policy_arn = "${aws_iam_policy.replication.arn}" +} + +resource "aws_kms_key" "kmskey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +resource "aws_s3_bucket" "source_bucket" { + region = "${var.region}" + bucket = "${local.bucket_name}" + acl = "private" + + versioning { + enabled = true + } + + server_side_encryption_configuration { + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = "${aws_kms_key.kmskey.arn}" + sse_algorithm = "aws:kms" + } + } + } + + replication_configuration { + role = "${aws_iam_role.replication.arn}" + "rules" { + "destination" { + bucket = "${var.destination_bucket_arn}" + replica_kms_key_id = "${var.destination_kms_key_arn}" + } + "source_selection_criteria" { + sse_kms_encrypted_objects { + enabled = true + } + } + status = "Enabled" + } + } + + tags = { + Environment = "${var.environment}" + } +} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/outputs.tf b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/outputs.tf new file mode 100644 index 00000000..529feb02 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/outputs.tf @@ -0,0 +1,9 @@ +output "bucket_arn" { + description = "bucket arn" + value = "${aws_s3_bucket.source_bucket.arn}" +} + +output "kms_key_arn" { + description = "kms key arn for the bucket encryption" + value = "${aws_kms_key.kmskey.arn}" +} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/assume-role-policy.json b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/assume-role-policy.json new file mode 100644 index 00000000..cfac0dce --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/assume-role-policy.json @@ -0,0 +1,13 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Principal": { + "Service": "s3.amazonaws.com" + }, + "Effect": "Allow", + "Sid": "" + } + ] +} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/replication-policy.json b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/replication-policy.json new file mode 100644 index 00000000..a6a10ef0 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/policies/replication-policy.json @@ -0,0 +1,65 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "s3:ListBucket", + "s3:Get", + "s3:DeleteBucket" + ], + "Effect": "Allow", + "Resource": [ + "${source_bucket_arn}", + "${destination_bucket_arn}" + ] + }, + { + "Action": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket", + "s3:Get" + ], + "Effect": "Allow", + "Resource": [ + "${source_bucket_arn}", + "${source_bucket_arn}/*" + ] + }, + { + "Action": [ + "s3:GetObjectVersion", + "s3:GetObjectVersionAcl" + ], + "Effect": "Allow", + "Resource": [ + "${source_bucket_arn}/*" + ] + }, + { + "Action": [ + "s3:ListBucket", + "s3:Get", + "s3:ReplicateObject", + "s3:ReplicateDelete", + "s3:ReplicateTags", + "s3:GetObjectVersionTagging" + ], + "Effect": "Allow", + "Resource": "${destination_bucket_arn}/*" + }, + { + "Effect": "Allow", + "Action": [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ], + "Resource": [ + "${source_kms_key_arn}", + "${destination_kms_key_arn}" + ] + } + ] +} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/dev.tfvars b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/dev.tfvars new file mode 100644 index 00000000..44843ce3 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/dev.tfvars @@ -0,0 +1,2 @@ +region = "us-east-2" +environment = "dev" diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/test.tfvars b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/test.tfvars new file mode 100644 index 00000000..3c3bd5f5 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/main/tf/s3_replicated_src/tfvars/test.tfvars @@ -0,0 +1,2 @@ +region = "us-east-2" +environment = "test" diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy new file mode 100644 index 00000000..8f7a7de9 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy @@ -0,0 +1,116 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +package ${package} + +import com.amazonaws.services.s3.AmazonS3 +import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.deliveredtechnologies.terraform.api.TerraformApply +import com.deliveredtechnologies.terraform.api.TerraformDestroy +import com.deliveredtechnologies.terraform.api.TerraformInit +import com.deliveredtechnologies.terraform.api.TerraformOutput +import com.deliveredtechnologies.terraform.api.TerraformPlan +import groovy.json.JsonSlurper +import spock.lang.Specification + +class S3Spec extends Specification { + + def "S3 module provisions a bucket in AWS"() { + given: + Properties tfProperties = new Properties() + + String region = 'us-east-1' + String environment = 'dev' + String stackName = 's3' + + TerraformInit init = new TerraformInit(stackName) + TerraformApply apply = new TerraformApply(stackName) + + AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion("us-east-1").build() + + tfProperties.put('tfRootDir', stackName) + tfProperties.put('tfVars', "region=${symbol_dollar}{region},environment=${symbol_dollar}{environment}".toString()) + + when: + init.execute(tfProperties) + apply.execute(tfProperties) + def jsonOutput = getTerraformOutput(stackName) + String bucketName = jsonOutput.bucket_arn.value[(jsonOutput.bucket_arn.value.lastIndexOf(":") + 1)..-1] + + then: + s3.doesBucketExistV2 bucketName + s3.getBucketTaggingConfiguration(bucketName).getTagSet().getTag('environment') == environment + + cleanup: + TerraformDestroy destroy = new TerraformDestroy(stackName) + destroy.execute(tfProperties) + } + + def "Replicated bucket replicates S3 objects from east to west"() { + given: + Properties tfSrcProperties = new Properties() + Properties tfDestProperties = new Properties() + + String srcRegion = 'us-east-1' + String destRegion = 'us-west-1' + String environment = 'dev' + String srcStackName = 's3_replicated_src' + String destStackName = 's3' + String s3ObjectName = 'test.txt' + + TerraformInit initDest = new TerraformInit(destStackName) + TerraformPlan planDest = new TerraformPlan(destStackName) + TerraformApply applyDest = new TerraformApply(destStackName) + TerraformInit initSrc = new TerraformInit(srcStackName) + TerraformApply applySrc = new TerraformApply(srcStackName) + + AmazonS3 sourceS3 = AmazonS3ClientBuilder.standard().withRegion(srcRegion).build() + AmazonS3 destS3 = AmazonS3ClientBuilder.standard().withRegion(destRegion).build() + + when: + //provision destination bucket + tfDestProperties.put('tfVars', "region=${symbol_dollar}{destRegion},environment=${symbol_dollar}{environment},is_versioned=true".toString()) + + initDest.execute(tfDestProperties) + applyDest.execute(tfDestProperties) + def destJsonOutput = getTerraformOutput(destStackName) + String destBucketArn = destJsonOutput.bucket_arn.value + String destKmsKeyArn = destJsonOutput.kms_key_arn.value + String destBucketName = destBucketArn[(destBucketArn.lastIndexOf(":") + 1)..-1] + + //provision source bucket with replication to destination bucket + tfSrcProperties.put('tfVars', "region=${symbol_dollar}{srcRegion},environment=${symbol_dollar}{environment},destination_bucket_arn=${symbol_dollar}{destBucketArn},destination_kms_key_arn=${symbol_dollar}{destKmsKeyArn}".toString()) + + initSrc.execute(tfSrcProperties) + applySrc.execute(tfSrcProperties) + + def srcJsonOutput = getTerraformOutput(destStackName) + String srcBucketArn = srcJsonOutput.bucket_arn.value + String srcBucketName = srcBucketArn[(srcBucketArn.lastIndexOf(":") + 1)..-1] + + //upload a file to the source region + sourceS3.putObject(srcBucketName, s3ObjectName, "This is a test!") + + //give a little time to replicate + sleep(5000) + + then: + sourceS3.getBucketTaggingConfiguration(srcBucketName).getTagSet().getTag('environment') == environment + destS3.getBucketTaggingConfiguration(destBucketName).getTagSet().getTag('environment') == environment + destS3.doesObjectExist(destBucketName, s3ObjectName) + + cleanup: + TerraformDestroy destroySrc = new TerraformDestroy(srcStackName) + TerraformDestroy destroyDest = new TerraformDestroy(destStackName) + + destroySrc.execute(tfSrcProperties) + destroyDest.execute(tfDestProperties) + } + + private def getTerraformOutput(String stackName) { + TerraformOutput output = new TerraformOutput(stackName) + String tfOutput = output.execute(new Properties()) + JsonSlurper slurper = new JsonSlurper() + slurper.parseText(tfOutput) + } +} diff --git a/tf-build-tools/tf-s3-archetype/src/test/resources/projects/basic/archetype.properties b/tf-build-tools/tf-s3-archetype/src/test/resources/projects/basic/archetype.properties new file mode 100644 index 00000000..3c470815 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/test/resources/projects/basic/archetype.properties @@ -0,0 +1,5 @@ +#Sun Jul 28 20:53:18 EDT 2019 +package=it.pkg +version=0.1-SNAPSHOT +groupId=archetype.it +artifactId=basic diff --git a/tf-build-tools/tf-s3-archetype/src/test/resources/projects/basic/goal.txt b/tf-build-tools/tf-s3-archetype/src/test/resources/projects/basic/goal.txt new file mode 100644 index 00000000..e69de29b From eb1067725c774b00f885c935a44defb91ab7d6c4 Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Wed, 31 Jul 2019 13:14:38 -0400 Subject: [PATCH 05/14] Added tf-s3-archetype to folder structure --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ec33fea7..cc724d11 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Not finding what you are looking for? [Try the Wiki!](https://github.com/deliver * tf-build-tools - The parent project of the tf-maven-plugin and tf-cmd-api projects * tf-maven-plugin - The Terraform Maven Plugin project * tf-cmd-api - A Java API for Terraform project + * tf-s3-archetype - An Archetype for a S3 Terraform Project ### Benefits of the Terraform Maven Plugin * Dependency Management From c0dd140dffaaaa572b5b8820404ab1023d18d183 Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Wed, 31 Jul 2019 15:59:04 -0400 Subject: [PATCH 06/14] v0.5 release patch * updated tf-s3-archetypes pom for deployment --- README.md | 2 +- tf-build-tools/tf-s3-archetype/pom.xml | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cc724d11..bd32415d 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Not finding what you are looking for? [Try the Wiki!](https://github.com/deliver * tf-build-tools - The parent project of the tf-maven-plugin and tf-cmd-api projects * tf-maven-plugin - The Terraform Maven Plugin project * tf-cmd-api - A Java API for Terraform project - * tf-s3-archetype - An Archetype for a S3 Terraform Project + * tf-s3-archetype - An Archetype for a S3 Terraform Project ### Benefits of the Terraform Maven Plugin * Dependency Management diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index a4abc1eb..6a0b1b50 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -10,7 +10,12 @@ pom tf-s3-archetype - + + false + false + false + false + @@ -19,7 +24,6 @@ 2.4 - From f2ade96745d39ea950084031919a6a4c164187d3 Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Sun, 4 Aug 2019 00:27:18 -0400 Subject: [PATCH 07/14] release v0.5.1 * fixed archetype error (#97) --- .gitignore | 1 + .travis.yml | 4 +- README.md | 18 +-- examples/pom.xml | 6 +- examples/tf-s3-consumer/pom.xml | 2 +- .../tf-s3-consumer/src/main/tf/root/inputs.tf | 6 - .../tf-s3-consumer/src/main/tf/root/main.tf | 6 +- .../src/main/tf/root/outputs.tf | 8 +- examples/tf-s3/pom.xml | 2 +- pom.xml | 14 --- tf-build-tools/pom.xml | 4 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- tf-build-tools/tf-maven-plugin/pom.xml | 2 +- tf-build-tools/tf-s3-archetype/pom.xml | 39 ++++-- .../META-INF/maven/archetype-metadata.xml | 29 ++++- .../resources/archetype-resources/pom.xml | 9 +- .../src/test/groovy/tf/s3/S3Spec.groovy | 113 ++++++++++++++++++ .../projects/it-basic/archetype.properties | 4 + .../test/resources/projects/it-basic/goal.txt | 0 19 files changed, 205 insertions(+), 64 deletions(-) delete mode 100644 pom.xml create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/tf/s3/S3Spec.groovy create mode 100644 tf-build-tools/tf-s3-archetype/src/test/resources/projects/it-basic/archetype.properties create mode 100644 tf-build-tools/tf-s3-archetype/src/test/resources/projects/it-basic/goal.txt diff --git a/.gitignore b/.gitignore index 1a4b14c0..8b59b2db 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ target .tfmodules .terraform .gpg +.flattened-pom.xml diff --git a/.travis.yml b/.travis.yml index 0dd79330..4c6a5644 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,8 +22,10 @@ script: VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) if [ $TRAVIS_PULL_REQUEST = "false" ] && echo $VERSION | grep -q SNAPSHOT; then - echo "*** Validating the build and deploying to Sonatype SNAPSHOT repo ***" + echo "*** Validating the build and deploying to Sonatype's SNAPSHOT repo ***" cp ../.mvn.settings.xml $HOME/.m2/settings.xml && ./mvnw clean test coveralls:report deploy + echo "*** Deploying the tf-s3-archetype to Sonatype's SNAPSHOT repo ***" + cd ../tf-s3-archetype && ./mvnw clean deploy else echo "*** Validating the build ***" ./mvnw clean test coveralls:report diff --git a/README.md b/README.md index bd32415d..b22f70a0 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5/jar -[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.1/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.1/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.1/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ [tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.5-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5-green.svg +[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.1-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.1-green.svg [tf-maven-plugin-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-cmd-api-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml @@ -65,7 +65,7 @@ Not finding what you are looking for? [Try the Wiki!](https://github.com/deliver * tf-build-tools - The parent project of the tf-maven-plugin and tf-cmd-api projects * tf-maven-plugin - The Terraform Maven Plugin project * tf-cmd-api - A Java API for Terraform project - * tf-s3-archetype - An Archetype for a S3 Terraform Project +* tf-s3-archetype - An Archetype for a S3 Terraform Project ### Benefits of the Terraform Maven Plugin * Dependency Management @@ -257,7 +257,7 @@ Deletes all 'terraform' files from terraform configurations along with the Terra ```xml - 0.4 + 0.5.1 ``` @@ -368,7 +368,7 @@ Instead of doing all the above steps you can simply build the module/project by An example on how to generate the project using an archetype is shown below. ```bash -mvn -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DgroupId= -DartifactId= +mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DgroupId= -DartifactId= ``` Maven Non-Interactive mode creates a project with the name that you passed in under . @@ -376,7 +376,7 @@ Maven Non-Interactive mode creates a project with the name that you passed in - + + 4.0.0 com.deliveredtechnologies.example.maven.tf examples diff --git a/examples/tf-s3-consumer/pom.xml b/examples/tf-s3-consumer/pom.xml index 17906e31..c3e9a60c 100644 --- a/examples/tf-s3-consumer/pom.xml +++ b/examples/tf-s3-consumer/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5 + 0.5.1 tf-s3-consumer com.deliveredtechnologies.example.maven.tf diff --git a/examples/tf-s3-consumer/src/main/tf/root/inputs.tf b/examples/tf-s3-consumer/src/main/tf/root/inputs.tf index eac832d3..9d3e6362 100644 --- a/examples/tf-s3-consumer/src/main/tf/root/inputs.tf +++ b/examples/tf-s3-consumer/src/main/tf/root/inputs.tf @@ -4,12 +4,6 @@ variable "region" { default = "us-east-1" } -variable "replication_region" { - description = "region where the bucket will be repliced to (destination), if applicable; defaults to us-west-1" - type = "string" - default = "us-west-1" -} - variable "bucket_name" { description = "name of the bucket; defaults to a 'bucket-{random id}'" type = "string" diff --git a/examples/tf-s3-consumer/src/main/tf/root/main.tf b/examples/tf-s3-consumer/src/main/tf/root/main.tf index 551f235d..22c53ef1 100644 --- a/examples/tf-s3-consumer/src/main/tf/root/main.tf +++ b/examples/tf-s3-consumer/src/main/tf/root/main.tf @@ -1,12 +1,10 @@ locals { - bucket_arns = "${split(",", module.s3.bucket_arns)}" + bucket_arns = "${split(",", module.s3.bucket_arn)}" } module "s3" { - source = "../../.tfmodules/s3" + source = "../../.tfmodules/s3/s3" bucket_name = "${var.bucket_name}" environment = "${var.environment}" region = "${var.region}" - replication_region = "${var.replication_region}" - is_replicated = true } diff --git a/examples/tf-s3-consumer/src/main/tf/root/outputs.tf b/examples/tf-s3-consumer/src/main/tf/root/outputs.tf index 288ab24d..d662bd0f 100644 --- a/examples/tf-s3-consumer/src/main/tf/root/outputs.tf +++ b/examples/tf-s3-consumer/src/main/tf/root/outputs.tf @@ -1,9 +1,5 @@ -output "bucket_arns" { +output "bucket_arn" { description = "The arn of the S3 bucket" - value = "${element(local.bucket_arns, 0)}" + value = "${module.s3.bucket_arn}" } -output "replicated_bucket_arn" { - description = "The arn of the S3 bucket that objects are replicated to" - value = "${element(local.bucket_arns, 1)}" -} diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index 59791e06..dd7224ee 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5 + 0.5.1 tf-s3 com.deliveredtechnologies.example.maven.tf diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 2777f3e0..00000000 --- a/pom.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - 4.0.0 - com.deliveredtechnologies - tf-maven-parent - pom - 1.0 - Parent project of tf-build-tools; used to enable synk security scans - - tf-build-tools - - diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index e7661015..20a2e49f 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.5 + 0.5.1 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api @@ -177,7 +177,7 @@ 1.1.0 true - minimum + oss diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 219d01f4..2a3ba5a3 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.5 + 0.5.1 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index f5ae8061..888bc0ad 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.5 + 0.5.1 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index 6a0b1b50..2dab69e4 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -1,34 +1,59 @@ - + + 4.0.0 com.deliveredtechnologies + 0.5.1 tf-build-tools - 0.5 tf-s3-archetype - pom + maven-archetype + + Archetype - tf-s3-archetype + Terraform Maven S3 Project Archetype + https://github.com/deliveredtechnologies/terraform-maven - tf-s3-archetype + UTF-8 + 1.8 + 1.8 false false false false + org.apache.maven.archetype archetype-packaging - 2.4 + 3.0.1 - + + + maven-clean-plugin + 3.1.0 + maven-archetype-plugin - 2.4 + 3.0.1 + + + maven-resources-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml index f694c5ec..d025271c 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml @@ -1,7 +1,28 @@ - + + + + + src/main/tf @@ -11,7 +32,7 @@ **/*.json - + src/test/groovy **/*.groovy diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml index a66c8a0b..ca17e8a6 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -1,8 +1,10 @@ - + 4.0.0 - 0.4-SNAPSHOT + 0.5.1 ${artifactId} ${groupId} @@ -116,7 +118,8 @@ org.codehaus.mojo flatten-maven-plugin 1.1.0 - + + diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/tf/s3/S3Spec.groovy b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/tf/s3/S3Spec.groovy new file mode 100644 index 00000000..72bdc8cd --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/tf/s3/S3Spec.groovy @@ -0,0 +1,113 @@ +package tf.s3 + +import com.amazonaws.services.s3.AmazonS3 +import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.deliveredtechnologies.terraform.api.TerraformApply +import com.deliveredtechnologies.terraform.api.TerraformDestroy +import com.deliveredtechnologies.terraform.api.TerraformInit +import com.deliveredtechnologies.terraform.api.TerraformOutput +import com.deliveredtechnologies.terraform.api.TerraformPlan +import groovy.json.JsonSlurper +import spock.lang.Specification + +class S3Spec extends Specification { + + def "S3 module provisions a bucket in AWS"() { + given: + Properties tfProperties = new Properties() + + String region = 'us-east-1' + String environment = 'dev' + String stackName = 's3' + + TerraformInit init = new TerraformInit(stackName) + TerraformApply apply = new TerraformApply(stackName) + + AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion("us-east-1").build() + + tfProperties.put('tfRootDir', stackName) + tfProperties.put('tfVars', "region=${region},environment=${environment}".toString()) + + when: + init.execute(tfProperties) + apply.execute(tfProperties) + def jsonOutput = getTerraformOutput(stackName) + String bucketName = jsonOutput.bucket_arn.value[(jsonOutput.bucket_arn.value.lastIndexOf(":") + 1)..-1] + + then: + s3.doesBucketExistV2 bucketName + s3.getBucketTaggingConfiguration(bucketName).getTagSet().getTag('environment') == environment + + cleanup: + TerraformDestroy destroy = new TerraformDestroy(stackName) + destroy.execute(tfProperties) + } + + def "Replicated bucket replicates S3 objects from east to west"() { + given: + Properties tfSrcProperties = new Properties() + Properties tfDestProperties = new Properties() + + String srcRegion = 'us-east-1' + String destRegion = 'us-west-1' + String environment = 'dev' + String srcStackName = 's3_replicated_src' + String destStackName = 's3' + String s3ObjectName = 'test.txt' + + TerraformInit initDest = new TerraformInit(destStackName) + TerraformPlan planDest = new TerraformPlan(destStackName) + TerraformApply applyDest = new TerraformApply(destStackName) + TerraformInit initSrc = new TerraformInit(srcStackName) + TerraformApply applySrc = new TerraformApply(srcStackName) + + AmazonS3 sourceS3 = AmazonS3ClientBuilder.standard().withRegion(srcRegion).build() + AmazonS3 destS3 = AmazonS3ClientBuilder.standard().withRegion(destRegion).build() + + when: + //provision destination bucket + tfDestProperties.put('tfVars', "region=${destRegion},environment=${environment},is_versioned=true".toString()) + + initDest.execute(tfDestProperties) + applyDest.execute(tfDestProperties) + def destJsonOutput = getTerraformOutput(destStackName) + String destBucketArn = destJsonOutput.bucket_arn.value + String destKmsKeyArn = destJsonOutput.kms_key_arn.value + String destBucketName = destBucketArn[(destBucketArn.lastIndexOf(":") + 1)..-1] + + //provision source bucket with replication to destination bucket + tfSrcProperties.put('tfVars', "region=${srcRegion},environment=${environment},destination_bucket_arn=${destBucketArn},destination_kms_key_arn=${destKmsKeyArn}".toString()) + + initSrc.execute(tfSrcProperties) + applySrc.execute(tfSrcProperties) + + def srcJsonOutput = getTerraformOutput(destStackName) + String srcBucketArn = srcJsonOutput.bucket_arn.value + String srcBucketName = srcBucketArn[(srcBucketArn.lastIndexOf(":") + 1)..-1] + + //upload a file to the source region + sourceS3.putObject(srcBucketName, s3ObjectName, "This is a test!") + + //give a little time to replicate + sleep(5000) + + then: + sourceS3.getBucketTaggingConfiguration(srcBucketName).getTagSet().getTag('environment') == environment + destS3.getBucketTaggingConfiguration(destBucketName).getTagSet().getTag('environment') == environment + destS3.doesObjectExist(destBucketName, s3ObjectName) + + cleanup: + TerraformDestroy destroySrc = new TerraformDestroy(srcStackName) + TerraformDestroy destroyDest = new TerraformDestroy(destStackName) + + destroySrc.execute(tfSrcProperties) + destroyDest.execute(tfDestProperties) + } + + private def getTerraformOutput(String stackName) { + TerraformOutput output = new TerraformOutput(stackName) + String tfOutput = output.execute(new Properties()) + JsonSlurper slurper = new JsonSlurper() + slurper.parseText(tfOutput) + } +} diff --git a/tf-build-tools/tf-s3-archetype/src/test/resources/projects/it-basic/archetype.properties b/tf-build-tools/tf-s3-archetype/src/test/resources/projects/it-basic/archetype.properties new file mode 100644 index 00000000..52de1ac3 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/test/resources/projects/it-basic/archetype.properties @@ -0,0 +1,4 @@ +groupId=archetype.it +artifactId=basic-project +version=0.1-SNAPSHOT +package=it.pkg diff --git a/tf-build-tools/tf-s3-archetype/src/test/resources/projects/it-basic/goal.txt b/tf-build-tools/tf-s3-archetype/src/test/resources/projects/it-basic/goal.txt new file mode 100644 index 00000000..e69de29b From d3edb6ebc09b1aff00130f4321643f1a84dc192c Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Tue, 6 Aug 2019 13:30:40 -0400 Subject: [PATCH 08/14] released v0.5.2 - fixed broken test in archetype --- README.md | 7 +- examples/tf-s3-consumer/pom.xml | 2 +- examples/tf-s3/pom.xml | 2 +- tf-build-tools/pom.xml | 2 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- tf-build-tools/tf-maven-plugin/pom.xml | 2 +- tf-build-tools/tf-s3-archetype/pom.xml | 2 +- .../resources/archetype-resources/pom.xml | 7 +- .../src/test/groovy/S3Spec.groovy | 116 ------------------ 9 files changed, 16 insertions(+), 126 deletions(-) delete mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy diff --git a/README.md b/README.md index b22f70a0..531b36d4 100644 --- a/README.md +++ b/README.md @@ -257,7 +257,7 @@ Deletes all 'terraform' files from terraform configurations along with the Terra ```xml - 0.5.1 + 0.5.2 ``` @@ -368,7 +368,7 @@ Instead of doing all the above steps you can simply build the module/project by An example on how to generate the project using an archetype is shown below. ```bash -mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DgroupId= -DartifactId= +mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersionId=0.5.2 -DgroupId= -DartifactId= ``` Maven Non-Interactive mode creates a project with the name that you passed in under . @@ -376,7 +376,7 @@ Maven Non-Interactive mode creates a project with the name that you passed in 4.0.0 - 0.5.1 + 0.5.2 tf-s3-consumer com.deliveredtechnologies.example.maven.tf diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index dd7224ee..47be38a0 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.1 + 0.5.2 tf-s3 com.deliveredtechnologies.example.maven.tf diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index 20a2e49f..f26d77ac 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.5.1 + 0.5.2 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 2a3ba5a3..6904ad74 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.5.1 + 0.5.2 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 888bc0ad..716980c2 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.5.1 + 0.5.2 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index 2dab69e4..e3b2347d 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.deliveredtechnologies - 0.5.1 + 0.5.2 tf-build-tools tf-s3-archetype diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml index ca17e8a6..c28d4c75 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.1 + 0.5.2 ${artifactId} ${groupId} @@ -22,6 +22,11 @@ + + com.fasterxml.jackson.core + jackson-databind + 2.8.3 + com.deliveredtechnologies tf-cmd-api diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy deleted file mode 100644 index 8f7a7de9..00000000 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy +++ /dev/null @@ -1,116 +0,0 @@ -#set( $symbol_pound = '#' ) -#set( $symbol_dollar = '$' ) -#set( $symbol_escape = '\' ) -package ${package} - -import com.amazonaws.services.s3.AmazonS3 -import com.amazonaws.services.s3.AmazonS3ClientBuilder -import com.deliveredtechnologies.terraform.api.TerraformApply -import com.deliveredtechnologies.terraform.api.TerraformDestroy -import com.deliveredtechnologies.terraform.api.TerraformInit -import com.deliveredtechnologies.terraform.api.TerraformOutput -import com.deliveredtechnologies.terraform.api.TerraformPlan -import groovy.json.JsonSlurper -import spock.lang.Specification - -class S3Spec extends Specification { - - def "S3 module provisions a bucket in AWS"() { - given: - Properties tfProperties = new Properties() - - String region = 'us-east-1' - String environment = 'dev' - String stackName = 's3' - - TerraformInit init = new TerraformInit(stackName) - TerraformApply apply = new TerraformApply(stackName) - - AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion("us-east-1").build() - - tfProperties.put('tfRootDir', stackName) - tfProperties.put('tfVars', "region=${symbol_dollar}{region},environment=${symbol_dollar}{environment}".toString()) - - when: - init.execute(tfProperties) - apply.execute(tfProperties) - def jsonOutput = getTerraformOutput(stackName) - String bucketName = jsonOutput.bucket_arn.value[(jsonOutput.bucket_arn.value.lastIndexOf(":") + 1)..-1] - - then: - s3.doesBucketExistV2 bucketName - s3.getBucketTaggingConfiguration(bucketName).getTagSet().getTag('environment') == environment - - cleanup: - TerraformDestroy destroy = new TerraformDestroy(stackName) - destroy.execute(tfProperties) - } - - def "Replicated bucket replicates S3 objects from east to west"() { - given: - Properties tfSrcProperties = new Properties() - Properties tfDestProperties = new Properties() - - String srcRegion = 'us-east-1' - String destRegion = 'us-west-1' - String environment = 'dev' - String srcStackName = 's3_replicated_src' - String destStackName = 's3' - String s3ObjectName = 'test.txt' - - TerraformInit initDest = new TerraformInit(destStackName) - TerraformPlan planDest = new TerraformPlan(destStackName) - TerraformApply applyDest = new TerraformApply(destStackName) - TerraformInit initSrc = new TerraformInit(srcStackName) - TerraformApply applySrc = new TerraformApply(srcStackName) - - AmazonS3 sourceS3 = AmazonS3ClientBuilder.standard().withRegion(srcRegion).build() - AmazonS3 destS3 = AmazonS3ClientBuilder.standard().withRegion(destRegion).build() - - when: - //provision destination bucket - tfDestProperties.put('tfVars', "region=${symbol_dollar}{destRegion},environment=${symbol_dollar}{environment},is_versioned=true".toString()) - - initDest.execute(tfDestProperties) - applyDest.execute(tfDestProperties) - def destJsonOutput = getTerraformOutput(destStackName) - String destBucketArn = destJsonOutput.bucket_arn.value - String destKmsKeyArn = destJsonOutput.kms_key_arn.value - String destBucketName = destBucketArn[(destBucketArn.lastIndexOf(":") + 1)..-1] - - //provision source bucket with replication to destination bucket - tfSrcProperties.put('tfVars', "region=${symbol_dollar}{srcRegion},environment=${symbol_dollar}{environment},destination_bucket_arn=${symbol_dollar}{destBucketArn},destination_kms_key_arn=${symbol_dollar}{destKmsKeyArn}".toString()) - - initSrc.execute(tfSrcProperties) - applySrc.execute(tfSrcProperties) - - def srcJsonOutput = getTerraformOutput(destStackName) - String srcBucketArn = srcJsonOutput.bucket_arn.value - String srcBucketName = srcBucketArn[(srcBucketArn.lastIndexOf(":") + 1)..-1] - - //upload a file to the source region - sourceS3.putObject(srcBucketName, s3ObjectName, "This is a test!") - - //give a little time to replicate - sleep(5000) - - then: - sourceS3.getBucketTaggingConfiguration(srcBucketName).getTagSet().getTag('environment') == environment - destS3.getBucketTaggingConfiguration(destBucketName).getTagSet().getTag('environment') == environment - destS3.doesObjectExist(destBucketName, s3ObjectName) - - cleanup: - TerraformDestroy destroySrc = new TerraformDestroy(srcStackName) - TerraformDestroy destroyDest = new TerraformDestroy(destStackName) - - destroySrc.execute(tfSrcProperties) - destroyDest.execute(tfDestProperties) - } - - private def getTerraformOutput(String stackName) { - TerraformOutput output = new TerraformOutput(stackName) - String tfOutput = output.execute(new Properties()) - JsonSlurper slurper = new JsonSlurper() - slurper.parseText(tfOutput) - } -} From e021cd7fbeac713c031e71e4e6ee363dfb84ec5e Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Tue, 6 Aug 2019 17:12:58 -0400 Subject: [PATCH 09/14] Updated maven badges --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 531b36d4..6a022d0f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.1/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.1/jar -[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.1/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.2/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.2/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.2/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ [tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.1-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.1-green.svg +[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.2-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.2-green.svg [tf-maven-plugin-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-cmd-api-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml From b82bd6d5f4416103ac791fc7d90d567f9ab75faa Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Thu, 22 Aug 2019 09:46:00 -0400 Subject: [PATCH 10/14] released v0.5.3 * fixed TerraformOutput on Windows & updated tf-cmd-api for Windows compatibility --- README.md | 15 +-- examples/tf-s3-consumer/pom.xml | 2 +- examples/tf-s3/pom.xml | 2 +- tf-build-tools/pom.xml | 2 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- .../deliveredtechnologies/io/CommandLine.java | 6 +- .../terraform/TerraformUtils.java | 16 ++- .../io/CommandLineTest.java | 25 +++- .../TerraformCommandLineDecoratorTest.java | 12 +- .../terraform/TerraformUtilsTest.java | 10 +- tf-build-tools/tf-maven-plugin/pom.xml | 2 +- .../io/ExpandableZippedArtifactTest.java | 4 +- tf-build-tools/tf-s3-archetype/pom.xml | 2 +- .../resources/archetype-resources/pom.xml | 2 +- .../src/test/groovy/S3Spec.groovy | 116 ++++++++++++++++++ 15 files changed, 184 insertions(+), 34 deletions(-) create mode 100644 tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy diff --git a/README.md b/README.md index 6a022d0f..b69a8a8a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.2/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.2/jar -[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.2/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.3/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.3/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.3/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ [tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.2-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.2-green.svg +[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.3-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.3-green.svg [tf-maven-plugin-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-cmd-api-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml @@ -41,6 +41,7 @@ The Terraform Maven Plugin brings Maven to Terraform, which greatly enhances Ter * [tf:package](#tfpackage) * [tf:deploy](#tfdeploy) * [tf:clean](#tfclean) +* [Getting Started](https://github.com/deliveredtechnologies/terraform-maven/wiki/Getting-Started) * [Setting Up a Terraform Maven Project](#setting-up-a-terraform-maven-project) * [Setting Up a Terraform Maven Project Using an ArcheType](#setting-up-a-terraform-maven-project-using-an-archetype) * [How to Use Terraform Maven Projects](#how-to-use-terraform-maven-projects) @@ -65,7 +66,7 @@ Not finding what you are looking for? [Try the Wiki!](https://github.com/deliver * tf-build-tools - The parent project of the tf-maven-plugin and tf-cmd-api projects * tf-maven-plugin - The Terraform Maven Plugin project * tf-cmd-api - A Java API for Terraform project -* tf-s3-archetype - An Archetype for a S3 Terraform Project + * tf-s3-archetype - An Archetype for a S3 Terraform Project ### Benefits of the Terraform Maven Plugin * Dependency Management @@ -74,7 +75,7 @@ Not finding what you are looking for? [Try the Wiki!](https://github.com/deliver that module is sourced. The Terraform Maven Plugin allows you to specify your dependencies for Terraform the same way you specify your dependencies with Java: in an external [Maven POM file](https://maven.apache.org/pom.html). And because it's Maven, Terraform modules sourced from Maven repos can also take advantage of version ranges and - Maven's SNAPSHOT functionality. No more modifying code for version updates! No more sourcing obscure URLs! + Maven's SNAPSHOT functionality. It also resoolves transitive dependencies. No more modifying code for version updates! No more sourcing obscure URLs! Hooray, Maven! * Packaging as Part of the Build Lifecycle * The [package goal](#tfpackage) can package a Terraform root module for deployment into a Maven repo diff --git a/examples/tf-s3-consumer/pom.xml b/examples/tf-s3-consumer/pom.xml index 7d50c29c..47e79a6c 100644 --- a/examples/tf-s3-consumer/pom.xml +++ b/examples/tf-s3-consumer/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.2 + 0.5.3-SNAPSHOT tf-s3-consumer com.deliveredtechnologies.example.maven.tf diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index 47be38a0..a2832339 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.2 + 0.5.3 tf-s3 com.deliveredtechnologies.example.maven.tf diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index f26d77ac..b9398790 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.5.2 + 0.5.3 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 6904ad74..15070506 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.5.2 + 0.5.3 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java index 887f71d6..503eb661 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java @@ -6,7 +6,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Path; -import java.util.Arrays; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -49,15 +48,14 @@ public String execute(String command, int timeout) throws IOException, Interrupt command }; ProcessBuilder processBuilder = new ProcessBuilder(cmd); - processBuilder.directory(directory.toFile()); - process = processBuilder.inheritIO().start(); + processBuilder.directory(directory.toAbsolutePath().toFile()); + process = processBuilder.start(); } else { String[] cmd = new String[] { "bash", "-c", command }; - logger.ifPresent(log -> log.debug(Arrays.stream(cmd).reduce("", (stringA, stringB) -> stringA + stringB))); ProcessBuilder processBuilder = new ProcessBuilder(cmd); processBuilder.directory(directory.toFile()); process = processBuilder.start(); diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java index b9227472..43f0e5d2 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformUtils.java @@ -1,6 +1,7 @@ package com.deliveredtechnologies.terraform; -import com.deliveredtechnologies.terraform.TerraformException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; @@ -15,18 +16,25 @@ public class TerraformUtils { private TerraformUtils() { } + private static final Logger LOGGER = LoggerFactory.getLogger(TerraformUtils.class); + /** * Gets the default Terraform root module directory `src/main/terraform/{root module dir}`. * @return a Path corresponding to the Terraform root module directory * @throws IOException */ public static Path getDefaultTerraformRootModuleDir() throws IOException { - Path tfSourcePath = Paths.get("src", "main", "tf"); - if (tfSourcePath.toFile().exists() && tfSourcePath.toFile().isDirectory()) { - return Files.walk(Paths.get("src", "main", "tf"), 2) + try { + Path tfSourcePath = Paths.get("src", "main", "tf"); + if (tfSourcePath.toFile().exists() && tfSourcePath.toFile().isDirectory()) { + return Files.walk(tfSourcePath, 2) .filter(path -> !path.toFile().isDirectory()) .filter(path -> path.getFileName().toString().endsWith(".tf")) .findFirst().orElseThrow(() -> new IOException("Terraform root module not found")).getParent(); + } + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + LOGGER.info("Unable to determine default Terraform root module directory; using current directory."); } return Paths.get("."); } diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java index 421b4b34..63e8e929 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java @@ -1,5 +1,6 @@ package com.deliveredtechnologies.io; +import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -25,11 +26,27 @@ public void setup() throws URISyntaxException { public void executeRunsCommandOnCommandLineShellAndReturnsTheOutput() throws IOException, InterruptedException { String echoString = "Hello World!"; Executable commandLine = new CommandLine(directory); - String output = commandLine.execute(String.format("echo \"%1$s\"", echoString)); - Assert.assertEquals(String.format("%1$s\n", echoString), output); + String output = commandLine.execute(String.format("echo %1$s", echoString)); + Assert.assertEquals(String.format("%1$s%n", echoString), output); - output = commandLine.execute(String.format("echo \"%1$s\"", echoString), 1000); - Assert.assertEquals(String.format("%1$s\n", echoString), output); + output = commandLine.execute(String.format("echo %1$s", echoString), 1000); + Assert.assertEquals(String.format("%1$s%n", echoString), output); + } + + @Test + public void executeRunsInTheSpecifiedDirectory() throws IOException, InterruptedException { + boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); + Path path = Paths.get("src", "main", "tf", "root"); + FileUtils.forceMkdir(path.toFile()); + Executable commandLine = new CommandLine(path); + if (isWindows) { + String output = commandLine.execute("cd"); + Assert.assertEquals(String.format("%1$s%n", path.toAbsolutePath().toString()), output); + } else { + String output = commandLine.execute("pwd"); + Assert.assertEquals(String.format("%1$s%n", path.toAbsolutePath().toString()), output); + } + FileUtils.forceDelete(path.getParent().toFile()); } @Test(expected = IOException.class) diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java index 9d95254c..65bdc18e 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java @@ -3,15 +3,16 @@ import com.deliveredtechnologies.io.CommandLine; import com.deliveredtechnologies.io.Executable; -import org.apache.commons.io.FileUtils; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Comparator; public class TerraformCommandLineDecoratorTest { @@ -50,11 +51,14 @@ public void terraformCommandLineDecoratorUsesDefaultRootModuleDirWhenTfSourceDir @Test public void terraformCommandLineDecoratorSucceedsOnCreationWhenTfSourceDirIsFound() throws IOException { - Path tfSrcPath = Paths.get("src", "main", "tf"); + Path tfMainPath = Paths.get("src", "main"); + Path tfSrcPath = tfMainPath.resolve("tf"); + if (tfSrcPath.toFile().exists()) Files.delete(tfSrcPath); Path rootModulePath = tfSrcPath.resolve("root"); - FileUtils.forceMkdir(rootModulePath.toFile()); + Files.createDirectory(tfSrcPath); + Files.createDirectory(rootModulePath); Files.createFile(rootModulePath.resolve("main.tf")); TerraformCommandLineDecorator terraformCommandLineDecorator = new TerraformCommandLineDecorator(TerraformCommand.APPLY); - FileUtils.forceDelete(tfSrcPath.toFile()); + Files.walk(tfSrcPath).sorted(Comparator.reverseOrder()).map(path -> path.toFile()).forEach(File::delete); } } diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java index e584c6c5..e9c47e5b 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformUtilsTest.java @@ -5,8 +5,12 @@ import org.junit.Test; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; /** * Tests for TerraformUtils. @@ -27,15 +31,17 @@ public void getTerraformRootModuleDirReturnsTheDefaultDirWhenTheTfSourceDirIsNot @Test public void getTerraformRootModuleDirReturnsTheRootModuleDirRelativeToTheSourceDir() throws IOException, TerraformException { + Path testModule = Paths.get("src", "main", "tf", "test"); try { FileUtils.copyDirectory( Paths.get("src", "test", "resources", "tf_initialized", "root").toFile(), - Paths.get("src", "main", "tf", "test").toFile() + testModule.toFile() ); Path tfRootModulePath = TerraformUtils.getTerraformRootModuleDir("test"); Assert.assertEquals(Paths.get("src", "main", "tf", "test"), tfRootModulePath); } finally { - FileUtils.forceDelete(Paths.get("src", "main", "tf").toFile()); + List paths = Files.walk(testModule).sorted(Comparator.reverseOrder()).collect(Collectors.toList()); + paths.forEach(path -> path.toFile().delete()); } } diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 716980c2..5f80bf30 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.5.2 + 0.5.3 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/io/ExpandableZippedArtifactTest.java b/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/io/ExpandableZippedArtifactTest.java index b0f0de2d..221ec5b7 100644 --- a/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/io/ExpandableZippedArtifactTest.java +++ b/tf-build-tools/tf-maven-plugin/src/test/java/com/deliveredtechnologies/maven/io/ExpandableZippedArtifactTest.java @@ -1,6 +1,5 @@ package com.deliveredtechnologies.maven.io; -import org.apache.commons.io.FileUtils; import org.apache.maven.plugin.logging.Log; import org.junit.After; import org.junit.Assert; @@ -8,6 +7,7 @@ import org.junit.Test; import org.mockito.Mockito; +import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; @@ -46,7 +46,7 @@ public void setup() throws URISyntaxException, IOException { */ @After public void teardown() throws IOException { - FileUtils.forceDelete(zipFileDir.toFile()); + Files.walk(zipFileDir).map(path -> path.toFile()).forEach(File::delete); } @Test diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index e3b2347d..1bd3ee51 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.deliveredtechnologies - 0.5.2 + 0.5.3 tf-build-tools tf-s3-archetype diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml index c28d4c75..e5d9efd8 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.2 + 0.5.3 ${artifactId} ${groupId} diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy new file mode 100644 index 00000000..8f7a7de9 --- /dev/null +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/src/test/groovy/S3Spec.groovy @@ -0,0 +1,116 @@ +#set( $symbol_pound = '#' ) +#set( $symbol_dollar = '$' ) +#set( $symbol_escape = '\' ) +package ${package} + +import com.amazonaws.services.s3.AmazonS3 +import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.deliveredtechnologies.terraform.api.TerraformApply +import com.deliveredtechnologies.terraform.api.TerraformDestroy +import com.deliveredtechnologies.terraform.api.TerraformInit +import com.deliveredtechnologies.terraform.api.TerraformOutput +import com.deliveredtechnologies.terraform.api.TerraformPlan +import groovy.json.JsonSlurper +import spock.lang.Specification + +class S3Spec extends Specification { + + def "S3 module provisions a bucket in AWS"() { + given: + Properties tfProperties = new Properties() + + String region = 'us-east-1' + String environment = 'dev' + String stackName = 's3' + + TerraformInit init = new TerraformInit(stackName) + TerraformApply apply = new TerraformApply(stackName) + + AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion("us-east-1").build() + + tfProperties.put('tfRootDir', stackName) + tfProperties.put('tfVars', "region=${symbol_dollar}{region},environment=${symbol_dollar}{environment}".toString()) + + when: + init.execute(tfProperties) + apply.execute(tfProperties) + def jsonOutput = getTerraformOutput(stackName) + String bucketName = jsonOutput.bucket_arn.value[(jsonOutput.bucket_arn.value.lastIndexOf(":") + 1)..-1] + + then: + s3.doesBucketExistV2 bucketName + s3.getBucketTaggingConfiguration(bucketName).getTagSet().getTag('environment') == environment + + cleanup: + TerraformDestroy destroy = new TerraformDestroy(stackName) + destroy.execute(tfProperties) + } + + def "Replicated bucket replicates S3 objects from east to west"() { + given: + Properties tfSrcProperties = new Properties() + Properties tfDestProperties = new Properties() + + String srcRegion = 'us-east-1' + String destRegion = 'us-west-1' + String environment = 'dev' + String srcStackName = 's3_replicated_src' + String destStackName = 's3' + String s3ObjectName = 'test.txt' + + TerraformInit initDest = new TerraformInit(destStackName) + TerraformPlan planDest = new TerraformPlan(destStackName) + TerraformApply applyDest = new TerraformApply(destStackName) + TerraformInit initSrc = new TerraformInit(srcStackName) + TerraformApply applySrc = new TerraformApply(srcStackName) + + AmazonS3 sourceS3 = AmazonS3ClientBuilder.standard().withRegion(srcRegion).build() + AmazonS3 destS3 = AmazonS3ClientBuilder.standard().withRegion(destRegion).build() + + when: + //provision destination bucket + tfDestProperties.put('tfVars', "region=${symbol_dollar}{destRegion},environment=${symbol_dollar}{environment},is_versioned=true".toString()) + + initDest.execute(tfDestProperties) + applyDest.execute(tfDestProperties) + def destJsonOutput = getTerraformOutput(destStackName) + String destBucketArn = destJsonOutput.bucket_arn.value + String destKmsKeyArn = destJsonOutput.kms_key_arn.value + String destBucketName = destBucketArn[(destBucketArn.lastIndexOf(":") + 1)..-1] + + //provision source bucket with replication to destination bucket + tfSrcProperties.put('tfVars', "region=${symbol_dollar}{srcRegion},environment=${symbol_dollar}{environment},destination_bucket_arn=${symbol_dollar}{destBucketArn},destination_kms_key_arn=${symbol_dollar}{destKmsKeyArn}".toString()) + + initSrc.execute(tfSrcProperties) + applySrc.execute(tfSrcProperties) + + def srcJsonOutput = getTerraformOutput(destStackName) + String srcBucketArn = srcJsonOutput.bucket_arn.value + String srcBucketName = srcBucketArn[(srcBucketArn.lastIndexOf(":") + 1)..-1] + + //upload a file to the source region + sourceS3.putObject(srcBucketName, s3ObjectName, "This is a test!") + + //give a little time to replicate + sleep(5000) + + then: + sourceS3.getBucketTaggingConfiguration(srcBucketName).getTagSet().getTag('environment') == environment + destS3.getBucketTaggingConfiguration(destBucketName).getTagSet().getTag('environment') == environment + destS3.doesObjectExist(destBucketName, s3ObjectName) + + cleanup: + TerraformDestroy destroySrc = new TerraformDestroy(srcStackName) + TerraformDestroy destroyDest = new TerraformDestroy(destStackName) + + destroySrc.execute(tfSrcProperties) + destroyDest.execute(tfDestProperties) + } + + private def getTerraformOutput(String stackName) { + TerraformOutput output = new TerraformOutput(stackName) + String tfOutput = output.execute(new Properties()) + JsonSlurper slurper = new JsonSlurper() + slurper.parseText(tfOutput) + } +} From 5bcab39897edeb526691456733be9988c861d750 Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Mon, 26 Aug 2019 14:24:12 -0400 Subject: [PATCH 11/14] released v0.5.4 * fixed weird redundant S3Spec.groovy in archetype (issue #109) --- README.md | 16 ++++++++-------- examples/tf-s3-consumer/pom.xml | 2 +- examples/tf-s3/pom.xml | 4 ++-- tf-build-tools/pom.xml | 2 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- tf-build-tools/tf-maven-plugin/pom.xml | 2 +- tf-build-tools/tf-s3-archetype/pom.xml | 2 +- .../META-INF/maven/archetype-metadata.xml | 4 ++-- .../main/resources/archetype-resources/pom.xml | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b69a8a8a..7b8b610e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.3/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.3/jar -[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.3/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.4/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.4/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.4/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ [tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.3-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.3-green.svg +[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.4-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.4-green.svg [tf-maven-plugin-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-cmd-api-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml @@ -258,7 +258,7 @@ Deletes all 'terraform' files from terraform configurations along with the Terra ```xml - 0.5.2 + 0.5.4 ``` @@ -369,7 +369,7 @@ Instead of doing all the above steps you can simply build the module/project by An example on how to generate the project using an archetype is shown below. ```bash -mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersionId=0.5.2 -DgroupId= -DartifactId= +mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.5.4 -DgroupId= -DartifactId= ``` Maven Non-Interactive mode creates a project with the name that you passed in under . @@ -377,7 +377,7 @@ Maven Non-Interactive mode creates a project with the name that you passed in 4.0.0 - 0.5.3-SNAPSHOT + 0.5.4 tf-s3-consumer com.deliveredtechnologies.example.maven.tf diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index a2832339..92447995 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.3 + 0.5.4 tf-s3 com.deliveredtechnologies.example.maven.tf @@ -142,7 +142,7 @@ org.codehaus.gmavenplus gmavenplus-plugin - 1.7.0 + 1.7.1 diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index b9398790..ecb3298e 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.5.3 + 0.5.4 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 15070506..35e43b46 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.5.3 + 0.5.4 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 5f80bf30..7aaa35c1 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.5.3 + 0.5.4 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index 1bd3ee51..cbe8374e 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.deliveredtechnologies - 0.5.3 + 0.5.4 tf-build-tools tf-s3-archetype diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml index d025271c..4caa38fd 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml @@ -33,9 +33,9 @@ under the License. - src/test/groovy + src/test/groovy/tf/s3 - **/*.groovy + S3Spec.groovy diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml index e5d9efd8..235687d7 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.3 + 0.5.4-SNAPSHOT ${artifactId} ${groupId} From bab5fc35a9286ef96da5727a668e931438b6feec Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Tue, 27 Aug 2019 16:02:32 -0400 Subject: [PATCH 12/14] released v0.6 * fixed issue #108 --- README.md | 16 ++++---- examples/tf-s3-consumer/pom.xml | 2 +- examples/tf-s3/pom.xml | 2 +- tf-build-tools/checkstyle.xml | 2 +- tf-build-tools/pom.xml | 2 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- .../deliveredtechnologies/io/CommandLine.java | 38 +++++++++++++++---- .../terraform/api/TerraformOutput.java | 9 +++-- .../io/CommandLineTest.java | 7 ++-- .../terraform/api/TerraformOutputTest.java | 8 ++++ tf-build-tools/tf-maven-plugin/pom.xml | 2 +- .../maven/terraform/mojo/TerraformMojo.java | 5 ++- tf-build-tools/tf-s3-archetype/pom.xml | 2 +- .../resources/archetype-resources/pom.xml | 2 +- 14 files changed, 68 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 7b8b610e..1345bc5e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.5.4/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.5.4/jar -[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.5.4/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.6/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.6/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.6/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ [tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.5.4-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.5.4-green.svg +[maven-badge]:https://img.shields.io/badge/maven%20central-0.6-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.6-green.svg [tf-maven-plugin-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml [tf-cmd-api-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml @@ -258,7 +258,7 @@ Deletes all 'terraform' files from terraform configurations along with the Terra ```xml - 0.5.4 + 0.6 ``` @@ -369,7 +369,7 @@ Instead of doing all the above steps you can simply build the module/project by An example on how to generate the project using an archetype is shown below. ```bash -mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.5.4 -DgroupId= -DartifactId= +mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.6 -DgroupId= -DartifactId= ``` Maven Non-Interactive mode creates a project with the name that you passed in under . @@ -377,7 +377,7 @@ Maven Non-Interactive mode creates a project with the name that you passed in 4.0.0 - 0.5.4 + 0.6 tf-s3-consumer com.deliveredtechnologies.example.maven.tf diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index 92447995..a27e4693 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.4 + 0.6 tf-s3 com.deliveredtechnologies.example.maven.tf diff --git a/tf-build-tools/checkstyle.xml b/tf-build-tools/checkstyle.xml index eb599055..1372f4df 100644 --- a/tf-build-tools/checkstyle.xml +++ b/tf-build-tools/checkstyle.xml @@ -147,7 +147,7 @@ - + diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index ecb3298e..32a39bb3 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.5.4 + 0.6 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 35e43b46..b0b53551 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.5.4 + 0.6 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java index 503eb661..d6a82fb1 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java @@ -17,6 +17,7 @@ public class CommandLine implements Executable { private static int DEFAULT_TIMEOUT = 600000; private Path directory; + private boolean inheritIO; private Optional logger; public CommandLine(Path directory) { @@ -24,7 +25,18 @@ public CommandLine(Path directory) { } public CommandLine(Path directory, Logger logger) { + this(directory, true, logger); + } + + /** + * CommandLine Constructor. + * @param directory the directory in which to run the command + * @param inheritIO true if the process running the command should inherit the stdout of the parent process + * @param logger SLF4J Logger + */ + public CommandLine(Path directory, boolean inheritIO, Logger logger) { this.logger = Optional.ofNullable(logger); + this.inheritIO = inheritIO; this.directory = directory; } @@ -40,35 +52,45 @@ public CommandLine(Path directory, Logger logger) { public String execute(String command, int timeout) throws IOException, InterruptedException { boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); - Process process; + ProcessBuilder processBuilder; + Optional output; + Optional error; if (isWindows) { String[] cmd = new String[] { "cmd.exe", "/c", command }; - ProcessBuilder processBuilder = new ProcessBuilder(cmd); + processBuilder = new ProcessBuilder(cmd); processBuilder.directory(directory.toAbsolutePath().toFile()); - process = processBuilder.start(); } else { String[] cmd = new String[] { "bash", "-c", command }; - ProcessBuilder processBuilder = new ProcessBuilder(cmd); + processBuilder = new ProcessBuilder(cmd); processBuilder.directory(directory.toFile()); + } + + Process process; + if (inheritIO) { + processBuilder = processBuilder.inheritIO(); + output = Optional.empty(); + error = Optional.empty(); + process = processBuilder.start(); + } else { process = processBuilder.start(); + output = Optional.ofNullable(IOUtils.toString(new InputStreamReader(process.getInputStream()))); + error = Optional.ofNullable(IOUtils.toString(new InputStreamReader(process.getErrorStream()))); } - String output = IOUtils.toString(new InputStreamReader(process.getInputStream())); - String error = IOUtils.toString(new InputStreamReader(process.getErrorStream())); process.waitFor(timeout, TimeUnit.MILLISECONDS); if (process.exitValue() > 0) { - throw new IOException("Exit value was greater than zero!\n" + error); + throw new IOException("Exit value was greater than zero!\n" + error.orElse("")); } - return output; + return output.orElse(""); } @Override diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java index 99a92b95..6fa6b9d0 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java @@ -1,9 +1,12 @@ package com.deliveredtechnologies.terraform.api; +import com.deliveredtechnologies.io.CommandLine; import com.deliveredtechnologies.io.Executable; import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; +import com.deliveredtechnologies.terraform.TerraformUtils; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Properties; @@ -15,12 +18,12 @@ public class TerraformOutput implements TerraformOperation { this.terraform = terraform; } - public TerraformOutput() throws IOException { - this(new TerraformCommandLineDecorator(TerraformCommand.OUTPUT)); + public TerraformOutput() throws IOException, TerraformException { + this(new String()); } public TerraformOutput(String tfRootDir) throws IOException, TerraformException { - this(new TerraformCommandLineDecorator(TerraformCommand.OUTPUT, tfRootDir)); + this(new TerraformCommandLineDecorator(TerraformCommand.OUTPUT, new CommandLine(tfRootDir == null || tfRootDir.isEmpty() ? TerraformUtils.getDefaultTerraformRootModuleDir() : TerraformUtils.getTerraformRootModuleDir(tfRootDir), false, LoggerFactory.getLogger(CommandLine.class)))); } /** diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java index 63e8e929..f63114e2 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java @@ -4,6 +4,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.URISyntaxException; @@ -25,7 +26,7 @@ public void setup() throws URISyntaxException { @Test public void executeRunsCommandOnCommandLineShellAndReturnsTheOutput() throws IOException, InterruptedException { String echoString = "Hello World!"; - Executable commandLine = new CommandLine(directory); + Executable commandLine = new CommandLine(directory, false, LoggerFactory.getLogger(CommandLine.class)); String output = commandLine.execute(String.format("echo %1$s", echoString)); Assert.assertEquals(String.format("%1$s%n", echoString), output); @@ -38,7 +39,7 @@ public void executeRunsInTheSpecifiedDirectory() throws IOException, Interrupted boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); Path path = Paths.get("src", "main", "tf", "root"); FileUtils.forceMkdir(path.toFile()); - Executable commandLine = new CommandLine(path); + Executable commandLine = new CommandLine(path, false, LoggerFactory.getLogger(CommandLine.class));; if (isWindows) { String output = commandLine.execute("cd"); Assert.assertEquals(String.format("%1$s%n", path.toAbsolutePath().toString()), output); @@ -52,7 +53,7 @@ public void executeRunsInTheSpecifiedDirectory() throws IOException, Interrupted @Test(expected = IOException.class) public void executeThatErrorsOnItsCommandThrowsTheErrorOutput() throws IOException, InterruptedException { String errorCommand = "exit 1"; - Executable commandLine = new CommandLine(directory); + Executable commandLine = new CommandLine(directory, false, LoggerFactory.getLogger(CommandLine.class)); String output = commandLine.execute(errorCommand); } } diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java index ae7ac6b6..cd472e8d 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java @@ -55,4 +55,12 @@ public void terraformOutputCallsOutputCommandWithTimeout() throws InterruptedExc Assert.assertEquals(successResponse, terraformOutput.execute(properties)); Mockito.verify(commandLine, Mockito.times(1)).execute(Mockito.anyString(), Mockito.anyInt()); } + + @Test(expected = TerraformException.class) + public void terraformExecuteThrowsTerraformException() throws IOException, InterruptedException, TerraformException { + Mockito.when(terraform.execute(Mockito.anyString())).thenThrow(new IOException()); + + TerraformOutput terraformOutput = new TerraformOutput(terraform); + terraformOutput.execute(properties); + } } diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 7aaa35c1..4ae1c221 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.5.4 + 0.6 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/TerraformMojo.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/TerraformMojo.java index 19664afc..cd6c374e 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/TerraformMojo.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/TerraformMojo.java @@ -24,7 +24,10 @@ protected final void execute(TerraformOperation tfOperation, Properties prope try { Object response = tfOperation.execute(properties); if (response instanceof String) { - getLog().info((String) response); + String responseString = (String)response; + if (!responseString.isEmpty()) { + getLog().info((String) response); + } } } catch (TerraformException e) { throw new MojoExecutionException("Failed to execute terraform operation", e); diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index cbe8374e..52faa01a 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.deliveredtechnologies - 0.5.4 + 0.6 tf-build-tools tf-s3-archetype diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml index 235687d7..5620b837 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.5.4-SNAPSHOT + 0.6 ${artifactId} ${groupId} From 910a330ac4f8b0d7b110d6b9eac39c8fe7eb89a6 Mon Sep 17 00:00:00 2001 From: clayton Date: Fri, 4 Oct 2019 09:38:32 -0400 Subject: [PATCH 13/14] released v0.7.1 --- .travis.yml | 3 ++ README.md | 41 ++++++++++++++----- examples/tf-s3-consumer/pom.xml | 2 +- examples/tf-s3/pom.xml | 2 +- tf-build-tools/pom.xml | 2 +- tf-build-tools/tf-cmd-api/pom.xml | 2 +- .../deliveredtechnologies/io/CommandLine.java | 26 +++++++++--- .../deliveredtechnologies/io/Executable.java | 4 ++ .../terraform/TerraformCommand.java | 2 +- .../TerraformCommandLineDecorator.java | 36 +++++++++++++++- .../terraform/api/TerraformApply.java | 14 +++++++ .../terraform/api/TerraformDestroy.java | 14 +++++++ .../terraform/api/TerraformInit.java | 21 +++++----- .../terraform/api/TerraformOutput.java | 10 +++++ .../terraform/api/TerraformPlan.java | 14 +++++++ .../io/CommandLineTest.java | 14 +++---- .../TerraformCommandLineDecoratorTest.java | 28 +++++++++++++ .../terraform/api/TerraformApplyTest.java | 10 +++++ .../terraform/api/TerraformDestroyTest.java | 10 +++++ .../terraform/api/TerraformInitTest.java | 10 +++++ .../terraform/api/TerraformOutputTest.java | 10 +++++ .../terraform/api/TerraformPlanTest.java | 10 +++++ tf-build-tools/tf-maven-plugin/pom.xml | 7 +++- .../maven/terraform/mojo/Apply.java | 3 +- .../maven/terraform/mojo/Destroy.java | 3 +- .../maven/terraform/mojo/Init.java | 3 +- .../maven/terraform/mojo/Plan.java | 3 +- tf-build-tools/tf-s3-archetype/pom.xml | 2 +- .../resources/archetype-resources/pom.xml | 2 +- 29 files changed, 260 insertions(+), 48 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4c6a5644..3e18c4b0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,9 @@ cache: - $HOME/.m2 jdk: - openjdk8 +before_install: + - curl -g https://releases.hashicorp.com/terraform/0.12.9/terraform_0.12.9_linux_amd64.zip -o /tmp/terraform.zip + - sudo unzip /tmp/terraform.zip -d /usr/bin script: - | cd tf-build-tools diff --git a/README.md b/README.md index 1345bc5e..0f864822 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.6/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.6/jar -[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.6/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.7.1/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.7.1/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.7.1/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ [tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.6-green.svg -[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.6-green.svg -[tf-maven-plugin-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml +[maven-badge]:https://img.shields.io/badge/maven%20central-0.7.1-green.svg +[maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.7-green.svg +[tf-maven-plugin-synk-badge]:https://img.shields.io/badge/vulnerabilities-1-yellow.svg [tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml -[tf-cmd-api-synk-badge]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven/badge.svg?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml +[tf-cmd-api-synk-badge]:https://img.shields.io/badge/vulnerabilities-0-green.svg [tf-cmd-api-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-cmd-api%2Fpom.xml ![terraform-maven](.docs/MavenTerraform.png) @@ -41,6 +41,9 @@ The Terraform Maven Plugin brings Maven to Terraform, which greatly enhances Ter * [tf:package](#tfpackage) * [tf:deploy](#tfdeploy) * [tf:clean](#tfclean) +* [How Commands Are Delegated to Terraform](#how-commands-are-delegated-to-terraform) + * [*nix-based Operating Systems](#nix-based-operating-systems) + * [Windows Operating Systems](#windows-operating-systems) * [Getting Started](https://github.com/deliveredtechnologies/terraform-maven/wiki/Getting-Started) * [Setting Up a Terraform Maven Project](#setting-up-a-terraform-maven-project) * [Setting Up a Terraform Maven Project Using an ArcheType](#setting-up-a-terraform-maven-project-using-an-archetype) @@ -250,6 +253,24 @@ Deletes all 'terraform' files from terraform configurations along with the Terra | tfRootDir | String | The terraform root module directory location; defaults to src/main/tf/{first directory found} | | tfModulesDir | String | The directory that contains the Terraform module depenencies; defaults to src/main/.tfmodules | +### How Commands Are Delegated to Terraform + +Terraform commands are executed in a forked shell that is joined to the Maven process. This has important implications +based on the operating system being used. + +#### *nix-based Operating Systems + +Terraform commands executed on *nix-based systems are forked into a bash shell that is joined to the Maven process. + +#### Windows Operating Systems + +Terraform commands executed on Windows operating systems by default use the Windows default command line (cmd.exe), +which is not strictly compatible with Terraform as of Terraform v0.12 (e.g. -var parameters fail). + +However, Git Bash can be used in place of the default Windows command line to improve compatibility with Terraform +commands. To enable Git Bash, either set a Java system property `shellPath` or an environment variable `SHELL_PATH` to +the absolute path of the Git Bash executable. + ### Setting Up a Terraform Maven Project 1. Create a generic Maven project. [see Maven Getting Started Guide](https://maven.apache.org/guides/getting-started/index.html) @@ -258,7 +279,7 @@ Deletes all 'terraform' files from terraform configurations along with the Terra ```xml - 0.6 + 0.7.1 ``` @@ -369,7 +390,7 @@ Instead of doing all the above steps you can simply build the module/project by An example on how to generate the project using an archetype is shown below. ```bash -mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.6 -DgroupId= -DartifactId= +mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.7.1 -DgroupId= -DartifactId= ``` Maven Non-Interactive mode creates a project with the name that you passed in under . @@ -377,7 +398,7 @@ Maven Non-Interactive mode creates a project with the name that you passed in 4.0.0 - 0.6 + 0.7.1 tf-s3-consumer com.deliveredtechnologies.example.maven.tf diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index a27e4693..ccc7d1fa 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.6 + 0.7.1 tf-s3 com.deliveredtechnologies.example.maven.tf diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index 32a39bb3..0e53e50a 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.6 + 0.7.1 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index b0b53551..4b2dffb8 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.6 + 0.7.1 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java index d6a82fb1..dc168cf3 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/CommandLine.java @@ -2,6 +2,7 @@ import org.apache.commons.io.IOUtils; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStreamReader; @@ -18,10 +19,10 @@ public class CommandLine implements Executable { private Path directory; private boolean inheritIO; - private Optional logger; + private Logger logger; public CommandLine(Path directory) { - this(directory, null); + this(directory, LoggerFactory.getLogger(CommandLine.class)); } public CommandLine(Path directory, Logger logger) { @@ -35,7 +36,7 @@ public CommandLine(Path directory, Logger logger) { * @param logger SLF4J Logger */ public CommandLine(Path directory, boolean inheritIO, Logger logger) { - this.logger = Optional.ofNullable(logger); + this.logger = logger; this.inheritIO = inheritIO; this.directory = directory; } @@ -56,9 +57,11 @@ public String execute(String command, int timeout) throws IOException, Interrupt Optional output; Optional error; if (isWindows) { + String defaultWindowsShell = "cmd.exe"; + String shell = System.getProperty("shellPath", System.getenv("SHELL_PATH") == null ? defaultWindowsShell : System.getenv("SHELL_PATH")); String[] cmd = new String[] { - "cmd.exe", - "/c", + shell, + shell.equals(defaultWindowsShell) ? "/c" : "-c", command }; processBuilder = new ProcessBuilder(cmd); @@ -72,6 +75,8 @@ public String execute(String command, int timeout) throws IOException, Interrupt processBuilder = new ProcessBuilder(cmd); processBuilder.directory(directory.toFile()); } + logger.debug(String.format("*** directory: %1$s ***", getDirectory().toAbsolutePath())); + logger.debug(String.format("*** command: %1$s ***", command)); Process process; if (inheritIO) { @@ -84,7 +89,7 @@ public String execute(String command, int timeout) throws IOException, Interrupt output = Optional.ofNullable(IOUtils.toString(new InputStreamReader(process.getInputStream()))); error = Optional.ofNullable(IOUtils.toString(new InputStreamReader(process.getErrorStream()))); } - + addShutdownHook(process); process.waitFor(timeout, TimeUnit.MILLISECONDS); if (process.exitValue() > 0) { @@ -98,7 +103,16 @@ public String execute(String command) throws IOException, InterruptedException { return this.execute(command, DEFAULT_TIMEOUT); } + @Override + public void setLogger(Logger logger) { + this.logger = logger; + } + public Path getDirectory() { return this.directory; } + + private void addShutdownHook(Process process) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> process.destroyForcibly())); + } } diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/Executable.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/Executable.java index 7fd459cb..36e380d1 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/Executable.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/io/Executable.java @@ -1,5 +1,7 @@ package com.deliveredtechnologies.io; +import org.slf4j.Logger; + import java.io.IOException; /** @@ -9,4 +11,6 @@ public interface Executable { public String execute(String command, int timeout) throws IOException, InterruptedException; public String execute(String command) throws IOException, InterruptedException; + + public void setLogger(Logger logger); } diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java index dae51d0e..45672709 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommand.java @@ -1,7 +1,7 @@ package com.deliveredtechnologies.terraform; public enum TerraformCommand { - INIT("init"), PLAN("plan"), APPLY("apply"), DESTROY("destroy"), OUTPUT("output"); + INIT("init"), PLAN("plan"), APPLY("apply"), DESTROY("destroy"), OUTPUT("output"), VERSION("version"); private String value; diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java index ce82db61..4adbb059 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecorator.java @@ -3,8 +3,10 @@ import com.deliveredtechnologies.io.CommandLine; import com.deliveredtechnologies.io.Executable; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; import java.io.IOException; +import java.util.Optional; /** * Decorates Executable (for use with CommandLine) to put in the context of Terraform commands. @@ -13,15 +15,39 @@ public class TerraformCommandLineDecorator implements Executable { private Executable commandLine; private TerraformCommand cmd; + private Optional logger = Optional.empty(); /** - * Instantiates TerraformCommandLineDecorator with a TerraformCommand (e.g. INIT, PLAN, etc.) and an Executable (i.e. CommandLine). + * Instantiates TerraformCommandLineDecorator with a TerraformCommand (e.g. INIT, PLAN, etc.), an Executable (i.e. CommandLine), and an SLF4J Logger. * @param cmd A TerraformCommand (e.g. INIT, PLAN, APPLY, etc.) * @param commandLine A CommandLine instance */ - public TerraformCommandLineDecorator(TerraformCommand cmd, Executable commandLine) { + public TerraformCommandLineDecorator(TerraformCommand cmd, Executable commandLine, Logger logger) { this.commandLine = commandLine; this.cmd = cmd; + this.logger = Optional.ofNullable(logger); + this.logger.ifPresent(log -> this.commandLine.setLogger(log)); + } + + /** + * Instantiates TerraformCommandLineDecorator with a TerraformCommand (e.g. INIT, PLAN, etc.) and an Executable (i.e. CommandLine). + * @param cmd A TerraformCommand (e.g. INIT, PLAN, APPLY, etc.) + * @param commandLine A CommandLine instance + */ + public TerraformCommandLineDecorator(TerraformCommand cmd, Executable commandLine) { + this(cmd, commandLine, null); + } + + /** + * Instantiates TerraformCommandLineDecorator using TerraformCommand and SLF4J Logger.
+ * The directory where commands are executed is src/main/terraform/{root module dir}. + * @param cmd the Terraform command to be executed + * @param logger SLF4J Logger object + * + * @throws IOException + */ + public TerraformCommandLineDecorator(TerraformCommand cmd, Logger logger) throws IOException { + this(cmd, new CommandLine(TerraformUtils.getDefaultTerraformRootModuleDir()), logger); } /** @@ -54,6 +80,12 @@ public String execute(String command) throws IOException, InterruptedException { return commandLine.execute(getTerraformCommand(command)); } + @Override + public void setLogger(Logger logger) { + this.logger = Optional.ofNullable(logger); + this.commandLine.setLogger(logger); + } + public Executable getCommandLine() { return this.commandLine; } diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java index 22478968..4501679b 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformApply.java @@ -4,6 +4,7 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; +import org.slf4j.Logger; import java.io.IOException; import java.util.Optional; @@ -38,6 +39,11 @@ public String toString() { } } + TerraformApply(Executable terraform, Logger logger) { + this.terraform = terraform; + this.terraform.setLogger(logger); + } + TerraformApply(Executable terraform) { this.terraform = terraform; } @@ -46,10 +52,18 @@ public TerraformApply() throws IOException { this(new TerraformCommandLineDecorator(TerraformCommand.APPLY)); } + public TerraformApply(Logger logger) throws IOException { + this(new TerraformCommandLineDecorator(TerraformCommand.APPLY, logger)); + } + public TerraformApply(String tfRootDir) throws IOException, TerraformException { this(new TerraformCommandLineDecorator(TerraformCommand.APPLY, tfRootDir)); } + public TerraformApply(String tfRootDir, Logger logger) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.APPLY, tfRootDir), logger); + } + /** * Executes terraform apply. *

diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java index 6236d878..46133d0f 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformDestroy.java @@ -4,6 +4,7 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; +import org.slf4j.Logger; import java.io.IOException; import java.util.Optional; @@ -37,10 +38,19 @@ public String toString() { } } + TerraformDestroy(Executable terraform, Logger logger) { + this.terraform = terraform; + this.terraform.setLogger(logger); + } + TerraformDestroy(Executable terraform) { this.terraform = terraform; } + public TerraformDestroy(Logger logger) throws IOException { + this(new TerraformCommandLineDecorator(TerraformCommand.DESTROY, logger)); + } + public TerraformDestroy() throws IOException { this(new TerraformCommandLineDecorator(TerraformCommand.DESTROY)); } @@ -49,6 +59,10 @@ public TerraformDestroy(String tfRootDir) throws IOException, TerraformException this(new TerraformCommandLineDecorator(TerraformCommand.DESTROY, tfRootDir)); } + public TerraformDestroy(String tfRootDir, Logger logger) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.DESTROY, tfRootDir), logger); + } + /** * Executes terraform destroy.
*

diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java index 291c688e..28bfad34 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformInit.java @@ -5,7 +5,6 @@ import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.Optional; @@ -19,7 +18,7 @@ public class TerraformInit implements TerraformOperation { private Executable terraform; - private Logger log; + private Logger logger; enum TerraformInitParam { pluginDir("plugin-dir"), @@ -42,28 +41,28 @@ public String toString() { } public TerraformInit() throws IOException { - this(LoggerFactory.getLogger(TerraformInit.class), new TerraformCommandLineDecorator(TerraformCommand.INIT)); + this(new TerraformCommandLineDecorator(TerraformCommand.INIT)); } public TerraformInit(String tfRootDir) throws IOException, TerraformException { - this(LoggerFactory.getLogger(TerraformInit.class), new TerraformCommandLineDecorator(TerraformCommand.INIT, tfRootDir)); + this(new TerraformCommandLineDecorator(TerraformCommand.INIT, tfRootDir)); } - public TerraformInit(Logger log) throws IOException { - this(log, new TerraformCommandLineDecorator(TerraformCommand.INIT)); + public TerraformInit(Logger logger) throws IOException { + this(new TerraformCommandLineDecorator(TerraformCommand.INIT, logger)); } - public TerraformInit(Logger log, String tfRootDir) throws IOException, TerraformException { - this(log, new TerraformCommandLineDecorator(TerraformCommand.INIT, tfRootDir)); + public TerraformInit(String tfRootDir, Logger logger) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.INIT, tfRootDir), logger); } TerraformInit(Executable terraform) { - this(LoggerFactory.getLogger(TerraformInit.class), terraform); + this.terraform = terraform; } - TerraformInit(Logger log, Executable terraform) { - this.log = log; + TerraformInit(Executable terraform, Logger logger) { this.terraform = terraform; + this.terraform.setLogger(logger); } /** diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java index 6fa6b9d0..a79bd1a5 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformOutput.java @@ -6,6 +6,7 @@ import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.TerraformUtils; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; @@ -18,6 +19,11 @@ public class TerraformOutput implements TerraformOperation { this.terraform = terraform; } + TerraformOutput(Executable terraform, Logger logger) { + this.terraform = terraform; + this.terraform.setLogger(logger); + } + public TerraformOutput() throws IOException, TerraformException { this(new String()); } @@ -26,6 +32,10 @@ public TerraformOutput(String tfRootDir) throws IOException, TerraformException this(new TerraformCommandLineDecorator(TerraformCommand.OUTPUT, new CommandLine(tfRootDir == null || tfRootDir.isEmpty() ? TerraformUtils.getDefaultTerraformRootModuleDir() : TerraformUtils.getTerraformRootModuleDir(tfRootDir), false, LoggerFactory.getLogger(CommandLine.class)))); } + public TerraformOutput(String tfRootDir, Logger logger) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.OUTPUT, new CommandLine(tfRootDir == null || tfRootDir.isEmpty() ? TerraformUtils.getDefaultTerraformRootModuleDir() : TerraformUtils.getTerraformRootModuleDir(tfRootDir), false, logger))); + } + /** * Executes `terraform output -json -module={tfRootDir}`. * diff --git a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java index 4e472216..da44ff14 100644 --- a/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java +++ b/tf-build-tools/tf-cmd-api/src/main/java/com/deliveredtechnologies/terraform/api/TerraformPlan.java @@ -4,6 +4,7 @@ import com.deliveredtechnologies.terraform.TerraformCommand; import com.deliveredtechnologies.terraform.TerraformCommandLineDecorator; import com.deliveredtechnologies.terraform.TerraformException; +import org.slf4j.Logger; import java.io.IOException; import java.util.Optional; @@ -47,14 +48,27 @@ public String toString() { this.terraform = terraform; } + TerraformPlan(Executable terraform, Logger logger) { + this.terraform = terraform; + this.terraform.setLogger(logger); + } + public TerraformPlan() throws IOException { this(new TerraformCommandLineDecorator(TerraformCommand.PLAN)); } + public TerraformPlan(Logger logger) throws IOException { + this(new TerraformCommandLineDecorator(TerraformCommand.PLAN, logger)); + } + public TerraformPlan(String tfRootDir) throws IOException, TerraformException { this(new TerraformCommandLineDecorator(TerraformCommand.PLAN, tfRootDir)); } + public TerraformPlan(String tfRootDir, Logger logger) throws IOException, TerraformException { + this(new TerraformCommandLineDecorator(TerraformCommand.PLAN, tfRootDir), logger); + } + /** * Executes terraform plan. *

diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java index f63114e2..23bd717d 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/io/CommandLineTest.java @@ -7,7 +7,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; -import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; @@ -19,7 +18,7 @@ public class CommandLineTest { private Path directory; @Before - public void setup() throws URISyntaxException { + public void setup() { directory = Paths.get("."); } @@ -39,14 +38,15 @@ public void executeRunsInTheSpecifiedDirectory() throws IOException, Interrupted boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); Path path = Paths.get("src", "main", "tf", "root"); FileUtils.forceMkdir(path.toFile()); - Executable commandLine = new CommandLine(path, false, LoggerFactory.getLogger(CommandLine.class));; + Executable commandLine = new CommandLine(path, false, LoggerFactory.getLogger(CommandLine.class)); if (isWindows) { String output = commandLine.execute("cd"); Assert.assertEquals(String.format("%1$s%n", path.toAbsolutePath().toString()), output); - } else { - String output = commandLine.execute("pwd"); - Assert.assertEquals(String.format("%1$s%n", path.toAbsolutePath().toString()), output); } + System.setProperty("shellPath", System.getenv("HOMEDRIVE") + System.getenv("HOMEPATH") + "\\AppData\\Local\\Programs\\Git\\bin\\bash.exe"); //set default Git Bash executable path + String output = commandLine.execute("pwd"); + Assert.assertEquals(String.format("%1$s%n", path.toAbsolutePath().toString()), output); + FileUtils.forceDelete(path.getParent().toFile()); } @@ -54,6 +54,6 @@ public void executeRunsInTheSpecifiedDirectory() throws IOException, Interrupted public void executeThatErrorsOnItsCommandThrowsTheErrorOutput() throws IOException, InterruptedException { String errorCommand = "exit 1"; Executable commandLine = new CommandLine(directory, false, LoggerFactory.getLogger(CommandLine.class)); - String output = commandLine.execute(errorCommand); + commandLine.execute(errorCommand); } } diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java index 65bdc18e..777b2e5e 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/TerraformCommandLineDecoratorTest.java @@ -6,6 +6,7 @@ import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; +import org.slf4j.Logger; import java.io.File; import java.io.IOException; @@ -61,4 +62,31 @@ public void terraformCommandLineDecoratorSucceedsOnCreationWhenTfSourceDirIsFoun TerraformCommandLineDecorator terraformCommandLineDecorator = new TerraformCommandLineDecorator(TerraformCommand.APPLY); Files.walk(tfSrcPath).sorted(Comparator.reverseOrder()).map(path -> path.toFile()).forEach(File::delete); } + + @Test + public void loggerPassedToTerraformCommandLineDecoratorIsUsedInCommandLineObject() throws IOException, InterruptedException { + Logger logger = Mockito.mock(Logger.class); + TerraformCommandLineDecorator terraformCommandLineDecorator = new TerraformCommandLineDecorator(TerraformCommand.VERSION, logger); + terraformCommandLineDecorator.execute(""); + + Mockito.verify(logger, Mockito.times(2)).debug(Mockito.anyString()); + + logger = Mockito.mock(Logger.class); + terraformCommandLineDecorator = new TerraformCommandLineDecorator(TerraformCommand.VERSION, new CommandLine(TerraformUtils.getDefaultTerraformRootModuleDir()), logger); + terraformCommandLineDecorator.execute(""); + + Mockito.verify(logger, Mockito.times(2)).debug(Mockito.anyString()); + + Executable executable = Mockito.mock(Executable.class); + terraformCommandLineDecorator = new TerraformCommandLineDecorator(TerraformCommand.VERSION, executable); + terraformCommandLineDecorator.setLogger(logger); + + Mockito.verify(executable, Mockito.times(1)).setLogger(logger); + } + + @Test + public void terraformCommandLineDecoratorDoesntBlowUpWithoutLogging() throws IOException, InterruptedException { + TerraformCommandLineDecorator terraformCommandLineDecorator = new TerraformCommandLineDecorator(TerraformCommand.VERSION); + terraformCommandLineDecorator.execute(""); + } } diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java index be4aa26a..f6c2235e 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformApplyTest.java @@ -12,6 +12,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.slf4j.Logger; import java.io.IOException; import java.nio.file.Paths; @@ -75,6 +76,15 @@ public void terraformApplyThrowsTerraformExceptionOnError() throws IOException, terraformApply.execute(properties); } + @Test + public void terraformApplyPassesLoggerToExecutable() { + Executable executable = Mockito.mock(Executable.class); + Logger logger = Mockito.mock(Logger.class); + TerraformApply terraformApply = new TerraformApply(executable, logger); + + Mockito.verify(executable, Mockito.times(1)).setLogger(logger); + } + @After public void destroy() throws IOException { FileUtils.forceDelete(Paths.get("src", "main", "tf").toFile()); diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java index c9d0bae1..89a25f7a 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformDestroyTest.java @@ -10,6 +10,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.slf4j.Logger; import java.io.IOException; import java.nio.file.Paths; @@ -73,6 +74,15 @@ public void terraformDestroyThrowsTerraformExceptionOnError() throws IOException terraformDestroy.execute(properties); } + @Test + public void terraformDestroyPassesLoggerToExecutable() { + Executable executable = Mockito.mock(Executable.class); + Logger logger = Mockito.mock(Logger.class); + TerraformDestroy terraformDestroy = new TerraformDestroy(executable, logger); + + Mockito.verify(executable, Mockito.times(1)).setLogger(logger); + } + @After public void destroy() throws IOException { FileUtils.forceDelete(Paths.get("src", "main", "tf").toFile()); diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java index a02b3a0c..103f6162 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformInitTest.java @@ -12,6 +12,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.slf4j.Logger; import java.io.IOException; import java.nio.file.Paths; @@ -79,6 +80,15 @@ public void executeThrowsTerraformExceptionOnError() throws IOException, Interru terraformInit.execute(new Properties()); } + @Test + public void terraformInitPassesLoggerToExecutable() { + Executable executable = Mockito.mock(Executable.class); + Logger logger = Mockito.mock(Logger.class); + TerraformInit terraformInit = new TerraformInit(executable, logger); + + Mockito.verify(executable, Mockito.times(1)).setLogger(logger); + } + @After public void destroy() throws IOException { FileUtils.forceDelete(Paths.get("src", "main", "tf").toFile()); diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java index cd472e8d..d70350ab 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformOutputTest.java @@ -8,6 +8,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.slf4j.Logger; import java.io.IOException; import java.util.Properties; @@ -63,4 +64,13 @@ public void terraformExecuteThrowsTerraformException() throws IOException, Inter TerraformOutput terraformOutput = new TerraformOutput(terraform); terraformOutput.execute(properties); } + + @Test + public void terraformOuputPassesLoggerToExecutable() { + Executable executable = Mockito.mock(Executable.class); + Logger logger = Mockito.mock(Logger.class); + TerraformOutput terraformOutput = new TerraformOutput(executable, logger); + + Mockito.verify(executable, Mockito.times(1)).setLogger(logger); + } } diff --git a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java index 4b16aa3e..c5256818 100644 --- a/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java +++ b/tf-build-tools/tf-cmd-api/src/test/java/com/deliveredtechnologies/terraform/api/TerraformPlanTest.java @@ -11,6 +11,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.slf4j.Logger; import java.io.IOException; import java.nio.file.Path; @@ -81,6 +82,15 @@ public void terraformPlanThrowsTerraformExceptionOnError() throws IOException, I terraformPlan.execute(properties); } + @Test + public void terraformPlanPassesLoggerToExecutable() { + Executable executable = Mockito.mock(Executable.class); + Logger logger = Mockito.mock(Logger.class); + TerraformPlan terraformPlan = new TerraformPlan(executable, logger); + + Mockito.verify(executable, Mockito.times(1)).setLogger(logger); + } + @After public void destroy() throws IOException { FileUtils.forceDelete(Paths.get("src", "main", "tf").toFile()); diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 4ae1c221..89427add 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.6 + 0.7.1 tf-maven-plugin maven-plugin @@ -108,6 +108,11 @@ 3.4 provided + + org.apache.commons + commons-compress + 1.19 + org.apache.maven.plugins maven-dependency-plugin diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java index f10f993a..06a56bea 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Apply.java @@ -1,5 +1,6 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.maven.logs.MavenSlf4jAdapter; import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformApply; import org.apache.maven.plugin.MojoExecutionException; @@ -22,7 +23,7 @@ public class Apply extends TerraformMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { try { - execute(new TerraformApply(tfRootDir), System.getProperties()); + execute(new TerraformApply(tfRootDir, new MavenSlf4jAdapter(getLog())), System.getProperties()); } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java index bf82fd11..c724aaac 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Destroy.java @@ -1,5 +1,6 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.maven.logs.MavenSlf4jAdapter; import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformDestroy; import org.apache.maven.plugin.MojoExecutionException; @@ -23,7 +24,7 @@ public class Destroy extends TerraformMojo { public void execute() throws MojoExecutionException, MojoFailureException { try { getLog().info("tfRootDir is " + tfRootDir); - execute(new TerraformDestroy(tfRootDir), System.getProperties()); + execute(new TerraformDestroy(tfRootDir, new MavenSlf4jAdapter(getLog())), System.getProperties()); } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java index a1f9695f..6e7cd667 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Init.java @@ -1,5 +1,6 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.maven.logs.MavenSlf4jAdapter; import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformInit; @@ -25,7 +26,7 @@ public class Init extends TerraformMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { try { - execute(new TerraformInit(tfRootDir), System.getProperties()); + execute(new TerraformInit(tfRootDir, new MavenSlf4jAdapter(getLog())), System.getProperties()); } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } diff --git a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java index 2607e82a..4eb10d8b 100644 --- a/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java +++ b/tf-build-tools/tf-maven-plugin/src/main/java/com/deliveredtechnologies/maven/terraform/mojo/Plan.java @@ -1,5 +1,6 @@ package com.deliveredtechnologies.maven.terraform.mojo; +import com.deliveredtechnologies.maven.logs.MavenSlf4jAdapter; import com.deliveredtechnologies.terraform.TerraformException; import com.deliveredtechnologies.terraform.api.TerraformPlan; import org.apache.maven.plugin.MojoExecutionException; @@ -22,7 +23,7 @@ public class Plan extends TerraformMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { try { - execute(new TerraformPlan(tfRootDir), System.getProperties()); + execute(new TerraformPlan(tfRootDir, new MavenSlf4jAdapter(getLog())), System.getProperties()); } catch (IOException | TerraformException e) { throw new MojoExecutionException(e.getMessage(), e); } diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index 52faa01a..5b322580 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.deliveredtechnologies - 0.6 + 0.7.1 tf-build-tools tf-s3-archetype diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml index 5620b837..83387590 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.6 + 0.7.1 ${artifactId} ${groupId} From 46df10a4424e837470f9692a6c95fcf63da85c96 Mon Sep 17 00:00:00 2001 From: Clayton Long Date: Tue, 15 Oct 2019 14:23:59 -0400 Subject: [PATCH 14/14] released v0.7.2 * fixed tf-s3-archetype version --- README.md | 14 +++++++------- examples/tf-s3-consumer/pom.xml | 2 +- examples/tf-s3/pom.xml | 2 +- tf-build-tools/pom.xml | 11 +++++------ tf-build-tools/tf-cmd-api/pom.xml | 2 +- tf-build-tools/tf-maven-plugin/pom.xml | 2 +- tf-build-tools/tf-s3-archetype/pom.xml | 2 +- .../src/main/resources/archetype-resources/pom.xml | 2 +- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 0f864822..3b6f4614 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.7.1/maven-plugin -[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.7.1/jar -[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.7.1/jar +[tf-maven-plugin]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-maven-plugin/0.7.2/maven-plugin +[tf-cmd-api]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-cmd-api/0.7.2/jar +[tf-s3-archetype]:https://search.maven.org/artifact/com.deliveredtechnologies/tf-s3-archetype/0.7.2/jar [tf-maven-plugin-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-maven-plugin/ [tf-cmd-api-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-cmd-api/ [tf-s3-archetype-snapshot]:https://oss.sonatype.org/content/repositories/snapshots/com/deliveredtechnologies/tf-s3-archetype/ -[maven-badge]:https://img.shields.io/badge/maven%20central-0.7.1-green.svg +[maven-badge]:https://img.shields.io/badge/maven%20central-0.7.2-green.svg [maven-snapshot-badge]:https://img.shields.io/badge/SNAPSHOT-0.7-green.svg [tf-maven-plugin-synk-badge]:https://img.shields.io/badge/vulnerabilities-1-yellow.svg [tf-maven-plugin-synk]:https://snyk.io/test/github/deliveredtechnologies/terraform-maven?targetFile=tf-build-tools%2Ftf-maven-plugin%2Fpom.xml @@ -279,7 +279,7 @@ the absolute path of the Git Bash executable. ```xml - 0.7.1 + 0.7.2 ``` @@ -390,7 +390,7 @@ Instead of doing all the above steps you can simply build the module/project by An example on how to generate the project using an archetype is shown below. ```bash -mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.7.1 -DgroupId= -DartifactId= +mvn archetype:generate -B -DarchetypeGroupId=com.deliveredtechnologies -DarchetypeArtifactId="tf-s3-archetype" -DarchetypeVersion=0.7.2 -DgroupId= -DartifactId= ``` Maven Non-Interactive mode creates a project with the name that you passed in under . @@ -398,7 +398,7 @@ Maven Non-Interactive mode creates a project with the name that you passed in 4.0.0 - 0.7.1 + 0.7.2 tf-s3-consumer com.deliveredtechnologies.example.maven.tf diff --git a/examples/tf-s3/pom.xml b/examples/tf-s3/pom.xml index ccc7d1fa..0d99ecb6 100644 --- a/examples/tf-s3/pom.xml +++ b/examples/tf-s3/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.7.1 + 0.7.2 tf-s3 com.deliveredtechnologies.example.maven.tf diff --git a/tf-build-tools/pom.xml b/tf-build-tools/pom.xml index 0e53e50a..bef8fdee 100644 --- a/tf-build-tools/pom.xml +++ b/tf-build-tools/pom.xml @@ -6,7 +6,7 @@ com.deliveredtechnologies tf-build-tools pom - 0.7.1 + 0.7.2 Terraform Build Tools: The parent POM project for Java and Terraform Tools tf-cmd-api @@ -56,17 +56,16 @@ America/New_York - - - + + s1234a6i Sai Chaitanya https://github.com/s1234a6i developer America/New_York - - + + snapshot diff --git a/tf-build-tools/tf-cmd-api/pom.xml b/tf-build-tools/tf-cmd-api/pom.xml index 4b2dffb8..1ae20ac1 100644 --- a/tf-build-tools/tf-cmd-api/pom.xml +++ b/tf-build-tools/tf-cmd-api/pom.xml @@ -5,7 +5,7 @@ tf-build-tools com.deliveredtechnologies - 0.7.1 + 0.7.2 4.0.0 tf-cmd-api diff --git a/tf-build-tools/tf-maven-plugin/pom.xml b/tf-build-tools/tf-maven-plugin/pom.xml index 89427add..0b54e737 100644 --- a/tf-build-tools/tf-maven-plugin/pom.xml +++ b/tf-build-tools/tf-maven-plugin/pom.xml @@ -4,7 +4,7 @@ com.deliveredtechnologies tf-build-tools - 0.7.1 + 0.7.2 tf-maven-plugin maven-plugin diff --git a/tf-build-tools/tf-s3-archetype/pom.xml b/tf-build-tools/tf-s3-archetype/pom.xml index 5b322580..f970abf2 100644 --- a/tf-build-tools/tf-s3-archetype/pom.xml +++ b/tf-build-tools/tf-s3-archetype/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.deliveredtechnologies - 0.7.1 + 0.7.2 tf-build-tools tf-s3-archetype diff --git a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml index 83387590..2bfee908 100644 --- a/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml +++ b/tf-build-tools/tf-s3-archetype/src/main/resources/archetype-resources/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - 0.7.1 + 0.7.2 ${artifactId} ${groupId}