Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add container cluster network policy addon #630

Merged
merged 15 commits into from
Nov 27, 2017
77 changes: 77 additions & 0 deletions google/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,28 @@ func resourceContainerCluster() *schema.Resource {
StateFunc: StoreResourceName,
},

"network_policy": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"provider": {
Type: schema.TypeString,
Default: "PROVIDER_UNSPECIFIED",
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"PROVIDER_UNSPECIFIED", "CALICO"}, false),
},
},
},
},

"node_config": schemaNodeConfig,

"node_pool": {
Expand Down Expand Up @@ -398,6 +420,10 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
cluster.Network = network
}

if v, ok := d.GetOk("network_policy"); ok && len(v.([]interface{})) > 0 {
cluster.NetworkPolicy = expandNetworkPolicy(v)
}

if v, ok := d.GetOk("subnetwork"); ok {
cluster.Subnetwork = v.(string)
}
Expand Down Expand Up @@ -480,6 +506,9 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
}

d.Set("name", cluster.Name)

d.Set("network_policy", flattenNetworkPolicy(cluster.NetworkPolicy))

d.Set("zone", cluster.Zone)

locations := []string{}
Expand Down Expand Up @@ -743,6 +772,29 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
d.SetPartial("monitoring_service")
}

if d.HasChange("network_policy") {
np, _ := d.GetOk("network_policy")

req := &container.SetNetworkPolicyRequest{
NetworkPolicy: expandNetworkPolicy(np),
}
op, err := config.clientContainer.Projects.Zones.Clusters.SetNetworkPolicy(
project, zoneName, clusterName, req).Do()
if err != nil {
return err
}

// Wait until it's updated
waitErr := containerOperationWait(config, op, project, zoneName, "updating GKE cluster network policy", timeoutInMinutes, 2)
if waitErr != nil {
return waitErr
}
log.Printf("[INFO] Network policy for GKE cluster %s has been updated", d.Id())

d.SetPartial("network_policy")

}

if n, ok := d.GetOk("node_pool.#"); ok {
for i := 0; i < n.(int); i++ {
if err := nodePoolUpdate(d, meta, clusterName, fmt.Sprintf("node_pool.%d.", i), timeoutInMinutes); err != nil {
Expand Down Expand Up @@ -886,6 +938,31 @@ func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.Mas
return result
}

func expandNetworkPolicy(configured interface{}) *container.NetworkPolicy {
result := &container.NetworkPolicy{}
if configured != nil && len(configured.([]interface{})) > 0 {
config := configured.([]interface{})[0].(map[string]interface{})
if enabled, ok := config["enabled"]; ok && enabled.(bool) {
result.Enabled = true
if provider, ok := config["provider"]; ok {
result.Provider = provider.(string)
}
}
}
return result
}

func flattenNetworkPolicy(c *container.NetworkPolicy) []map[string]interface{} {
result := []map[string]interface{}{}
if c != nil {
result = append(result, map[string]interface{}{
"enabled": c.Enabled,
"provider": c.Provider,
})
}
return result
}

func flattenClusterAddonsConfig(c *container.AddonsConfig) []map[string]interface{} {
result := make(map[string]interface{})
if c.HorizontalPodAutoscaling != nil {
Expand Down
61 changes: 61 additions & 0 deletions google/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,38 @@ func TestAccContainerCluster_withMasterAuth(t *testing.T) {
})
}

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

clusterName := fmt.Sprintf("cluster-test-%s", acctest.RandString(10))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckContainerClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withNetworkPolicyEnabled(clusterName),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerCluster(
"google_container_cluster.with_network_policy_enabled"),
resource.TestCheckResourceAttr("google_container_cluster.with_network_policy_enabled",
"network_policy.#", "1"),
),
},
{
Config: testAccContainerCluster_removeNetworkPolicy(clusterName),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerCluster(
"google_container_cluster.with_network_policy_enabled"),
resource.TestCheckNoResourceAttr("google_container_cluster.with_network_policy_enabled",
"network_policy"),
),
},
},
})
}

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

Expand Down Expand Up @@ -659,6 +691,12 @@ func testAccCheckContainerCluster(n string) resource.TestCheckFunc {
{"node_version", cluster.CurrentNodeVersion},
}

if cluster.NetworkPolicy != nil {
clusterTests = append(clusterTests,
clusterTestField{"network_policy.0.enabled", cluster.NetworkPolicy.Enabled},
clusterTestField{"network_policy.0.provider", cluster.NetworkPolicy.Provider},
)
}
// Remove Zone from additional_zones since that's what the resource writes in state
additionalZones := []string{}
for _, location := range cluster.Locations {
Expand Down Expand Up @@ -921,6 +959,29 @@ resource "google_container_cluster" "with_master_auth" {
}
}`, acctest.RandString(10))

func testAccContainerCluster_withNetworkPolicyEnabled(clusterName string) string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_network_policy_enabled" {
name = "%s"
zone = "us-central1-a"
initial_node_count = 1

network_policy {
enabled = true
provider = "CALICO"
}
}`, clusterName)
}

func testAccContainerCluster_removeNetworkPolicy(clusterName string) string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_network_policy_enabled" {
name = "%s"
zone = "us-central1-a"
initial_node_count = 1
}`, clusterName)
}

func testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName string, cidrs []string) string {

cidrBlocks := ""
Expand Down
10 changes: 10 additions & 0 deletions website/docs/r/container_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ output "cluster_ca_certificate" {
* `network` - (Optional) The name or self_link of the Google Compute Engine
network to which the cluster is connected.

* `network_policy` - (Optional) Configuration options for the
[NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/networkpolicies/)
feature. Structure is documented below.

* `node_config` - (Optional) Parameters used in creating the cluster's nodes.
Structure is documented below.

Expand Down Expand Up @@ -187,6 +191,12 @@ The `master_authorized_networks_config.cidr_blocks` block supports:

* `display_name` - (Optional) Field for users to identify CIDR blocks.

The `network_policy` block supports:

* `provider` - (Optional) The selected network policy provider. Defaults to PROVIDER_UNSPECIFIED.

* `enabled` - (Optional) Whether network policy is enabled on the cluster. Defaults to false.

The `node_config` block supports:

* `disk_size_gb` - (Optional) Size of the disk attached to each node, specified
Expand Down