diff --git a/docs/resources/google_appengine_standard_app_version.md b/docs/resources/google_appengine_standard_app_version.md new file mode 100644 index 000000000..eb68a11c8 --- /dev/null +++ b/docs/resources/google_appengine_standard_app_version.md @@ -0,0 +1,34 @@ +--- +title: About the google_appengine_standard_app_version resource +platform: gcp +--- + +## Syntax +A `google_appengine_standard_app_version` is used to test a Google StandardAppVersion resource + +## Examples +``` + +describe google_appengine_standard_app_version(project: 'chef-gcp-inspec', location: 'europe-west2', version_id: 'v2', service: 'default') do + it { should exist } + its('version_id') { should eq 'v2' } + its('runtime') { should eq 'nodejs10' } +end +``` + +## Properties +Properties that can be accessed from the `google_appengine_standard_app_version` resource: + + * `name`: Full path to the Version resource in the API. Example, "v1". + + * `version_id`: Relative name of the version within the service. For example, `v1`. Version names can contain only lowercase letters, numbers, or hyphens. Reserved names,"default", "latest", and any name with the prefix "ah-". + + * `runtime`: Desired runtime. Example python27. + + * `threadsafe`: Whether multiple requests can be dispatched to this version at once. + + + +## GCP Permissions + +Ensure the [App Engine Admin API](https://console.cloud.google.com/apis/library/appengine.googleapis.com/) is enabled for the current project. diff --git a/docs/resources/google_appengine_standard_app_versions.md b/docs/resources/google_appengine_standard_app_versions.md new file mode 100644 index 000000000..407535f74 --- /dev/null +++ b/docs/resources/google_appengine_standard_app_versions.md @@ -0,0 +1,32 @@ +--- +title: About the google_appengine_standard_app_versions resource +platform: gcp +--- + +## Syntax +A `google_appengine_standard_app_versions` is used to test a Google StandardAppVersion resource + +## Examples +``` + +describe google_appengine_standard_app_versions(project: 'chef-gcp-inspec', location: 'europe-west2',service: 'default') do + its('runtimes') { should include 'nodejs10' } +end +``` + +## Properties +Properties that can be accessed from the `google_appengine_standard_app_versions` resource: + +See [google_appengine_standard_app_version.md](google_appengine_standard_app_version.md) for more detailed information + * `names`: an array of `google_appengine_standard_app_version` name + * `version_ids`: an array of `google_appengine_standard_app_version` version_id + * `runtimes`: an array of `google_appengine_standard_app_version` runtime + * `threadsaves`: an array of `google_appengine_standard_app_version` threadsafe + +## 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 [App Engine Admin API](https://console.cloud.google.com/apis/library/appengine.googleapis.com/) is enabled for the current project. diff --git a/libraries/google_appengine_standard_app_version.rb b/libraries/google_appengine_standard_app_version.rb new file mode 100644 index 000000000..a1cc14340 --- /dev/null +++ b/libraries/google_appengine_standard_app_version.rb @@ -0,0 +1,66 @@ +# 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 App Engine resources. +class StandardAppVersion < GcpResourceBase + name 'google_appengine_standard_app_version' + desc 'StandardAppVersion' + supports platform: 'gcp' + + attr_reader :params + attr_reader :name + attr_reader :version_id + attr_reader :runtime + attr_reader :threadsafe + + 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'] + @version_id = @fetched['id'] + @runtime = @fetched['runtime'] + @threadsafe = @fetched['threadsafe'] + 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 + "StandardAppVersion #{@params[:version_id]}" + end + + private + + def product_url + 'https://appengine.googleapis.com/v1/' + end + + def resource_base_url + 'apps/{{project}}/services/{{service}}/versions/{{version_id}}' + end +end diff --git a/libraries/google_appengine_standard_app_versions.rb b/libraries/google_appengine_standard_app_versions.rb new file mode 100644 index 000000000..9e595203c --- /dev/null +++ b/libraries/google_appengine_standard_app_versions.rb @@ -0,0 +1,90 @@ +# 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 StandardAppVersions < GcpResourceBase + name 'google_appengine_standard_app_versions' + desc 'StandardAppVersion plural resource' + supports platform: 'gcp' + + attr_reader :table + + filter_table_config = FilterTable.create + + filter_table_config.add(:names, field: :name) + filter_table_config.add(:version_ids, field: :version_id) + filter_table_config.add(:runtimes, field: :runtime) + filter_table_config.add(:threadsaves, field: :threadsafe) + + filter_table_config.connect(self, :table) + + def initialize(params = {}) + super(params.merge({ use_http_transport: true })) + @params = params + @table = fetch_wrapped_resource('versions') + 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'] }, + 'id' => ->(obj) { return :version_id, obj['id'] }, + 'runtime' => ->(obj) { return :runtime, obj['runtime'] }, + 'threadsafe' => ->(obj) { return :threadsafe, obj['threadsafe'] }, + } + 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://appengine.googleapis.com/v1/' + end + + def resource_base_url + 'apps/{{project}}/services/{{service}}/versions' + end +end diff --git a/test/integration/build/gcp-mm.tf b/test/integration/build/gcp-mm.tf index 86211476e..235f3c0c5 100644 --- a/test/integration/build/gcp-mm.tf +++ b/test/integration/build/gcp-mm.tf @@ -145,6 +145,10 @@ variable "org_sink" { type = "map" } +variable "standardappversion" { + type = "map" +} + resource "google_compute_ssl_policy" "custom-ssl-policy" { name = "${var.ssl_policy["name"]}" min_tls_version = "${var.ssl_policy["min_tls_version"]}" @@ -568,4 +572,35 @@ resource "google_logging_organization_sink" "my-sink" { # Log all WARN or higher severity messages relating to instances filter = "${var.org_sink.filter}" -} \ No newline at end of file +} + +resource "google_storage_bucket" "bucket" { + name = "appengine-static-content" +} + +resource "google_storage_bucket_object" "object" { + name = "hello-world.zip" + bucket = "${google_storage_bucket.bucket.name}" + source = "./test-fixtures/appengine/hello-world.zip" +} + +resource "google_app_engine_standard_app_version" "default" { + project = "${var.gcp_project_id}" + version_id = "${var.standardappversion["version_id"]}" + service = "${var.standardappversion["service"]}" + runtime = "${var.standardappversion["runtime"]}" + noop_on_destroy = true + entrypoint { + shell = "${var.standardappversion["entrypoint"]}" + } + + deployment { + zip { + source_url = "https://storage.googleapis.com/${google_storage_bucket.bucket.name}/hello-world.zip" + } + } + + env_variables = { + port = "${var.standardappversion["port"]}" + } +} diff --git a/test/integration/configuration/hello-world.zip b/test/integration/configuration/hello-world.zip new file mode 100644 index 000000000..34c746dd3 Binary files /dev/null and b/test/integration/configuration/hello-world.zip differ diff --git a/test/integration/configuration/mm-attributes.yml b/test/integration/configuration/mm-attributes.yml index e422a48d5..d5476c8ea 100644 --- a/test/integration/configuration/mm-attributes.yml +++ b/test/integration/configuration/mm-attributes.yml @@ -224,4 +224,12 @@ regional_node_pool: org_sink: name: inspec-gcp-org-sink - filter: resource.type = gce_instance \ No newline at end of file + filter: resource.type = gce_instance + +standardappversion: + version_id: v2 + service: default + runtime: nodejs10 + entrypoint: "node ./app.js" + port: "8080" + \ No newline at end of file diff --git a/test/integration/verify/controls/google_appengine_standard_app_version.rb b/test/integration/verify/controls/google_appengine_standard_app_version.rb new file mode 100644 index 000000000..48ec6a4f3 --- /dev/null +++ b/test/integration/verify/controls/google_appengine_standard_app_version.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_appengine_standard_app_version resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +gcp_location = attribute(:gcp_location, default: 'gcp_location', description: 'The GCP project location.') +standardappversion = attribute('standardappversion', default: { + "version_id": "v2", + "service": "default", + "runtime": "nodejs10", + "entrypoint": "node ./app.js", + "port": "8080" +}, description: 'Cloud App Engine definition') +control 'google_appengine_standard_app_version-1.0' do + impact 1.0 + title 'google_appengine_standard_app_version resource test' + + + describe google_appengine_standard_app_version(project: gcp_project_id, location: gcp_location, version_id: standardappversion['version_id'], service: standardappversion['service']) do + it { should exist } + its('version_id') { should eq standardappversion['version_id'] } + its('runtime') { should eq standardappversion['runtime'] } + end +end diff --git a/test/integration/verify/controls/google_appengine_standard_app_versions.rb b/test/integration/verify/controls/google_appengine_standard_app_versions.rb new file mode 100644 index 000000000..4bbb0e889 --- /dev/null +++ b/test/integration/verify/controls/google_appengine_standard_app_versions.rb @@ -0,0 +1,34 @@ +# ---------------------------------------------------------------------------- +# +# *** 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_appengine_standard_app_versions resource.' + +gcp_project_id = attribute(:gcp_project_id, default: 'gcp_project_id', description: 'The GCP project identifier.') +gcp_location = attribute(:gcp_location, default: 'gcp_location', description: 'The GCP project location.') +standardappversion = attribute('standardappversion', default: { + "version_id": "v2", + "service": "default", + "runtime": "nodejs10", + "entrypoint": "node ./app.js", + "port": "8080" +}, description: 'Cloud App Engine definition') +control 'google_appengine_standard_app_versions-1.0' do + impact 1.0 + title 'google_appengine_standard_app_versions resource test' + + + describe google_appengine_standard_app_versions(project: gcp_project_id, location: gcp_location,service: standardappversion['service']) do + its('runtimes') { should include standardappversion['runtime'] } + end +end