Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new resource "WasmPlugin" #12275

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions mmv1/products/networkservicesplugins/WasmPlugin.yaml

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that all tests defines the single version configuration. Could you please extend at least one of them to define at least 2 versions? The perfect would updating "update" test to modify WasmPlugin from having v1(main)+v2 versions into v2(main)+v3?

Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Copyright 2024 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
name: 'WasmPlugin'
description: |
WasmPlugin is a resource representing a service executing a customer-provided Wasm module.
min_version: 'beta'
references:
guides:
'Configure a route extension': 'https://cloud.google.com/service-extensions/docs/create-plugin'
api: 'https://cloud.google.com/service-extensions/docs/reference/rest/v1beta1/projects.locations.wasmPlugins'
docs:
base_url: 'projects/{{project}}/locations/{{location}}/wasmPlugins'
self_link: 'projects/{{project}}/locations/{{location}}/wasmPlugins/{{name}}'
create_url: 'projects/{{project}}/locations/{{location}}/wasmPlugins?wasmPluginId={{name}}'
create_verb: 'POST'
update_verb: 'PATCH'
update_mask: true
read_query_params: '?view=WASM_PLUGIN_VIEW_FULL'
timeouts:
insert_minutes: 20
update_minutes: 20
delete_minutes: 20
autogen_async: true
async:
actions: ['create', 'delete', 'update']
type: 'OpAsync'
operation:
base_url: '{{op_id}}'
result:
resource_inside_response: false
custom_code:
examples:
- name: 'wasm_plugin_basic'
primary_resource_id: 'wasm_plugin'
min_version: 'beta'
vars:
wasm_plugin_name: 'my-wasm-plugin'
skip_vcr: true
parameters:
- name: 'location'
type: String
description: |
The location of the traffic extension
url_param_only: true
required: true
immutable: true
- name: 'name'
type: String
description: |
Identifier. Name of the WasmPlugin resource.
url_param_only: true
required: true
immutable: true
properties:
- name: 'createTime'
type: Time
description: 'Output only. The timestamp when the resource was created.'
output: true
- name: 'updateTime'
type: Time
description: 'Output only. The timestamp when the resource was updated.'
output: true
- name: 'description'
type: String
description: |
Optional. A human-readable description of the resource.
- name: 'labels'
type: KeyValueLabels
description: 'Optional. Set of labels associated with the WasmPlugin resource.'
- name: 'mainVersionId'
type: String
description: |
The ID of the WasmPluginVersion resource that is the currently serving one. The version referred to must be a child of this WasmPlugin resource and should be listed in the "versions" field.
required: true
- name: 'logConfig'
type: NestedObject
description: |
Optional. Specifies the logging options for the activity performed by this plugin. If logging is enabled, plugin logs are exported to Cloud Logging.
Note that the settings relate to the logs generated by using logging statements in your Wasm code.
properties:
- name: 'enable'
type: Boolean
description: |
Optional. Specifies whether to enable logging for activity by this plugin.
- name: 'sampleRate'
type: Double
validation:
function: 'validation.FloatBetween(0, 1)'
description: |
Non-empty default. Configures the sampling rate of activity logs, where 1.0 means all logged activity is reported and 0.0 means no activity is reported.
A floating point value between 0.0 and 1.0 indicates that a percentage of log messages is stored.
The default value when logging is enabled is 1.0. The value of the field must be between 0 and 1 (inclusive).
This field can be specified only if logging is enabled for this plugin.
default_from_api: true
- name: 'minLogLevel'
type: Enum
description: |
Non-empty default. Specificies the lowest level of the plugin logs that are exported to Cloud Logging. This setting relates to the logs generated by using logging statements in your Wasm code.
This field is can be set only if logging is enabled for the plugin.
If the field is not provided when logging is enabled, it is set to INFO by default.
default_from_api: true
enum_values:
- 'LOG_LEVEL_UNSPECIFIED'
- 'TRACE'
- 'DEBUG'
- 'INFO'
- 'WARN'
- 'ERROR'
- 'CRITICAL'
- name: 'versions'
type: Map
description: |
All versions of this WasmPlugin resource in the key-value format. The key is the resource ID, and the value is the VersionDetails object.
required: true
key_name: 'version_name'
key_description: 'Name of the WasmPluginVersion'
# custom_expand is used for both preventing empty maps being created on update and to remove output fields that are being incorrecty included in the expand when inside a map
custom_expand: 'templates/terraform/custom_expand/wasm_plugin_skip_empty_versions.go.tmpl'
value_type:
name: value
type: NestedObject
properties:
- name: 'createTime'
type: Time
description: 'Output only. The timestamp when the resource was created.'
output: true
- name: 'updateTime'
type: Time
description: 'Output only. The timestamp when the resource was updated.'
output: true
- name: 'description'
type: String
description: |
Optional. A human-readable description of the resource.
- name: 'labels'
type: KeyValuePairs
description: 'Optional. Set of labels associated with the WasmPlugin resource.'
- name: 'imageUri'
type: String
description: |
Optional. URI of the container image containing the plugin, stored in the Artifact Registry. When a new WasmPluginVersion resource is created, the digest of the container image is saved in the imageDigest field.
When downloading an image, the digest value is used instead of an image tag.
- name: 'imageDigest'
type: String
description: |
Output only. The resolved digest for the image specified in the image field. The digest is resolved during the creation of WasmPluginVersion resource.
This field holds the digest value, regardless of whether a tag or digest was originally specified in the image field.
output: true
- name: 'pluginConfigDigest'
type: String
description: |
Output only. This field holds the digest (usually checksum) value for the plugin configuration.
The value is calculated based on the contents of pluginConfigData or the container image defined by the pluginConfigUri field.
output: true
- name: 'pluginConfigData'
type: String
description: |
A base64-encoded string containing the configuration for the plugin. The configuration is provided to the plugin at runtime through the ON_CONFIGURE callback.
When a new WasmPluginVersion resource is created, the digest of the contents is saved in the pluginConfigDigest field.
Conflics with pluginConfigUri.
conflicts:
- pluginConfigUri
validation:
function: 'verify.ValidateBase64String'
- name: 'pluginConfigUri'
type: String
description: |
URI of the plugin configuration stored in the Artifact Registry. The configuration is provided to the plugin at runtime through the ON_CONFIGURE callback.
The container image must contain only a single file with the name plugin.config.
When a new WasmPluginVersion resource is created, the digest of the container image is saved in the pluginConfigDigest field.
Conflics with pluginConfigData.
conflicts:
- pluginConfigData
- name: 'usedBy'
type: Array
description: |
Output only. List of all extensions that use this WasmPlugin resource.
output: true
item_type:
name: 'name'
type: string
description: 'Output only. Full name of the resource'
23 changes: 23 additions & 0 deletions mmv1/products/networkservicesplugins/product.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2024 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

---
name: 'NetworkServicesPlugins'
display_name: 'Network Services Plugins'
versions:
- name: 'beta'
base_url: 'https://networkservices.googleapis.com/v1beta1/'
- name: 'ga'
base_url: 'https://networkservices.googleapis.com/v1/'
scopes:
- 'https://www.googleapis.com/auth/cloud-identity'
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
func expand{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
if v == nil {
return map[string]interface{}{}, nil
}
m := make(map[string]interface{})
for _, raw := range v.(*schema.Set).List() {
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

// Ensure we don't send empty versions
if tpgresource.IsEmptyValue(reflect.ValueOf(original["version_name"])) {
continue
}

transformedDescription, err := expandNetworkServicesWasmPluginVersionsFields(original["description"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedDescription); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["description"] = transformedDescription
}

transformedLabels, err := expandNetworkServicesWasmPluginVersionsLabels(original["labels"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["labels"] = transformedLabels
}

transformedImageUri, err := expandNetworkServicesWasmPluginVersionsFields(original["image_uri"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedImageUri); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["imageUri"] = transformedImageUri
}

transformedPluginConfigData, err := expandNetworkServicesWasmPluginVersionsFields(original["plugin_config_data"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedPluginConfigData); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["pluginConfigData"] = transformedPluginConfigData
}

transformedPluginConfigUri, err := expandNetworkServicesWasmPluginVersionsFields(original["plugin_config_uri"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedPluginConfigUri); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["pluginConfigUri"] = transformedPluginConfigUri
}

transformedVersionName, err := tpgresource.ExpandString(original["version_name"], d, config)
if err != nil {
return nil, err
}
m[transformedVersionName] = transformed
}
return m, nil
}

func expandNetworkServicesWasmPluginVersionsFields(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandNetworkServicesWasmPluginVersionsLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
}
m := make(map[string]string)
for k, val := range v.(map[string]interface{}) {
m[k] = val.(string)
}
return m, nil
}
30 changes: 30 additions & 0 deletions mmv1/templates/terraform/examples/wasm_plugin_basic.tf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
data "google_project" "project" { provider = google-beta }

resource "google_network_services_plugins_wasm_plugin" "{{$.PrimaryResourceId}}" {
provider = google-beta
name = "{{index $.Vars "wasm_plugin_name"}}"
description = "my wasm plugin"
location = "global"

main_version_id = "v1"

labels = {
test_label = "test_value"
}
log_config {
enable = true
sample_rate = 1
min_log_level = "WARN"
}

versions {
version_name = "v1"
description = "v1 version of my wasm plugin"
image_uri = "us-central1-docker.pkg.dev/${data.google_project.project.name}/svextensionplugin/my-wasm-plugin:prod"

labels = {
test_label = "test_value"
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,11 @@ var ServicesListBeta = mapOf(
"displayName" to "Networkservices",
"path" to "./google-beta/services/networkservices"
),
"networkservicesplugins" to mapOf(
"name" to "networkservicesplugins",
"displayName" to "Networkservicesplugins",
"path" to "./google-beta/services/networkservicesplugins"
),
"notebooks" to mapOf(
"name" to "notebooks",
"displayName" to "Notebooks",
Expand Down

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WasmPlugin is in Public Preview phase (beta), should reach GA in Q1 2025.
Is it valid to add it here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the answer is no, as the only product that I can find that exists in beta but not in ga is firebasestorage and it does not have an entry in the ga file.

Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,11 @@ var ServicesListGa = mapOf(
"displayName" to "Networkservices",
"path" to "./google/services/networkservices"
),
"networkservicesplugins" to mapOf(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this "networkservicesplugins" value customer visible?
Can it be safely changed in the future?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is customer visible, the name of the resource will be google_network_services_plugins_wasm_plugin (instead of google_network_services_wasm_plugin) and the documentation for the resource will land in a section called "Network Services Plugins" (though I think the docs section might be changeable so that it lands in the main "Network Services" section instead).

It can't be changed later, but I'm not at all stuck on the name - I suggested "Network Services Plugins" as it needed a new name and that seemed like a fitting description. If there's a better name, let's change it here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I need to discuss it with the product owner (next week). I suppose that he would prefer something like "service_extensions" instead of "network_services_plugins".
AFAIK the main reason of moving it to the new product were failing tests for other network_services resources.
Do you think that there is a chance to make them passing? What should change on networkservices API?

"name" to "networkservicesplugins",
"displayName" to "Networkservicesplugins",
"path" to "./google/services/networkservicesplugins"
),
"notebooks" to mapOf(
"name" to "notebooks",
"displayName" to "Notebooks",
Expand Down
Loading
Loading