-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support CodeBuild within VPC #2547
Changes from all commits
56a5b3d
4581628
cd23499
0bef8ec
f417d49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would change this to (note about function signature update below in another comment):
|
||
vpcConfig := expandVpcConfig(d) | ||
params.VpcConfig = vpcConfig | ||
} | ||
|
||
if v, ok := d.GetOk("tags"); ok { | ||
params.Tags = tagsFromMapCodeBuild(v.(map[string]interface{})) | ||
} | ||
|
@@ -228,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) | ||
} | ||
|
||
|
@@ -324,6 +358,29 @@ func expandProjectEnvironment(d *schema.ResourceData) *codebuild.ProjectEnvironm | |
return projectEnv | ||
} | ||
|
||
func expandVpcConfig(d *schema.ResourceData) *codebuild.VpcConfig { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We really try to limit the usage of |
||
configs := d.Get("vpc_config").(*schema.Set).List() | ||
data := configs[0].(map[string]interface{}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is generating a panic for me running the acceptance test:
It will go away with the function signature refactor and TypeList changes mentioned above. |
||
|
||
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 +447,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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When this is TypeList this can become:
|
||
return err | ||
} | ||
|
||
d.Set("description", project.Description) | ||
d.Set("encryption_key", project.EncryptionKey) | ||
d.Set("name", project.Name) | ||
|
@@ -425,6 +486,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 +622,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 +653,25 @@ func resourceAwsCodeBuildProjectArtifactsHash(v interface{}) int { | |
return hashcode.String(buf.String()) | ||
} | ||
|
||
func resourceAwsCodeBuildVpcConfigHash(v interface{}) int { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is extraneous with switch to |
||
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{}) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 = <<EOF | ||
|
@@ -343,10 +356,10 @@ EOF | |
} | ||
|
||
resource "aws_iam_policy" "codebuild_policy" { | ||
name = "codebuild-policy-%s" | ||
path = "/service-role/" | ||
description = "Policy used in trust relationship with CodeBuild" | ||
policy = <<POLICY | ||
name = "codebuild-policy-%s" | ||
path = "/service-role/" | ||
description = "Policy used in trust relationship with CodeBuild" | ||
policy = <<POLICY | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
|
@@ -360,6 +373,34 @@ resource "aws_iam_policy" "codebuild_policy" { | |
"logs:CreateLogStream", | ||
"logs:PutLogEvents" | ||
] | ||
}, | ||
{ | ||
"Effect": "Allow", | ||
"Action": [ | ||
"ec2:CreateNetworkInterface", | ||
"ec2:DescribeDhcpOptions", | ||
"ec2:DescribeNetworkInterfaces", | ||
"ec2:DeleteNetworkInterface", | ||
"ec2:DescribeSubnets", | ||
"ec2:DescribeSecurityGroups", | ||
"ec2:DescribeVpcs" | ||
], | ||
"Resource": "*" | ||
}, | ||
{ | ||
"Effect": "Allow", | ||
"Action": [ | ||
"ec2:CreateNetworkInterfacePermission" | ||
], | ||
"Resource": "arn:aws:ec2::*:network-interface/*", | ||
"Condition": { | ||
"StringEquals": { | ||
"ec2:Subnet": [ | ||
"arn:aws:ec2::*:subnet/${aws_subnet.codebuild_subnet.id}" | ||
], | ||
"ec2:AuthorizedService": "codebuild.amazonaws.com" | ||
} | ||
} | ||
} | ||
] | ||
} | ||
|
@@ -373,10 +414,10 @@ resource "aws_iam_policy_attachment" "codebuild_policy_attachment" { | |
} | ||
|
||
resource "aws_codebuild_project" "foo" { | ||
name = "test-project-%s" | ||
description = "test_codebuild_project" | ||
build_timeout = "5" | ||
service_role = "${aws_iam_role.codebuild_role.arn}" | ||
name = "test-project-%s" | ||
description = "test_codebuild_project" | ||
build_timeout = "5" | ||
service_role = "${aws_iam_role.codebuild_role.arn}" | ||
|
||
artifacts { | ||
type = "NO_ARTIFACTS" | ||
|
@@ -401,6 +442,18 @@ resource "aws_codebuild_project" "foo" { | |
tags { | ||
"Environment" = "Test" | ||
} | ||
|
||
vpc_config { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this new attribute is optional and has some complexity, we should probably split it out into its own acceptance test. We need to verify the resource creation (what's done here already), the update of
|
||
vpc_id = "${aws_vpc.codebuild_vpc.id}" | ||
|
||
subnets = [ | ||
"${aws_subnet.codebuild_subnet.id}" | ||
] | ||
|
||
security_group_ids = [ | ||
"${aws_security_group.codebuild_security_group.id}" | ||
] | ||
} | ||
} | ||
`, rName, rName, rName, rName) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would switch this to
Type: schema.TypeList,
. There are subtleties between the two, but the gist being that list in this context is much easier to work with when there's only 1 item.