Skip to content

Commit c9841d2

Browse files
varshatumburuBBBmau
authored andcommitted
Add autoscaling settings to pc management cluster (GoogleCloudPlatform#12002)
1 parent 3db2bfc commit c9841d2

File tree

5 files changed

+292
-8
lines changed

5 files changed

+292
-8
lines changed

mmv1/products/vmwareengine/PrivateCloud.yaml

+104-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ custom_code:
5252
update_encoder: 'templates/terraform/update_encoder/private_cloud.go.tmpl'
5353
decoder: 'templates/terraform/decoders/private_cloud.go.tmpl'
5454
pre_create: 'templates/terraform/pre_create/vmwareengine_private_cloud.go.tmpl'
55+
post_create: 'templates/terraform/post_create/private_cloud.go.tmpl'
5556
post_delete: 'templates/terraform/post_delete/private_cloud.go.tmpl'
5657
post_update: 'templates/terraform/post_update/private_cloud.go.tmpl'
5758
pre_delete: 'templates/terraform/pre_delete/vmwareengine_private_cloud.go.tmpl'
@@ -67,7 +68,7 @@ examples:
6768
management_cluster_id: 'sample-mgmt-cluster'
6869
test_env_vars:
6970
region: 'REGION'
70-
# update tests will take care of create and update. PC creation is expensive and node reservation is required.
71+
# update tests will take care of create and update. PC creation is expensive and node reservation is required.
7172
exclude_test: true
7273
- name: 'vmware_engine_private_cloud_full'
7374
primary_resource_id: 'vmw-engine-pc'
@@ -77,7 +78,7 @@ examples:
7778
management_cluster_id: 'sample-mgmt-cluster'
7879
test_env_vars:
7980
region: 'REGION'
80-
# update tests will take care of create and update. PC creation is expensive and node reservation is required.
81+
# update tests will take care of create and update. PC creation is expensive and node reservation is required.
8182
exclude_test: true
8283
virtual_fields:
8384
- name: 'deletion_delay_hours'
@@ -218,6 +219,107 @@ properties:
218219
type: String
219220
description: |
220221
Additional zone for a higher level of availability and load balancing.
222+
- name: 'autoscalingSettings'
223+
type: NestedObject
224+
description: |
225+
Configuration of the autoscaling applied to this cluster
226+
Private cloud must have a minimum of 3 nodes to add autoscale settings
227+
properties:
228+
- name: 'autoscalingPolicies'
229+
type: Map
230+
required: true
231+
description: |
232+
The map with autoscaling policies applied to the cluster.
233+
The key is the identifier of the policy.
234+
It must meet the following requirements:
235+
* Only contains 1-63 alphanumeric characters and hyphens
236+
* Begins with an alphabetical character
237+
* Ends with a non-hyphen character
238+
* Not formatted as a UUID
239+
* Complies with [RFC 1034](https://datatracker.ietf.org/doc/html/rfc1034) (section 3.5)
240+
241+
Currently the map must contain only one element
242+
that describes the autoscaling policy for compute nodes.
243+
key_name: 'autoscale_policy_id'
244+
key_description: 'The key is the identifier of the policy.'
245+
value_type:
246+
name: AutoscalingPolicy
247+
type: NestedObject
248+
properties:
249+
- name: 'nodeTypeId'
250+
type: String
251+
required: true
252+
description: |
253+
The canonical identifier of the node type to add or remove.
254+
- name: 'scaleOutSize'
255+
type: Integer
256+
required: true
257+
description: |
258+
Number of nodes to add to a cluster during a scale-out operation.
259+
Must be divisible by 2 for stretched clusters.
260+
- name: 'cpuThresholds'
261+
type: NestedObject
262+
description: |
263+
Utilization thresholds pertaining to CPU utilization.
264+
properties:
265+
- name: 'scaleOut'
266+
type: Integer
267+
required: true
268+
description: |
269+
The utilization triggering the scale-out operation in percent.
270+
- name: 'scaleIn'
271+
type: Integer
272+
required: true
273+
description: |
274+
The utilization triggering the scale-in operation in percent.
275+
- name: 'consumedMemoryThresholds'
276+
type: NestedObject
277+
description: |
278+
Utilization thresholds pertaining to amount of consumed memory.
279+
properties:
280+
- name: 'scaleOut'
281+
type: Integer
282+
required: true
283+
description: |
284+
The utilization triggering the scale-out operation in percent.
285+
- name: 'scaleIn'
286+
type: Integer
287+
required: true
288+
description: |
289+
The utilization triggering the scale-in operation in percent.
290+
- name: 'storageThresholds'
291+
type: NestedObject
292+
description: |
293+
Utilization thresholds pertaining to amount of consumed storage.
294+
properties:
295+
- name: 'scaleOut'
296+
type: Integer
297+
required: true
298+
description: |
299+
The utilization triggering the scale-out operation in percent.
300+
- name: 'scaleIn'
301+
type: Integer
302+
required: true
303+
description: |
304+
The utilization triggering the scale-in operation in percent.
305+
- name: 'minClusterNodeCount'
306+
type: Integer
307+
description: |
308+
Minimum number of nodes of any type in a cluster.
309+
Mandatory for successful addition of autoscaling settings in cluster.
310+
- name: 'maxClusterNodeCount'
311+
type: Integer
312+
description: |
313+
Maximum number of nodes of any type in a cluster.
314+
Mandatory for successful addition of autoscaling settings in cluster.
315+
- name: 'coolDownPeriod'
316+
type: String
317+
description: |
318+
The minimum duration between consecutive autoscale operations.
319+
It starts once addition or removal of nodes is fully completed.
320+
Minimum cool down period is 30m.
321+
Cool down period must be in whole minutes (for example, 30m, 31m, 50m).
322+
Mandatory for successful addition of autoscaling settings in cluster.
221323
- name: 'hcx'
222324
type: NestedObject
223325
description: |

mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.tmpl

+22
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@ resource "google_vmwareengine_private_cloud" "{{$.PrimaryResourceId}}" {
1414
node_count = 1
1515
custom_core_count = 32
1616
}
17+
autoscaling_settings {
18+
autoscaling_policies {
19+
autoscale_policy_id = "autoscaling-policy"
20+
node_type_id = "standard-72"
21+
scale_out_size = 1
22+
cpu_thresholds {
23+
scale_out = 80
24+
scale_in = 15
25+
}
26+
consumed_memory_thresholds {
27+
scale_out = 75
28+
scale_in = 20
29+
}
30+
storage_thresholds {
31+
scale_out = 80
32+
scale_in = 20
33+
}
34+
}
35+
min_cluster_node_count = 3
36+
max_cluster_node_count = 8
37+
cool_down_period = "1800s"
38+
}
1739
}
1840
deletion_delay_hours = 0
1941
send_deletion_delay_hours_if_zero = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
mgmtClusterProp, err := expandVmwareenginePrivateCloudManagementCluster(d.Get("management_cluster"), d, config)
2+
if v, ok := d.GetOkExists("management_cluster"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, mgmtClusterProp)) {
3+
obj["managementCluster"] = mgmtClusterProp
4+
}
5+
6+
mgmtMap := mgmtClusterProp.(map[string]interface{})
7+
parentUrl, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}VmwareengineBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/locations/{{"{{"}}location{{"}}"}}/privateClouds/{{"{{"}}name{{"}}"}}")
8+
if err != nil {
9+
return err
10+
}
11+
12+
clusterUrl := fmt.Sprintf("%s/clusters/%s", parentUrl, mgmtMap["clusterId"])
13+
clusterUpdateMask := []string{}
14+
clusterObj := make(map[string]interface{})
15+
16+
if v, ok := d.GetOkExists("management_cluster"); !tpgresource.IsEmptyValue(reflect.ValueOf(mgmtClusterProp)) && (ok || !reflect.DeepEqual(v, mgmtClusterProp)) {
17+
clusterObj["autoscalingSettings"] = mgmtMap["autoscalingSettings"]
18+
}
19+
20+
if d.HasChange("management_cluster") {
21+
clusterUpdateMask = append(clusterUpdateMask, "autoscalingSettings")
22+
}
23+
24+
clusterPatchUrl, err := transport_tpg.AddQueryParams(clusterUrl, map[string]string{"updateMask": strings.Join(clusterUpdateMask, ",")})
25+
if err != nil {
26+
return err
27+
}
28+
29+
// check if there is anything to update to avoid API call if not required.
30+
if len(clusterUpdateMask) > 0 {
31+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
32+
Config: config,
33+
Method: "PATCH",
34+
Project: billingProject,
35+
RawURL: clusterPatchUrl,
36+
UserAgent: userAgent,
37+
Body: clusterObj,
38+
Timeout: d.Timeout(schema.TimeoutUpdate),
39+
})
40+
41+
if err != nil {
42+
return fmt.Errorf("Error updating magament cluster %q: %s", d.Id(), err)
43+
} else {
44+
log.Printf("[DEBUG] Finished updating magament cluster %q: %#v", d.Id(), res)
45+
}
46+
47+
err = VmwareengineOperationWaitTime(
48+
config, res, project, "Updating Managment Cluster", userAgent,
49+
d.Timeout(schema.TimeoutUpdate))
50+
51+
if err != nil {
52+
return err
53+
}
54+
}

mmv1/templates/terraform/post_update/private_cloud.go.tmpl

+2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ clusterObj := make(map[string]interface{})
1515

1616
if v, ok := d.GetOkExists("management_cluster"); !tpgresource.IsEmptyValue(reflect.ValueOf(mgmtClusterProp)) && (ok || !reflect.DeepEqual(v, mgmtClusterProp)) {
1717
clusterObj["nodeTypeConfigs"] = mgmtMap["nodeTypeConfigs"]
18+
clusterObj["autoscalingSettings"] = mgmtMap["autoscalingSettings"]
1819
}
1920

2021
if d.HasChange("management_cluster") {
2122
clusterUpdateMask = append(clusterUpdateMask, "nodeTypeConfigs.*.nodeCount")
23+
clusterUpdateMask = append(clusterUpdateMask, "autoscalingSettings")
2224
}
2325

2426
clusterPatchUrl, err := transport_tpg.AddQueryParams(clusterUrl, map[string]string{"updateMask": strings.Join(clusterUpdateMask, ",")})

mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go

+110-6
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,27 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T
5555
},
5656

5757
{
58-
Config: testVmwareenginePrivateCloudUpdateConfig(context),
58+
Config: testVmwareenginePrivateCloudUpdateNodeConfig(context),
59+
Check: resource.ComposeTestCheckFunc(
60+
acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(
61+
"data.google_vmwareengine_private_cloud.ds",
62+
"google_vmwareengine_private_cloud.vmw-engine-pc",
63+
map[string]struct{}{
64+
"type": {},
65+
"deletion_delay_hours": {},
66+
"send_deletion_delay_hours_if_zero": {},
67+
}),
68+
),
69+
},
70+
{
71+
ResourceName: "google_vmwareengine_private_cloud.vmw-engine-pc",
72+
ImportState: true,
73+
ImportStateVerify: true,
74+
ImportStateVerifyIgnore: []string{"location", "name", "update_time", "type", "deletion_delay_hours", "send_deletion_delay_hours_if_zero"},
75+
},
76+
77+
{
78+
Config: testVmwareenginePrivateCloudUpdateAutoscaleConfig(context),
5979
Check: resource.ComposeTestCheckFunc(
6080
acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(
6181
"data.google_vmwareengine_private_cloud.ds",
@@ -131,27 +151,31 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T
131151
}
132152

133153
func testVmwareenginePrivateCloudCreateConfig(context map[string]interface{}) string {
134-
return testVmwareenginePrivateCloudConfig(context, "sample description", "TIME_LIMITED", 1, 1) + testVmwareengineVcenterNSXCredentailsConfig(context)
154+
return testVmwareenginePrivateCloudConfig(context, "sample description", "STANDARD", 3, 8) + testVmwareengineVcenterNSXCredentailsConfig(context)
135155
}
136156

137-
func testVmwareenginePrivateCloudUpdateConfig(context map[string]interface{}) string {
157+
func testVmwareenginePrivateCloudUpdateNodeConfig(context map[string]interface{}) string {
138158
return testVmwareenginePrivateCloudConfig(context, "sample updated description", "STANDARD", 3, 8) + testVmwareengineVcenterNSXCredentailsConfig(context)
139159
}
140160

161+
func testVmwareenginePrivateCloudUpdateAutoscaleConfig(context map[string]interface{}) string {
162+
return testVmwareenginePrivateCloudAutoscaleConfig(context, "sample updated description", "STANDARD", 3, 8) + testVmwareengineVcenterNSXCredentailsConfig(context)
163+
}
164+
141165
func testVmwareenginePrivateCloudDelayedDeleteConfig(context map[string]interface{}) string {
142166
return testVmwareenginePrivateCloudDeletedConfig(context)
143167
}
144168

145169
func testVmwareenginePrivateCloudUndeleteConfig(context map[string]interface{}) string {
146-
return testVmwareenginePrivateCloudConfig(context, "sample updated description", "STANDARD", 3, 0) + testVmwareengineVcenterNSXCredentailsConfig(context)
170+
return testVmwareenginePrivateCloudAutoscaleConfig(context, "sample updated description", "STANDARD", 3, 0) + testVmwareengineVcenterNSXCredentailsConfig(context)
147171
}
148172

149173
func testVmwareengineSubnetImportConfig(context map[string]interface{}) string {
150-
return testVmwareenginePrivateCloudConfig(context, "sample updated description", "STANDARD", 3, 0) + testVmwareengineSubnetConfig(context, "192.168.1.0/26")
174+
return testVmwareenginePrivateCloudAutoscaleConfig(context, "sample updated description", "STANDARD", 3, 0) + testVmwareengineSubnetConfig(context, "192.168.1.0/26")
151175
}
152176

153177
func testVmwareengineSubnetUpdateConfig(context map[string]interface{}) string {
154-
return testVmwareenginePrivateCloudConfig(context, "sample updated description", "STANDARD", 3, 0) + testVmwareengineSubnetConfig(context, "192.168.2.0/26")
178+
return testVmwareenginePrivateCloudAutoscaleConfig(context, "sample updated description", "STANDARD", 3, 0) + testVmwareengineSubnetConfig(context, "192.168.2.0/26")
155179
}
156180

157181
func testVmwareenginePrivateCloudConfig(context map[string]interface{}, description, pcType string, nodeCount, delayHours int) string {
@@ -184,6 +208,86 @@ resource "google_vmwareengine_private_cloud" "vmw-engine-pc" {
184208
node_type_id = "standard-72"
185209
node_count = "%{node_count}"
186210
custom_core_count = 32
211+
}
212+
autoscaling_settings {
213+
autoscaling_policies {
214+
autoscale_policy_id = "autoscaling-policy"
215+
node_type_id = "standard-72"
216+
scale_out_size = 1
217+
storage_thresholds {
218+
scale_out = 60
219+
scale_in = 20
220+
}
221+
}
222+
min_cluster_node_count = 3
223+
max_cluster_node_count = 8
224+
cool_down_period = "1800s"
225+
}
226+
}
227+
}
228+
229+
data "google_vmwareengine_private_cloud" "ds" {
230+
location = "%{region}-b"
231+
name = "tf-test-sample-pc%{random_suffix}"
232+
depends_on = [
233+
google_vmwareengine_private_cloud.vmw-engine-pc,
234+
]
235+
}
236+
`, context)
237+
}
238+
239+
func testVmwareenginePrivateCloudAutoscaleConfig(context map[string]interface{}, description, pcType string, nodeCount, delayHours int) string {
240+
context["node_count"] = nodeCount
241+
context["delay_hrs"] = delayHours
242+
context["description"] = description
243+
context["type"] = pcType
244+
return acctest.Nprintf(`
245+
resource "google_vmwareengine_network" "vmw-engine-nw" {
246+
name = "tf-test-pc-nw-%{random_suffix}"
247+
location = "global"
248+
type = "STANDARD"
249+
description = "PC network description."
250+
}
251+
252+
resource "google_vmwareengine_private_cloud" "vmw-engine-pc" {
253+
location = "%{region}-b"
254+
name = "tf-test-sample-pc%{random_suffix}"
255+
description = "%{description}"
256+
type = "%{type}"
257+
deletion_delay_hours = "%{delay_hrs}"
258+
send_deletion_delay_hours_if_zero = true
259+
network_config {
260+
management_cidr = "192.168.0.0/24"
261+
vmware_engine_network = google_vmwareengine_network.vmw-engine-nw.id
262+
}
263+
management_cluster {
264+
cluster_id = "tf-test-sample-mgmt-cluster-custom-core-count%{random_suffix}"
265+
node_type_configs {
266+
node_type_id = "standard-72"
267+
node_count = "%{node_count}"
268+
custom_core_count = 32
269+
}
270+
autoscaling_settings {
271+
autoscaling_policies {
272+
autoscale_policy_id = "autoscaling-policy"
273+
node_type_id = "standard-72"
274+
scale_out_size = 1
275+
cpu_thresholds {
276+
scale_out = 80
277+
scale_in = 15
278+
}
279+
consumed_memory_thresholds {
280+
scale_out = 75
281+
scale_in = 20
282+
}
283+
storage_thresholds {
284+
scale_out = 80
285+
scale_in = 20
286+
}
287+
}
288+
min_cluster_node_count = 3
289+
max_cluster_node_count = 8
290+
cool_down_period = "1800s"
187291
}
188292
}
189293
}

0 commit comments

Comments
 (0)