Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
226 changes: 226 additions & 0 deletions mmv1/products/compute/GlobalVmExtensionPolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# Copyright 2026 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: 'GlobalVmExtensionPolicy'
description: 'A Global VM Extension Policy.'
base_url: 'projects/{{project}}/global/vmExtensionPolicies'
self_link: 'projects/{{project}}/global/vmExtensionPolicies/{{name}}'
update_verb: 'PATCH'
delete_url: 'projects/{{project}}/global/vmExtensionPolicies/{{name}}/delete'
delete_verb: 'POST'
custom_code:
pre_update: 'templates/terraform/pre_update/vm_extension_policy_name.go.tmpl'
test_check_destroy: 'templates/terraform/test_check_destroy/global_vm_extension_policy.go.tmpl'
pre_delete: 'templates/terraform/pre_delete/vm_extension_policy_rollout.go.tmpl'

samples:
- name: 'compute_global_vm_extension_policy_basic'
primary_resource_id: 'ops_agent_policy'
steps:
- name: 'compute_global_vm_extension_policy_basic'
vars:
policy_name: 'global-ops-agent-policy'
ignore_read_extra:
- 'rollout_operation'
- name: 'compute_global_vm_extension_policy_update'
vars:
policy_name: 'global-ops-agent-policy'
ignore_read_extra:
- 'rollout_operation'
- name: 'compute_global_vm_extension_policy_rollout'
primary_resource_id: 'ops_agent_policy'
steps:
- name: 'compute_global_vm_extension_policy_basic'
vars:
policy_name: 'global-ops-agent-policy'
ignore_read_extra:
- 'rollout_operation'
- name: 'compute_global_vm_extension_policy_update_rollout'
vars:
policy_name: 'global-ops-agent-policy'
ignore_read_extra:
- 'rollout_operation'


autogen_async: true
async:
actions: ['create', 'delete', 'update']
type: 'OpAsync'
operation:
base_url: 'projects/{{project}}/global/operations/{{op_id}}'

properties:
- name: 'name'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please add name validation consistent with API requirement: 1- 63 characters, RFC1035-style, lowercase letter first, etc based on the API doc.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Done in new commit

type: String
required: true
immutable: true
description: |-
Name of the resource. Provided by the client when the resource is created. The name must be 1-63 characters long and match the regular expression '^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$' to comply with RFC1035.
validation:
regex: '^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$'
- name: 'description'
type: String
description: 'An optional description of this resource.'
- name: 'extensionPolicies'
type: Map
required: true
description: |-
Map from extension (eg: "cloudops") to its policy configuration.
value_type:
type: NestedObject
properties:
- name: 'pinnedVersion'
type: String
description: 'The version pinning for the extension.'
- name: 'stringConfig'
type: String
description: 'String configuration payload.'
key_name: 'extension_name'
- name: 'instanceSelectors'
type: Array
description: 'Selector to target VMs for a policy.'
item_type:
type: NestedObject
properties:
- name: 'labelSelector'
type: NestedObject
description: 'LabelSelector matches VM labels.'
properties:
- name: 'inclusionLabels'
type: KeyValuePairs
description: 'Labels as key value pairs.'
- name: 'priority'
type: Integer
default_from_api: true
description: 'Used to resolve conflicts when multiple policies are active. Defaults to 0.'
- name: 'rolloutOperation'
type: NestedObject
required: true
description: 'Represents the rollout operation.'
properties:
- name: 'rolloutInput'
type: NestedObject
required: true
description: 'Rollout input settings.'
properties:
- name: 'conflictBehavior'
type: String
description: 'Specifies the behavior of the rollout if a conflict is detected.'
- name: 'name'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Based on the doc the rolloutInput.name and rolloutInput.predefinedRolloutPlan are defined as union field: only one of them can be set. Please add terraform-side conflick/ exactly-one-of validation for this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Done in new commit.

type: String
description: 'The name of the rollout plan.'
exactly_one_of:
- 'rollout_operation.0.rollout_input.0.name'
- 'rollout_operation.0.rollout_input.0.predefined_rollout_plan'
- name: 'predefinedRolloutPlan'
type: String
description: 'Specifies the predefined rollout plan for the policy.'
exactly_one_of:
- 'rollout_operation.0.rollout_input.0.name'
- 'rollout_operation.0.rollout_input.0.predefined_rollout_plan'
- name: 'retryUuid'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could you please clarify the intended terraform behavior for retry_uuid ? Based on the API docs it should be only set when retrying an existing rollout, and update erros if retryUuid is set while policy is modified. So document it clearly or handle this case.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yea that's accurate. I updated the description to let the user know about the policy needing to be unmodified on retries.

type: String
description: 'The UUID that identifies a policy rollout retry attempt. It should only be set when retrying an existing rollout. Updating this field along with other policy fields (description, extension_policies, instance_selectors, priority) in the same plan will return an error.'
- name: 'rolloutStatus'
type: NestedObject
description: 'Rollout status.'
output: true
properties:
- name: 'currentRollouts'
type: Array
description: 'The current rollouts for the latest version of the resource.'
output: true
item_type:
type: NestedObject
output: true
properties:
- name: 'locationRolloutStatus'
type: Map
description: 'The rollout status for each location.'
output: true
value_type:
type: NestedObject
output: true
properties:
- name: 'state'
type: String
description: 'The state of the location rollout.'
output: true
key_name: 'location_name'
- name: 'rollout'
type: String
description: 'The name of the rollout.'
output: true
- name: 'rolloutPlan'
type: String
description: 'The name of the rollout plan.'
output: true
- name: 'state'
type: String
description: 'The overall state of the rollout.'
output: true
- name: 'previousRollout'
type: NestedObject
description: 'Rollout status of the previous rollout.'
output: true
properties:
- name: 'locationRolloutStatus'
type: Map
description: 'The rollout status for each location.'
output: true
value_type:
type: NestedObject
output: true
properties:
- name: 'state'
type: String
description: 'The state of the location rollout.'
output: true
key_name: 'location_name'
- name: 'rollout'
type: String
description: 'The name of the rollout.'
output: true
- name: 'rolloutPlan'
type: String
description: 'The name of the rollout plan.'
output: true
- name: 'state'
type: String
description: 'The overall state of the rollout.'
output: true
- name: 'scopedResourceStatus'
type: String
description: 'The scoped resource status.'
output: true
- name: 'creationTimestamp'
type: String
description: 'Creation timestamp in RFC3339 text format.'
output: true
- name: 'id'
type: String
description: 'The unique identifier for the resource.'
output: true
- name: 'kind'
type: String
description: 'Type of the resource.'
output: true
- name: 'selfLink'
type: String
description: 'Server-defined fully-qualified URL for this resource.'
output: true
- name: 'updateTimestamp'
type: String
description: 'Update timestamp in RFC3339 text format.'
output: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// predefinedRolloutPlan is required in the request body for GCE VM extension policy deletion.
obj = map[string]interface{}{
"predefinedRolloutPlan": "FAST_ROLLOUT",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
obj["name"] = d.Get("name").(string)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
resource "google_compute_global_vm_extension_policy" "{{$.PrimaryResourceId}}" {
name = "global-ops-agent-vme-policy-%{random_suffix}"
description = "A basic global VM extension policy"
priority = 10

extension_policies {
extension_name = "ops-agent"
pinned_version = "2.66.0"
}

instance_selectors {
label_selector {
inclusion_labels = {
env = "test"
}
}
}

rollout_operation {
rollout_input {
predefined_rollout_plan = "FAST_ROLLOUT"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
resource "google_compute_global_vm_extension_policy" "{{$.PrimaryResourceId}}" {
name = "global-ops-agent-vme-policy-%{random_suffix}"
description = "A basic global VM extension policy"
priority = 20

extension_policies {
extension_name = "ops-agent"
pinned_version = "2.66.0"
string_config = "logging:\n receivers:\n syslog:\n type: files\n include_paths:\n - /var/log/messages\n"
}

instance_selectors {
label_selector {
inclusion_labels = {
env = "test"
}
}
}

rollout_operation {
rollout_input {
predefined_rollout_plan = "FAST_ROLLOUT"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
resource "google_compute_global_vm_extension_policy" "{{$.PrimaryResourceId}}" {
name = "global-ops-agent-vme-policy-%{random_suffix}"
description = "A basic global VM extension policy"
priority = 10

extension_policies {
extension_name = "ops-agent"
pinned_version = "2.66.0"
}

instance_selectors {
label_selector {
inclusion_labels = {
env = "test"
}
}
}

rollout_operation {
rollout_input {
conflict_behavior = "overwrite"
predefined_rollout_plan = "SLOW_ROLLOUT"
retry_uuid = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Skip destroy check to avoid eventual consistency issues of global rollouts.
// The global VM extension policy deletion triggers a background purge rollout
// that can take a few minutes to fully propagate across GCE zones.
return nil