diff --git a/docs/resources/google_compute_zone.md b/docs/resources/google_compute_zone.md
index 6f826445c..320745758 100644
--- a/docs/resources/google_compute_zone.md
+++ b/docs/resources/google_compute_zone.md
@@ -1,27 +1,22 @@
---
-title: About the google_compute_zone Resource
+title: About the google_compute_zone resource
platform: gcp
---
-# google\_compute\_zone
-
-Use the `google_compute_zone` InSpec audit resource to test properties of a single GCP compute zone.
-
-
-
## Syntax
+A `google_compute_zone` is used to test a Google Zone resource
-A `google_compute_zone` resource block declares the tests for a single GCP zone by project and name.
-
- describe google_compute_zone(project: 'chef-inspec-gcp', zone: 'us-east1-b') do
- its('name') { should match 'us-east1-b' }
- end
-
+## Beta Resource
+This resource has beta fields available. To retrieve these fields, include `beta: true` in the constructor for the resource
## Examples
-
-The following examples show how to use this InSpec audit resource.
+```
+describe google_compute_zone(project: 'chef-gcp-inspec', "us-central1-a") do
+ it { should exist }
+ it { should be_up }
+end
+```
### Test that a GCP compute zone exists
@@ -43,15 +38,37 @@ The following examples show how to use this InSpec audit resource.
its('available_cpu_platforms') { should include "Intel Skylake" }
end
-
-
## Properties
+Properties that can be accessed from the `google_compute_zone` resource:
+
+
+ * `creation_timestamp`: Creation timestamp in RFC3339 text format.
+
+ * `deprecated`: The deprecation status associated with this machine type.
+
+ * `deleted`: An optional RFC3339 timestamp on or after which the state of this resource is intended to change to DELETED. This is only informational and the status will not change unless the client explicitly changes it.
+
+ * `deprecated`: An optional RFC3339 timestamp on or after which the state of this resource is intended to change to DEPRECATED. This is only informational and the status will not change unless the client explicitly changes it.
+
+ * `obsolete`: An optional RFC3339 timestamp on or after which the state of this resource is intended to change to OBSOLETE. This is only informational and the status will not change unless the client explicitly changes it.
+
+ * `replacement`: The URL of the suggested replacement for a deprecated resource. The suggested replacement resource must be the same kind of resource as the deprecated resource.
+
+ * `state`: The deprecation state of this resource. This can be DEPRECATED, OBSOLETE, or DELETED. Operations which create a new resource using a DEPRECATED resource will return successfully, but with a warning indicating the deprecated resource and recommending its replacement. Operations which use OBSOLETE or DELETED resources will be rejected and result in an error.
+
+ * `description`: An optional textual description of the resource.
+
+ * `id`: The unique identifier for the resource.
+
+ * `name`: Name of the resource.
+
+ * `region`: The region where the zone is located.
-* `available_cpu_platforms`, `creation_timestamp`, `description`, `id`, `kind`, `name`, `region`, `status`, `region_name`
+ * `status`: The status of the zone.
-
+ * `available_cpu_platforms`: The available CPU platforms in this zone
## GCP Permissions
-Ensure the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
+Ensure the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com/) is enabled for the current project.
diff --git a/docs/resources/google_compute_zones.md b/docs/resources/google_compute_zones.md
index 63253c532..2b65b3d95 100644
--- a/docs/resources/google_compute_zones.md
+++ b/docs/resources/google_compute_zones.md
@@ -1,87 +1,42 @@
---
-title: About the google_compute_zones Resource
+title: About the google_compute_zones resource
platform: gcp
---
-# google\_compute\_zones
-
-Use the `google_compute_zones` InSpec audit resource to test properties of all, or a filtered group of, GCP compute zones for a project in a particular zone.
-
-
-
## Syntax
+A `google_compute_zones` is used to test a Google Zone resource
-A `google_compute_zones` resource block collects GCP zones by project then tests that group.
-
- describe google_compute_zones(project: 'chef-inspec-gcp') do
- it { should exist }
- end
-
-Use this InSpec resource to enumerate IDs then test in-depth using `google_compute_zone`.
-
- google_compute_zones(project: 'chef-inspec-gcp').zone_names.each do |zone_name|
- describe google_compute_zone(project: 'chef-inspec-gcp', zone: zone_name) do
- it { should exist }
- its('kind') { should eq "compute#zone" }
- its('status') { should eq 'UP' }
- end
- end
-
+## Beta Resource
+This resource has beta fields available. To retrieve these fields, include `beta: true` in the constructor for the resource
## Examples
-
-The following examples show how to use this InSpec audit resource.
-
-### Test that there are no more than a specified number of zones available for the project
-
- describe google_compute_zones(project: 'chef-inspec-gcp') do
- its('count') { should be <= 100}
- end
-
-### Test the exact number of zones in the project
-
- describe google_compute_zones(project: 'chef-inspec-gcp') do
- its('zone_ids.count') { should cmp 9 }
- end
-
-### Test that an expected zone is available for the project
-
- describe google_compute_zones(project: 'chef-inspec-gcp') do
- its('zone_names') { should include "us-east1-b" }
- end
-
-### Test whether any zones are in status "DOWN"
-
- describe google_compute_zones(project: 'chef-inspec-gcp') do
- its('zone_statuses') { should_not include "DOWN" }
- end
-
-### Test that a subset of all zones matching "us*" are "UP"
-
- google_compute_zones(project: 'chef-inspec-gcp').where(zone_name: /^us/).zone_names.each do |zone_name|
- describe google_compute_zone(project: 'chef-inspec-gcp', zone: zone_name) do
- it { should exist }
- its('kind') { should eq "compute#zone" }
- its('status') { should eq 'UP' }
- end
- end
-
-
-
-## Filter Criteria
-
-This resource supports the following filter criteria: `zone_id`; `zone_name` and `zone_status`. Any of these may be used with `where`, as a block or as a method.
+```
+google_compute_zones(project: 'chef-gcp-inspec').zone_names.each do |zone_name|
+ describe google_compute_zones(project: 'chef-gcp-inspec', name: zone_name) do
+ it { should exist }
+ it { should be_up }
+ end
+end
+```
## Properties
+Properties that can be accessed from the `google_compute_zones` resource:
+
+See [google_compute_zone.md](google_compute_zone.md) for more detailed information
+ * `creation_timestamps`: an array of `google_compute_zone` creation_timestamp
+ * `deprecateds`: an array of `google_compute_zone` deprecated
+ * `descriptions`: an array of `google_compute_zone` description
+ * `zone_ids`: an array of `google_compute_zone` id
+ * `zone_names`: an array of `google_compute_zone` name
+ * `regions`: an array of `google_compute_zone` region
+ * `zone_statuses`: an array of `google_compute_zone` status
+ * `available_cpu_platforms`: an array of `google_compute_zone` available_cpu_platforms
-* `zone_ids` - an array of google_compute_zone identifier integers
-* `zone_names` - an array of google_compute_zone name strings
-* `zone_statuses`- an array of google_compute_zone statuses
-
-
-
+## Filter Criteria
+This resource supports all of the above properties as filter criteria, which can be used
+with `where` as a block or a method.
## GCP Permissions
-Ensure the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com/) is enabled for the project where the resource is located.
\ No newline at end of file
+Ensure the [Compute Engine API](https://console.cloud.google.com/apis/library/compute.googleapis.com/) is enabled for the current project.
diff --git a/libraries/google/compute/property/zone_deprecated.rb b/libraries/google/compute/property/zone_deprecated.rb
new file mode 100644
index 000000000..263636681
--- /dev/null
+++ b/libraries/google/compute/property/zone_deprecated.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: false
+
+# ----------------------------------------------------------------------------
+#
+# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
+#
+# ----------------------------------------------------------------------------
+#
+# This file is automatically generated by Magic Modules and manual
+# changes will be clobbered when the file is regenerated.
+#
+# Please read more about how to change this file in README.md and
+# CONTRIBUTING.md located at the root of this package.
+#
+# ----------------------------------------------------------------------------
+module GoogleInSpec
+ module Compute
+ module Property
+ class ZoneDeprecated
+ attr_reader :deleted
+
+ attr_reader :deprecated
+
+ attr_reader :obsolete
+
+ attr_reader :replacement
+
+ attr_reader :state
+
+ def initialize(args = nil, parent_identifier = nil)
+ return if args.nil?
+ @parent_identifier = parent_identifier
+ @deleted = parse_time_string(args['deleted'])
+ @deprecated = parse_time_string(args['deprecated'])
+ @obsolete = parse_time_string(args['obsolete'])
+ @replacement = args['replacement']
+ @state = args['state']
+ end
+
+ def to_s
+ "#{@parent_identifier} ZoneDeprecated"
+ end
+
+ # Handles parsing RFC3339 time string
+ def parse_time_string(time_string)
+ time_string ? Time.parse(time_string) : nil
+ end
+ end
+ end
+ end
+end
diff --git a/libraries/google_compute_zone.rb b/libraries/google_compute_zone.rb
index 171bec85c..172791554 100644
--- a/libraries/google_compute_zone.rb
+++ b/libraries/google_compute_zone.rb
@@ -1,46 +1,88 @@
-# frozen_string_literal: true
+# frozen_string_literal: false
+# ----------------------------------------------------------------------------
+#
+# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
+#
+# ----------------------------------------------------------------------------
+#
+# This file is automatically generated by Magic Modules and manual
+# changes will be clobbered when the file is regenerated.
+#
+# Please read more about how to change this file in README.md and
+# CONTRIBUTING.md located at the root of this package.
+#
+# ----------------------------------------------------------------------------
require 'gcp_backend'
+require 'google/compute/property/zone_deprecated'
-module Inspec::Resources
- class GoogleComputeZone < GcpResourceBase
- name 'google_compute_zone'
- desc 'Verifies settings for a zone'
-
- example "
- describe google_compute_zone(project: 'chef-inspec-gcp', zone: 'us-east1-b') do
- it { should exist }
- its('name') { should match 'us-east1-b' }
- end
- "
-
- def initialize(opts = {})
- # Call the parent class constructor
- super(opts)
- @display_name = opts[:name]
- catch_gcp_errors do
- @zone = @gcp.gcp_compute_client.get_zone(opts[:project], opts[:name])
- create_resource_methods(@zone)
- end
- end
+# A provider to manage Compute Engine resources.
+class ComputeZone < GcpResourceBase
+ name 'google_compute_zone'
+ desc 'Zone'
+ supports platform: 'gcp'
- # helper method for retrieving a region name
- def region_name
- return '' if !defined?(region) || region.nil?
- region.split('/').last
- end
+ attr_reader :params
+ attr_reader :creation_timestamp
+ attr_reader :deprecated
+ attr_reader :description
+ attr_reader :id
+ attr_reader :name
+ attr_reader :region
+ attr_reader :status
+ attr_reader :available_cpu_platforms
- def exists?
- !@zone.nil?
- end
+ def initialize(params)
+ super(params.merge({ use_http_transport: true }))
+ @params = params
+ @fetched = @connection.fetch(product_url(params[:beta]), resource_base_url, params, 'Get')
+ parse unless @fetched.nil?
+ end
- def up?
- return false if !defined?(status) || status.nil?
- status == 'UP'
- end
+ def parse
+ @creation_timestamp = parse_time_string(@fetched['creationTimestamp'])
+ @deprecated = GoogleInSpec::Compute::Property::ZoneDeprecated.new(@fetched['deprecated'], to_s)
+ @description = @fetched['description']
+ @id = @fetched['id']
+ @name = @fetched['name']
+ @region = @fetched['region']
+ @status = @fetched['status']
+ @available_cpu_platforms = @fetched['availableCpuPlatforms']
+ end
+
+ # Handles parsing RFC3339 time string
+ def parse_time_string(time_string)
+ time_string ? Time.parse(time_string) : nil
+ end
+
+ def exists?
+ !@fetched.nil?
+ end
- def to_s
- "Zone #{@display_name}"
+ def to_s
+ "Zone #{@params[:name]}"
+ end
+
+ # helper method for retrieving a region name
+ def region_name
+ @region&.split('/').last
+ end
+
+ def up?
+ @status == 'UP'
+ end
+
+ private
+
+ def product_url(beta = false)
+ if beta
+ 'https://www.googleapis.com/compute/beta/'
+ else
+ 'https://www.googleapis.com/compute/v1/'
end
end
+
+ def resource_base_url
+ 'projects/{{project}}/zones/{{name}}'
+ end
end
diff --git a/libraries/google_compute_zones.rb b/libraries/google_compute_zones.rb
index 611a8e3b6..d91e9642f 100644
--- a/libraries/google_compute_zones.rb
+++ b/libraries/google_compute_zones.rb
@@ -1,43 +1,102 @@
-# frozen_string_literal: true
+# frozen_string_literal: false
+# ----------------------------------------------------------------------------
+#
+# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
+#
+# ----------------------------------------------------------------------------
+#
+# This file is automatically generated by Magic Modules and manual
+# changes will be clobbered when the file is regenerated.
+#
+# Please read more about how to change this file in README.md and
+# CONTRIBUTING.md located at the root of this package.
+#
+# ----------------------------------------------------------------------------
require 'gcp_backend'
+class ComputeZones < GcpResourceBase
+ name 'google_compute_zones'
+ desc 'Zone plural resource'
+ supports platform: 'gcp'
-module Inspec::Resources
- class GoogleComputeZones < GcpResourceBase
- name 'google_compute_zones'
- desc 'Verifies settings for GCP compute zones in bulk'
+ attr_reader :table
- example "
- describe google_compute_zones(project: 'chef-inspec-gcp') do
- it { should exist }
- end
- "
+ filter_table_config = FilterTable.create
- def initialize(opts = {})
- # Call the parent class constructor
- super(opts)
- @project = opts[:project]
- end
+ filter_table_config.add(:creation_timestamps, field: :creation_timestamp)
+ filter_table_config.add(:deprecateds, field: :deprecated)
+ filter_table_config.add(:descriptions, field: :description)
+ filter_table_config.add(:zone_ids, field: :zone_id)
+ filter_table_config.add(:zone_names, field: :zone_name)
+ filter_table_config.add(:regions, field: :region)
+ filter_table_config.add(:zone_statuses, field: :zone_status)
+ filter_table_config.add(:available_cpu_platforms, field: :available_cpu_platforms)
- # FilterTable setup
- filter_table_config = FilterTable.create
- filter_table_config.add(:zone_ids, field: :zone_id)
- filter_table_config.add(:zone_names, field: :zone_name)
- filter_table_config.add(:zone_statuses, field: :zone_status)
- filter_table_config.connect(self, :fetch_data)
-
- def fetch_data
- zone_rows = []
- catch_gcp_errors do
- @zones = @gcp.gcp_compute_client.list_zones(@project)
- end
- return [] if !@zones || !@zones.items
- @zones.items.map do |zone|
- zone_rows+=[{ zone_id: zone.id,
- zone_name: zone.name,
- zone_status: zone.status }]
+ filter_table_config.connect(self, :table)
+
+ def initialize(params = {})
+ super(params.merge({ use_http_transport: true }))
+ @params = params
+ @table = fetch_wrapped_resource('items')
+ end
+
+ def fetch_wrapped_resource(wrap_path)
+ # fetch_resource returns an array of responses (to handle pagination)
+ result = @connection.fetch_all(product_url, resource_base_url, @params, 'Get')
+ return if result.nil?
+
+ # Conversion of string -> object hash to symbol -> object hash that InSpec needs
+ converted = []
+ result.each do |response|
+ next if response.nil? || !response.key?(wrap_path)
+ response[wrap_path].each do |hash|
+ hash_with_symbols = {}
+ hash.each_key do |key|
+ name, value = transform(key, hash)
+ hash_with_symbols[name] = value
+ end
+ converted.push(hash_with_symbols)
end
- @table = zone_rows
end
+
+ converted
+ end
+
+ def transform(key, value)
+ return transformers[key].call(value) if transformers.key?(key)
+
+ [key.to_sym, value]
+ end
+
+ def transformers
+ {
+ 'creationTimestamp' => ->(obj) { return :creation_timestamp, parse_time_string(obj['creationTimestamp']) },
+ 'deprecated' => ->(obj) { return :deprecated, GoogleInSpec::Compute::Property::ZoneDeprecated.new(obj['deprecated'], to_s) },
+ 'description' => ->(obj) { return :description, obj['description'] },
+ 'id' => ->(obj) { return :zone_id, obj['id'] },
+ 'name' => ->(obj) { return :zone_name, obj['name'] },
+ 'region' => ->(obj) { return :region, obj['region'] },
+ 'status' => ->(obj) { return :zone_status, obj['status'] },
+ 'availableCpuPlatforms' => ->(obj) { return :available_cpu_platforms, obj['availableCpuPlatforms'] },
+ }
+ end
+
+ # Handles parsing RFC3339 time string
+ def parse_time_string(time_string)
+ time_string ? Time.parse(time_string) : nil
+ end
+
+ private
+
+ def product_url(beta = false)
+ if beta
+ 'https://www.googleapis.com/compute/beta/'
+ else
+ 'https://www.googleapis.com/compute/v1/'
+ end
+ end
+
+ def resource_base_url
+ 'projects/{{project}}/zones'
end
end
diff --git a/test/integration/verify/controls/google_compute_zone.rb b/test/integration/verify/controls/google_compute_zone.rb
index 2bf2d4174..c8a39d4dd 100644
--- a/test/integration/verify/controls/google_compute_zone.rb
+++ b/test/integration/verify/controls/google_compute_zone.rb
@@ -1,15 +1,26 @@
-title 'Test single GCP Zone'
+# ----------------------------------------------------------------------------
+#
+# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
+#
+# ----------------------------------------------------------------------------
+#
+# This file is automatically generated by Magic Modules and manual
+# changes will be clobbered when the file is regenerated.
+#
+# Please read more about how to change this file in README.md and
+# CONTRIBUTING.md located at the root of this package.
+#
+# ----------------------------------------------------------------------------
-gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
-gcp_zone = attribute(:gcp_zone, default: '', description: 'The GCP zone being used.')
-
-control 'gcp-single-zone-1.0' do
+title 'Test GCP google_compute_zone resource.'
+gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.')
+control 'google_compute_zone-1.0' do
impact 1.0
- title 'Ensure single zone has the correct properties.'
+ title 'google_compute_zone resource test'
- describe google_compute_zone(project: gcp_project_id, name: gcp_zone) do
+ describe google_compute_zone(project: gcp_project_id, "us-central1-a") do
it { should exist }
it { should be_up }
end
-end
\ No newline at end of file
+end
diff --git a/test/integration/verify/controls/google_compute_zones.rb b/test/integration/verify/controls/google_compute_zones.rb
index b6f06d34d..c196e107b 100644
--- a/test/integration/verify/controls/google_compute_zones.rb
+++ b/test/integration/verify/controls/google_compute_zones.rb
@@ -1,19 +1,28 @@
-title 'Zones Properties'
+# ----------------------------------------------------------------------------
+#
+# *** AUTO GENERATED CODE *** AUTO GENERATED CODE ***
+#
+# ----------------------------------------------------------------------------
+#
+# This file is automatically generated by Magic Modules and manual
+# changes will be clobbered when the file is regenerated.
+#
+# Please read more about how to change this file in README.md and
+# CONTRIBUTING.md located at the root of this package.
+#
+# ----------------------------------------------------------------------------
-gcp_project_id = attribute(:gcp_project_id, default: '', description: 'The GCP project identifier.')
-gcp_zone = attribute(:gcp_zone, default: '', description: 'The GCP zone being used.')
-
-control 'gcp-zones-1.0' do
+title 'Test GCP google_compute_zones resource.'
+gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.')
+control 'google_compute_zones-1.0' do
impact 1.0
- title 'Ensure zones have the correct properties in bulk'
+ title 'google_compute_zones resource test'
- describe google_compute_zones(project: gcp_project_id) do
- it { should exist }
- its('count') { should be <= 100} # 46 at the time of writing
- its('zone_names') { should include gcp_zone }
- its('zone_statuses') { should_not include "DOWN" }
- its('zone_ids') { should include 2290 }
+ google_compute_zones(project: gcp_project_id).zone_names.each do |zone_name|
+ describe google_compute_zones(project: gcp_project_id, name: zone_name) do
+ it { should exist }
+ it { should be_up }
+ end
end
-
-end
\ No newline at end of file
+end