mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-03 01:01:06 +00:00
Add support for master authorized networks in google_container_cluster
(#626)
* Add support for master authorized networks in `google_container_cluster` * [review] remove enabled flag / restructure schema - remove `google_container_cluster.master_authorized_networks_config.enabled` - add `display_name` and restructure schema as follows: master_authorized_networks_config { cidr_blocks { cidr_block = "0.0.0.0/0" display_name = "foo" } } - amend tests * [review] add test for validateRFC1918Network, fix acc test
This commit is contained in:
parent
8cf605f23e
commit
ca7551c8c5
@ -3,7 +3,6 @@ package google
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -134,20 +133,11 @@ func resourceContainerCluster() *schema.Resource {
|
|||||||
},
|
},
|
||||||
|
|
||||||
"cluster_ipv4_cidr": {
|
"cluster_ipv4_cidr": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
ValidateFunc: validateRFC1918Network(8, 32),
|
||||||
value := v.(string)
|
|
||||||
_, ipnet, err := net.ParseCIDR(value)
|
|
||||||
|
|
||||||
if err != nil || ipnet == nil || value != ipnet.String() {
|
|
||||||
errors = append(errors, fmt.Errorf(
|
|
||||||
"%q must contain a valid CIDR", k))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"description": {
|
"description": {
|
||||||
@ -222,6 +212,35 @@ func resourceContainerCluster() *schema.Resource {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"master_authorized_networks_config": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cidr_blocks": {
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: 10,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"cidr_block": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ValidateFunc: validation.CIDRNetwork(0, 32),
|
||||||
|
},
|
||||||
|
"display_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
"min_master_version": {
|
"min_master_version": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
@ -317,6 +336,10 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("master_authorized_networks_config"); ok {
|
||||||
|
cluster.MasterAuthorizedNetworksConfig = expandMasterAuthorizedNetworksConfig(v)
|
||||||
|
}
|
||||||
|
|
||||||
if v, ok := d.GetOk("min_master_version"); ok {
|
if v, ok := d.GetOk("min_master_version"); ok {
|
||||||
cluster.InitialClusterVersion = v.(string)
|
cluster.InitialClusterVersion = v.(string)
|
||||||
}
|
}
|
||||||
@ -482,6 +505,10 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
|
|||||||
}
|
}
|
||||||
d.Set("master_auth", masterAuth)
|
d.Set("master_auth", masterAuth)
|
||||||
|
|
||||||
|
if cluster.MasterAuthorizedNetworksConfig != nil {
|
||||||
|
d.Set("master_authorized_networks_config", flattenMasterAuthorizedNetworksConfig(cluster.MasterAuthorizedNetworksConfig))
|
||||||
|
}
|
||||||
|
|
||||||
d.Set("initial_node_count", cluster.InitialNodeCount)
|
d.Set("initial_node_count", cluster.InitialNodeCount)
|
||||||
d.Set("master_version", cluster.CurrentMasterVersion)
|
d.Set("master_version", cluster.CurrentMasterVersion)
|
||||||
d.Set("node_version", cluster.CurrentNodeVersion)
|
d.Set("node_version", cluster.CurrentNodeVersion)
|
||||||
@ -526,6 +553,29 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
|
|||||||
|
|
||||||
d.Partial(true)
|
d.Partial(true)
|
||||||
|
|
||||||
|
if d.HasChange("master_authorized_networks_config") {
|
||||||
|
c := d.Get("master_authorized_networks_config")
|
||||||
|
req := &container.UpdateClusterRequest{
|
||||||
|
Update: &container.ClusterUpdate{
|
||||||
|
DesiredMasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(c),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
op, err := config.clientContainer.Projects.Zones.Clusters.Update(
|
||||||
|
project, zoneName, clusterName, req).Do()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until it's updated
|
||||||
|
waitErr := containerOperationWait(config, op, project, zoneName, "updating GKE cluster master authorized networks", timeoutInMinutes, 2)
|
||||||
|
if waitErr != nil {
|
||||||
|
return waitErr
|
||||||
|
}
|
||||||
|
log.Printf("[INFO] GKE cluster %s master authorized networks config has been updated", d.Id())
|
||||||
|
|
||||||
|
d.SetPartial("master_authorized_networks_config")
|
||||||
|
}
|
||||||
|
|
||||||
// The master must be updated before the nodes
|
// The master must be updated before the nodes
|
||||||
if d.HasChange("min_master_version") {
|
if d.HasChange("min_master_version") {
|
||||||
desiredMasterVersion := d.Get("min_master_version").(string)
|
desiredMasterVersion := d.Get("min_master_version").(string)
|
||||||
@ -816,6 +866,26 @@ func expandClusterAddonsConfig(configured interface{}) *container.AddonsConfig {
|
|||||||
return ac
|
return ac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.MasterAuthorizedNetworksConfig {
|
||||||
|
result := &container.MasterAuthorizedNetworksConfig{}
|
||||||
|
if len(configured.([]interface{})) > 0 {
|
||||||
|
result.Enabled = true
|
||||||
|
config := configured.([]interface{})[0].(map[string]interface{})
|
||||||
|
if _, ok := config["cidr_blocks"]; ok {
|
||||||
|
cidrBlocks := config["cidr_blocks"].(*schema.Set).List()
|
||||||
|
result.CidrBlocks = make([]*container.CidrBlock, 0)
|
||||||
|
for _, v := range cidrBlocks {
|
||||||
|
cidrBlock := v.(map[string]interface{})
|
||||||
|
result.CidrBlocks = append(result.CidrBlocks, &container.CidrBlock{
|
||||||
|
CidrBlock: cidrBlock["cidr_block"].(string),
|
||||||
|
DisplayName: cidrBlock["display_name"].(string),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func flattenClusterAddonsConfig(c *container.AddonsConfig) []map[string]interface{} {
|
func flattenClusterAddonsConfig(c *container.AddonsConfig) []map[string]interface{} {
|
||||||
result := make(map[string]interface{})
|
result := make(map[string]interface{})
|
||||||
if c.HorizontalPodAutoscaling != nil {
|
if c.HorizontalPodAutoscaling != nil {
|
||||||
@ -856,6 +926,21 @@ func flattenClusterNodePools(d *schema.ResourceData, config *Config, c []*contai
|
|||||||
return nodePools, nil
|
return nodePools, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func flattenMasterAuthorizedNetworksConfig(c *container.MasterAuthorizedNetworksConfig) []map[string]interface{} {
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
if c.Enabled && len(c.CidrBlocks) > 0 {
|
||||||
|
cidrBlocks := make([]map[string]interface{}, 0, len(c.CidrBlocks))
|
||||||
|
for _, v := range c.CidrBlocks {
|
||||||
|
cidrBlocks = append(cidrBlocks, map[string]interface{}{
|
||||||
|
"cidr_block": v.CidrBlock,
|
||||||
|
"display_name": v.DisplayName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
result["cidr_blocks"] = cidrBlocks
|
||||||
|
}
|
||||||
|
return []map[string]interface{}{result}
|
||||||
|
}
|
||||||
|
|
||||||
func resourceContainerClusterStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
func resourceContainerClusterStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
||||||
parts := strings.Split(d.Id(), "/")
|
parts := strings.Split(d.Id(), "/")
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package google
|
package google
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
@ -106,6 +107,44 @@ func TestAccContainerCluster_withMasterAuth(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccContainerCluster_withMasterAuthorizedNetworksConfig(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_withMasterAuthorizedNetworksConfig(clusterName, []string{"0.0.0.0/0"}),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckContainerCluster("google_container_cluster.with_master_authorized_networks"),
|
||||||
|
resource.TestCheckResourceAttr("google_container_cluster.with_master_authorized_networks",
|
||||||
|
"master_authorized_networks_config.0.cidr_blocks.#", "1"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName, []string{}),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckContainerCluster("google_container_cluster.with_master_authorized_networks"),
|
||||||
|
resource.TestCheckNoResourceAttr("google_container_cluster.with_master_authorized_networks",
|
||||||
|
"master_authorized_networks_config.0.cidr_blocks"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName, []string{"8.8.8.8/32"}),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckContainerCluster("google_container_cluster.with_master_authorized_networks"),
|
||||||
|
resource.TestCheckResourceAttr("google_container_cluster.with_master_authorized_networks",
|
||||||
|
"master_authorized_networks_config.0.cidr_blocks.#", "1"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestAccContainerCluster_withAdditionalZones(t *testing.T) {
|
func TestAccContainerCluster_withAdditionalZones(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -882,6 +921,32 @@ resource "google_container_cluster" "with_master_auth" {
|
|||||||
}
|
}
|
||||||
}`, acctest.RandString(10))
|
}`, acctest.RandString(10))
|
||||||
|
|
||||||
|
func testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName string, cidrs []string) string {
|
||||||
|
|
||||||
|
cidrBlocks := ""
|
||||||
|
if len(cidrs) > 0 {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, c := range cidrs {
|
||||||
|
buf.WriteString(fmt.Sprintf(`
|
||||||
|
cidr_blocks {
|
||||||
|
cidr_block = "%s"
|
||||||
|
}`, c))
|
||||||
|
}
|
||||||
|
cidrBlocks = buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "google_container_cluster" "with_master_authorized_networks" {
|
||||||
|
name = "%s"
|
||||||
|
zone = "us-central1-a"
|
||||||
|
initial_node_count = 1
|
||||||
|
|
||||||
|
master_authorized_networks_config {
|
||||||
|
%s
|
||||||
|
}
|
||||||
|
}`, clusterName, cidrBlocks)
|
||||||
|
}
|
||||||
|
|
||||||
func testAccContainerCluster_withAdditionalZones(clusterName string) string {
|
func testAccContainerCluster_withAdditionalZones(clusterName string) string {
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
resource "google_container_cluster" "with_additional_zones" {
|
resource "google_container_cluster" "with_additional_zones" {
|
||||||
|
@ -3,6 +3,8 @@ package google
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/helper/validation"
|
||||||
|
"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,6 +17,12 @@ const (
|
|||||||
SubnetworkLinkRegex = "projects/(" + ProjectRegex + ")/regions/(" + RegionRegex + ")/subnetworks/(" + SubnetworkRegex + ")$"
|
SubnetworkLinkRegex = "projects/(" + ProjectRegex + ")/regions/(" + RegionRegex + ")/subnetworks/(" + SubnetworkRegex + ")$"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var rfc1918Networks = []string{
|
||||||
|
"10.0.0.0/8",
|
||||||
|
"172.16.0.0/12",
|
||||||
|
"192.168.0.0/16",
|
||||||
|
}
|
||||||
|
|
||||||
func validateGCPName(v interface{}, k string) (ws []string, errors []error) {
|
func validateGCPName(v interface{}, k string) (ws []string, errors []error) {
|
||||||
re := `^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$`
|
re := `^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$`
|
||||||
return validateRegexp(re)(v, k)
|
return validateRegexp(re)(v, k)
|
||||||
@ -31,3 +39,25 @@ func validateRegexp(re string) schema.SchemaValidateFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateRFC1918Network(min, max int) schema.SchemaValidateFunc {
|
||||||
|
return func(i interface{}, k string) (s []string, es []error) {
|
||||||
|
|
||||||
|
s, es = validation.CIDRNetwork(min, max)(i, k)
|
||||||
|
if len(es) > 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v, _ := i.(string)
|
||||||
|
ip, _, _ := net.ParseCIDR(v)
|
||||||
|
for _, c := range rfc1918Networks {
|
||||||
|
if _, ipnet, _ := net.ParseCIDR(c); ipnet.Contains(ip) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
es = append(es, fmt.Errorf("expected %q to be an RFC1918-compliant CIDR, got: %s", k, v))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -28,12 +28,45 @@ func TestValidateGCPName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateRFC1918Network(t *testing.T) {
|
||||||
|
x := []RFC1918NetworkTestCase{
|
||||||
|
// No errors
|
||||||
|
{TestName: "valid 10.x", CIDR: "10.0.0.0/8", MinPrefix: 0, MaxPrefix: 32},
|
||||||
|
{TestName: "valid 172.x", CIDR: "172.16.0.0/16", MinPrefix: 0, MaxPrefix: 32},
|
||||||
|
{TestName: "valid 192.x", CIDR: "192.168.0.0/32", MinPrefix: 0, MaxPrefix: 32},
|
||||||
|
{TestName: "valid, bounded 10.x CIDR", CIDR: "10.0.0.0/8", MinPrefix: 8, MaxPrefix: 32},
|
||||||
|
{TestName: "valid, bounded 172.x CIDR", CIDR: "172.16.0.0/16", MinPrefix: 12, MaxPrefix: 32},
|
||||||
|
{TestName: "valid, bounded 192.x CIDR", CIDR: "192.168.0.0/32", MinPrefix: 16, MaxPrefix: 32},
|
||||||
|
|
||||||
|
// With errors
|
||||||
|
{TestName: "empty CIDR", CIDR: "", MinPrefix: 0, MaxPrefix: 32, ExpectError: true},
|
||||||
|
{TestName: "missing mask", CIDR: "10.0.0.0", MinPrefix: 0, MaxPrefix: 32, ExpectError: true},
|
||||||
|
{TestName: "invalid CIDR", CIDR: "10.1.0.0/8", MinPrefix: 0, MaxPrefix: 32, ExpectError: true},
|
||||||
|
{TestName: "valid 10.x CIDR with lower bound violation", CIDR: "10.0.0.0/8", MinPrefix: 16, MaxPrefix: 32, ExpectError: true},
|
||||||
|
{TestName: "valid 10.x CIDR with upper bound violation", CIDR: "10.0.0.0/24", MinPrefix: 8, MaxPrefix: 16, ExpectError: true},
|
||||||
|
{TestName: "valid public CIDR", CIDR: "8.8.8.8/32", MinPrefix: 0, MaxPrefix: 32, ExpectError: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
es := testRFC1918Networks(x)
|
||||||
|
if len(es) > 0 {
|
||||||
|
t.Errorf("Failed to validate RFC1918 Networks: %v", es)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type GCPNameTestCase struct {
|
type GCPNameTestCase struct {
|
||||||
TestName string
|
TestName string
|
||||||
Value string
|
Value string
|
||||||
ExpectError bool
|
ExpectError bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RFC1918NetworkTestCase struct {
|
||||||
|
TestName string
|
||||||
|
CIDR string
|
||||||
|
MinPrefix int
|
||||||
|
MaxPrefix int
|
||||||
|
ExpectError bool
|
||||||
|
}
|
||||||
|
|
||||||
func testGCPNames(cases []GCPNameTestCase) []error {
|
func testGCPNames(cases []GCPNameTestCase) []error {
|
||||||
es := make([]error, 0)
|
es := make([]error, 0)
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
@ -55,3 +88,26 @@ func testGCPName(testCase GCPNameTestCase) []error {
|
|||||||
|
|
||||||
return es
|
return es
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testRFC1918Networks(cases []RFC1918NetworkTestCase) []error {
|
||||||
|
es := make([]error, 0)
|
||||||
|
for _, c := range cases {
|
||||||
|
es = append(es, testRFC1918Network(c)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRFC1918Network(testCase RFC1918NetworkTestCase) []error {
|
||||||
|
f := validateRFC1918Network(testCase.MinPrefix, testCase.MaxPrefix)
|
||||||
|
_, es := f(testCase.CIDR, testCase.TestName)
|
||||||
|
if testCase.ExpectError {
|
||||||
|
if len(es) > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return []error{fmt.Errorf("Didn't see expected error in case \"%s\" with CIDR=\"%s\" MinPrefix=%v MaxPrefix=%v",
|
||||||
|
testCase.TestName, testCase.CIDR, testCase.MinPrefix, testCase.MaxPrefix)}
|
||||||
|
}
|
||||||
|
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
@ -41,11 +41,11 @@ resource "google_container_cluster" "primary" {
|
|||||||
"https://www.googleapis.com/auth/logging.write",
|
"https://www.googleapis.com/auth/logging.write",
|
||||||
"https://www.googleapis.com/auth/monitoring",
|
"https://www.googleapis.com/auth/monitoring",
|
||||||
]
|
]
|
||||||
|
|
||||||
labels {
|
labels {
|
||||||
foo = "bar"
|
foo = "bar"
|
||||||
}
|
}
|
||||||
|
|
||||||
tags = ["foo", "bar"]
|
tags = ["foo", "bar"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,6 +105,10 @@ output "cluster_ca_certificate" {
|
|||||||
* `master_auth` - (Optional) The authentication information for accessing the
|
* `master_auth` - (Optional) The authentication information for accessing the
|
||||||
Kubernetes master. Structure is documented below.
|
Kubernetes master. Structure is documented below.
|
||||||
|
|
||||||
|
* `master_authorized_networks_config` - (Optional) The desired configuration options
|
||||||
|
for master authorized networks. Omit the nested `cidr_blocks` attribute to disallow
|
||||||
|
external access (except the cluster node IPs, which GKE automatically whitelists).
|
||||||
|
|
||||||
* `min_master_version` - (Optional) The minimum version of the master. GKE
|
* `min_master_version` - (Optional) The minimum version of the master. GKE
|
||||||
will auto-update the master to new versions, so this does not guarantee the
|
will auto-update the master to new versions, so this does not guarantee the
|
||||||
current master version--use the read-only `master_version` field to obtain that.
|
current master version--use the read-only `master_version` field to obtain that.
|
||||||
@ -171,6 +175,18 @@ The `master_auth` block supports:
|
|||||||
* `username` - (Required) The username to use for HTTP basic authentication when accessing
|
* `username` - (Required) The username to use for HTTP basic authentication when accessing
|
||||||
the Kubernetes master endpoint
|
the Kubernetes master endpoint
|
||||||
|
|
||||||
|
The `master_authorized_networks_config` block supports:
|
||||||
|
|
||||||
|
* `cidr_blocks` - (Optional) Defines up to 10 external networks that can access
|
||||||
|
Kubernetes master through HTTPS.
|
||||||
|
|
||||||
|
The `master_authorized_networks_config.cidr_blocks` block supports:
|
||||||
|
|
||||||
|
* `cidr_block` - (Optional) External network that can access Kubernetes master through HTTPS.
|
||||||
|
Must be specified in CIDR notation.
|
||||||
|
|
||||||
|
* `display_name` - (Optional) Field for users to identify CIDR blocks.
|
||||||
|
|
||||||
The `node_config` block supports:
|
The `node_config` block supports:
|
||||||
|
|
||||||
* `disk_size_gb` - (Optional) Size of the disk attached to each node, specified
|
* `disk_size_gb` - (Optional) Size of the disk attached to each node, specified
|
||||||
@ -214,7 +230,7 @@ The `node_config` block supports:
|
|||||||
* `service_account` - (Optional) The service account to be used by the Node VMs.
|
* `service_account` - (Optional) The service account to be used by the Node VMs.
|
||||||
If not specified, the "default" service account is used.
|
If not specified, the "default" service account is used.
|
||||||
|
|
||||||
* `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify
|
* `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify
|
||||||
valid sources or targets for network firewalls.
|
valid sources or targets for network firewalls.
|
||||||
|
|
||||||
## Attributes Reference
|
## Attributes Reference
|
||||||
|
Loading…
Reference in New Issue
Block a user