Skip to content

Commit

Permalink
Perform deprecation of GKE subnetwork creation
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
rileykarson authored and modular-magician committed Oct 30, 2019
1 parent 8553081 commit a28f717
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 23 deletions.
78 changes: 64 additions & 14 deletions google-beta/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func resourceContainerCluster() *schema.Resource {

CustomizeDiff: customdiff.All(
resourceContainerClusterIpAllocationCustomizeDiff,
resourceContainerClusterIpAllocationSubnetworkCustomizeDiff,
resourceNodeConfigEmptyGuestAccelerator,
containerClusterPrivateClusterConfigCustomDiff,
),
Expand Down Expand Up @@ -627,24 +628,30 @@ func resourceContainerCluster() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"use_ip_aliases": {
Type: schema.TypeBool,
Optional: true,
Default: true,
ForceNew: true,
Type: schema.TypeBool,
Deprecated: "This field is being removed in 3.0.0. If set to true, remove it from your config. If false, remove i.",
Optional: true,
Default: true,
ForceNew: true,
},

// GKE creates subnetwork automatically
"create_subnetwork": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Type: schema.TypeBool,
Deprecated: "This field is being removed in 3.0.0. Define an explicit google_compute_subnetwork and use subnetwork instead.",
Computed: true,
Optional: true,
// Simulated with CustomizeDiff resourceContainerClusterIpAllocationSubnetworkCustomizeDiff
// ForceNew: true,
ConflictsWith: ipAllocationRangeFields,
},

"subnetwork_name": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Type: schema.TypeString,
Deprecated: "This field is being removed in 3.0.0. Define an explicit google_compute_subnetwork and use subnetwork instead.",
Optional: true,
// Simulated with CustomizeDiff resourceContainerClusterIpAllocationSubnetworkCustomizeDiff
// ForceNew: true,
ConflictsWith: ipAllocationRangeFields,
},

Expand All @@ -666,10 +673,12 @@ func resourceContainerCluster() *schema.Resource {
DiffSuppressFunc: cidrOrSizeDiffSuppress,
},
"node_ipv4_cidr_block": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
Type: schema.TypeString,
Deprecated: "This field is being removed in 3.0.0. Define an explicit google_compute_subnetwork and use subnetwork instead.",
Optional: true,
Computed: true,
// Simulated with CustomizeDiff resourceContainerClusterIpAllocationSubnetworkCustomizeDiff
// ForceNew: true,
ConflictsWith: ipAllocationRangeFields,
DiffSuppressFunc: cidrOrSizeDiffSuppress,
},
Expand Down Expand Up @@ -949,6 +958,47 @@ func resourceContainerClusterIpAllocationCustomizeDiffFunc(diff TerraformResourc
return diff.Clear("ip_allocation_policy")
}

func resourceContainerClusterIpAllocationSubnetworkCustomizeDiff(diff *schema.ResourceDiff, meta interface{}) error {
o, n := diff.GetChange("ip_allocation_policy")

oList := o.([]interface{})
nList := n.([]interface{})
if len(oList) != 1 || len(nList) != 1 {
// we only care about the case where the field is set in both, so return
// early if that's not the case. If a user is moving from VPC-native to
// routes-based, they'll change a different incompatible field.
return nil
}

nMap := nList[0].(map[string]interface{})
oMap := oList[0].(map[string]interface{})

// If the values aren't identical and the new value is not empty, forcenew.
if oMap["create_subnetwork"] != nMap["create_subnetwork"] {
log.Printf("[DEBUG] Reading subnet values")
if nMap["create_subnetwork"] != false {
diff.ForceNew("ip_allocation_policy.0.create_subnetwork")
} else if oMap["create_subnetwork"] == true && nMap["create_subnetwork"] == false {
diff.Clear("ip_allocation_policy.0.create_subnetwork")
}
}

if oMap["subnetwork_name"] != nMap["subnetwork_name"] {
if nMap["subnetwork_name"] != "" {
diff.ForceNew("ip_allocation_policy.0.subnetwork_name")
}
}

// This value is Computed and will be unknown when compared.
if oMap["node_ipv4_cidr_block"] != nMap["node_ipv4_cidr_block"] {
if nMap["node_ipv4_cidr_block"] != "" {
diff.ForceNew("ip_allocation_policy.0.node_ipv4_cidr_block")
}
}

return nil
}

func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

Expand Down
67 changes: 58 additions & 9 deletions google-beta/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,15 @@ func TestAccContainerCluster_withIPAllocationPolicy_createSubnetwork(t *testing.
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerCluster_withIPAllocationPolicy_createSubnetworkUpdated(cluster),
},
{
ResourceName: "google_container_cluster.with_ip_allocation_policy",
ImportStateIdPrefix: "us-central1-a/",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand Down Expand Up @@ -3036,27 +3045,67 @@ resource "google_container_cluster" "with_ip_allocation_policy" {

func testAccContainerCluster_withIPAllocationPolicy_createSubnetwork(cluster string) string {
return fmt.Sprintf(`
resource "google_compute_network" "container_network" {
name = "%s-network"
auto_create_subnetworks = false
}
resource "google_container_cluster" "with_ip_allocation_policy" {
name = "%s"
zone = "us-central1-a"
name = "%s"
location = "us-central1"
network = "${google_compute_network.container_network.name}"
initial_node_count = 1
ip_allocation_policy {
use_ip_aliases = true
create_subnetwork = true
}
}`, cluster)
initial_node_count = 1
ip_allocation_policy {
use_ip_aliases = true
create_subnetwork = true
subnetwork_name = "%s-subnet"
cluster_ipv4_cidr_block = "10.0.0.0/16"
services_ipv4_cidr_block = "10.1.0.0/16"
node_ipv4_cidr_block = "10.2.0.0/16"
}
}`, cluster, cluster, cluster)
}

func testAccContainerCluster_withIPAllocationPolicy_createSubnetworkUpdated(cluster string) string {
return fmt.Sprintf(`
resource "google_compute_network" "container_network" {
name = "%s-network"
auto_create_subnetworks = false
}
resource "google_container_cluster" "with_ip_allocation_policy" {
name = "%s"
location = "us-central1"
network = "${google_compute_network.container_network.name}"
subnetwork = "%s-subnet"
initial_node_count = 1
ip_allocation_policy {
use_ip_aliases = true
cluster_ipv4_cidr_block = "10.0.0.0/16"
services_ipv4_cidr_block = "10.1.0.0/16"
}
}`, cluster, cluster, cluster)
}

func testAccContainerCluster_withIPAllocationPolicy_explicitEmpty(cluster string) string {
return fmt.Sprintf(`
resource "google_compute_network" "container_network" {
name = "%s-network"
auto_create_subnetworks = false
}
resource "google_container_cluster" "with_ip_allocation_policy" {
name = "%s"
zone = "us-central1-a"
initial_node_count = 1
ip_allocation_policy = []
}`, cluster)
}`, cluster, cluster)
}

func testAccContainerCluster_withResourceUsageExportConfig(clusterName, datasetId string, resourceUsage bool) string {
Expand Down
96 changes: 96 additions & 0 deletions website/docs/version_3_upgrade.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,102 @@ provider "google" {

## Resource: `google_container_cluster`

### Automatic subnetwork creation for VPC-native clusters removed

Automatic creation of subnetworks in GKE has been removed. Now, users of
VPC-native clusters will always need to provide a `google_compute_subnetwork`
resource to use `ip_allocation_policy`. Routes-based clusters are unaffected.

Representing resources managed by another source in Terraform is painful, and
leads to confusing patterns that often involve unnecessarily recreating user
resources. A number of fields in GKE are dedicated to a feature that allows
users to create a GKE-managed subnetwork.

This is a great fit for an imperative tool like `gcloud`, but with Terraform
it's relatively easy to specify a subnetwork in config alongside the cluster.
Not only is it more explicit, it allows the subnetwork to be repurposed or
persist through cluster deletion.

Particularly, Shared VPC was incompatible with `create_subnetwork`, and
`node_ipv4_cidr` was easy to confuse with
`ip_allocation_policy.node_ipv4_cidr_block`.

#### Detailed changes:

* `ip_allocation_policy.node_ipv4_cidr_block` removed (This controls the primary range of the created subnetwork)
* `ip_allocation_policy.create_subnetwork`, `ip_allocation_policy.subnetwork_name` removed
* `ip_allocation_policy.use_ip_aliases` removed
* Enablement is now based on `ip_allocation_policy` being defined instead
* Conflict added between `node_ipv4_cidr`, `ip_allocation_policy`

#### Upgrade instructions

1. Remove the removed fields from `google_container_cluster`
1. Add a `google_compute_subnetwork` to your config, import it using `terraform import`
1. Reference the subnetwork using the `subnetwork` field on your `google_container_cluster`

-> Note that subnetworks originaly created as part of `create_subnetwork` will
be deleted alongside the cluster if there are no other users of the subnetwork.
If it's deleted, `terraform apply` will recreate the same subnetwork except that
it won't be connected to any GKE cluster.

#### Old Config

```hcl
resource "google_compute_network" "container_network" {
name = "container-network"
auto_create_subnetworks = false
}
resource "google_container_cluster" "primary" {
name = "my-cluster"
location = "us-central1"
network = "${google_compute_network.container_network.name}"
initial_node_count = 1
ip_allocation_policy {
use_ip_aliases = true
create_subnetwork = true
cluster_ipv4_cidr_block = "10.0.0.0/16"
services_ipv4_cidr_block = "10.1.0.0/16"
node_ipv4_cidr_block = "10.2.0.0/16"
}
}
```

#### New Config

```hcl
resource "google_compute_network" "container_network" {
name = "container-network"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "container_subnetwork" {
name = "container-subnetwork"
description = "auto-created subnetwork for cluster \"my-cluster\""
ip_cidr_range = "10.2.0.0/16"
region = "us-central1"
network = "${google_compute_network.container_network.self_link}"
}
resource "google_container_cluster" "primary" {
name = "my-cluster"
location = "us-central1"
network = "${google_compute_network.container_network.name}"
subnetwork = "${google_compute_subnetwork.container_subnetwork.name}"
initial_node_count = 1
ip_allocation_policy {
use_ip_aliases = true
cluster_ipv4_cidr_block = "10.0.0.0/16"
services_ipv4_cidr_block = "10.1.0.0/16"
}
}
```

### `logging_service` and `monitoring_service` defaults changed

GKE Stackdriver Monitoring (the GKE-specific Stackdriver experience) is now
Expand Down

0 comments on commit a28f717

Please sign in to comment.