Skip to content

Commit

Permalink
Merge b9e9c4c into b7a16b9
Browse files Browse the repository at this point in the history
  • Loading branch information
nat-henderson authored Sep 20, 2018
2 parents b7a16b9 + b9e9c4c commit c9ebc85
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 4 deletions.
1 change: 1 addition & 0 deletions .ci/magic-modules/generate-terraform.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ bundle exec compiler -p products/compute -e terraform -o "${GOPATH}/src/github.c
bundle exec compiler -p products/containeranalysis -e terraform -o "${GOPATH}/src/github.com/terraform-providers/terraform-provider-google/"
bundle exec compiler -p products/resourcemanager -e terraform -o "${GOPATH}/src/github.com/terraform-providers/terraform-provider-google/"
bundle exec compiler -p products/redis -e terraform -o "${GOPATH}/src/github.com/terraform-providers/terraform-provider-google/"
bundle exec compiler -p products/filestore -e terraform -o "${GOPATH}/src/github.com/terraform-providers/terraform-provider-google/"

# Resources that were already using beta APIs before they started being autogenerated
bundle exec compiler -v beta -p products/compute -t Address,Firewall,ForwardingRule,GlobalAddress,RegionDisk,Subnetwork,VpnTunnel -e terraform -o "${GOPATH}/src/github.com/terraform-providers/terraform-provider-google/"
Expand Down
10 changes: 8 additions & 2 deletions api/type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ module Fields

attr_reader :output # If set value will not be sent to server on sync
attr_reader :input # If set to true value is used only on creation
attr_reader :url_param_only # If, true will not be send in request body
attr_reader :required
attr_reader :update_verb
attr_reader :update_url
Expand Down Expand Up @@ -60,6 +61,7 @@ def validate

check_optional_property :output, :boolean
check_optional_property :required, :boolean
check_optional_property :url_param_only, :boolean

raise 'Property cannot be output and required at the same time.' \
if @output && @required
Expand Down Expand Up @@ -250,22 +252,24 @@ class Array < Composite
NESTED_ARRAY_TYPE = [Api::Type::Array, Api::Type::NestedObject].freeze
RREF_ARRAY_TYPE = [Api::Type::Array, Api::Type::ResourceRef].freeze

# rubocop:disable Metrics/CyclomaticComplexity
def validate
super
if @item_type.is_a?(NestedObject) || @item_type.is_a?(ResourceRef)
@item_type.set_variable(@name, :__name)
@item_type.set_variable(@__resource, :__resource)
@item_type.set_variable(self, :__parent)
end
check_property :item_type, [::String, NestedObject, ResourceRef]
check_property :item_type, [::String, NestedObject, ResourceRef, Enum]
unless @item_type.is_a?(NestedObject) || @item_type.is_a?(ResourceRef) \
|| type?(@item_type)
|| @item_type.is_a?(Enum) || type?(@item_type)
raise "Invalid type #{@item_type}"
end

check_optional_property :min_size, ::Integer
check_optional_property :max_size, ::Integer
end
# rubocop:enable Metrics/CyclomaticComplexity

def item_type_class
return Api::Type::NestedObject if @item_type.is_a? NestedObject
Expand All @@ -276,6 +280,8 @@ def item_type_class
def property_class
if @item_type.is_a?(NestedObject) || @item_type.is_a?(ResourceRef)
type = @item_type.property_class
elsif @item_type.is_a?(Enum)
raise 'aaaa'
else
type = property_ns_prefix
type << get_type(@item_type).new(@name).type
Expand Down
159 changes: 159 additions & 0 deletions products/filestore/api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Copyright 2018 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

--- !ruby/object:Api::Product
name: Google Cloud Filestore
prefix: gfile
versions:
- !ruby/object:Api::Product::Version
name: beta
base_url: https://file.googleapis.com/v1beta1/
scopes:
- https://www.googleapis.com/auth/cloud-platform
objects:
- !ruby/object:Api::Resource
name: 'Instance'
exclude: true
base_url: |
projects/{{project}}/locations/{{zone}}/instances?instanceId={{name}}
self_link: projects/{{project}}/locations/{{zone}}/instances/{{name}}
update_verb: :PATCH
description: |
A Google Cloud Filestore instance.
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
'Official Documentation':
'https://cloud.google.com/memorystore/docs/redis/'
api: 'https://cloud.google.com/memorystore/docs/redis/reference/rest/'
<%=
indent(compile_file({timeouts: { insert_sec: 5 * 60 }},
'templates/zonal_async.yaml.erb'), 4)
%>
parameters:
- !ruby/object:Api::Type::String
name: 'zone'
description: |
The name of the Filestore zone of the instance.
required: true
input: true
url_param_only: true
properties:
- !ruby/object:Api::Type::String
name: 'name'
description: |
The resource name of the instance, in the format
`projects/{project_id}/locations/{locationId}/instances/{instanceId}`.
required: true
url_param_only: true
- !ruby/object:Api::Type::String
name: 'description'
description: |
A description of the instance.
- !ruby/object:Api::Type::String
name: 'state'
description: |
The instance state - short description.
output: true
exclude: true
- !ruby/object:Api::Type::String
name: 'statusMessage'
description: |
Additional information about the instance state, if available.
output: true
exclude: true
- !ruby/object:Api::Type::Time
name: 'createTime'
description: 'Creation timestamp in RFC3339 text format.'
output: true
- !ruby/object:Api::Type::Enum
name: 'tier'
description: |
The service tier of the instance.
required: true
input: true
values:
- TIER_UNSPECIFIED
- STANDARD
- PREMIUM
- !ruby/object:Api::Type::NameValues
name: 'labels'
description: |
Resource labels to represent user-provided metadata.
key_type: Api::Type::String
value_type: Api::Type::String
- !ruby/object:Api::Type::Array
name: 'fileShares'
required: true
description: |
File system shares on the instance. For this version, only a
single file share is supported.
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::String
name: 'name'
description: |
The name of the fileshare (16 characters or less)
required: true
input: true
- !ruby/object:Api::Type::Integer
name: 'capacityGb'
description: |
File share capacity in GB.
required: true
- !ruby/object:Api::Type::Array
name: 'networks'
description: |
VPC networks to which the instance is connected. For this version,
only a single network is supported.
required: true
input: true
item_type: !ruby/object:Api::Type::NestedObject
properties:
- !ruby/object:Api::Type::String
name: 'network'
description: |
The name of the GCE VPC network to which the
instance is connected.
required: true
input: true
- !ruby/object:Api::Type::Array
name: 'modes'
description: |
IP versions for which the instance has
IP addresses assigned.
required: true
input: true
item_type: !ruby/object:Api::Type::Enum
name: 'mode'
description: An IP version.
values:
- ADDRESS_MODE_UNSPECIFIED
- MODE_IPV4
- MODE_IPV6
- !ruby/object:Api::Type::String
name: 'reservedIpRange'
description: |
A /29 CIDR block that identifies the range of IP
addresses reserved for this instance.
- !ruby/object:Api::Type::Array
name: 'ipAddresses'
description: |
A list of IPv4 or IPv6 addresses.
output: true
item_type: Api::Type::String
- !ruby/object:Api::Type::String
name: 'etag'
description: |
Server-specified ETag for the instance resource to prevent
simultaneous updates from overwriting each other.
output: true
60 changes: 60 additions & 0 deletions products/filestore/terraform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright 2017 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

--- !ruby/object:Provider::Terraform::Config
overrides: !ruby/object:Provider::ResourceOverrides
Instance: !ruby/object:Provider::Terraform::ResourceOverride
exclude: false
id_format: "{{project}}/{{zone}}/{{name}}"
import_format: ["projects/{{project}}/locations/{{zone}}/instances/{{name}}"]
examples: |
### Basic Usage
```hcl
```
properties:
name: !ruby/object:Provider::Terraform::PropertyOverride
custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb'
zone: !ruby/object:Provider::Terraform::PropertyOverride
ignore_read: true
networks.reservedIpRange: !ruby/object:Provider::Terraform::PropertyOverride
default_from_api: true
custom_code: !ruby/object:Provider::Terraform::CustomCode
pre_update: templates/terraform/pre_update/update_mask.erb

# This is for a list of example files.
examples: !ruby/object:Api::Resource::HashArray

# This is for copying files over
files: !ruby/object:Provider::Config::Files
# All of these files will be copied verbatim.
copy:
'google/transport.go': 'templates/terraform/transport.go'
'google/transport_test.go': 'templates/terraform/transport_test.go'
'google/import.go': 'templates/terraform/import.go'
'google/import_test.go': 'templates/terraform/import_test.go'
'google/filestore_operation.go': 'templates/terraform/filestore_operation.go'
# These files have templating (ERB) code that will be run.
# This is usually to add licensing info, autogeneration notices, etc.
compile:
'google/provider_{{product_name}}_gen.go': 'templates/terraform/provider_gen.erb'

# This is for custom testing code. All of our tests follow a specific pattern
# that sometimes needs to be deviated from. We're working towards a world where
# these handwritten tests would be unnecessary in many cases (custom types).
tests: !ruby/object:Api::Resource::HashArray

# This would be for custom network responses. Tests work by running some block
# of autogenerated code and then verifying the network calls.
# The network call verifications are automatically generated, but can be
# overriden.
test_data: !ruby/object:Provider::Config::TestData
1 change: 1 addition & 0 deletions products/redis/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ objects:
The name of the Redis region of the instance.
required: true
input: true
url_param_only: true
properties:
- !ruby/object:Api::Type::String
name: alternativeLocationId
Expand Down
71 changes: 71 additions & 0 deletions templates/terraform/filestore_operation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package google

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform/helper/resource"
file "google.golang.org/api/file/v1beta1"
)

type FilestoreOperationWaiter struct {
Service *file.ProjectsLocationsService
Op *file.Operation
}

func (w *FilestoreOperationWaiter) RefreshFunc() resource.StateRefreshFunc {
return func() (interface{}, string, error) {
op, err := w.Service.Operations.Get(w.Op.Name).Do()

if err != nil {
return nil, "", err
}

log.Printf("[DEBUG] Got %v while polling for operation %s's 'done' status", op.Done, w.Op.Name)

return op, fmt.Sprint(op.Done), nil
}
}

func (w *FilestoreOperationWaiter) Conf() *resource.StateChangeConf {
return &resource.StateChangeConf{
Pending: []string{"false"},
Target: []string{"true"},
Refresh: w.RefreshFunc(),
}
}

func fileOperationWait(service *file.Service, op *file.Operation, project, activity string) error {
return fileOperationWaitTime(service, op, project, activity, 4)
}

func fileOperationWaitTime(service *file.Service, op *file.Operation, project, activity string, timeoutMin int) error {
if op.Done {
if op.Error != nil {
return fmt.Errorf("Error code %v, message: %s", op.Error.Code, op.Error.Message)
}
return nil
}

w := &FilestoreOperationWaiter{
Service: service.Projects.Locations,
Op: op,
}

state := w.Conf()
state.Delay = 10 * time.Second
state.Timeout = time.Duration(timeoutMin) * time.Minute
state.MinTimeout = 2 * time.Second
opRaw, err := state.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for %s: %s", activity, err)
}

op = opRaw.(*file.Operation)
if op.Error != nil {
return fmt.Errorf("Error code %v, message: %s", op.Error.Code, op.Error.Message)
}

return nil
}
2 changes: 1 addition & 1 deletion templates/terraform/flatten_property_method.erb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}) in
for _, raw := range l {
original := raw.(map[string]interface{})
transformed = append(transformed, map[string]interface{}{
<% property.item_type.properties.each do |prop| -%>
<% property.item_type.properties.reject(&:ignore_read).each do |prop| -%>
"<%= prop.name.underscore -%>": flatten<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(original["<%= prop.api_name -%>"]),
<% end -%>
})
Expand Down
21 changes: 21 additions & 0 deletions templates/terraform/pre_update/update_mask.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
updateMask := []string{}

<% settable_properties.each do |prop| -%>
<%# UpdateMask documentation is not not obvious about which fields are supported or
how deeply nesting is supported. For instance, if we change the field foo.bar.baz,
it seems that *sometimes*, 'foo' is a valid value. Other times, it needs to be
'foo.bar', and other times 'foo.bar.baz'. For now, this only works on top-level
fields - this has not been a problem yet. It might be someday! Consider modeling
the nesting off of what you see in `schema_property.erb` - that nests arbitrarily
far.
-#%>
if d.HasChange("<%= prop.name.underscore -%>") {
updateMask = append(updateMask, "<%= prop.api_name -%>")
}
<% end -%>
// updateMask is a URL parameter but not present in the schema, so replaceVars
// won't set it
url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
if err != nil {
return err
}
Loading

0 comments on commit c9ebc85

Please sign in to comment.