From 77ffe18f2854d14bfe8c64f636835a6696749aaa Mon Sep 17 00:00:00 2001 From: Ilia ZLobin Date: Thu, 27 Jun 2019 15:34:00 +0300 Subject: [PATCH 1/4] add registry credential configuration option for codebuild_project environment --- aws/resource_aws_codebuild_project.go | 50 ++++++++++++++++++ aws/resource_aws_codebuild_project_test.go | 60 ++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/aws/resource_aws_codebuild_project.go b/aws/resource_aws_codebuild_project.go index 5642522f9284..80e6d40db89d 100644 --- a/aws/resource_aws_codebuild_project.go +++ b/aws/resource_aws_codebuild_project.go @@ -197,6 +197,26 @@ func resourceAwsCodeBuildProject() *schema.Resource { Optional: true, ValidateFunc: validation.StringMatch(regexp.MustCompile(`\.(pem|zip)$`), "must end in .pem or .zip"), }, + "registry_credential": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "credential": { + Type: schema.TypeString, + Required: true, + }, + "credential_provider": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + codebuild.CredentialProviderTypeSecretsManager, + }, false), + }, + }, + }, + }, }, }, Set: resourceAwsCodeBuildProjectEnvironmentHash, @@ -659,6 +679,22 @@ func expandProjectEnvironment(d *schema.ResourceData) *codebuild.ProjectEnvironm projectEnv.ImagePullCredentialsType = aws.String(v.(string)) } + if v := envConfig["registry_credential"]; v != nil { + config := v.(*schema.Set).List()[0].(map[string]interface{}) + + projectRegistryCredential := &codebuild.RegistryCredential{} + + if v := config["credential"].(string); v != "" { + projectRegistryCredential.Credential = &v + } + + if v := config["credential_provider"].(string); v != "" { + projectRegistryCredential.CredentialProvider = &v + } + + projectEnv.RegistryCredential = projectRegistryCredential + } + if v := envConfig["environment_variable"]; v != nil { envVariables := v.([]interface{}) if len(envVariables) > 0 { @@ -1027,12 +1063,26 @@ func flattenAwsCodeBuildProjectEnvironment(environment *codebuild.ProjectEnviron envConfig["privileged_mode"] = *environment.PrivilegedMode envConfig["image_pull_credentials_type"] = *environment.ImagePullCredentialsType + envConfig["registry_credential"] = flattenAwsCodebuildRegistryCredential(environment.RegistryCredential) + if environment.EnvironmentVariables != nil { envConfig["environment_variable"] = environmentVariablesToMap(environment.EnvironmentVariables) } return []interface{}{envConfig} +} + +func flattenAwsCodebuildRegistryCredential(registryCredential *codebuild.RegistryCredential) []interface{} { + if registryCredential == nil { + return []interface{}{} + } + values := map[string]interface{}{ + "credential": aws.StringValue(registryCredential.Credential), + "credential_provider": aws.StringValue(registryCredential.CredentialProvider), + } + + return []interface{}{values} } func flattenAwsCodeBuildProjectSecondarySources(sourceList []*codebuild.ProjectSource) []interface{} { diff --git a/aws/resource_aws_codebuild_project_test.go b/aws/resource_aws_codebuild_project_test.go index c8b8c6ffe170..410b78bb83c8 100644 --- a/aws/resource_aws_codebuild_project_test.go +++ b/aws/resource_aws_codebuild_project_test.go @@ -896,6 +896,26 @@ func TestAWSCodeBuildProject_nameValidation(t *testing.T) { } } +func TestAccAWSCodeBuildProject_Environment_RegistryCredential(t *testing.T) { + var project codebuild.Project + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_codebuild_project.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSCodeBuild(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSCodeBuildProjectDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSCodeBuildProjectConfig_Environment_RegistryCredential(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSCodeBuildProjectExists(resourceName, &project), + ), + }, + }, + }) +} + func testAccCheckAWSCodeBuildProjectExists(n string, project *codebuild.Project) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -1399,6 +1419,46 @@ resource "aws_codebuild_project" "test" { `, oName, rName) } +func testAccAWSCodeBuildProjectConfig_Environment_RegistryCredential(rName string) string { + return testAccAWSCodeBuildProjectConfig_Base_ServiceRole(rName) + fmt.Sprintf(` +resource "aws_codebuild_project" "test" { + name = %[1]q + service_role = "${aws_iam_role.test.arn}" + + artifacts { + type = "NO_ARTIFACTS" + } + + environment { + compute_type = "BUILD_GENERAL1_SMALL" + image = "2" + type = "LINUX_CONTAINER" + image_pull_credentials_type = "SERVICE_ROLE" + + registry_credential { + credential = "${aws_secretsmanager_secret_version.test.arn}" + credential_provider = "SECRETS_MANAGER" + } + } + + source { + type = "GITHUB" + location = "https://github.com/hashicorp/packer.git" + } +} + +resource "aws_secretsmanager_secret" "test" { + name = "docker-auth" + recovery_window_in_days = 0 +} + +resource "aws_secretsmanager_secret_version" "test" { + secret_id = "${aws_secretsmanager_secret.docker-auth.id}" + secret_string = "${jsonencode(map("username", "user", "password", "pass"))}" +} +`, rName) +} + func testAccAWSCodeBuildProjectConfig_Source_Auth(rName, authResource, authType string) string { return testAccAWSCodeBuildProjectConfig_Base_ServiceRole(rName) + fmt.Sprintf(` resource "aws_codebuild_project" "test" { From c3fc893b2111cddd1ffd02340e9a34ebfe071293 Mon Sep 17 00:00:00 2001 From: Ilia ZLobin Date: Thu, 27 Jun 2019 19:03:47 +0300 Subject: [PATCH 2/4] update codebuild_project docs --- website/docs/r/codebuild_project.html.markdown | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/website/docs/r/codebuild_project.html.markdown b/website/docs/r/codebuild_project.html.markdown index 6c67463c51b2..783705e6248a 100644 --- a/website/docs/r/codebuild_project.html.markdown +++ b/website/docs/r/codebuild_project.html.markdown @@ -224,6 +224,7 @@ The following arguments are supported: * `environment_variable` - (Optional) A set of environment variables to make available to builds for this build project. * `privileged_mode` - (Optional) If set to true, enables running the Docker daemon inside a Docker container. Defaults to `false`. * `certificate` - (Optional) The ARN of the S3 bucket, path prefix and object key that contains the PEM-encoded certificate. +* `registry_credential` - (Optional) Information about credentials for access to a private Docker registry. Registry Credential config blocks are documented below. `environment_variable` supports the following: @@ -252,6 +253,10 @@ The following arguments are supported: * `subnets` - (Required) The subnet IDs within which to run builds. * `vpc_id` - (Required) The ID of the VPC within which to run builds. +`registry_credential` supports the following: + +* `credential` - (Required) The Amazon Resource Name (ARN) or name of credentials created using AWS Secrets Manager. +* `credential_provider` - (Required) The service that created the credentials to access a private Docker registry. The valid value, SECRETS_MANAGER, is for AWS Secrets Manager. `secondary_artifacts` supports the following: From 738fd2f310040a907cbc7eaceace4615b91ec48c Mon Sep 17 00:00:00 2001 From: Ilia ZLobin Date: Thu, 27 Jun 2019 19:21:49 +0300 Subject: [PATCH 3/4] fix acceptance test --- aws/resource_aws_codebuild_project_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_codebuild_project_test.go b/aws/resource_aws_codebuild_project_test.go index 410b78bb83c8..2bbe1c329f99 100644 --- a/aws/resource_aws_codebuild_project_test.go +++ b/aws/resource_aws_codebuild_project_test.go @@ -1448,12 +1448,12 @@ resource "aws_codebuild_project" "test" { } resource "aws_secretsmanager_secret" "test" { - name = "docker-auth" + name = "test" recovery_window_in_days = 0 } resource "aws_secretsmanager_secret_version" "test" { - secret_id = "${aws_secretsmanager_secret.docker-auth.id}" + secret_id = "${aws_secretsmanager_secret.test.id}" secret_string = "${jsonencode(map("username", "user", "password", "pass"))}" } `, rName) From e099db098825c1ddf13ac7a4b22335178fde8770 Mon Sep 17 00:00:00 2001 From: Ilia ZLobin Date: Fri, 28 Jun 2019 10:54:19 +0300 Subject: [PATCH 4/4] code review issues --- aws/resource_aws_codebuild_project.go | 14 ++--- aws/resource_aws_codebuild_project_test.go | 69 ++++++++++++---------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/aws/resource_aws_codebuild_project.go b/aws/resource_aws_codebuild_project.go index 80e6d40db89d..4703c73fdd9a 100644 --- a/aws/resource_aws_codebuild_project.go +++ b/aws/resource_aws_codebuild_project.go @@ -198,7 +198,7 @@ func resourceAwsCodeBuildProject() *schema.Resource { ValidateFunc: validation.StringMatch(regexp.MustCompile(`\.(pem|zip)$`), "must end in .pem or .zip"), }, "registry_credential": { - Type: schema.TypeSet, + Type: schema.TypeList, Optional: true, MaxItems: 1, Elem: &schema.Resource{ @@ -679,17 +679,17 @@ func expandProjectEnvironment(d *schema.ResourceData) *codebuild.ProjectEnvironm projectEnv.ImagePullCredentialsType = aws.String(v.(string)) } - if v := envConfig["registry_credential"]; v != nil { - config := v.(*schema.Set).List()[0].(map[string]interface{}) + if v, ok := envConfig["registry_credential"]; ok && len(v.([]interface{})) > 0 { + config := v.([]interface{})[0].(map[string]interface{}) projectRegistryCredential := &codebuild.RegistryCredential{} - if v := config["credential"].(string); v != "" { - projectRegistryCredential.Credential = &v + if v, ok := config["credential"]; ok && v.(string) != "" { + projectRegistryCredential.Credential = aws.String(v.(string)) } - if v := config["credential_provider"].(string); v != "" { - projectRegistryCredential.CredentialProvider = &v + if v, ok := config["credential_provider"]; ok && v.(string) != "" { + projectRegistryCredential.CredentialProvider = aws.String(v.(string)) } projectEnv.RegistryCredential = projectRegistryCredential diff --git a/aws/resource_aws_codebuild_project_test.go b/aws/resource_aws_codebuild_project_test.go index 2bbe1c329f99..93f477050e6b 100644 --- a/aws/resource_aws_codebuild_project_test.go +++ b/aws/resource_aws_codebuild_project_test.go @@ -912,6 +912,11 @@ func TestAccAWSCodeBuildProject_Environment_RegistryCredential(t *testing.T) { testAccCheckAWSCodeBuildProjectExists(resourceName, &project), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -1421,41 +1426,41 @@ resource "aws_codebuild_project" "test" { func testAccAWSCodeBuildProjectConfig_Environment_RegistryCredential(rName string) string { return testAccAWSCodeBuildProjectConfig_Base_ServiceRole(rName) + fmt.Sprintf(` -resource "aws_codebuild_project" "test" { - name = %[1]q - service_role = "${aws_iam_role.test.arn}" - - artifacts { - type = "NO_ARTIFACTS" - } - - environment { - compute_type = "BUILD_GENERAL1_SMALL" - image = "2" - type = "LINUX_CONTAINER" - image_pull_credentials_type = "SERVICE_ROLE" - - registry_credential { - credential = "${aws_secretsmanager_secret_version.test.arn}" - credential_provider = "SECRETS_MANAGER" + resource "aws_codebuild_project" "test" { + name = %[1]q + service_role = "${aws_iam_role.test.arn}" + + artifacts { + type = "NO_ARTIFACTS" + } + + environment { + compute_type = "BUILD_GENERAL1_SMALL" + image = "2" + type = "LINUX_CONTAINER" + image_pull_credentials_type = "SERVICE_ROLE" + + registry_credential { + credential = "${aws_secretsmanager_secret_version.test.arn}" + credential_provider = "SECRETS_MANAGER" + } + } + + source { + type = "GITHUB" + location = "https://github.com/hashicorp/packer.git" } } - - source { - type = "GITHUB" - location = "https://github.com/hashicorp/packer.git" + + resource "aws_secretsmanager_secret" "test" { + name = "test" + recovery_window_in_days = 0 + } + + resource "aws_secretsmanager_secret_version" "test" { + secret_id = "${aws_secretsmanager_secret.test.id}" + secret_string = "${jsonencode(map("username", "user", "password", "pass"))}" } -} - -resource "aws_secretsmanager_secret" "test" { - name = "test" - recovery_window_in_days = 0 -} - -resource "aws_secretsmanager_secret_version" "test" { - secret_id = "${aws_secretsmanager_secret.test.id}" - secret_string = "${jsonencode(map("username", "user", "password", "pass"))}" -} `, rName) }