-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
Add cache option to AWS CodeBuild projects #2860
Changes from all commits
75db1c4
27d6221
8246aff
b3a3bf4
ec70fe1
536dea9
0090b9f
16e0b42
28a1404
69f1a23
1516c4e
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 |
---|---|---|
|
@@ -66,6 +66,28 @@ func resourceAwsCodeBuildProject() *schema.Resource { | |
}, | ||
Set: resourceAwsCodeBuildProjectArtifactsHash, | ||
}, | ||
"cache": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Computed: true, | ||
MaxItems: 1, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"type": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.StringInSlice([]string{ | ||
codebuild.CacheTypeNoCache, | ||
codebuild.CacheTypeS3, | ||
}, false), | ||
}, | ||
"location": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
|
@@ -248,6 +270,10 @@ func resourceAwsCodeBuildProjectCreate(d *schema.ResourceData, meta interface{}) | |
Artifacts: &projectArtifacts, | ||
} | ||
|
||
if v, ok := d.GetOk("cache"); ok { | ||
params.Cache = expandProjectCache(v.([]interface{})) | ||
} | ||
|
||
if v, ok := d.GetOk("description"); ok { | ||
params.Description = aws.String(v.(string)) | ||
} | ||
|
@@ -334,6 +360,19 @@ func expandProjectArtifacts(d *schema.ResourceData) codebuild.ProjectArtifacts { | |
return projectArtifacts | ||
} | ||
|
||
func expandProjectCache(s []interface{}) *codebuild.ProjectCache { | ||
var projectCache *codebuild.ProjectCache | ||
|
||
data := s[0].(map[string]interface{}) | ||
|
||
projectCache = &codebuild.ProjectCache{ | ||
Type: aws.String(data["type"].(string)), | ||
Location: aws.String(data["location"].(string)), | ||
} | ||
|
||
return projectCache | ||
} | ||
|
||
func expandProjectEnvironment(d *schema.ResourceData) *codebuild.ProjectEnvironment { | ||
configs := d.Get("environment").(*schema.Set).List() | ||
|
||
|
@@ -460,6 +499,10 @@ func resourceAwsCodeBuildProjectRead(d *schema.ResourceData, meta interface{}) e | |
return err | ||
} | ||
|
||
if err := d.Set("cache", flattenAwsCodebuildProjectCache(project.Cache)); err != nil { | ||
return err | ||
} | ||
|
||
if err := d.Set("source", flattenAwsCodeBuildProjectSource(project.Source)); err != nil { | ||
return err | ||
} | ||
|
@@ -507,6 +550,16 @@ func resourceAwsCodeBuildProjectUpdate(d *schema.ResourceData, meta interface{}) | |
params.VpcConfig = expandCodeBuildVpcConfig(d.Get("vpc_config").([]interface{})) | ||
} | ||
|
||
if d.HasChange("cache") { | ||
if v, ok := d.GetOk("cache"); ok { | ||
params.Cache = expandProjectCache(v.([]interface{})) | ||
} else { | ||
params.Cache = &codebuild.ProjectCache{ | ||
Type: aws.String("NO_CACHE"), | ||
} | ||
} | ||
} | ||
|
||
if d.HasChange("description") { | ||
params.Description = aws.String(d.Get("description").(string)) | ||
} | ||
|
@@ -589,6 +642,24 @@ func flattenAwsCodeBuildProjectArtifacts(artifacts *codebuild.ProjectArtifacts) | |
return &artifactSet | ||
} | ||
|
||
func flattenAwsCodebuildProjectCache(cache *codebuild.ProjectCache) []interface{} { | ||
values := map[string]interface{}{} | ||
|
||
if cache.Type != nil { | ||
if *cache.Type == "NO_CACHE" { | ||
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. Have you considered making I'm not sure where's the balance between hiding API's implementation details and helping the user to be honest - just food for thought. 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. Edit: the code for my first step was wrong, as I didn't use I wasn't aware of I gave it a go just now, however I couldn't make it work. I can't set func defaultAwsCodeBuildProjectCache() (interface{}, error) {
values := map[string]interface{}{}
values["type"] = "NO_CACHE"
return []interface{}{values}, nil
} and I was getting func defaultAwsCodeBuildProjectCache() (interface{}, error) {
defaultValue := make([]map[string]interface{}, 1)
defaultValue[0] = make(map[string]interface{}, 1)
defaultValue[0]["type"] = "NO_CACHE"
return defaultValue, nil
} But I'm still getting the same error as above. Any ideas on what might be wrong? Please bear in mind that this is my first real contact with Go whatsoever, so I might be stuck in something very basic :-) 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 gave it another try yesterday and came to the conclusion that it doesn't make sense to pursue this as a default, since "NO_CACHE" is not a user facing value that is going to be used in HCL. The behaviour of Codebuild projects in the AWS side is a bit weird in the sense that if you don't specify Cache you get a project without caching enabled, while once you set a caching option, the only way to remove it is by updating the project with "NO_CACHE" set. I don't think it makes sense to ask from the user that, once they enabled cached for their Codebuild project on Terraform, they must apply a configuration with "NO_CACHE" explicitly set in order for caching to be disabled. If I remove the cache block from my aws_codebuild_project I wouldn't expect for caching to still be enabled. If anyone is waiting on me to merge, you can go ahead since I'm done with it unless anyone has some more feedback about it :-) |
||
values["type"] = "" | ||
} else { | ||
values["type"] = *cache.Type | ||
} | ||
} | ||
|
||
if cache.Location != nil { | ||
values["location"] = *cache.Location | ||
} | ||
|
||
return []interface{}{values} | ||
} | ||
|
||
func flattenAwsCodeBuildProjectEnvironment(environment *codebuild.ProjectEnvironment) []interface{} { | ||
envConfig := map[string]interface{}{} | ||
|
||
|
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.
This parent attribute needs to be set as
Computed: true
due to some quirks working with default values in children attributes. Otherwise this shows up as a perpetual difference for anyone who does not define the cache configuration (also failing the acceptance testing):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.
hi @bflad! Thanks for your very detailed and helpful feedback. I think I've addressed all of your comments. The new acceptance test I wrote also showed me the effect of lacking the
Computed
flag you mentioned.If you have some time, would you mind explaining in a little more detail what this flag is actually doing? I know if I faced this error on my own I would never be able to guess that I should use it, but also if I face something similar in the future I don't wanna feel I'm just cargo culting my way out of it.
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.
Sorry I do not have time to give a full and well thought out response, but the short of it is that
Computed
tells Terraform to ignore changes to the attribute if it is undefined in the Terraform configuration. It has a side effect of meaning that Terraform cannot reflect drift of a configuration from a default to the operator. Its necessary in this case because we are setting a default for thetype
child attribute where we allow the operator to not define the configuration to not break backwards compatibility.A better implementation here would be using
CustomizeDiff
to manage the nested attributes so we can properly show drift (e.g. someone enabling S3 caching outside TF, but it not being defined in their configuration). In the interest of not holding up this PR longer, I am going to merge this PR as is. We can remove theComputed
later.We will be releasing some public documentation about provider development shortly that will hopefully clear up the usage and caveats with this flag.