diff --git a/docs/resources/google_spanner_database.md b/docs/resources/google_spanner_database.md new file mode 100644 index 000000000..890bac2cf --- /dev/null +++ b/docs/resources/google_spanner_database.md @@ -0,0 +1,29 @@ +--- +title: About the google_spanner_database resource +platform: gcp +--- + +## Syntax +A `google_spanner_database` is used to test a Google Database resource + +## Examples +``` + +describe google_spanner_database(project: 'chef-gcp-inspec', instance: 'spinstance', name: 'spdatabase') do + it { should exist } + its('name') { should match 'spdatabase' } +end +``` + +## Properties +Properties that can be accessed from the `google_spanner_database` resource: + + + * `name`: A unique identifier for the database, which cannot be changed after the instance is created. Values are of the form [a-z][-a-z0-9]*[a-z0-9]. + + * `instance`: The instance to create the database on. + + +## GCP Permissions + +Ensure the [Cloud Spanner API](https://console.cloud.google.com/apis/library/spanner.googleapis.com/) is enabled for the current project. diff --git a/docs/resources/google_spanner_databases.md b/docs/resources/google_spanner_databases.md new file mode 100644 index 000000000..97996833c --- /dev/null +++ b/docs/resources/google_spanner_databases.md @@ -0,0 +1,34 @@ +--- +title: About the google_spanner_databases resource +platform: gcp +--- + +## Syntax +A `google_spanner_databases` is used to test a Google Database resource + +## Examples +``` + +describe.one do + google_spanner_databases(project: 'chef-gcp-inspec', instance: 'spinstance').names.each do |name| + describe name do + it { should match 'spdatabase' } + end + end +end +``` + +## Properties +Properties that can be accessed from the `google_spanner_databases` resource: + +See [google_spanner_database.md](google_spanner_database.md) for more detailed information + * `names`: an array of `google_spanner_database` name + * `instances`: an array of `google_spanner_database` instance + +## 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 [Cloud Spanner API](https://console.cloud.google.com/apis/library/spanner.googleapis.com/) is enabled for the current project. diff --git a/docs/resources/google_spanner_instance.md b/docs/resources/google_spanner_instance.md new file mode 100644 index 000000000..e627462fd --- /dev/null +++ b/docs/resources/google_spanner_instance.md @@ -0,0 +1,39 @@ +--- +title: About the google_spanner_instance resource +platform: gcp +--- + +## Syntax +A `google_spanner_instance` is used to test a Google Instance resource + +## Examples +``` + +describe google_spanner_instance(project: 'chef-gcp-inspec', name: 'spinstance', config: 'regional-us-east1') do + it { should exist } + its('config') { should match 'regional-us-east1' } + its('name') { should match 'spinstance' } + its('display_name') { should eq 'inspectest' } + its('node_count') { should eq '1' } + its('labels') { should include('env' => 'test') } +end +``` + +## Properties +Properties that can be accessed from the `google_spanner_instance` resource: + + + * `name`: A unique identifier for the instance, which cannot be changed after the instance is created. The name must be between 6 and 30 characters in length. + + * `config`: The name of the instance's configuration (similar but not quite the same as a region) which defines defines the geographic placement and replication of your databases in this instance. It determines where your data is stored. Values are typically of the form `regional-europe-west1` , `us-central` etc. In order to obtain a valid list please consult the [Configuration section of the docs](https://cloud.google.com/spanner/docs/instances). + + * `display_name`: The descriptive name for this instance as it appears in UIs. Must be unique per project and between 4 and 30 characters in length. + + * `node_count`: The number of nodes allocated to this instance. + + * `labels`: An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. + + +## GCP Permissions + +Ensure the [Cloud Spanner API](https://console.cloud.google.com/apis/library/spanner.googleapis.com/) is enabled for the current project. diff --git a/docs/resources/google_spanner_instances.md b/docs/resources/google_spanner_instances.md new file mode 100644 index 000000000..710d3ccfc --- /dev/null +++ b/docs/resources/google_spanner_instances.md @@ -0,0 +1,37 @@ +--- +title: About the google_spanner_instances resource +platform: gcp +--- + +## Syntax +A `google_spanner_instances` is used to test a Google Instance resource + +## Examples +``` + +describe.one do + google_spanner_instances(project: 'chef-gcp-inspec', config: 'regional-us-east1').configs.each do |config| + describe config do + it { should match 'regional-us-east1' } + end + end +end +``` + +## Properties +Properties that can be accessed from the `google_spanner_instances` resource: + +See [google_spanner_instance.md](google_spanner_instance.md) for more detailed information + * `names`: an array of `google_spanner_instance` name + * `configs`: an array of `google_spanner_instance` config + * `display_names`: an array of `google_spanner_instance` display_name + * `node_counts`: an array of `google_spanner_instance` node_count + * `labels`: an array of `google_spanner_instance` labels + +## 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 [Cloud Spanner API](https://console.cloud.google.com/apis/library/spanner.googleapis.com/) is enabled for the current project. diff --git a/libraries/google_spanner_database.rb b/libraries/google_spanner_database.rb new file mode 100644 index 000000000..1e91e8e79 --- /dev/null +++ b/libraries/google_spanner_database.rb @@ -0,0 +1,62 @@ +# 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' + +# A provider to manage Cloud Spanner resources. +class SpannerDatabase < GcpResourceBase + name 'google_spanner_database' + desc 'Database' + supports platform: 'gcp' + + attr_reader :params + attr_reader :name + attr_reader :instance + + def initialize(params) + super(params.merge({ use_http_transport: true })) + @params = params + @fetched = @connection.fetch(product_url, resource_base_url, params, 'Get') + parse unless @fetched.nil? + end + + def parse + @name = @fetched['name'] + @instance = @fetched['instance'] + 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 + "Database #{@params[:name]}" + end + + private + + def product_url + 'https://spanner.googleapis.com/v1/' + end + + def resource_base_url + 'projects/{{project}}/instances/{{instance}}/databases/{{name}}' + end +end diff --git a/libraries/google_spanner_databases.rb b/libraries/google_spanner_databases.rb new file mode 100644 index 000000000..dd6d01337 --- /dev/null +++ b/libraries/google_spanner_databases.rb @@ -0,0 +1,86 @@ +# 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 SpannerDatabases < GcpResourceBase + name 'google_spanner_databases' + desc 'Database plural resource' + supports platform: 'gcp' + + attr_reader :table + + filter_table_config = FilterTable.create + + filter_table_config.add(:names, field: :name) + filter_table_config.add(:instances, field: :instance) + + filter_table_config.connect(self, :table) + + def initialize(params = {}) + super(params.merge({ use_http_transport: true })) + @params = params + @table = fetch_wrapped_resource('databases') + 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 + end + + converted + end + + def transform(key, value) + return transformers[key].call(value) if transformers.key?(key) + + [key.to_sym, value] + end + + def transformers + { + 'name' => ->(obj) { return :name, obj['name'] }, + 'instance' => ->(obj) { return :instance, obj['instance'] }, + } + end + + # Handles parsing RFC3339 time string + def parse_time_string(time_string) + time_string ? Time.parse(time_string) : nil + end + + private + + def product_url + 'https://spanner.googleapis.com/v1/' + end + + def resource_base_url + 'projects/{{project}}/instances/{{instance}}/databases' + end +end diff --git a/libraries/google_spanner_instance.rb b/libraries/google_spanner_instance.rb new file mode 100644 index 000000000..7066a3620 --- /dev/null +++ b/libraries/google_spanner_instance.rb @@ -0,0 +1,68 @@ +# 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' + +# A provider to manage Cloud Spanner resources. +class SpannerInstance < GcpResourceBase + name 'google_spanner_instance' + desc 'Instance' + supports platform: 'gcp' + + attr_reader :params + attr_reader :name + attr_reader :config + attr_reader :display_name + attr_reader :node_count + attr_reader :labels + + def initialize(params) + super(params.merge({ use_http_transport: true })) + @params = params + @fetched = @connection.fetch(product_url, resource_base_url, params, 'Get') + parse unless @fetched.nil? + end + + def parse + @name = @fetched['name'] + @config = @fetched['config'] + @display_name = @fetched['displayName'] + @node_count = @fetched['nodeCount'] + @labels = @fetched['labels'] + 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 + "Instance #{@params[:name]}" + end + + private + + def product_url + 'https://spanner.googleapis.com/v1/' + end + + def resource_base_url + 'projects/{{project}}/instances/{{name}}' + end +end diff --git a/libraries/google_spanner_instances.rb b/libraries/google_spanner_instances.rb new file mode 100644 index 000000000..11036bfdf --- /dev/null +++ b/libraries/google_spanner_instances.rb @@ -0,0 +1,92 @@ +# 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 SpannerInstances < GcpResourceBase + name 'google_spanner_instances' + desc 'Instance plural resource' + supports platform: 'gcp' + + attr_reader :table + + filter_table_config = FilterTable.create + + filter_table_config.add(:names, field: :name) + filter_table_config.add(:configs, field: :config) + filter_table_config.add(:display_names, field: :display_name) + filter_table_config.add(:node_counts, field: :node_count) + filter_table_config.add(:labels, field: :labels) + + filter_table_config.connect(self, :table) + + def initialize(params = {}) + super(params.merge({ use_http_transport: true })) + @params = params + @table = fetch_wrapped_resource('instances') + 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 + end + + converted + end + + def transform(key, value) + return transformers[key].call(value) if transformers.key?(key) + + [key.to_sym, value] + end + + def transformers + { + 'name' => ->(obj) { return :name, obj['name'] }, + 'config' => ->(obj) { return :config, obj['config'] }, + 'displayName' => ->(obj) { return :display_name, obj['displayName'] }, + 'nodeCount' => ->(obj) { return :node_count, obj['nodeCount'] }, + 'labels' => ->(obj) { return :labels, obj['labels'] }, + } + end + + # Handles parsing RFC3339 time string + def parse_time_string(time_string) + time_string ? Time.parse(time_string) : nil + end + + private + + def product_url + 'https://spanner.googleapis.com/v1/' + end + + def resource_base_url + 'projects/{{project}}/instances' + end +end diff --git a/test/integration/build/gcp-mm.tf b/test/integration/build/gcp-mm.tf index be9ec4c48..21678b63f 100644 --- a/test/integration/build/gcp-mm.tf +++ b/test/integration/build/gcp-mm.tf @@ -201,6 +201,15 @@ variable "service" { type = "map" } +variable "spannerinstance" { + type = "map" +} + +variable "spannerdatabase" { + type = "map" +} + + resource "google_compute_ssl_policy" "custom-ssl-policy" { name = "${var.ssl_policy["name"]}" min_tls_version = "${var.ssl_policy["min_tls_version"]}" @@ -865,4 +874,22 @@ resource "google_compute_router_nat" "inspec-nat" { resource "google_project_service" "project" { project = var.gcp_project_id service = var.service["name"] -} \ No newline at end of file +} + +resource "google_spanner_instance" "spanner_instance" { + project = "${var.gcp_project_id}" + config = "${var.spannerinstance["config"]}" + name = "${var.spannerinstance["name"]}" + display_name = "${var.spannerinstance["display_name"]}" + num_nodes = "${var.spannerinstance["num_nodes"]}" + labels = { + "${var.spannerinstance["label_key"]}" = "${var.spannerinstance["label_value"]}" + } +} + +resource "google_spanner_database" "database" { + project = "${var.gcp_project_id}" + instance = "${google_spanner_instance.spanner_instance.name}" + name = "${var.spannerdatabase["name"]}" + ddl = ["${var.spannerdatabase["ddl"]}"] +} diff --git a/test/integration/configuration/mm-attributes.yml b/test/integration/configuration/mm-attributes.yml index d5bd4937f..f4ed2a05b 100644 --- a/test/integration/configuration/mm-attributes.yml +++ b/test/integration/configuration/mm-attributes.yml @@ -328,4 +328,17 @@ router_nat: log_config_filter: ERRORS_ONLY service: - name: maps-android-backend.googleapis.com \ No newline at end of file + name: maps-android-backend.googleapis.com + +spannerinstance: + config: regional-us-east1 + name: spinstance + display_name: inspectest + num_nodes: 1 + label_key: env + label_value: test + +spannerdatabase: + name: spdatabase + instance: spinstance + ddl: "CREATE TABLE test (test STRING(MAX),) PRIMARY KEY (test)" diff --git a/test/integration/verify/controls/google_spanner_database.rb b/test/integration/verify/controls/google_spanner_database.rb new file mode 100644 index 000000000..d008bd47d --- /dev/null +++ b/test/integration/verify/controls/google_spanner_database.rb @@ -0,0 +1,33 @@ +# ---------------------------------------------------------------------------- +# +# *** 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. +# +# ---------------------------------------------------------------------------- + +title 'Test GCP google_spanner_database resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +spannerdatabase = attribute('spannerdatabase', default: { + "name": "spdatabase", + "instance": "spinstance", + "ddl": "CREATE TABLE test (test STRING(MAX),) PRIMARY KEY (test)" +}, description: 'Cloud Spanner definition') + +control 'google_spanner_database-1.0' do + impact 1.0 + title 'google_spanner_database resource test' + + + describe google_spanner_database(project: gcp_project_id, instance: spannerdatabase['instance'], name: spannerdatabase['name']) do + it { should exist } + its('name') { should match spannerdatabase['name'] } + end +end diff --git a/test/integration/verify/controls/google_spanner_databases.rb b/test/integration/verify/controls/google_spanner_databases.rb new file mode 100644 index 000000000..b63780f64 --- /dev/null +++ b/test/integration/verify/controls/google_spanner_databases.rb @@ -0,0 +1,36 @@ +# ---------------------------------------------------------------------------- +# +# *** 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. +# +# ---------------------------------------------------------------------------- + +title 'Test GCP google_spanner_databases resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +spannerdatabase = attribute('spannerdatabase', default: { + "name": "spdatabase", + "instance": "spinstance", + "ddl": "CREATE TABLE test (test STRING(MAX),) PRIMARY KEY (test)" +}, description: 'Cloud Spanner definition') + +control 'google_spanner_databases-1.0' do + impact 1.0 + title 'google_spanner_databases resource test' + + + describe.one do + google_spanner_databases(project: gcp_project_id, instance: spannerdatabase['instance']).names.each do |name| + describe name do + it { should match spannerdatabase['name'] } + end + end + end +end diff --git a/test/integration/verify/controls/google_spanner_instance.rb b/test/integration/verify/controls/google_spanner_instance.rb new file mode 100644 index 000000000..b9d68a1ec --- /dev/null +++ b/test/integration/verify/controls/google_spanner_instance.rb @@ -0,0 +1,40 @@ +# ---------------------------------------------------------------------------- +# +# *** 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. +# +# ---------------------------------------------------------------------------- + +title 'Test GCP google_spanner_instance resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +spannerinstance = attribute('spannerinstance', default: { + "config": "regional-us-east1", + "name": "spinstance", + "display_name": "inspectest", + "num_nodes": 1, + "label_key": "env", + "label_value": "test" +}, description: 'Cloud Spanner definition') + +control 'google_spanner_instance-1.0' do + impact 1.0 + title 'google_spanner_instance resource test' + + + describe google_spanner_instance(project: gcp_project_id, name: spannerinstance['name'], config: spannerinstance['config']) do + it { should exist } + its('config') { should match spannerinstance['config'] } + its('name') { should match spannerinstance['name'] } + its('display_name') { should eq spannerinstance['display_name'] } + its('node_count') { should eq spannerinstance['num_nodes'] } + its('labels') { should include(spannerinstance['label_key'] => spannerinstance['label_value']) } + end +end diff --git a/test/integration/verify/controls/google_spanner_instances.rb b/test/integration/verify/controls/google_spanner_instances.rb new file mode 100644 index 000000000..b1ba52c2a --- /dev/null +++ b/test/integration/verify/controls/google_spanner_instances.rb @@ -0,0 +1,39 @@ +# ---------------------------------------------------------------------------- +# +# *** 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. +# +# ---------------------------------------------------------------------------- + +title 'Test GCP google_spanner_instances resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +spannerinstance = attribute('spannerinstance', default: { + "config": "regional-us-east1", + "name": "spinstance", + "display_name": "inspectest", + "num_nodes": 1, + "label_key": "env", + "label_value": "test" +}, description: 'Cloud Spanner definition') + +control 'google_spanner_instances-1.0' do + impact 1.0 + title 'google_spanner_instances resource test' + + + describe.one do + google_spanner_instances(project: gcp_project_id, config: spannerinstance['config']).configs.each do |config| + describe config do + it { should match spannerinstance['config'] } + end + end + end +end