Skip to content

Commit b29e0ff

Browse files
Added Resource google_compute_global_vm_extension_policy (#18013)
Co-authored-by: Avnoor Singh Ludhar <avnoor@google.com>
1 parent f1498a3 commit b29e0ff

8 files changed

Lines changed: 483 additions & 0 deletions
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# Copyright 2026 Google Inc.
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
---
15+
name: 'GlobalVmExtensionPolicy'
16+
description: 'A Global VM Extension Policy.'
17+
min_version: 'beta'
18+
base_url: 'projects/{{project}}/global/vmExtensionPolicies'
19+
self_link: 'projects/{{project}}/global/vmExtensionPolicies/{{name}}'
20+
update_verb: 'PATCH'
21+
delete_url: 'projects/{{project}}/global/vmExtensionPolicies/{{name}}/delete'
22+
delete_verb: 'POST'
23+
custom_code:
24+
pre_update: 'templates/terraform/pre_update/vm_extension_policy_name.go.tmpl'
25+
test_check_destroy: 'templates/terraform/test_check_destroy/global_vm_extension_policy.go.tmpl'
26+
pre_delete: 'templates/terraform/pre_delete/vm_extension_policy_rollout.go.tmpl'
27+
post_delete: 'templates/terraform/post_delete/global_vm_extension_policy.go.tmpl'
28+
29+
samples:
30+
- name: 'compute_global_vm_extension_policy_basic'
31+
primary_resource_id: 'ops_agent_policy'
32+
steps:
33+
- name: 'compute_global_vm_extension_policy_basic'
34+
vars:
35+
policy_name: 'global-ops-agent-policy'
36+
ignore_read_extra:
37+
- 'rollout_operation'
38+
- name: 'compute_global_vm_extension_policy_update'
39+
vars:
40+
policy_name: 'global-ops-agent-policy'
41+
ignore_read_extra:
42+
- 'rollout_operation'
43+
- name: 'compute_global_vm_extension_policy_rollout'
44+
primary_resource_id: 'ops_agent_policy'
45+
steps:
46+
- name: 'compute_global_vm_extension_policy_basic'
47+
vars:
48+
policy_name: 'global-ops-agent-policy'
49+
ignore_read_extra:
50+
- 'rollout_operation'
51+
- name: 'compute_global_vm_extension_policy_update_rollout'
52+
vars:
53+
policy_name: 'global-ops-agent-policy'
54+
ignore_read_extra:
55+
- 'rollout_operation'
56+
- name: 'compute_global_vm_extension_policy_custom_rollout'
57+
primary_resource_id: 'ops_agent_policy'
58+
steps:
59+
- name: 'compute_global_vm_extension_policy_custom_rollout'
60+
vars:
61+
policy_name: 'global-ops-agent-policy'
62+
ignore_read_extra:
63+
- 'rollout_operation'
64+
65+
autogen_async: true
66+
async:
67+
actions: ['create', 'delete', 'update']
68+
type: 'OpAsync'
69+
operation:
70+
base_url: 'projects/{{project}}/global/operations/{{op_id}}'
71+
72+
properties:
73+
- name: 'name'
74+
type: String
75+
required: true
76+
immutable: true
77+
description: |-
78+
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.
79+
validation:
80+
regex: '^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$'
81+
- name: 'description'
82+
type: String
83+
description: 'An optional description of this resource.'
84+
- name: 'extensionPolicies'
85+
type: Map
86+
required: true
87+
description: |-
88+
Map from extension (eg: "cloudops") to its policy configuration.
89+
value_type:
90+
type: NestedObject
91+
properties:
92+
- name: 'pinnedVersion'
93+
type: String
94+
description: 'The version pinning for the extension.'
95+
- name: 'stringConfig'
96+
type: String
97+
description: 'String configuration payload.'
98+
key_name: 'extension_name'
99+
- name: 'instanceSelectors'
100+
type: Array
101+
description: 'Selector to target VMs for a policy.'
102+
item_type:
103+
type: NestedObject
104+
properties:
105+
- name: 'labelSelector'
106+
type: NestedObject
107+
description: 'LabelSelector matches VM labels.'
108+
properties:
109+
- name: 'inclusionLabels'
110+
type: KeyValuePairs
111+
description: 'Labels as key value pairs.'
112+
- name: 'priority'
113+
type: Integer
114+
default_from_api: true
115+
description: 'Used to resolve conflicts when multiple policies are active. Defaults to 0.'
116+
- name: 'rolloutOperation'
117+
type: NestedObject
118+
required: true
119+
description: 'Represents the rollout operation.'
120+
properties:
121+
- name: 'rolloutInput'
122+
type: NestedObject
123+
required: true
124+
description: 'Rollout input settings.'
125+
properties:
126+
- name: 'conflictBehavior'
127+
type: String
128+
description: 'Specifies the behavior of the rollout if a conflict is detected.'
129+
- name: 'name'
130+
type: String
131+
description: 'The name of the rollout plan.'
132+
exactly_one_of:
133+
- 'rollout_operation.0.rollout_input.0.name'
134+
- 'rollout_operation.0.rollout_input.0.predefined_rollout_plan'
135+
- name: 'predefinedRolloutPlan'
136+
type: String
137+
description: 'Specifies the predefined rollout plan for the policy.'
138+
exactly_one_of:
139+
- 'rollout_operation.0.rollout_input.0.name'
140+
- 'rollout_operation.0.rollout_input.0.predefined_rollout_plan'
141+
- name: 'retryUuid'
142+
type: String
143+
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.'
144+
- name: 'rolloutStatus'
145+
type: NestedObject
146+
description: 'Rollout status.'
147+
output: true
148+
properties:
149+
- name: 'currentRollouts'
150+
type: Array
151+
description: 'The current rollouts for the latest version of the resource.'
152+
output: true
153+
item_type:
154+
type: NestedObject
155+
output: true
156+
properties:
157+
- name: 'locationRolloutStatus'
158+
type: Map
159+
description: 'The rollout status for each location.'
160+
output: true
161+
value_type:
162+
type: NestedObject
163+
output: true
164+
properties:
165+
- name: 'state'
166+
type: String
167+
description: 'The state of the location rollout.'
168+
output: true
169+
key_name: 'location_name'
170+
- name: 'rollout'
171+
type: String
172+
description: 'The name of the rollout.'
173+
output: true
174+
- name: 'rolloutPlan'
175+
type: String
176+
description: 'The name of the rollout plan.'
177+
output: true
178+
- name: 'state'
179+
type: String
180+
description: 'The overall state of the rollout.'
181+
output: true
182+
- name: 'previousRollout'
183+
type: NestedObject
184+
description: 'Rollout status of the previous rollout.'
185+
output: true
186+
properties:
187+
- name: 'locationRolloutStatus'
188+
type: Map
189+
description: 'The rollout status for each location.'
190+
output: true
191+
value_type:
192+
type: NestedObject
193+
output: true
194+
properties:
195+
- name: 'state'
196+
type: String
197+
description: 'The state of the location rollout.'
198+
output: true
199+
key_name: 'location_name'
200+
- name: 'rollout'
201+
type: String
202+
description: 'The name of the rollout.'
203+
output: true
204+
- name: 'rolloutPlan'
205+
type: String
206+
description: 'The name of the rollout plan.'
207+
output: true
208+
- name: 'state'
209+
type: String
210+
description: 'The overall state of the rollout.'
211+
output: true
212+
- name: 'scopedResourceStatus'
213+
type: String
214+
description: 'The scoped resource status.'
215+
output: true
216+
- name: 'creationTimestamp'
217+
type: String
218+
description: 'Creation timestamp in RFC3339 text format.'
219+
output: true
220+
- name: 'id'
221+
type: String
222+
description: 'The unique identifier for the resource.'
223+
output: true
224+
- name: 'kind'
225+
type: String
226+
description: 'Type of the resource.'
227+
output: true
228+
- name: 'selfLink'
229+
type: String
230+
description: 'Server-defined fully-qualified URL for this resource.'
231+
output: true
232+
- name: 'updateTimestamp'
233+
type: String
234+
description: 'Update timestamp in RFC3339 text format.'
235+
output: true
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
readUrl, err := tpgresource.ReplaceVars(d, config, transport_tpg.BaseUrl(Product, config)+"projects/{{"{{"}}project{{"}}"}}/global/vmExtensionPolicies/{{"{{"}}name{{"}}"}}")
2+
if err != nil {
3+
return err
4+
}
5+
6+
// Wait for deletion (up to 10 minutes) to avoid eventual consistency issues during subsequent resource deletions (e.g. RolloutPlan)
7+
deadline := time.Now().Add(10 * time.Minute)
8+
for {
9+
_, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
10+
Config: config,
11+
Method: "GET",
12+
Project: billingProject,
13+
RawURL: readUrl,
14+
UserAgent: userAgent,
15+
})
16+
if err != nil {
17+
if transport_tpg.IsGoogleApiErrorWithCode(err, 404) {
18+
break
19+
}
20+
return err
21+
}
22+
if time.Now().After(deadline) {
23+
return fmt.Errorf("timeout waiting for GlobalVmExtensionPolicy %q to be deleted", d.Id())
24+
}
25+
log.Printf("[DEBUG] GlobalVmExtensionPolicy %q is still deleting, waiting...", d.Id())
26+
time.Sleep(5 * time.Second)
27+
}
28+
29+
// Clean up any historical rollout records owned by this GlobalVmExtensionPolicy
30+
policyName := ""
31+
if n, ok := d.GetOk("name"); ok {
32+
policyName = n.(string)
33+
}
34+
35+
if policyName != "" {
36+
listUrl := fmt.Sprintf("https://compute.googleapis.com/compute/beta/projects/%s/global/rollouts?filter=rolloutEntity.orchestratedEntity.orchestrationSource%%20eq%%20%%22.*%s%%22", project, policyName)
37+
listRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
38+
Config: config,
39+
Method: "GET",
40+
Project: billingProject,
41+
RawURL: listUrl,
42+
UserAgent: userAgent,
43+
})
44+
if err != nil {
45+
return fmt.Errorf("Error listing rollouts to clean up references: %s", err)
46+
}
47+
48+
if listRes != nil {
49+
if items, ok := listRes["items"].([]interface{}); ok {
50+
for _, item := range items {
51+
if rollout, ok := item.(map[string]interface{}); ok {
52+
if rolloutName, ok := rollout["name"].(string); ok && rolloutName != "" {
53+
log.Printf("[DEBUG] Deleting historical rollout %q owned by policy %q to unlock referenced rollout plan", rolloutName, policyName)
54+
deleteUrl := fmt.Sprintf("https://compute.googleapis.com/compute/beta/projects/%s/global/rollouts/%s", project, rolloutName)
55+
56+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
57+
Config: config,
58+
Method: "DELETE",
59+
Project: billingProject,
60+
RawURL: deleteUrl,
61+
UserAgent: userAgent,
62+
})
63+
if err != nil {
64+
log.Printf("[WARNING] Error deleting rollout %q: %s", rolloutName, err)
65+
continue
66+
}
67+
68+
err = ComputeOperationWaitTime(
69+
config, res, project, fmt.Sprintf("Deleting rollout %q", rolloutName), userAgent,
70+
d.Timeout(schema.TimeoutDelete))
71+
if err != nil {
72+
log.Printf("[WARNING] Error waiting for rollout %q deletion: %s", rolloutName, err)
73+
}
74+
}
75+
}
76+
}
77+
}
78+
}
79+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// predefinedRolloutPlan is required in the request body for GCE VM extension policy deletion.
2+
obj = map[string]interface{}{
3+
"predefinedRolloutPlan": "FAST_ROLLOUT",
4+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
resource "google_compute_global_vm_extension_policy" "{{$.PrimaryResourceId}}" {
2+
provider = google-beta
3+
name = "global-ops-agent-vme-policy-%{random_suffix}"
4+
description = "A basic global VM extension policy"
5+
priority = 10
6+
7+
extension_policies {
8+
extension_name = "ops-agent"
9+
pinned_version = "2.66.0"
10+
}
11+
12+
instance_selectors {
13+
label_selector {
14+
inclusion_labels = {
15+
env = "test"
16+
}
17+
}
18+
}
19+
20+
rollout_operation {
21+
rollout_input {
22+
predefined_rollout_plan = "FAST_ROLLOUT"
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)