Skip to content

Commit

Permalink
Add reservation affinity (#6412) (#12375)
Browse files Browse the repository at this point in the history
* Add reservation affinity

* Add reservation affinity tests

* Fix tests

* Create reservation in test sample

* Fix expected reservation name

* Fix specific reservation affinity test

* Disable on destroy to false in test

* Add node pool tests and documentation

* Fix test argument

* Node pool test corrections

Signed-off-by: Modular Magician <magic-modules@google.com>

Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
modular-magician authored Aug 24, 2022
1 parent fd20707 commit cdc6ec5
Show file tree
Hide file tree
Showing 5 changed files with 399 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .changelog/6412.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
container: Added general field `reservation_affinity` to `google_container_node_pool`
```
62 changes: 61 additions & 1 deletion google/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,39 @@ func schemaNodeConfig() *schema.Schema {
Default: false,
Description: `Whether the nodes are created as preemptible VM instances.`,
},

"reservation_affinity": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Description: `The reservation affinity configuration for the node pool.`,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"consume_reservation_type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Corresponds to the type of reservation consumption.`,
ValidateFunc: validation.StringInSlice([]string{"UNSPECIFIED", "NO_RESERVATION", "ANY_RESERVATION", "SPECIFIC_RESERVATION"}, false),
},
"key": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: `The label key of a reservation resource.`,
},
"values": {
Type: schema.TypeSet,
Description: "The label values of the reservation resource.",
ForceNew: true,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
"spot": {
Type: schema.TypeBool,
Optional: true,
Expand Down Expand Up @@ -369,6 +401,21 @@ func expandNodeConfig(v interface{}) *container.NodeConfig {
}
}

if v, ok := nodeConfig["reservation_affinity"]; ok && len(v.([]interface{})) > 0 {
conf := v.([]interface{})[0].(map[string]interface{})
valuesSet := conf["values"].(*schema.Set)
values := make([]string, valuesSet.Len())
for i, value := range valuesSet.List() {
values[i] = value.(string)
}

nc.ReservationAffinity = &container.ReservationAffinity{
ConsumeReservationType: conf["consume_reservation_type"].(string),
Key: conf["key"].(string),
Values: values,
}
}

if scopes, ok := nodeConfig["oauth_scopes"]; ok {
scopesSet := scopes.(*schema.Set)
scopes := make([]string, scopesSet.Len())
Expand Down Expand Up @@ -496,6 +543,7 @@ func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} {
"local_ssd_count": c.LocalSsdCount,
"gcfs_config": flattenGcfsConfig(c.GcfsConfig),
"gvnic": flattenGvnic(c.Gvnic),
"reservation_affinity": flattenGKEReservationAffinity(c.ReservationAffinity),
"service_account": c.ServiceAccount,
"metadata": c.Metadata,
"image_type": c.ImageType,
Expand Down Expand Up @@ -561,6 +609,18 @@ func flattenGvnic(c *container.VirtualNIC) []map[string]interface{} {
return result
}

func flattenGKEReservationAffinity(c *container.ReservationAffinity) []map[string]interface{} {
result := []map[string]interface{}{}
if c != nil {
result = append(result, map[string]interface{}{
"consume_reservation_type": c.ConsumeReservationType,
"key": c.Key,
"values": c.Values,
})
}
return result
}

func flattenTaints(c []*container.NodeTaint) []map[string]interface{} {
result := []map[string]interface{}{}
for _, taint := range c {
Expand Down
173 changes: 173 additions & 0 deletions google/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,69 @@ func TestAccContainerCluster_withNodeConfigShieldedInstanceConfig(t *testing.T)
})
}

func TestAccContainerCluster_withNodeConfigReservationAffinity(t *testing.T) {
t.Parallel()

clusterName := fmt.Sprintf("tf-test-cluster-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withNodeConfigReservationAffinity(clusterName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.with_node_config",
"node_config.0.reservation_affinity.#", "1"),
resource.TestCheckResourceAttr("google_container_cluster.with_node_config",
"node_config.0.reservation_affinity.0.consume_reservation_type", "ANY_RESERVATION"),
),
},
{
ResourceName: "google_container_cluster.with_node_config",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccContainerCluster_withNodeConfigReservationAffinitySpecific(t *testing.T) {
t.Parallel()

reservationName := fmt.Sprintf("tf-test-reservation-%s", randString(t, 10))
clusterName := fmt.Sprintf("tf-test-cluster-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withNodeConfigReservationAffinitySpecific(reservationName, clusterName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.with_node_config",
"node_config.0.reservation_affinity.#", "1"),
resource.TestCheckResourceAttr("google_container_cluster.with_node_config",
"node_config.0.reservation_affinity.0.consume_reservation_type", "SPECIFIC_RESERVATION"),
resource.TestCheckResourceAttr("google_container_cluster.with_node_config",
"node_config.0.reservation_affinity.0.key", "compute.googleapis.com/reservation-name"),
resource.TestCheckResourceAttr("google_container_cluster.with_node_config",
"node_config.0.reservation_affinity.0.values.#", "1"),
resource.TestCheckResourceAttr("google_container_cluster.with_node_config",
"node_config.0.reservation_affinity.0.values.0", reservationName),
),
},
{
ResourceName: "google_container_cluster.with_node_config",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccContainerCluster_withWorkloadMetadataConfig(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -3112,6 +3175,116 @@ resource "google_container_cluster" "with_node_config" {
`, clusterName)
}

func testAccContainerCluster_withNodeConfigReservationAffinity(clusterName string) string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_node_config" {
name = "%s"
location = "us-central1-f"
initial_node_count = 1
node_config {
machine_type = "e2-medium"
disk_size_gb = 15
disk_type = "pd-ssd"
oauth_scopes = [
"https://www.googleapis.com/auth/monitoring",
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
]
service_account = "default"
metadata = {
foo = "bar"
disable-legacy-endpoints = "true"
}
labels = {
foo = "bar"
}
tags = ["foo", "bar"]
preemptible = true
// Updatable fields
image_type = "COS_CONTAINERD"
reservation_affinity {
consume_reservation_type = "ANY_RESERVATION"
}
}
}
`, clusterName)
}

func testAccContainerCluster_withNodeConfigReservationAffinitySpecific(reservation, clusterName string) string {
return fmt.Sprintf(`
resource "google_project_service" "compute" {
service = "compute.googleapis.com"
disable_on_destroy = false
}
resource "google_project_service" "container" {
service = "container.googleapis.com"
disable_on_destroy = false
depends_on = [google_project_service.compute]
}
resource "google_compute_reservation" "gce_reservation" {
name = "%s"
zone = "us-central1-f"
specific_reservation {
count = 1
instance_properties {
machine_type = "n1-standard-1"
}
}
specific_reservation_required = true
depends_on = [google_project_service.compute]
}
resource "google_container_cluster" "with_node_config" {
name = "%s"
location = "us-central1-f"
initial_node_count = 1
node_config {
machine_type = "n1-standard-1"
disk_size_gb = 15
disk_type = "pd-ssd"
oauth_scopes = [
"https://www.googleapis.com/auth/monitoring",
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
]
service_account = "default"
metadata = {
foo = "bar"
disable-legacy-endpoints = "true"
}
labels = {
foo = "bar"
}
tags = ["foo", "bar"]
// Updatable fields
image_type = "COS_CONTAINERD"
reservation_affinity {
consume_reservation_type = "SPECIFIC_RESERVATION"
key = "compute.googleapis.com/reservation-name"
values = [
google_compute_reservation.gce_reservation.name
]
}
}
depends_on = [google_project_service.container]
}
`, reservation, clusterName)
}

func testAccContainerCluster_withWorkloadMetadataConfig(clusterName string) string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
Expand Down
Loading

0 comments on commit cdc6ec5

Please sign in to comment.