diff --git a/.changelog/7059.txt b/.changelog/7059.txt
new file mode 100644
index 00000000000..347ede44cb9
--- /dev/null
+++ b/.changelog/7059.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+compute: added `share_settings` field to the `google_compute_node_group` resource.
+```
diff --git a/google/resource_compute_node_group.go b/google/resource_compute_node_group.go
index 7237dd2c460..5dcd79fcdcb 100644
--- a/google/resource_compute_node_group.go
+++ b/google/resource_compute_node_group.go
@@ -133,6 +133,46 @@ than or equal to max-nodes. The default value is 0.`,
ForceNew: true,
Description: `Name of the resource.`,
},
+ "share_settings": {
+ Type: schema.TypeList,
+ Computed: true,
+ Optional: true,
+ ForceNew: true,
+ Description: `Share settings for the node group.`,
+ MaxItems: 1,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "share_type": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ ValidateFunc: validateEnum([]string{"ORGANIZATION", "SPECIFIC_PROJECTS", "LOCAL"}),
+ Description: `Node group sharing type. Possible values: ["ORGANIZATION", "SPECIFIC_PROJECTS", "LOCAL"]`,
+ },
+ "project_map": {
+ Type: schema.TypeSet,
+ Optional: true,
+ ForceNew: true,
+ Description: `A map of project id and project config. This is only valid when shareType's value is SPECIFIC_PROJECTS.`,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "id": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ },
+ "project_id": {
+ Type: schema.TypeString,
+ Required: true,
+ ForceNew: true,
+ Description: `The project id/number should be the same as the key of this project config in the project map.`,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
"size": {
Type: schema.TypeInt,
Computed: true,
@@ -219,6 +259,12 @@ func resourceComputeNodeGroupCreate(d *schema.ResourceData, meta interface{}) er
} else if v, ok := d.GetOkExists("autoscaling_policy"); !isEmptyValue(reflect.ValueOf(autoscalingPolicyProp)) && (ok || !reflect.DeepEqual(v, autoscalingPolicyProp)) {
obj["autoscalingPolicy"] = autoscalingPolicyProp
}
+ shareSettingsProp, err := expandComputeNodeGroupShareSettings(d.Get("share_settings"), d, config)
+ if err != nil {
+ return err
+ } else if v, ok := d.GetOkExists("share_settings"); !isEmptyValue(reflect.ValueOf(shareSettingsProp)) && (ok || !reflect.DeepEqual(v, shareSettingsProp)) {
+ obj["shareSettings"] = shareSettingsProp
+ }
zoneProp, err := expandComputeNodeGroupZone(d.Get("zone"), d, config)
if err != nil {
return err
@@ -338,6 +384,9 @@ func resourceComputeNodeGroupRead(d *schema.ResourceData, meta interface{}) erro
if err := d.Set("autoscaling_policy", flattenComputeNodeGroupAutoscalingPolicy(res["autoscalingPolicy"], d, config)); err != nil {
return fmt.Errorf("Error reading NodeGroup: %s", err)
}
+ if err := d.Set("share_settings", flattenComputeNodeGroupShareSettings(res["shareSettings"], d, config)); err != nil {
+ return fmt.Errorf("Error reading NodeGroup: %s", err)
+ }
if err := d.Set("zone", flattenComputeNodeGroupZone(res["zone"], d, config)); err != nil {
return fmt.Errorf("Error reading NodeGroup: %s", err)
}
@@ -583,6 +632,44 @@ func flattenComputeNodeGroupAutoscalingPolicyMaxNodes(v interface{}, d *schema.R
return v // let terraform core handle it otherwise
}
+func flattenComputeNodeGroupShareSettings(v interface{}, d *schema.ResourceData, config *Config) interface{} {
+ if v == nil {
+ return nil
+ }
+ original := v.(map[string]interface{})
+ if len(original) == 0 {
+ return nil
+ }
+ transformed := make(map[string]interface{})
+ transformed["share_type"] =
+ flattenComputeNodeGroupShareSettingsShareType(original["shareType"], d, config)
+ transformed["project_map"] =
+ flattenComputeNodeGroupShareSettingsProjectMap(original["projectMap"], d, config)
+ return []interface{}{transformed}
+}
+func flattenComputeNodeGroupShareSettingsShareType(v interface{}, d *schema.ResourceData, config *Config) interface{} {
+ return v
+}
+
+func flattenComputeNodeGroupShareSettingsProjectMap(v interface{}, d *schema.ResourceData, config *Config) interface{} {
+ if v == nil {
+ return v
+ }
+ l := v.(map[string]interface{})
+ transformed := make([]interface{}, 0, len(l))
+ for k, raw := range l {
+ original := raw.(map[string]interface{})
+ transformed = append(transformed, map[string]interface{}{
+ "id": k,
+ "project_id": flattenComputeNodeGroupShareSettingsProjectMapProjectId(original["projectId"], d, config),
+ })
+ }
+ return transformed
+}
+func flattenComputeNodeGroupShareSettingsProjectMapProjectId(v interface{}, d *schema.ResourceData, config *Config) interface{} {
+ return v
+}
+
func flattenComputeNodeGroupZone(v interface{}, d *schema.ResourceData, config *Config) interface{} {
if v == nil {
return v
@@ -682,6 +769,65 @@ func expandComputeNodeGroupAutoscalingPolicyMaxNodes(v interface{}, d TerraformR
return v, nil
}
+func expandComputeNodeGroupShareSettings(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+ l := v.([]interface{})
+ if len(l) == 0 || l[0] == nil {
+ return nil, nil
+ }
+ raw := l[0]
+ original := raw.(map[string]interface{})
+ transformed := make(map[string]interface{})
+
+ transformedShareType, err := expandComputeNodeGroupShareSettingsShareType(original["share_type"], d, config)
+ if err != nil {
+ return nil, err
+ } else if val := reflect.ValueOf(transformedShareType); val.IsValid() && !isEmptyValue(val) {
+ transformed["shareType"] = transformedShareType
+ }
+
+ transformedProjectMap, err := expandComputeNodeGroupShareSettingsProjectMap(original["project_map"], d, config)
+ if err != nil {
+ return nil, err
+ } else if val := reflect.ValueOf(transformedProjectMap); val.IsValid() && !isEmptyValue(val) {
+ transformed["projectMap"] = transformedProjectMap
+ }
+
+ return transformed, nil
+}
+
+func expandComputeNodeGroupShareSettingsShareType(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+ return v, nil
+}
+
+func expandComputeNodeGroupShareSettingsProjectMap(v interface{}, d TerraformResourceData, config *Config) (map[string]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{})
+
+ transformedProjectId, err := expandComputeNodeGroupShareSettingsProjectMapProjectId(original["project_id"], d, config)
+ if err != nil {
+ return nil, err
+ } else if val := reflect.ValueOf(transformedProjectId); val.IsValid() && !isEmptyValue(val) {
+ transformed["projectId"] = transformedProjectId
+ }
+
+ transformedId, err := expandString(original["id"], d, config)
+ if err != nil {
+ return nil, err
+ }
+ m[transformedId] = transformed
+ }
+ return m, nil
+}
+
+func expandComputeNodeGroupShareSettingsProjectMapProjectId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+ return v, nil
+}
+
func expandComputeNodeGroupZone(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
f, err := parseGlobalFieldValue("zones", v.(string), "project", d, config, true)
if err != nil {
diff --git a/google/resource_compute_node_group_generated_test.go b/google/resource_compute_node_group_generated_test.go
index fce30529de2..e112e99c514 100644
--- a/google/resource_compute_node_group_generated_test.go
+++ b/google/resource_compute_node_group_generated_test.go
@@ -119,6 +119,65 @@ resource "google_compute_node_group" "nodes" {
`, context)
}
+func TestAccComputeNodeGroup_nodeGroupShareSettingsExample(t *testing.T) {
+ t.Parallel()
+
+ context := map[string]interface{}{
+ "org_id": getTestOrgFromEnv(t),
+ "random_suffix": randString(t, 10),
+ }
+
+ vcrTest(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ Providers: testAccProviders,
+ CheckDestroy: testAccCheckComputeNodeGroupDestroyProducer(t),
+ Steps: []resource.TestStep{
+ {
+ Config: testAccComputeNodeGroup_nodeGroupShareSettingsExample(context),
+ },
+ {
+ ResourceName: "google_compute_node_group.nodes",
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"node_template", "initial_size", "zone"},
+ },
+ },
+ })
+}
+
+func testAccComputeNodeGroup_nodeGroupShareSettingsExample(context map[string]interface{}) string {
+ return Nprintf(`
+resource "google_project" "guest_project" {
+ project_id = "tf-test-project-id%{random_suffix}"
+ name = "tf-test-project-name%{random_suffix}"
+ org_id = "%{org_id}"
+}
+
+resource "google_compute_node_template" "soletenant-tmpl" {
+ name = "tf-test-soletenant-tmpl%{random_suffix}"
+ region = "us-central1"
+ node_type = "n1-node-96-624"
+}
+
+resource "google_compute_node_group" "nodes" {
+ name = "tf-test-soletenant-group%{random_suffix}"
+ zone = "us-central1-f"
+ description = "example google_compute_node_group for Terraform Google Provider"
+
+ size = 1
+ node_template = google_compute_node_template.soletenant-tmpl.id
+
+ share_settings {
+ share_type = "SPECIFIC_PROJECTS"
+ project_map {
+ id = google_project.guest_project.project_id
+ project_id = google_project.guest_project.project_id
+ }
+ }
+}
+`, context)
+}
+
func testAccCheckComputeNodeGroupDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
diff --git a/website/docs/r/compute_node_group.html.markdown b/website/docs/r/compute_node_group.html.markdown
index 5bc81bb0927..bb7432d45e7 100644
--- a/website/docs/r/compute_node_group.html.markdown
+++ b/website/docs/r/compute_node_group.html.markdown
@@ -90,6 +90,39 @@ resource "google_compute_node_group" "nodes" {
}
}
```
+## Example Usage - Node Group Share Settings
+
+
+```hcl
+resource "google_project" "guest_project" {
+ project_id = "project-id"
+ name = "project-name"
+ org_id = "123456789"
+}
+
+resource "google_compute_node_template" "soletenant-tmpl" {
+ name = "soletenant-tmpl"
+ region = "us-central1"
+ node_type = "n1-node-96-624"
+}
+
+resource "google_compute_node_group" "nodes" {
+ name = "soletenant-group"
+ zone = "us-central1-f"
+ description = "example google_compute_node_group for Terraform Google Provider"
+
+ size = 1
+ node_template = google_compute_node_template.soletenant-tmpl.id
+
+ share_settings {
+ share_type = "SPECIFIC_PROJECTS"
+ project_map {
+ id = google_project.guest_project.project_id
+ project_id = google_project.guest_project.project_id
+ }
+ }
+}
+```
## Argument Reference
@@ -135,6 +168,11 @@ The following arguments are supported:
group autoscaler to automatically manage the sizes of your node groups.
Structure is [documented below](#nested_autoscaling_policy).
+* `share_settings` -
+ (Optional)
+ Share settings for the node group.
+ Structure is [documented below](#nested_share_settings).
+
* `zone` -
(Optional)
Zone where this node group is located
@@ -171,6 +209,27 @@ The following arguments are supported:
Maximum size of the node group. Set to a value less than or equal
to 100 and greater than or equal to min-nodes.
+The `share_settings` block supports:
+
+* `share_type` -
+ (Required)
+ Node group sharing type.
+ Possible values are `ORGANIZATION`, `SPECIFIC_PROJECTS`, and `LOCAL`.
+
+* `project_map` -
+ (Optional)
+ A map of project id and project config. This is only valid when shareType's value is SPECIFIC_PROJECTS.
+ Structure is [documented below](#nested_project_map).
+
+
+The `project_map` block supports:
+
+* `id` - (Required) The identifier for this object. Format specified above.
+
+* `project_id` -
+ (Required)
+ The project id/number should be the same as the key of this project config in the project map.
+
## Attributes Reference
In addition to the arguments listed above, the following computed attributes are exported: