mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-07-09 03:28:29 +00:00
add support for ip aliasing in google_container_cluster
(#654)
* add support for ip aliasing in `google_container_cluster` * [review] cleanup galore, infer feature enablement from `ip_allocation_policy` * [review] cleanup, round 2 * add nil check back (when reading ip allocation policy from API)
This commit is contained in:
parent
96726bdc48
commit
d57db91143
|
@ -359,6 +359,27 @@ func resourceContainerCluster() *schema.Resource {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"ip_allocation_policy": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cluster_secondary_range_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"services_secondary_range_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -499,6 +520,13 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
|
||||||
cluster.NodePools = nodePools
|
cluster.NodePools = nodePools
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("ip_allocation_policy"); ok {
|
||||||
|
cluster.IpAllocationPolicy, err = expandIPAllocationPolicy(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req := &container.CreateClusterRequest{
|
req := &container.CreateClusterRequest{
|
||||||
Cluster: cluster,
|
Cluster: cluster,
|
||||||
}
|
}
|
||||||
|
@ -618,6 +646,12 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
|
||||||
}
|
}
|
||||||
d.Set("node_pool", nps)
|
d.Set("node_pool", nps)
|
||||||
|
|
||||||
|
if cluster.IpAllocationPolicy != nil {
|
||||||
|
if err := d.Set("ip_allocation_policy", flattenIPAllocationPolicy(cluster.IpAllocationPolicy)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if igUrls, err := getInstanceGroupUrlsFromManagerUrls(config, cluster.InstanceGroupUrls); err != nil {
|
if igUrls, err := getInstanceGroupUrlsFromManagerUrls(config, cluster.InstanceGroupUrls); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
|
@ -977,6 +1011,30 @@ func expandClusterAddonsConfig(configured interface{}) *container.AddonsConfig {
|
||||||
return ac
|
return ac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func expandIPAllocationPolicy(configured interface{}) (*container.IPAllocationPolicy, error) {
|
||||||
|
ap := &container.IPAllocationPolicy{}
|
||||||
|
if len(configured.([]interface{})) > 0 {
|
||||||
|
if config, ok := configured.([]interface{})[0].(map[string]interface{}); ok {
|
||||||
|
ap.UseIpAliases = true
|
||||||
|
if v, ok := config["cluster_secondary_range_name"]; ok {
|
||||||
|
ap.ClusterSecondaryRangeName = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := config["services_secondary_range_name"]; ok {
|
||||||
|
ap.ServicesSecondaryRangeName = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ap.UseIpAliases &&
|
||||||
|
(ap.ClusterSecondaryRangeName == "" || ap.ServicesSecondaryRangeName == "") {
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("clusters using IP aliases must specify secondary ranges.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ap, nil
|
||||||
|
}
|
||||||
|
|
||||||
func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.MasterAuthorizedNetworksConfig {
|
func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.MasterAuthorizedNetworksConfig {
|
||||||
result := &container.MasterAuthorizedNetworksConfig{}
|
result := &container.MasterAuthorizedNetworksConfig{}
|
||||||
if len(configured.([]interface{})) > 0 {
|
if len(configured.([]interface{})) > 0 {
|
||||||
|
@ -1062,6 +1120,15 @@ func flattenClusterNodePools(d *schema.ResourceData, config *Config, c []*contai
|
||||||
return nodePools, nil
|
return nodePools, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func flattenIPAllocationPolicy(c *container.IPAllocationPolicy) []map[string]interface{} {
|
||||||
|
return []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"cluster_secondary_range_name": c.ClusterSecondaryRangeName,
|
||||||
|
"services_secondary_range_name": c.ServicesSecondaryRangeName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func flattenMasterAuthorizedNetworksConfig(c *container.MasterAuthorizedNetworksConfig) []map[string]interface{} {
|
func flattenMasterAuthorizedNetworksConfig(c *container.MasterAuthorizedNetworksConfig) []map[string]interface{} {
|
||||||
result := make(map[string]interface{})
|
result := make(map[string]interface{})
|
||||||
if c.Enabled && len(c.CidrBlocks) > 0 {
|
if c.Enabled && len(c.CidrBlocks) > 0 {
|
||||||
|
|
|
@ -627,6 +627,64 @@ func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccContainerCluster_withIPAllocationPolicy(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cluster := 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_withIPAllocationPolicy(
|
||||||
|
cluster,
|
||||||
|
map[string]string{
|
||||||
|
"pods": "10.1.0.0/16",
|
||||||
|
"services": "10.2.0.0/20",
|
||||||
|
},
|
||||||
|
map[string]string{
|
||||||
|
"cluster_secondary_range_name": "pods",
|
||||||
|
"services_secondary_range_name": "services",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckContainerCluster(
|
||||||
|
"google_container_cluster.with_ip_allocation_policy"),
|
||||||
|
resource.TestCheckResourceAttr("google_container_cluster.with_ip_allocation_policy",
|
||||||
|
"ip_allocation_policy.0.cluster_secondary_range_name", "pods"),
|
||||||
|
resource.TestCheckResourceAttr("google_container_cluster.with_ip_allocation_policy",
|
||||||
|
"ip_allocation_policy.0.services_secondary_range_name", "services"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testAccContainerCluster_withIPAllocationPolicy(
|
||||||
|
cluster,
|
||||||
|
map[string]string{
|
||||||
|
"pods": "10.1.0.0/16",
|
||||||
|
"services": "10.2.0.0/20",
|
||||||
|
},
|
||||||
|
map[string]string{},
|
||||||
|
),
|
||||||
|
ExpectError: regexp.MustCompile("clusters using IP aliases must specify secondary ranges"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testAccContainerCluster_withIPAllocationPolicy(
|
||||||
|
cluster,
|
||||||
|
map[string]string{
|
||||||
|
"pods": "10.1.0.0/16",
|
||||||
|
},
|
||||||
|
map[string]string{
|
||||||
|
"cluster_secondary_range_name": "pods",
|
||||||
|
"services_secondary_range_name": "services",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ExpectError: regexp.MustCompile("services secondary range \"pods\" not found in subnet"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckContainerClusterDestroy(s *terraform.State) error {
|
func testAccCheckContainerClusterDestroy(s *terraform.State) error {
|
||||||
config := testAccProvider.Meta().(*Config)
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
@ -747,6 +805,11 @@ func testAccCheckContainerCluster(n string) resource.TestCheckFunc {
|
||||||
clusterTests = append(clusterTests, clusterTestField{"maintenance_policy.0.daily_maintenance_window.0.duration", cluster.MaintenancePolicy.Window.DailyMaintenanceWindow.Duration})
|
clusterTests = append(clusterTests, clusterTestField{"maintenance_policy.0.daily_maintenance_window.0.duration", cluster.MaintenancePolicy.Window.DailyMaintenanceWindow.Duration})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cluster.IpAllocationPolicy != nil && cluster.IpAllocationPolicy.UseIpAliases {
|
||||||
|
clusterTests = append(clusterTests, clusterTestField{"ip_allocation_policy.0.cluster_secondary_range_name", cluster.IpAllocationPolicy.ClusterSecondaryRangeName})
|
||||||
|
clusterTests = append(clusterTests, clusterTestField{"ip_allocation_policy.0.services_secondary_range_name", cluster.IpAllocationPolicy.ServicesSecondaryRangeName})
|
||||||
|
}
|
||||||
|
|
||||||
for i, np := range cluster.NodePools {
|
for i, np := range cluster.NodePools {
|
||||||
prefix := fmt.Sprintf("node_pool.%d.", i)
|
prefix := fmt.Sprintf("node_pool.%d.", i)
|
||||||
clusterTests = append(clusterTests, clusterTestField{prefix + "name", np.Name})
|
clusterTests = append(clusterTests, clusterTestField{prefix + "name", np.Name})
|
||||||
|
@ -1541,3 +1604,49 @@ resource "google_container_cluster" "with_maintenance_window" {
|
||||||
}
|
}
|
||||||
}`, acctest.RandString(10), startTime)
|
}`, acctest.RandString(10), startTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAccContainerCluster_withIPAllocationPolicy(cluster string, ranges, policy map[string]string) string {
|
||||||
|
|
||||||
|
var secondaryRanges bytes.Buffer
|
||||||
|
for rangeName, cidr := range ranges {
|
||||||
|
secondaryRanges.WriteString(fmt.Sprintf(`
|
||||||
|
secondary_ip_range {
|
||||||
|
range_name = "%s"
|
||||||
|
ip_cidr_range = "%s"
|
||||||
|
}`, rangeName, cidr))
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipAllocationPolicy bytes.Buffer
|
||||||
|
for key, value := range policy {
|
||||||
|
ipAllocationPolicy.WriteString(fmt.Sprintf(`
|
||||||
|
%s = "%s"`, key, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_compute_network" "container_network" {
|
||||||
|
name = "container-net-%s"
|
||||||
|
auto_create_subnetworks = false
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_subnetwork" "container_subnetwork" {
|
||||||
|
name = "${google_compute_network.container_network.name}"
|
||||||
|
network = "${google_compute_network.container_network.name}"
|
||||||
|
ip_cidr_range = "10.0.0.0/24"
|
||||||
|
region = "us-central1"
|
||||||
|
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_container_cluster" "with_ip_allocation_policy" {
|
||||||
|
name = "%s"
|
||||||
|
zone = "us-central1-a"
|
||||||
|
|
||||||
|
network = "${google_compute_network.container_network.name}"
|
||||||
|
subnetwork = "${google_compute_subnetwork.container_subnetwork.name}"
|
||||||
|
|
||||||
|
initial_node_count = 1
|
||||||
|
ip_allocation_policy {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
}`, acctest.RandString(10), secondaryRanges.String(), cluster, ipAllocationPolicy.String())
|
||||||
|
}
|
||||||
|
|
|
@ -98,6 +98,8 @@ output "cluster_ca_certificate" {
|
||||||
* `initial_node_count` - (Optional) The number of nodes to create in this
|
* `initial_node_count` - (Optional) The number of nodes to create in this
|
||||||
cluster (not including the Kubernetes master). Must be set if `node_pool` is not set.
|
cluster (not including the Kubernetes master). Must be set if `node_pool` is not set.
|
||||||
|
|
||||||
|
* `ip_allocation_policy` - (Optional) Configuration for cluster IP allocation. As of now, only pre-allocated subnetworks (custom type with secondary ranges) are supported.
|
||||||
|
|
||||||
* `logging_service` - (Optional) The logging service that the cluster should
|
* `logging_service` - (Optional) The logging service that the cluster should
|
||||||
write logs to. Available options include `logging.googleapis.com` and
|
write logs to. Available options include `logging.googleapis.com` and
|
||||||
`none`. Defaults to `logging.googleapis.com`
|
`none`. Defaults to `logging.googleapis.com`
|
||||||
|
@ -188,6 +190,18 @@ maintenance_policy {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `ip_allocation_policy` block supports:
|
||||||
|
|
||||||
|
* `cluster_secondary_range_name` - (Optional) The name of the secondary range to be
|
||||||
|
used as for the cluster CIDR block. The secondary range will be used for pod IP
|
||||||
|
addresses. This must be an existing secondary range associated with the cluster
|
||||||
|
subnetwork.
|
||||||
|
|
||||||
|
* `services_secondary_range_name` - (Optional) The name of the secondary range to be
|
||||||
|
used as for the services CIDR block. The secondary range will be used for service
|
||||||
|
ClusterIPs. This must be an existing secondary range associated with the cluster
|
||||||
|
subnetwork.
|
||||||
|
|
||||||
The `master_auth` block supports:
|
The `master_auth` block supports:
|
||||||
|
|
||||||
* `password` - (Required) The password to use for HTTP basic authentication when accessing
|
* `password` - (Required) The password to use for HTTP basic authentication when accessing
|
||||||
|
|
Loading…
Reference in New Issue
Block a user