-
-
Notifications
You must be signed in to change notification settings - Fork 1.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
modules/gcp - GCP support #141
Conversation
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.
Wonderful, thanks Rob! The tests look great 👍
name = "${var.bucket_name}" | ||
location = "${var.location}" | ||
project = "${var.project}" | ||
} |
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 README mentions a google compute instance, but this just seems to create a storage bucket?
Also, do you need any configuration for the google provider
?
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.
Yeah, that's a good point. I think this example was originally added by @Dahs81. I'll either cleanup the README or even better should we actually add compute resources like terraform-aws-example
, then add tests for those?
And yes we should definitely add a provider block just for clarity.
Right now I'm only setting the following ENV vars locally to test the GCP module:
GOOGLE_APPLICATION_CREDENTIALS
GOOGLE_CLOUD_PROJECT_ID
GOOGLE_STORAGE_PROJECT_ID
We might be able to consolidate that a bit better.
default = "US" | ||
} | ||
|
||
variable "project" {} |
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.
Please add a description
to all variables
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.
Also, I noticed you are using a project
variable in the Terraform code, but a GOOGLE_CLOUD_PROJECT_ID
env var in the test code, which seems a bit redundant. Is there a convention around the best way to do this with GCP and Terraform?
it := bucket.Objects(ctx, nil) | ||
if _, err := it.Next(); err == storage.ErrBucketNotExist { | ||
return err | ||
} |
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 haven't used GCP's SDK, but this looks like a really strange API for checking if a bucket exists! What does the bucket.Attrs
call above check? Will bucket.Objects
give you an error on empty buckets (as opposed to those that don't exist at all)?
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 @brikis98, I spent a while digging through their Go & Java SDK, but it didn't turn up much luck. It appears some calls e.g: client.Bucket(name)
create an object but don't actually do any activity across the network.
I stumbled on their own integration tests and adapted a bit of the code from there.
You might want to take a look: https://github.com/GoogleCloudPlatform/google-cloud-go/blob/de879f7be552d57556875b8aaa383bce9396cc8c/storage/integration_test.go#L1231
I thought it might be a tad easier and theres still the possibilty I'm on the wrong track.
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 had the same reaction as @brikis98, though I agree the API here is confusing. Let's add a comment clarifying the uncertainty and linking back to the URL you posted above. If this passes tests, I think it's good enough for now.
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.
@josh-padnick ok sure
modules/gcp/storage_test.go
Outdated
) | ||
|
||
var ( | ||
projectId = os.Getenv("GOOGLE_STORAGE_PROJECT_ID") |
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.
Is this env var a convention used with GCP? If so, you may want to add a helper function in Terratest called something like getGoogleProjectIdFromEnvVar
and use it throughout these tests.
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.
Not that I'm aware of.
I have a feeling @Dahs81 may have adapted it from the Google examples, see: https://cloud.google.com/storage/docs/reference/libraries#client-libraries-usage-go.
What would be the best way for us to handle PROJECT_ID
for GCP in Terratest? I guess the AWS GO SDK just automatically reads ENV vars right?
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.
One option is that you could create something similar to the ~/.aws directory, but for terratest. Maybe have a ~/.terratest/config.toml that looks something like this:
[google]
project_id="somegoogleprojectidhere"
Then maybe have a terratest config
command that configures it. Then check if that file exists. I'd probably use env variable as a failback though.
I'm not sure if that is too much for this feature. Just an idea.
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.
@josh-padnick Could you chime on with thoughts on how to handle GCP env vars?
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.
So far I've just thrown a few functions in a provider.go
file: https://github.com/gruntwork-io/terratest/pull/141/files#diff-86e2fd38705590c638b44a550afeaab3
modules/gcp/storage_test.go
Outdated
|
||
gsBucketName := "gruntwork-terratest-" + strings.ToLower(id) | ||
|
||
CreateStorageBucket(t, projectId, gsBucketName, nil) |
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.
Perhaps write something to the bucket and read it back as a sanity check it actually exists? Otherwise, even if CreateStorageBucket
and DeleteStorageBucket
were no-ops, this test would still pass.
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 good point!
Thanks, @robmorgan for taking over. I have been busy doing a bunch of k8s stuff and haven't had time to work on this. I appreciate your willingness to take over. Sorry for not getting too far with this. |
@Dahs81 yeah sure, not a problem! |
@josh-padnick Hi Josh, Yes definitely, Jim mentioned this to me last week. I was going to try and break everything down into smaller PRs, but it looks like you've reviewed it all now.. so thanks! No, I've replied to all of your feedback. Just work through the remaining issues and then merge it as it stands. I'm happy to implement new functionality in subsequent PRs. |
Alright, I think we're ready to merge! There were one or two open comments, so I'll wait for your ok to officially merge. Thanks again for this awesome work. |
Hi @josh-padnick, I've made another two micro changes based on your feedback, but I'm happy with how it stands now. Ok to merge! 😎 👍 |
'cc @infosecgithub on this significant update to Terratest which will be directly leveraged to add tests for the Consul and Vault modules for GCP. |
@robmorgan The original merge of this PR failed because we hadn't yet set up our GCP creds in our CircleCI account. I've now done that and all the GCP tests pass except one:
Any idea why? |
@brikis98 Hi Jim, Just scanning through some of your commits - I believe you may need to create a new project under your Gruntwork GCP account and then add Here's another test that failed:
I can see it complaining about a project id. We could extend Your commit: |
@robmorgan Yea, I fixed all of those by adding the necessary env vars. In the most recent build, all of those issues are fixed. The only remaining one is |
@brikis98 hmmm looks like a good one this one. I haven't been able to reproduce locally yet:
let me keep digging. I'll try and run it on my own Circle/GCP accounts tomorrow. |
Could it be an eventual consistency thing? The tags are applied after a few seconds (sometimes), so it's timing dependent? If so, you may just need to use |
@brikis98 yeah I believe it probably is. From memory I found during development there was a lag for this operation, I'm going to go down the |
Yea. In the example automated tests, anything that is eventually consistent should be done in a retry loop. |
Hi Guys,
I'm contributing a module with initial support for GCP in Terratest.
Cheers,
Rob
New Features & Changes
Packer Module
packer-basic-example
to build both AWS & GCP resources.BuildArtifact
&BuildArtifactE
extractAMIID -> extractArtifactID
.The change to the Packer module is potentially controversial. I have deprecated the
BuildAmi
andBuildAmiE
methods and addedBuildArtifact
andBuildArtifactE
. I thought this makes more sense when working with multiple Packer builders. Thoughts?Test Structure Module
SaveArtifactID
: A possible replacement forSaveAmiId
.LoadArtifactID
: A possible replacement forLoadAmiId
.GCP Module
Misc
compute.go
GetPublicIPOfInstance
GetPublicIPOfInstanceE
GetLabelsForComputeInstance
GetLabelsForComputeInstanceE
AddLabelsToInstance
AddLabelsToInstanceE
GetInstanceIdsForInstanceGroup
GetInstanceIdsForInstanceGroupE
DeleteImage
DeleteImageE
NewComputeService
NewComputeServiceE
provider.go
GetGoogleCredentialsFromEnvVar
GetGoogleProjectIDFromEnvVar
GetGoogleRegionFromEnvVar
multiEnvSearch
region.go
GetRandomRegion
GetRandomRegionE
GetRandomZone
GetRandomZoneE
GetAllGcpRegions
GetAllGcpRegionsE
GetAllGcpZones
GetAllGcpZonesE
region_test.go
TestGetRandomRegion
TestGetRandomZone
TestGetRandomRegionExcludesForbiddenRegions
TestGetRandomZoneExcludesForbiddenZones
TestGetAllGcpRegions
TestGetAllGcpZones
assertLooksLikeRegionName
assertLooksLikeZoneName
storage.go
CreateStorageBucket
CreateStorageBucketE
DeleteStorageBucket
DeleteStorageBucketE
ReadBucketObject
ReadBucketObjectE
WriteBucketObject
WriteBucketObjectE
EmptyStorageBucket
EmptyStorageBucketE
AssertStorageBucketExists
AssertStorageBucketExistsE
storage_test.go
GOOGLE_STORAGE_PROJECT_ID
TestCreateAndDestroyStorageBucket
TestAssertStorageBucketExistsNoFalseNegative
TestAssertStorageBucketExistsNoFalsePositive
Examples
terraform-gcp-example
packer-basic-example
Tests
test/packer_basic_example_test.go
should only build the AWS AMI.test/packer_gcp_basic_example_test.go
should only build the GCP Image.test/packer_gcp_basic_example_test.go
should bake using a random zone.test/terraform_gcp_example_test.go
should create and validate Compute resources.