-
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
Add cache option to AWS CodeBuild projects #2860
Conversation
@kaofelix Thanks for putting this together! I was going to add this myself. I'm not a maintainer, but on the last PR I submitted, they asked that validators be put into https://github.com/terraform-providers/terraform-provider-aws/blob/master/aws/validators.go. I imagine they'll ask the same thing here! |
Hey @nathanielks, thanks for the heads up! I was not aware of the |
@kaofelix I'd say that's out of scope for this PR. They just had me add my individual validator to the file, as well as move my test to |
For reference: #2090 (comment) |
Cool, @nathanielks! I moved it to the validators file, thanks again for the heads up :) |
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 @kaofelix
thanks for raising the PR.
I left you some comments there.
Just FYI for future PRs - it may be helpful/easier for you (and others) to always raise a PR from a branch, rather than master
. It is easier to collaborate (if necessary), you can raise multiple PRs to the same repo without conflicts and finally you don't need to force-push to master
when rebasing and/or squashing commits.
@@ -59,6 +59,25 @@ func resourceAwsCodeBuildProject() *schema.Resource { | |||
}, | |||
Set: resourceAwsCodeBuildProjectArtifactsHash, | |||
}, | |||
"cache": { | |||
Type: schema.TypeSet, |
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.
Since there won't ever be more than 1 cache
stanza we should make it TypeList
instead as there's no point in computing the hash for a set and dealing with ordering (as there's nothing to order). Also it will be easier possible to reference nested fields like ${aws_codebuild_project.cache.0.type}
etc.
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.
Ok, I've changed it into a List now, seems to work fine. Thanks for the tip!
}, | ||
}, | ||
}, | ||
Set: resourceAwsCodeBuildProjectCacheHash, |
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.
The Set
will become unnecessary after turning the parent field into TypeList
.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered making NO_CACHE
the Default
value of type
field instead of "magically" turning it into empty string here?
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 comment
The 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 make
initially
I wasn't aware of Default
so I haven't even tried to go this route. But I do think it sounds a lot cleaner and transparent than what I came up with.
I gave it a go just now, however I couldn't make it work. I can't set Default
for only the type
, since type
is required when cache
is present. My next try was to give a Default
to the whole cache
block, but it won't allow me since it's a list. I figured in this case I should use DefaultFunc
instead, however I can't make it work. I came up with
func defaultAwsCodeBuildProjectCache() (interface{}, error) {
values := map[string]interface{}{}
values["type"] = "NO_CACHE"
return []interface{}{values}, nil
}
and I was getting Error: aws_codebuild_project.foo: cache.0: expected object, got invalid
when trying to generate a plan containing a codebuild project with no cache defined. So I guessed maybe I need to allocate those objects since the might have been gc'ed or something like, so I tried:
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 comment
The 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 :-)
r/aws_codebuild_project: Add cache options r/aws_codebuild_project: Add documentation cache option r/aws_codebuild_project: Do not display NO_CACHE value in the plan r/aws_codebuild_project: Fix acceptance test r/aws_codebuild_project: Fix indentation in code samples r/aws_codebuild_project: Move cache type validator to validators.go r/aws_codebuild_project: Make cache option into a *schema.List instead of *schema.Set
@kaofelix There are merge conflicts present, would you mind patching those up? Looking forward to this! |
@nathanielks I didn’t have time to do it yesterday, but I’ll do it later today. Thanks for the heads up! |
@nathanielks are we go with this one? |
@TaiSHiNet unfortunately I'm not a core contributor 😅 just helping where I can! |
Any plans to finish this @radeksimko @nathanielks ? :) |
I'm anxiously awaiting this myself! |
I'm solving the conflicts again, also hoping it gets merged soon |
It'd be awesome if someone would review/merge this - I've got some big ivy builds begging for a cache :) |
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.
Thanks so much for this contribution. Please see the below comments and let me know if you have any questions or do not have time to implement the feedback.
aws/validators.go
Outdated
@@ -15,6 +15,8 @@ import ( | |||
"github.com/aws/aws-sdk-go/service/cognitoidentityprovider" | |||
"github.com/aws/aws-sdk-go/service/configservice" | |||
"github.com/aws/aws-sdk-go/service/ec2" | |||
"github.com/aws/aws-sdk-go/service/gamelift" |
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.
Looks like there was some wonky behavior from merge conflicts. I think the validation functions for gamelift/guardduty are not present in this file in master.
@@ -459,6 +464,11 @@ resource "aws_codebuild_project" "foo" { | |||
type = "NO_ARTIFACTS" | |||
} | |||
|
|||
cache { |
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.
Rather than modifying the baseline configuration, we should probably create another acceptance test and configuration(s) that implements these steps:
- Create project without the
cache
configuration - Adding the
cache
configuration to the project - Updates the location
- Removes the
cache
configuration from the project
@@ -59,6 +59,24 @@ func resourceAwsCodeBuildProject() *schema.Resource { | |||
}, | |||
Set: resourceAwsCodeBuildProjectArtifactsHash, | |||
}, | |||
"cache": { |
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):
=== RUN TestAccAWSCodeBuildProject_default_build_timeout
--- FAIL: TestAccAWSCodeBuildProject_default_build_timeout (24.72s)
testing.go:518: Step 0 error: After applying this step, the plan was not empty:
DIFF:
UPDATE: aws_codebuild_project.foo
cache.#: "1" => "0"
=== RUN TestAccAWSCodeBuildProject_sourceAuth
--- FAIL: TestAccAWSCodeBuildProject_sourceAuth (24.39s)
testing.go:518: Step 1 error: After applying this step, the plan was not empty:
DIFF:
UPDATE: aws_codebuild_project.foo
cache.#: "1" => "0"
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 the type
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 the Computed
later.
We will be releasing some public documentation about provider development shortly that will hopefully clear up the usage and caveats with this flag.
"type": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validateAwsCodeBuildCacheType, |
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.
Nitpick: This can be simplified with:
ValidateFunc: validation.StringInSlice([]string{
codebuild.CacheTypeNoCache,
codebuild.CacheTypeS3,
}, false),
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.
Merging, thanks! 🚀
Please note that we are pulling this in with the caveat it will not properly detect if S3 cache is already enabled and the cache
configuration is not defined (Computed
on that attribute), which can be fixed with CustomizeDiff
later or improvements into Terraform core to work better with defaults for children attributes.
5 tests passed (all tests)
=== RUN TestAccAWSCodeBuildProject_basic
--- PASS: TestAccAWSCodeBuildProject_basic (26.63s)
=== RUN TestAccAWSCodeBuildProject_sourceAuth
--- PASS: TestAccAWSCodeBuildProject_sourceAuth (26.67s)
=== RUN TestAccAWSCodeBuildProject_default_build_timeout
--- PASS: TestAccAWSCodeBuildProject_default_build_timeout (33.63s)
=== RUN TestAccAWSCodeBuildProject_vpc
--- PASS: TestAccAWSCodeBuildProject_vpc (43.00s)
=== RUN TestAccAWSCodeBuildProject_cache
--- PASS: TestAccAWSCodeBuildProject_cache (46.94s)
This has been released in version 1.14.0 of the AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading. |
Woohoo!! |
Cheers! Thanks a lot! |
Many thanks @kaofelix for your efforts ! 🎉 |
Hi there! I'm afraid we need to revisit this
I don't agree here, because...
Unfortunately |
Followup PR submitted: #4134 |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks! |
This is for implementing support for the cache feature I requested in #2842.