diff --git a/build/inspec b/build/inspec index 257d3f760307..f359ebbf01dc 160000 --- a/build/inspec +++ b/build/inspec @@ -1 +1 @@ -Subproject commit 257d3f760307559938568aeed74261df5cde4b87 +Subproject commit f359ebbf01dc1294dc5338ad2dc380a888a14563 diff --git a/build/terraform b/build/terraform index 56f6530712f9..d622ec466e68 160000 --- a/build/terraform +++ b/build/terraform @@ -1 +1 @@ -Subproject commit 56f6530712f9cbfa5db40e9238d35703931fa951 +Subproject commit d622ec466e688b09c601d34f5ce1c7e5796dadf3 diff --git a/provider/inspec.rb b/provider/inspec.rb index ac6e7ab631a8..0b01ed0a2aa5 100644 --- a/provider/inspec.rb +++ b/provider/inspec.rb @@ -101,28 +101,61 @@ def emit_nested_object_overrides(data) ) end - def primitive? (property) - return property.is_a?(::Api::Type::Primitive) || (property.is_a?(Api::Type::Array) && !property.item_type.is_a?(::Api::Type::NestedObject)) + # Figuring out if a property is a primitive ruby type is a hassle. But it is important + # Fingerprints are strings, NameValues are hashes, and arrays of primitives are arrays + # Arrays of NestedObjects need to have their contents parsed and returned in an array + # ResourceRefs are strings + def primitive?(property) + array_primitive = (property.is_a?(Api::Type::Array)\ + && !property.item_type.is_a?(::Api::Type::NestedObject)) + property.is_a?(::Api::Type::Primitive)\ + || array_primitive\ + || property.is_a?(::Api::Type::NameValues)\ + || property.is_a?(::Api::Type::Fingerprint)\ + || property.is_a?(::Api::Type::ResourceRef) end - def resource_ref? (property) - return property.is_a?(::Api::Type::ResourceRef) + # Arrays of nested objects need special requires statements + def typed_array?(property) + property.is_a?(::Api::Type::Array) && nested_object?(property.item_type) end - def typed_array? (property) - return property.is_a?(::Api::Type::Array) + def nested_object?(property) + property.is_a?(::Api::Type::NestedObject) end - def nested_object? (property) - return property.is_a?(::Api::Type::NestedObject) + # Only arrays of nested objects and nested object properties need require statements + # for InSpec. Primitives are all handled natively + def generate_requires(properties) + nested_props = properties.select { |type| nested_object?(type) } + nested_object_arrays = properties.select\ + { |type| typed_array?(type) && nested_object?(type.item_type) } + nested_array_requires = nested_object_arrays.collect { |type| array_requires(type) } + # Need to include requires statements for the requirements of a nested object + # TODO is this needed? Not sure how ruby works so well + nested_prop_requires = nested_props.map\ + { |nested_prop| generate_requires(nested_prop.properties) } + nested_object_requires = nested_props.map\ + { |nested_object| nested_object_requires(nested_object) } + nested_object_requires + nested_prop_requires + nested_array_requires end - def generate_requires(properties, requires = []) - nested_props = properties.select{ |type| nested_object?(type) } - requires.concat(properties.reject{ |type| primitive?(type) || resource_ref?(type) || nested_object?(type) }.collect(&:requires)) - requires.concat(nested_props.map{|nested_prop| generate_requires(nested_prop.properties) } ) - requires.concat(nested_props.map{|nested_prop| nested_prop.property_file }) - requires + def array_requires(type) + File.join( + 'google', + type.__resource.__product.prefix[1..-1], + 'property', + [type.__resource.name.downcase, type.item_type.name.underscore].join('_') + ) + end + + def nested_object_requires(nested_object_type) + File.join( + 'google', + nested_object_type.__resource.__product.prefix[1..-1], + 'property', + [nested_object_type.__resource.name, nested_object_type.name.underscore].join('_') + ).downcase end end end diff --git a/templates/inspec/singular_resource.erb b/templates/inspec/singular_resource.erb index 1a8056d7daa3..f8753b55a32b 100644 --- a/templates/inspec/singular_resource.erb +++ b/templates/inspec/singular_resource.erb @@ -47,25 +47,27 @@ class <%= object.name -%> < Inspec.resource(1) end <% if object.self_link_query.nil? -%> - def initialize(params) - @fetched = <%= method_call('fetch_resource', ['params', ("'#{object.kind}'" if object.kind?)], 2) %> - parse unless @fetched.nil? - end -<% else # object.self_link_query.nil? -%> - def initialize(params) - @fetched = <%= method_call('fetch_wrapped_resource', ['params', ("'#{object.kind}'" if object.kind?), - "'#{object.self_link_query.kind}'", - "'#{object.self_link_query.items}'"], 2) %> + def initialize(params) + @fetched = fetch_resource(params) parse unless @fetched.nil? end +<% else # object.self_link_query.nil? -%> + # TODO(slevenick) for other products + def initialize(params) + raise 'Not implemented' + end <% end # object.self_link_query.nil? -%> + def fetch_resource(params) + get_request = inspec.backend.fetch(base, url, params) + end + def parse - <% - fetch_code = object.properties.map do |prop| +<% + parse_code = object.properties.map do |prop| name = prop.out_name - if primitive?(prop) || resource_ref?(prop) + if primitive?(prop) init = "@fetched['#{prop.api_name}']" elsif typed_array?(prop) init = "#{prop.property_type}.parse(@fetched['#{prop.api_name}'])" @@ -76,7 +78,7 @@ class <%= object.name -%> < Inspec.resource(1) assignment = "@#{name} = #{init}" end -%> -<%= lines(indent(fetch_code, 4)) -%> +<%= lines(indent(parse_code, 4)) -%> end def exists?