Skip to content

Commit

Permalink
Add GKE Sandbox support to Terraform.
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
jeremyje authored and modular-magician committed Jun 18, 2019
1 parent 138039c commit aa675d9
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 10 deletions.
42 changes: 40 additions & 2 deletions google-beta/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ var schemaNodeConfig = &schema.Schema{
"labels": {
Type: schema.TypeMap,
Optional: true,
// Computed=true because GKE Sandbox will automatically add labels to nodes that can/cannot run sandboxed pods.
Computed: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
Expand Down Expand Up @@ -146,8 +148,10 @@ var schemaNodeConfig = &schema.Schema{
},

"taint": {
Type: schema.TypeList,
Optional: true,
Type: schema.TypeList,
Optional: true,
// Computed=true because GKE Sandbox will automatically add taints to nodes that can/cannot run sandboxed pods.
Computed: true,
ForceNew: true,
DiffSuppressFunc: taintDiffSuppress,
Elem: &schema.Resource{
Expand Down Expand Up @@ -188,6 +192,22 @@ var schemaNodeConfig = &schema.Schema{
},
},
},

"sandbox_config": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sandbox_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"gvisor"}, false),
},
},
},
},
},
},
}
Expand Down Expand Up @@ -306,6 +326,13 @@ func expandNodeConfig(v interface{}) *containerBeta.NodeConfig {
}
}

if v, ok := nodeConfig["sandbox_config"]; ok && len(v.([]interface{})) > 0 {
conf := v.([]interface{})[0].(map[string]interface{})
nc.SandboxConfig = &containerBeta.SandboxConfig{
SandboxType: conf["sandbox_type"].(string),
}
}

return nc
}

Expand All @@ -331,6 +358,7 @@ func flattenNodeConfig(c *containerBeta.NodeConfig) []map[string]interface{} {
"min_cpu_platform": c.MinCpuPlatform,
"taint": flattenTaints(c.Taints),
"workload_metadata_config": flattenWorkloadMetadataConfig(c.WorkloadMetadataConfig),
"sandbox_config": flattenSandboxConfig(c.SandboxConfig),
})

if len(c.OauthScopes) > 0 {
Expand Down Expand Up @@ -373,6 +401,16 @@ func flattenWorkloadMetadataConfig(c *containerBeta.WorkloadMetadataConfig) []ma
return result
}

func flattenSandboxConfig(c *containerBeta.SandboxConfig) []map[string]interface{} {
result := []map[string]interface{}{}
if c != nil {
result = append(result, map[string]interface{}{
"sandbox_type": c.SandboxType,
})
}
return result
}

func taintDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
if strings.HasSuffix(k, "#") {
oldCount, oldErr := strconv.Atoi(old)
Expand Down
71 changes: 64 additions & 7 deletions google-beta/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,34 @@ func TestAccContainerCluster_withWorkloadMetadataConfig(t *testing.T) {
})
}

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

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withSandboxConfig(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.with_sandbox_config",
"node_config.0.sandbox_config.0.sandbox_type", "gvisor"),
resource.TestCheckResourceAttr("google_container_cluster.with_sandbox_config",
"node_pool.0.node_config.0.sandbox_config.0.sandbox_type", "gvisor"),
),
},
{
ResourceName: "google_container_cluster.with_sandbox_config",
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"min_master_version"},
},
},
})
}

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

Expand Down Expand Up @@ -2620,19 +2648,48 @@ resource "google_container_cluster" "with_workload_metadata_config" {
node_version = "${data.google_container_engine_versions.central1a.latest_node_version}"
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
workload_metadata_config {
node_metadata = "SECURE"
}
workload_metadata_config {
node_metadata = "SECURE"
}
}
}
`, acctest.RandString(10))
}

func testAccContainerCluster_withSandboxConfig() string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
zone = "us-central1-a"
}
resource "google_container_cluster" "with_sandbox_config" {
name = "cluster-test-%s"
zone = "us-central1-a"
initial_node_count = 1
min_master_version = "${data.google_container_engine_versions.central1a.latest_master_version}"
node_version = "${data.google_container_engine_versions.central1a.latest_node_version}"
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
image_type = "COS_CONTAINERD"
sandbox_config {
sandbox_type = "gvisor"
}
}
}
`, acctest.RandString(10))
}

func testAccContainerCluster_networkRef() string {
return fmt.Sprintf(`
resource "google_compute_network" "container_network" {
Expand Down
61 changes: 60 additions & 1 deletion google-beta/resource_container_node_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,34 @@ func TestAccContainerNodePool_withWorkloadIdentityConfig(t *testing.T) {
})
}

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

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerNodePool_withSandboxConfig(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config",
"node_config.0.sandbox_config.0.sandbox_type", "gvisor"),
// The default-pool does not get gvisor.
// https://cloud.google.com/kubernetes-engine/docs/how-to/sandbox-pods#limitations-nodepool
resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config",
"node_pool.1.node_config.0.sandbox_config.0.sandbox_type", "gvisor"),
),
},
{
ResourceName: "google_container_node_pool.with_sandbox_config",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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

Expand Down Expand Up @@ -994,7 +1022,6 @@ resource "google_container_node_pool" "with_workload_metadata_config" {
zone = "us-central1-a"
cluster = "${google_container_cluster.cluster.name}"
initial_node_count = 1
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
Expand All @@ -1009,6 +1036,38 @@ resource "google_container_node_pool" "with_workload_metadata_config" {
`, projectID, acctest.RandString(10), acctest.RandString(10))
}

func testAccContainerNodePool_withSandboxConfig() string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
zone = "us-central1-a"
}
resource "google_container_cluster" "cluster" {
name = "tf-cluster-nodepool-test-%s"
zone = "us-central1-a"
initial_node_count = 1
min_master_version = "${data.google_container_engine_versions.central1a.latest_master_version}"
}
resource "google_container_node_pool" "with_sandbox_config" {
name = "tf-nodepool-test-%s"
zone = "us-central1-a"
cluster = "${google_container_cluster.cluster.name}"
initial_node_count = 1
node_config {
image_type = "COS_CONTAINERD"
sandbox_config {
sandbox_type = "gvisor"
}
oauth_scopes = [
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
}
}
`, acctest.RandString(10), acctest.RandString(10))
}

func testAccContainerNodePool_withGPU() string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1c" {
Expand Down
1 change: 1 addition & 0 deletions google-beta/resource_sql_database_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"

sqladmin "google.golang.org/api/sqladmin/v1beta4"
)

Expand Down
9 changes: 9 additions & 0 deletions website/docs/r/container_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,9 @@ The `node_config` block supports:
are preemptible. See the [official documentation](https://cloud.google.com/container-engine/docs/preemptible-vm)
for more information. Defaults to false.

* `sandbox_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/provider_versions.html)) [GKE Sandbox](https://cloud.google.com/kubernetes-engine/docs/how-to/sandbox-pods) configuration. When enabling this feature you must specify `image_type = "cos_containerd"` and `node_version = "1.12.6-gke.8"` or later to use it.
Structure is documented below.

* `service_account` - (Optional) The service account to be used by the Node VMs.
If not specified, the "default" service account is used.
In order to use the configured `oauth_scopes` for logging and monitoring, the service account being used needs the
Expand Down Expand Up @@ -572,6 +575,12 @@ In addition, the `private_cluster_config` allows access to the following read-on

* `public_endpoint` - The external IP address of this cluster's master endpoint.

The `sandbox_type` block supports:

* `sandbox_type` (Required) Which sandbox to use for pods in the node pool.
Accepted values are:
* gvisor: Pods run within a gVisor sandbox.

The `taint` block supports:

* `key` (Required) Key for taint.
Expand Down

0 comments on commit aa675d9

Please sign in to comment.