From 56a5b3d7b589c3774a1c3bdf79180941dc296cef Mon Sep 17 00:00:00 2001 From: Ryan Moore Date: Tue, 5 Dec 2017 14:48:04 +0000 Subject: [PATCH 1/5] Add VPC config block to aws_codebuild_project resource --- aws/resource_aws_codebuild_project.go | 101 ++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/aws/resource_aws_codebuild_project.go b/aws/resource_aws_codebuild_project.go index 32745251606..b46bdfaa3b9 100644 --- a/aws/resource_aws_codebuild_project.go +++ b/aws/resource_aws_codebuild_project.go @@ -179,6 +179,31 @@ func resourceAwsCodeBuildProject() *schema.Resource { ValidateFunc: validateAwsCodeBuildTimeout, }, "tags": tagsSchema(), + "vpc_config": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vpc_id": { + Type: schema.TypeString, + Required: true, + }, + "subnets": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + MaxItems: 16, + }, + "security_group_ids": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + MaxItems: 5, + }, + }, + }, + }, }, } } @@ -213,6 +238,11 @@ func resourceAwsCodeBuildProjectCreate(d *schema.ResourceData, meta interface{}) params.TimeoutInMinutes = aws.Int64(int64(v.(int))) } + if _, ok := d.GetOk("vpc_config"); ok { + vpcConfig := expandVpcConfig(d) + params.VpcConfig = vpcConfig + } + if v, ok := d.GetOk("tags"); ok { params.Tags = tagsFromMapCodeBuild(v.(map[string]interface{})) } @@ -324,6 +354,29 @@ func expandProjectEnvironment(d *schema.ResourceData) *codebuild.ProjectEnvironm return projectEnv } +func expandVpcConfig(d *schema.ResourceData) *codebuild.VpcConfig { + configs := d.Get("vpc_config").(*schema.Set).List() + data := configs[0].(map[string]interface{}) + + vpcConfig := codebuild.VpcConfig{ + VpcId: aws.String(data["vpc_id"].(string)), + } + + var vpcConfigSubnets []*string + for _, v := range data["subnets"].([]interface{}) { + vpcConfigSubnets = append(vpcConfigSubnets, aws.String(v.(string))) + } + vpcConfig.Subnets = vpcConfigSubnets + + var vpcSecurityGroupIds []*string + for _, s := range data["security_group_ids"].([]interface{}) { + vpcSecurityGroupIds = append(vpcSecurityGroupIds, aws.String(s.(string))) + } + vpcConfig.SecurityGroupIds = vpcSecurityGroupIds + + return &vpcConfig +} + func expandProjectSource(d *schema.ResourceData) codebuild.ProjectSource { configs := d.Get("source").(*schema.Set).List() projectSource := codebuild.ProjectSource{} @@ -390,6 +443,10 @@ func resourceAwsCodeBuildProjectRead(d *schema.ResourceData, meta interface{}) e return err } + if err := d.Set("vpc_config", schema.NewSet(resourceAwsCodeBuildVpcConfigHash, flattenAwsCodebuildVpcConfig(project.VpcConfig))); err != nil { + return err + } + d.Set("description", project.Description) d.Set("encryption_key", project.EncryptionKey) d.Set("name", project.Name) @@ -425,6 +482,11 @@ func resourceAwsCodeBuildProjectUpdate(d *schema.ResourceData, meta interface{}) params.Artifacts = &projectArtifacts } + if d.HasChange("vpc_config") { + vpcConfig := expandVpcConfig(d) + params.VpcConfig = vpcConfig + } + if d.HasChange("description") { params.Description = aws.String(d.Get("description").(string)) } @@ -556,6 +618,26 @@ func flattenAwsCodebuildProjectSource(source *codebuild.ProjectSource) *schema.S } +func flattenAwsCodebuildVpcConfig(vpcConfig *codebuild.VpcConfig) []interface{} { + values := map[string]interface{}{} + + values["vpc_id"] = *vpcConfig.VpcId + + var subnets []string + for _, s := range vpcConfig.Subnets { + subnets = append(subnets, *s) + } + values["subnets"] = subnets + + var securityGroupIds []string + for _, s := range vpcConfig.SecurityGroupIds { + securityGroupIds = append(securityGroupIds, *s) + } + values["security_group_ids"] = securityGroupIds + + return []interface{}{values} +} + func resourceAwsCodeBuildProjectArtifactsHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) @@ -567,6 +649,25 @@ func resourceAwsCodeBuildProjectArtifactsHash(v interface{}) int { return hashcode.String(buf.String()) } +func resourceAwsCodeBuildVpcConfigHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + buf.WriteString(fmt.Sprintf("%s-", m["vpc_id"].(string))) + + for _, s := range m["subnets"].([]string) { + buf.WriteString(fmt.Sprintf("%s-", s)) + } + + if m["security_group_ids"] != nil { + for _, s := range m["security_group_ids"].([]string) { + buf.WriteString(fmt.Sprintf("%s-", s)) + } + } + + return hashcode.String(buf.String()) +} + func resourceAwsCodeBuildProjectEnvironmentHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) From 45816281f9de0c391a6a281451c3e8e6ce9b3ac0 Mon Sep 17 00:00:00 2001 From: Ryan Moore Date: Tue, 5 Dec 2017 14:49:23 +0000 Subject: [PATCH 2/5] Documentation for VPC block within aws_codebuild_project resource --- .../docs/r/codebuild_project.html.markdown | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/website/docs/r/codebuild_project.html.markdown b/website/docs/r/codebuild_project.html.markdown index de86cb5d5af..adb909ae5a3 100644 --- a/website/docs/r/codebuild_project.html.markdown +++ b/website/docs/r/codebuild_project.html.markdown @@ -94,6 +94,20 @@ resource "aws_codebuild_project" "foo" { location = "https://github.com/mitchellh/packer.git" } + vpc_config { + vpc_id = "vpc-725fca" + + subnets = [ + "subnet-ba35d2e0", + "subnet-ab129af1", + ] + + security_group_ids = [ + "sg-f9f27d91", + "sg-e4f48g23", + ] + } + tags { "Environment" = "Test" } @@ -113,6 +127,7 @@ The following arguments are supported: * `artifacts` - (Required) Information about the project's build output artifacts. Artifact blocks are documented below. * `environment` - (Required) Information about the project's build environment. Environment blocks are documented below. * `source` - (Required) Information about the project's input source code. Source blocks are documented below. +* `vpc_config` - (Optional) Configuration for the builds to run inside a VPC. VPC config blocks are documented below. `artifacts` supports the following: @@ -147,6 +162,12 @@ The following arguments are supported: * `type` - (Required) The authorization type to use. The only valid value is `OAUTH` * `resource` - (Optional) The resource value that applies to the specified authorization type. +`vpc_config` supports the following: + +* `vpc_id` - (Required) The ID of the VPC within which to run builds. +* `subnets` - (Required) The subnet IDs within which to run builds. +* `security_group_ids` - (Required) The security group IDs to assign to running builds. + ## Attributes Reference The following attributes are exported: @@ -156,4 +177,3 @@ The following attributes are exported: * `encryption_key` - The AWS Key Management Service (AWS KMS) customer master key (CMK) that was used for encrypting the build project's build output artifacts. * `name` - The projects name. * `service_role` - The ARN of the IAM service role. - From cd23499910c1b7ad03d2794dff944876667f23a3 Mon Sep 17 00:00:00 2001 From: Ryan Moore Date: Tue, 5 Dec 2017 14:50:36 +0000 Subject: [PATCH 3/5] Update basic codebuild test to support VPC block. Currently contains IAM race condition --- aws/resource_aws_codebuild_project_test.go | 71 +++++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/aws/resource_aws_codebuild_project_test.go b/aws/resource_aws_codebuild_project_test.go index e79e49a8ff2..cebf4becad6 100644 --- a/aws/resource_aws_codebuild_project_test.go +++ b/aws/resource_aws_codebuild_project_test.go @@ -324,6 +324,19 @@ func testAccCheckAWSCodeBuildProjectDestroy(s *terraform.State) error { func testAccAWSCodeBuildProjectConfig_basic(rName string) string { return fmt.Sprintf(` +resource "aws_vpc" "codebuild_vpc" { + cidr_block = "10.0.0.0/16" +} + +resource "aws_subnet" "codebuild_subnet" { + vpc_id = "${aws_vpc.codebuild_vpc.id}" + cidr_block = "10.0.0.0/24" +} + +resource "aws_security_group" "codebuild_security_group" { + vpc_id = "${aws_vpc.codebuild_vpc.id}" +} + resource "aws_iam_role" "codebuild_role" { name = "codebuild-role-%s" assume_role_policy = < Date: Tue, 5 Dec 2017 17:18:20 +0000 Subject: [PATCH 4/5] Add further error catching to CodeBuild resource creation to deal with more IAM eventual consistency. Remove unnecessary depends_on clause from CodeBuild basic acceptance test. --- aws/resource_aws_codebuild_project.go | 4 ++++ aws/resource_aws_codebuild_project_test.go | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_codebuild_project.go b/aws/resource_aws_codebuild_project.go index b46bdfaa3b9..3283511ef52 100644 --- a/aws/resource_aws_codebuild_project.go +++ b/aws/resource_aws_codebuild_project.go @@ -258,6 +258,10 @@ func resourceAwsCodeBuildProjectCreate(d *schema.ResourceData, meta interface{}) return resource.RetryableError(err) } + if isAWSErr(err, "InvalidInputException", "Not authorized to perform DescribeSecurityGroups") { + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) } diff --git a/aws/resource_aws_codebuild_project_test.go b/aws/resource_aws_codebuild_project_test.go index cebf4becad6..91215648dac 100644 --- a/aws/resource_aws_codebuild_project_test.go +++ b/aws/resource_aws_codebuild_project_test.go @@ -454,8 +454,6 @@ resource "aws_codebuild_project" "foo" { "${aws_security_group.codebuild_security_group.id}" ] } - - depends_on = ["aws_iam_policy_attachment.codebuild_policy_attachment"] } `, rName, rName, rName, rName) } From f417d49fb319944651c951f7ba84f6bce75bab4f Mon Sep 17 00:00:00 2001 From: Ryan Moore Date: Tue, 5 Dec 2017 20:44:23 +0000 Subject: [PATCH 5/5] Formatting fix for codepipline environment variables documentation --- website/docs/r/codebuild_project.html.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/r/codebuild_project.html.markdown b/website/docs/r/codebuild_project.html.markdown index adb909ae5a3..af9c119a113 100644 --- a/website/docs/r/codebuild_project.html.markdown +++ b/website/docs/r/codebuild_project.html.markdown @@ -147,6 +147,7 @@ The following arguments are supported: * `environment_variable` - (Optional) A set of environment variables to make available to builds for this build project. `environment_variable` supports the following: + * `name` - (Required) The environment variable's name or key. * `value` - (Required) The environment variable's value.