diff --git a/README.md b/README.md index 908d58322..69ec0de17 100644 --- a/README.md +++ b/README.md @@ -426,6 +426,23 @@ control 'gcp-projects-zones-vm-label-loop-1.0' do end end ``` +This example verifies there are sufficient privileges to list all regions. + +``` +next unless google_compute_regions(project: gcp_project_id).resource_failed? +google_compute_regions(project: gcp_project_id).region_names.each do |region_name| + describe google_compute_region(project: gcp_project_id, region: region_name) do + it { should be_up } + end +end + +if google_compute_regions(project: gcp_project_id).resource_failed? + puts google_compute_regions(project: gcp_project_id).resource_exception_message + puts google_compute_regions(project: gcp_project_id,name: region_name).pretty_inspect +end +``` + + This example assumes there are sufficient privileges to list all GCP projects. diff --git a/libraries/gcp_backend.rb b/libraries/gcp_backend.rb index ca60cd4cb..2591f2308 100644 --- a/libraries/gcp_backend.rb +++ b/libraries/gcp_backend.rb @@ -22,7 +22,7 @@ def initialize(opts) # Magic Modules generated resources use an alternate transport method # In the future this will be moved into the train-gcp plugin itself - @connection = GcpApiConnection.new if opts[:use_http_transport] + @connection = GcpApiConnection.new(self) if opts[:use_http_transport] end def failed_resource? @@ -194,7 +194,10 @@ def camel_case(data) end class GcpApiConnection - def initialize + attr_reader :resource + + def initialize(resource) + @resource = resource config_name = Inspec::Config.cached.unpack_train_credentials[:host] ENV['CLOUDSDK_ACTIVE_CONFIG_NAME'] = config_name @google_application_credentials = config_name.blank? && ENV['GOOGLE_APPLICATION_CREDENTIALS'] @@ -237,7 +240,7 @@ def next_page(uri, request_type, token = nil) fetch_auth, request_type, ) - result = JSON.parse(get_request.send.body) + result = return_if_object(get_request.send) next_page_token = result['nextPageToken'] return [result] if next_page_token.nil? @@ -245,19 +248,26 @@ def next_page(uri, request_type, token = nil) end def return_if_object(response) - raise "Bad response: #{response.body}" \ - if response.is_a?(Net::HTTPBadRequest) - raise "Bad response: #{response}" \ - unless response.is_a?(Net::HTTPResponse) - return if response.is_a?(Net::HTTPNotFound) - return if response.is_a?(Net::HTTPNoContent) - result = JSON.parse(response.body) - raise_if_errors result, %w{error errors}, 'message' - raise "Bad response: #{response}" unless response.is_a?(Net::HTTPOK) + unless response.is_a?(Net::HTTPSuccess) + if response.is_a?(Net::HTTPResponse) + body = response.body + else + body = response + end + result = parser(body) + raise_if_errors result, %w{error errors}, 'message' + end + result = parser(response.body) fetch_id result result end + def parser(json) + JSON.parse(json) + rescue JSON::ParserError + raise StandardError, "Bad response: #{json}" \ + end + def fetch_id(result) @resource_id = if result.key?('id') result['id'] @@ -269,6 +279,8 @@ def fetch_id(result) def raise_if_errors(response, err_path, msg_field) errors = self.class.navigate(response, err_path) + resource.fail_resource errors + resource.failed_resource = true raise_error(errors, msg_field) unless errors.nil? end