From e85a587ec0992215eb9c8f044698f5ffdd23441d Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Mon, 13 Apr 2020 08:35:51 -0700 Subject: [PATCH 1/3] Catch up to mm master, bucket labels Signed-off-by: Sam Levenick --- ...ccess_context_manager_service_perimeter.md | 16 +++++++ ...cess_context_manager_service_perimeters.md | 2 + docs/resources/google_compute_health_check.md | 4 ++ .../resources/google_compute_health_checks.md | 1 + .../google_compute_network_endpoint_group.md | 2 +- docs/resources/google_storage_bucket.md | 6 +++ docs/resources/google_storage_buckets.md | 1 + .../property/serviceperimeter_spec.rb | 44 +++++++++++++++++++ ...eperimeter_spec_vpc_accessible_services.rb | 37 ++++++++++++++++ .../property/healthcheck_log_config.rb | 34 ++++++++++++++ ...ccess_context_manager_service_perimeter.rb | 6 +++ ...cess_context_manager_service_perimeters.rb | 4 ++ libraries/google_compute_health_check.rb | 3 ++ libraries/google_compute_health_checks.rb | 2 + libraries/google_storage_bucket.rb | 5 +++ libraries/google_storage_buckets.rb | 2 + test/integration/build/gcp-mm.tf | 4 ++ .../verify/controls/google_storage_bucket.rb | 1 + 18 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 libraries/google/accesscontextmanager/property/serviceperimeter_spec.rb create mode 100644 libraries/google/accesscontextmanager/property/serviceperimeter_spec_vpc_accessible_services.rb create mode 100644 libraries/google/compute/property/healthcheck_log_config.rb diff --git a/docs/resources/google_access_context_manager_service_perimeter.md b/docs/resources/google_access_context_manager_service_perimeter.md index dd8496103..9ebb7434d 100644 --- a/docs/resources/google_access_context_manager_service_perimeter.md +++ b/docs/resources/google_access_context_manager_service_perimeter.md @@ -48,6 +48,22 @@ Properties that can be accessed from the `google_access_context_manager_service_ * `allowed_services`: The list of APIs usable within the Service Perimeter. Must be empty unless `enableRestriction` is True. + * `spec`: Proposed (or dry run) ServicePerimeter configuration. This configuration allows to specify and test ServicePerimeter configuration without enforcing actual access restrictions. Only allowed to be set when the `useExplicitDryRunSpec` flag is set. + + * `resources`: A list of GCP resources that are inside of the service perimeter. Currently only projects are allowed. Format: projects/{project_number} + + * `access_levels`: A list of AccessLevel resource names that allow resources within the ServicePerimeter to be accessed from the internet. AccessLevels listed must be in the same policy as this ServicePerimeter. Referencing a nonexistent AccessLevel is a syntax error. If no AccessLevel names are listed, resources within the perimeter can only be accessed via GCP calls with request origins within the perimeter. For Service Perimeter Bridge, must be empty. Format: accessPolicies/{policy_id}/accessLevels/{access_level_name} + + * `restricted_services`: GCP services that are subject to the Service Perimeter restrictions. Must contain a list of services. For example, if `storage.googleapis.com` is specified, access to the storage buckets inside the perimeter must meet the perimeter's access restrictions. + + * `vpc_accessible_services`: Specifies how APIs are allowed to communicate within the Service Perimeter. + + * `enable_restriction`: Whether to restrict API calls within the Service Perimeter to the list of APIs specified in 'allowedServices'. + + * `allowed_services`: The list of APIs usable within the Service Perimeter. Must be empty unless `enableRestriction` is True. + + * `use_explicit_dry_run_spec`: Use explicit dry run spec flag. Ordinarily, a dry-run spec implicitly exists for all Service Perimeters, and that spec is identical to the status for those Service Perimeters. When this flag is set, it inhibits the generation of the implicit spec, thereby allowing the user to explicitly provide a configuration ("spec") to use in a dry-run version of the Service Perimeter. This allows the user to test changes to the enforced config ("status") without actually enforcing them. This testing is done through analyzing the differences between currently enforced and suggested restrictions. useExplicitDryRunSpec must bet set to True if any of the fields in the spec are set to non-default values. + * `parent`: The AccessPolicy this ServicePerimeter lives in. Format: accessPolicies/{policy_id} * `name`: Resource name for the ServicePerimeter. The short_name component must begin with a letter and only include alphanumeric and '_'. Format: accessPolicies/{policy_id}/servicePerimeters/{short_name} diff --git a/docs/resources/google_access_context_manager_service_perimeters.md b/docs/resources/google_access_context_manager_service_perimeters.md index 2732e5756..8b6431186 100644 --- a/docs/resources/google_access_context_manager_service_perimeters.md +++ b/docs/resources/google_access_context_manager_service_perimeters.md @@ -29,6 +29,8 @@ See [google_access_context_manager_service_perimeter.md](google_access_context_m * `update_times`: an array of `google_access_context_manager_service_perimeter` update_time * `perimeter_types`: an array of `google_access_context_manager_service_perimeter` perimeter_type * `statuses`: an array of `google_access_context_manager_service_perimeter` status + * `specs`: an array of `google_access_context_manager_service_perimeter` spec + * `use_explicit_dry_run_specs`: an array of `google_access_context_manager_service_perimeter` use_explicit_dry_run_spec * `parents`: an array of `google_access_context_manager_service_perimeter` parent * `names`: an array of `google_access_context_manager_service_perimeter` name diff --git a/docs/resources/google_compute_health_check.md b/docs/resources/google_compute_health_check.md index 7a1d6071e..64b2ba8e2 100644 --- a/docs/resources/google_compute_health_check.md +++ b/docs/resources/google_compute_health_check.md @@ -121,6 +121,10 @@ Properties that can be accessed from the `google_compute_health_check` resource: * `port_specification`: Specifies how port is selected for health checking, can be one of the following values: * `USE_FIXED_PORT`: The port number in `port` is used for health checking. * `USE_NAMED_PORT`: The `portName` is used for health checking. * `USE_SERVING_PORT`: For NetworkEndpointGroup, the port specified for each network endpoint is used for health checking. For other backends, the port or named port specified in the Backend Service is used for health checking. If not specified, HTTP2 health check follows behavior specified in `port` and `portName` fields. + * `log_config`: (Beta only) Configure logging on this health check. + + * `enable`: Indicates whether or not to export logs. This is false by default, which means no health check logging will be done. + ## GCP Permissions diff --git a/docs/resources/google_compute_health_checks.md b/docs/resources/google_compute_health_checks.md index f37775753..5457723a8 100644 --- a/docs/resources/google_compute_health_checks.md +++ b/docs/resources/google_compute_health_checks.md @@ -36,6 +36,7 @@ See [google_compute_health_check.md](google_compute_health_check.md) for more de * `tcp_health_checks`: an array of `google_compute_health_check` tcp_health_check * `ssl_health_checks`: an array of `google_compute_health_check` ssl_health_check * `http2_health_checks`: an array of `google_compute_health_check` http2_health_check + * `log_configs`: (Beta only) an array of `google_compute_health_check` log_config ## Filter Criteria This resource supports all of the above properties as filter criteria, which can be used diff --git a/docs/resources/google_compute_network_endpoint_group.md b/docs/resources/google_compute_network_endpoint_group.md index 0a030d0cb..7c809ab99 100644 --- a/docs/resources/google_compute_network_endpoint_group.md +++ b/docs/resources/google_compute_network_endpoint_group.md @@ -33,7 +33,7 @@ Properties that can be accessed from the `google_compute_network_endpoint_group` * `description`: An optional description of this resource. Provide this property when you create the resource. - * `network_endpoint_type`: Type of network endpoints in this network endpoint group. Currently the only supported value is GCE_VM_IP_PORT. + * `network_endpoint_type`: Type of network endpoints in this network endpoint group. The only supported value is GCE_VM_IP_PORT * `size`: Number of network endpoints in the network endpoint group. diff --git a/docs/resources/google_storage_bucket.md b/docs/resources/google_storage_bucket.md index 88bd586fb..e8203d1ef 100644 --- a/docs/resources/google_storage_bucket.md +++ b/docs/resources/google_storage_bucket.md @@ -13,6 +13,10 @@ describe google_storage_bucket(name: bucket-name) do its('location') { should cmp 'europe-west2'.upcase } its('storage_class') { should eq "STANDARD" } +<<<<<<< HEAD + its('labels') { should include("key" => "value") } +======= +>>>>>>> gcp/master end describe google_storage_bucket(name: "nonexistent") do @@ -166,6 +170,8 @@ Properties that can be accessed from the `google_storage_bucket` resource: * `predefined_default_object_acl`: Apply a predefined set of default object access controls to this bucket. Acceptable values are: - "authenticatedRead": Object owner gets OWNER access, and allAuthenticatedUsers get READER access. - "bucketOwnerFullControl": Object owner gets OWNER access, and project team owners get OWNER access. - "bucketOwnerRead": Object owner gets OWNER access, and project team owners get READER access. - "private": Object owner gets OWNER access. - "projectPrivate": Object owner gets OWNER access, and project team members get access according to their roles. - "publicRead": Object owner gets OWNER access, and allUsers get READER access. + * `labels`: Labels applied to this bucket. A list of key->value pairs. + ## GCP Permissions diff --git a/docs/resources/google_storage_buckets.md b/docs/resources/google_storage_buckets.md index c805dbe20..bfbc1a1c0 100644 --- a/docs/resources/google_storage_buckets.md +++ b/docs/resources/google_storage_buckets.md @@ -58,6 +58,7 @@ See [google_storage_bucket.md](google_storage_bucket.md) for more detailed infor * `websites`: an array of `google_storage_bucket` website * `projects`: an array of `google_storage_bucket` project * `predefined_default_object_acls`: an array of `google_storage_bucket` predefined_default_object_acl + * `labels`: an array of `google_storage_bucket` labels ## Filter Criteria This resource supports all of the above properties as filter criteria, which can be used diff --git a/libraries/google/accesscontextmanager/property/serviceperimeter_spec.rb b/libraries/google/accesscontextmanager/property/serviceperimeter_spec.rb new file mode 100644 index 000000000..551f51978 --- /dev/null +++ b/libraries/google/accesscontextmanager/property/serviceperimeter_spec.rb @@ -0,0 +1,44 @@ +# 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 'google/accesscontextmanager/property/serviceperimeter_spec_vpc_accessible_services' +module GoogleInSpec + module AccessContextManager + module Property + class ServicePerimeterSpec + attr_reader :resources + + attr_reader :access_levels + + attr_reader :restricted_services + + attr_reader :vpc_accessible_services + + def initialize(args = nil, parent_identifier = nil) + return if args.nil? + @parent_identifier = parent_identifier + @resources = args['resources'] + @access_levels = args['accessLevels'] + @restricted_services = args['restrictedServices'] + @vpc_accessible_services = GoogleInSpec::AccessContextManager::Property::ServicePerimeterSpecVPCAccessibleServices.new(args['vpcAccessibleServices'], to_s) + end + + def to_s + "#{@parent_identifier} ServicePerimeterSpec" + end + end + end + end +end diff --git a/libraries/google/accesscontextmanager/property/serviceperimeter_spec_vpc_accessible_services.rb b/libraries/google/accesscontextmanager/property/serviceperimeter_spec_vpc_accessible_services.rb new file mode 100644 index 000000000..bf3d4d73b --- /dev/null +++ b/libraries/google/accesscontextmanager/property/serviceperimeter_spec_vpc_accessible_services.rb @@ -0,0 +1,37 @@ +# 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 AccessContextManager + module Property + class ServicePerimeterSpecVPCAccessibleServices + attr_reader :enable_restriction + + attr_reader :allowed_services + + def initialize(args = nil, parent_identifier = nil) + return if args.nil? + @parent_identifier = parent_identifier + @enable_restriction = args['enableRestriction'] + @allowed_services = args['allowedServices'] + end + + def to_s + "#{@parent_identifier} ServicePerimeterSpecVPCAccessibleServices" + end + end + end + end +end diff --git a/libraries/google/compute/property/healthcheck_log_config.rb b/libraries/google/compute/property/healthcheck_log_config.rb new file mode 100644 index 000000000..4b71157d8 --- /dev/null +++ b/libraries/google/compute/property/healthcheck_log_config.rb @@ -0,0 +1,34 @@ +# 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 HealthCheckLogConfig + attr_reader :enable + + def initialize(args = nil, parent_identifier = nil) + return if args.nil? + @parent_identifier = parent_identifier + @enable = args['enable'] + end + + def to_s + "#{@parent_identifier} HealthCheckLogConfig" + end + end + end + end +end diff --git a/libraries/google_access_context_manager_service_perimeter.rb b/libraries/google_access_context_manager_service_perimeter.rb index 5b5d8b43c..e938f784d 100644 --- a/libraries/google_access_context_manager_service_perimeter.rb +++ b/libraries/google_access_context_manager_service_perimeter.rb @@ -14,6 +14,8 @@ # # ---------------------------------------------------------------------------- require 'gcp_backend' +require 'google/accesscontextmanager/property/serviceperimeter_spec' +require 'google/accesscontextmanager/property/serviceperimeter_spec_vpc_accessible_services' require 'google/accesscontextmanager/property/serviceperimeter_status' require 'google/accesscontextmanager/property/serviceperimeter_status_vpc_accessible_services' @@ -30,6 +32,8 @@ class AccessContextManagerServicePerimeter < GcpResourceBase attr_reader :update_time attr_reader :perimeter_type attr_reader :status + attr_reader :spec + attr_reader :use_explicit_dry_run_spec attr_reader :parent attr_reader :name @@ -47,6 +51,8 @@ def parse @update_time = parse_time_string(@fetched['updateTime']) @perimeter_type = @fetched['perimeterType'] @status = GoogleInSpec::AccessContextManager::Property::ServicePerimeterStatus.new(@fetched['status'], to_s) + @spec = GoogleInSpec::AccessContextManager::Property::ServicePerimeterSpec.new(@fetched['spec'], to_s) + @use_explicit_dry_run_spec = @fetched['useExplicitDryRunSpec'] @parent = @fetched['parent'] @name = name_from_self_link(@fetched['name']) end diff --git a/libraries/google_access_context_manager_service_perimeters.rb b/libraries/google_access_context_manager_service_perimeters.rb index d1d846e15..6f6025eed 100644 --- a/libraries/google_access_context_manager_service_perimeters.rb +++ b/libraries/google_access_context_manager_service_perimeters.rb @@ -29,6 +29,8 @@ class AccessContextManagerServicePerimeters < GcpResourceBase filter_table_config.add(:update_times, field: :update_time) filter_table_config.add(:perimeter_types, field: :perimeter_type) filter_table_config.add(:statuses, field: :status) + filter_table_config.add(:specs, field: :spec) + filter_table_config.add(:use_explicit_dry_run_specs, field: :use_explicit_dry_run_spec) filter_table_config.add(:parents, field: :parent) filter_table_config.add(:names, field: :name) @@ -76,6 +78,8 @@ def transformers 'updateTime' => ->(obj) { return :update_time, parse_time_string(obj['updateTime']) }, 'perimeterType' => ->(obj) { return :perimeter_type, obj['perimeterType'] }, 'status' => ->(obj) { return :status, GoogleInSpec::AccessContextManager::Property::ServicePerimeterStatus.new(obj['status'], to_s) }, + 'spec' => ->(obj) { return :spec, GoogleInSpec::AccessContextManager::Property::ServicePerimeterSpec.new(obj['spec'], to_s) }, + 'useExplicitDryRunSpec' => ->(obj) { return :use_explicit_dry_run_spec, obj['useExplicitDryRunSpec'] }, 'parent' => ->(obj) { return :parent, obj['parent'] }, 'name' => ->(obj) { return :name, name_from_self_link(obj['name']) }, } diff --git a/libraries/google_compute_health_check.rb b/libraries/google_compute_health_check.rb index 90943cc3f..ff72c00e4 100644 --- a/libraries/google_compute_health_check.rb +++ b/libraries/google_compute_health_check.rb @@ -17,6 +17,7 @@ require 'google/compute/property/healthcheck_http2_health_check' require 'google/compute/property/healthcheck_http_health_check' require 'google/compute/property/healthcheck_https_health_check' +require 'google/compute/property/healthcheck_log_config' require 'google/compute/property/healthcheck_ssl_health_check' require 'google/compute/property/healthcheck_tcp_health_check' @@ -41,6 +42,7 @@ class ComputeHealthCheck < GcpResourceBase attr_reader :tcp_health_check attr_reader :ssl_health_check attr_reader :http2_health_check + attr_reader :log_config def initialize(params) super(params.merge({ use_http_transport: true })) @@ -64,6 +66,7 @@ def parse @tcp_health_check = GoogleInSpec::Compute::Property::HealthCheckTcpHealthCheck.new(@fetched['tcpHealthCheck'], to_s) @ssl_health_check = GoogleInSpec::Compute::Property::HealthCheckSslHealthCheck.new(@fetched['sslHealthCheck'], to_s) @http2_health_check = GoogleInSpec::Compute::Property::HealthCheckHttp2HealthCheck.new(@fetched['http2HealthCheck'], to_s) + @log_config = GoogleInSpec::Compute::Property::HealthCheckLogConfig.new(@fetched['logConfig'], to_s) end # Handles parsing RFC3339 time string diff --git a/libraries/google_compute_health_checks.rb b/libraries/google_compute_health_checks.rb index f98609a17..62c814d6b 100644 --- a/libraries/google_compute_health_checks.rb +++ b/libraries/google_compute_health_checks.rb @@ -37,6 +37,7 @@ class ComputeHealthChecks < GcpResourceBase filter_table_config.add(:tcp_health_checks, field: :tcp_health_check) filter_table_config.add(:ssl_health_checks, field: :ssl_health_check) filter_table_config.add(:http2_health_checks, field: :http2_health_check) + filter_table_config.add(:log_configs, field: :log_config) filter_table_config.connect(self, :table) @@ -90,6 +91,7 @@ def transformers 'tcpHealthCheck' => ->(obj) { return :tcp_health_check, GoogleInSpec::Compute::Property::HealthCheckTcpHealthCheck.new(obj['tcpHealthCheck'], to_s) }, 'sslHealthCheck' => ->(obj) { return :ssl_health_check, GoogleInSpec::Compute::Property::HealthCheckSslHealthCheck.new(obj['sslHealthCheck'], to_s) }, 'http2HealthCheck' => ->(obj) { return :http2_health_check, GoogleInSpec::Compute::Property::HealthCheckHttp2HealthCheck.new(obj['http2HealthCheck'], to_s) }, + 'logConfig' => ->(obj) { return :log_config, GoogleInSpec::Compute::Property::HealthCheckLogConfig.new(obj['logConfig'], to_s) }, } end diff --git a/libraries/google_storage_bucket.rb b/libraries/google_storage_bucket.rb index ffe317324..91cef6c4a 100644 --- a/libraries/google_storage_bucket.rb +++ b/libraries/google_storage_bucket.rb @@ -50,6 +50,10 @@ class StorageBucket < GcpResourceBase attr_reader :website attr_reader :project attr_reader :predefined_default_object_acl +<<<<<<< HEAD + attr_reader :labels +======= +>>>>>>> gcp/master def initialize(params) super(params.merge({ use_http_transport: true })) @@ -78,6 +82,7 @@ def parse @website = GoogleInSpec::Storage::Property::BucketWebsite.new(@fetched['website'], to_s) @project = @fetched['project'] @predefined_default_object_acl = @fetched['predefinedDefaultObjectAcl'] + @labels = @fetched['labels'] end # Handles parsing RFC3339 time string diff --git a/libraries/google_storage_buckets.rb b/libraries/google_storage_buckets.rb index 0291d984b..1493d5774 100644 --- a/libraries/google_storage_buckets.rb +++ b/libraries/google_storage_buckets.rb @@ -42,6 +42,7 @@ class StorageBuckets < GcpResourceBase filter_table_config.add(:websites, field: :website) filter_table_config.add(:projects, field: :project) filter_table_config.add(:predefined_default_object_acls, field: :predefined_default_object_acl) + filter_table_config.add(:labels, field: :labels) filter_table_config.connect(self, :table) @@ -100,6 +101,7 @@ def transformers 'website' => ->(obj) { return :website, GoogleInSpec::Storage::Property::BucketWebsite.new(obj['website'], to_s) }, 'project' => ->(obj) { return :project, obj['project'] }, 'predefinedDefaultObjectAcl' => ->(obj) { return :predefined_default_object_acl, obj['predefinedDefaultObjectAcl'] }, + 'labels' => ->(obj) { return :labels, obj['labels'] }, } end diff --git a/test/integration/build/gcp-mm.tf b/test/integration/build/gcp-mm.tf index 887e9395f..3e77c33cb 100644 --- a/test/integration/build/gcp-mm.tf +++ b/test/integration/build/gcp-mm.tf @@ -652,6 +652,10 @@ resource "google_storage_bucket" "bucket" { project = var.gcp_project_id location = var.gcp_location force_destroy = true + + labels = { + "key" = "value" + } } resource "google_storage_bucket_object" "object" { diff --git a/test/integration/verify/controls/google_storage_bucket.rb b/test/integration/verify/controls/google_storage_bucket.rb index 361a8bb85..8db5ee895 100644 --- a/test/integration/verify/controls/google_storage_bucket.rb +++ b/test/integration/verify/controls/google_storage_bucket.rb @@ -25,6 +25,7 @@ its('location') { should cmp gcp_location.upcase } its('storage_class') { should eq "STANDARD" } + its('labels') { should include("key" => "value") } end describe google_storage_bucket(name: "nonexistent") do From 3d7bdf9cfc8fad4469ac9fe035e7a2019f17cec8 Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Mon, 13 Apr 2020 09:20:56 -0700 Subject: [PATCH 2/3] Merge issue Signed-off-by: Sam Levenick --- libraries/google_storage_bucket.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/google_storage_bucket.rb b/libraries/google_storage_bucket.rb index 91cef6c4a..8ac0fcc37 100644 --- a/libraries/google_storage_bucket.rb +++ b/libraries/google_storage_bucket.rb @@ -50,10 +50,7 @@ class StorageBucket < GcpResourceBase attr_reader :website attr_reader :project attr_reader :predefined_default_object_acl -<<<<<<< HEAD attr_reader :labels -======= ->>>>>>> gcp/master def initialize(params) super(params.merge({ use_http_transport: true })) From 577e61fb2e846b39b8924a9624ea15717760b795 Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 13 Apr 2020 13:17:44 -0700 Subject: [PATCH 3/3] add new project for app engine flex tests (#3348) (#380) * add new project for app engine flex tests * remove delete_service_on_destroy * do not delete the 'default' service * add noop_on_destroy to tests * ignore noop_on_destroy in tests Signed-off-by: Modular Magician --- docs/resources/google_storage_bucket.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/resources/google_storage_bucket.md b/docs/resources/google_storage_bucket.md index e8203d1ef..f021d3388 100644 --- a/docs/resources/google_storage_bucket.md +++ b/docs/resources/google_storage_bucket.md @@ -13,10 +13,7 @@ describe google_storage_bucket(name: bucket-name) do its('location') { should cmp 'europe-west2'.upcase } its('storage_class') { should eq "STANDARD" } -<<<<<<< HEAD its('labels') { should include("key" => "value") } -======= ->>>>>>> gcp/master end describe google_storage_bucket(name: "nonexistent") do