-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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 cloud endpoints resource #933
Add cloud endpoints resource #933
Conversation
New Resource: - Endpoints Service Create/Read/Delete - Example terraform config To do: - Endpoints Service Update - Tests
|
||
# google_endpoints_service | ||
|
||
This resource creates and rolls out a Cloud Endpoints service using OpenAPI. View the relevant docs [here](https://cloud.google.com/endpoints/docs/openapi/). |
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.
Add also a or gRPC
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.
Done.
|
||
This resource creates and rolls out a Cloud Endpoints service using OpenAPI. View the relevant docs [here](https://cloud.google.com/endpoints/docs/openapi/). | ||
|
||
## Example Usage |
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.
Consider putting two examples, one for gRPC and one for open API.
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.
Done.
In addition to the arguments, the following attributes are available: | ||
* `config_id`: The autogenerated ID for the configuration that is rolled out as part of the creation of this resource. Must be provided to compute engine instances as a tag. | ||
* `dns_address`: The address at which the service can be found - usually the same as the service name. | ||
* `apis`: A list of API objects; details below. |
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.
We often used Structure is documented below
instead
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.
Done.
google/resource_endpoints_service.go
Outdated
// rollouts or A/B testing is going to need a more precise tool than this resource. | ||
config := meta.(*Config) | ||
serviceName := d.Get("service_name").(string) | ||
openapi_config, ok := d.GetOk("openapi_config") |
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.
We should be using camelcase for variable and method parameter names
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.
haha, you can see where I went and wrote some python between starting and finishing this method. So embarrassing - thanks. Is there a go linter I should run to catch this sort of thing?
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.
https://github.com/golang/lint
Unfortunately, there is a lot of noise because historically, we haven't been strict about it
google/resource_endpoints_service.go
Outdated
}, | ||
"openapi_config": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, |
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.
Add a ConflictsWith: []string{"grpc_config", "protoc_output"}
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.
Nice, I didn't know about that.
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"protoc_output": &schema.Schema{ |
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 am not sure I like the name protoc_output, seems like a computed field to me at first glance. Would protoc_config
be a better name?
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.
Well, it's not a config - it's just a giant raw binary file which is output by protoc. I can rename it to, maybe, protoc_service_descriptor_bytes
or something like that - thoughts?
google/resource_endpoints_service.go
Outdated
"config_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
ForceNew: true, |
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.
Which is this ForceNew if it is only an exported field?
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.
You're right, that makes no sense. Removed - you can't get a new config_id unless the configs change, anyway.
google/resource_endpoints_service.go
Outdated
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"grpc_config": &schema.Schema{ |
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.
If the content of the config file changes, does it create a diff? If not, it should
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.
It does, yep.
} | ||
} | ||
// Do a rollout using the update mechanism. | ||
err = resourceEndpointsServiceUpdate(d, meta) |
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.
Should it fail instead if the resource already exists? Like in all our other resources, if the resource already exists, the user should call terraform import.
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 "resource" here is really the rollout, I think - the creation of the service object is incidental to the creation of the first rollout.
google/resource_endpoints_service.go
Outdated
}, | ||
"config_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, |
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.
we tend to use the order Required -> Optional -> Computed for schema elements (and if something is both optional and computed it just counts as optional for this ordering)
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.
Done.
google/resource_endpoints_service.go
Outdated
} | ||
} | ||
|
||
func getServiceConfigSource(config_text string) servicemanagement.ConfigSource { |
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.
nit: s/config_text/configText
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.
Done - and all the other ones.
google/resource_endpoints_service.go
Outdated
} | ||
serviceName := d.Get("service_name").(string) | ||
servicesService := servicemanagement.NewServicesService(config.clientServiceMan) | ||
_, err = servicesService.Get(serviceName).Do() |
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 usually in tf we would assume that if we made it to the Create fn then the resource doesn't exist in GCP, or if it does the Create call should error (and then the user can import the resource if it does already exist). If there is something that makes endpoints special that we should still allow create to be called if it does already exist, then let's comment why that is.
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.
Agreed! Added comment.
} | ||
|
||
metadata { | ||
endpoints-service-name = "${google_endpoints_service.endpoints_service.service_name}" |
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.
nit: alignment (terraform fmt
in this directory should take care 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.
Done.
google/resource_endpoints_service.go
Outdated
} | ||
} | ||
|
||
func getGrpcConfigSource(service_config, proto_config string) servicemanagement.ConfigSource { |
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.
nit: initialisms are all caps: https://github.com/golang/go/wiki/CodeReviewComments#initialisms
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.
Interesting! Okay, thanks.
google/resource_endpoints_service.go
Outdated
serviceName := d.Get("service_name").(string) | ||
openapi_config, ok := d.GetOk("openapi_config") | ||
var source servicemanagement.ConfigSource | ||
if ok { |
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.
you could do if openapiConfig, ok := d.GetOk("openapi_config"); ok {
here since that var is only used within the scope of the if/else
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.
Done.
google/resource_endpoints_service.go
Outdated
Schema: map[string]*schema.Schema{ | ||
"name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, |
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 field isn't settable, so it should be computed and not required (likewise for all the others in here and endpoints)
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.
Done.
google/resource_endpoints_service.go
Outdated
} | ||
d.Set("config_id", service.Id) | ||
d.Set("dns_address", service.Name) | ||
d.Set("apis", flattenServiceManagementApi(service.Apis)) |
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.
nit: flattenServiceManagementApis, perhaps?
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.
Done.
} | ||
} | ||
|
||
func TestAccEndpointsService_basic(t *testing.T) { |
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.
eh, we normally put the capital-T test functions at the top of the file and the helpers below 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.
Done.
} | ||
``` | ||
|
||
The example in `examples/endpoints_on_compute_engine` shows the API from the quickstart running on a Compute Engine VM and reachable through Cloud Endpoints, which may also be useful. |
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'd remove "which may also be useful" since that's implied, but you're welcome to keep it if you want
Ping @danawillow and @rosbo - what else needs to be done? :) |
OpenAPI & gRPC Endpoints on Compute Engine. New Resource: - Endpoints Service Create/Read/Delete - Example terraform config
add support for port_specification to resource `google_compute_health_check`
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. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 [email protected]. Thanks! |
If merged, this closes #714. The resource works like this:
This also includes a simple test, and an example which brings up an echo-api running on Compute Engine as in https://cloud.google.com/endpoints/docs/openapi/get-started-compute-engine.
Worth noting: this only works for the OpenAPI spec - gRPC is not implemented here, and Endpoints Frameworks is app-engine only. If someone needs / wants that, please post here or on #714.
This should deploy any OpenAPI spec you provide, including one that works with App Engine Standard or Kubernetes.