diff --git a/google-beta/resource_composer_environment.go b/google-beta/resource_composer_environment.go index 67aebdefe3..ffb7479f36 100644 --- a/google-beta/resource_composer_environment.go +++ b/google-beta/resource_composer_environment.go @@ -150,6 +150,50 @@ func resourceComposerEnvironment() *schema.Resource { }, Set: schema.HashString, }, + "ip_allocation_policy": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + ConfigMode: schema.SchemaConfigModeAttr, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "use_ip_aliases": { + Type: schema.TypeBool, + Optional: true, + Default: true, + ForceNew: true, + }, + "cluster_secondary_range_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ConflictsWith: []string{"config.0.node_config.0.ip_allocation_policy.0.cluster_ipv4_cidr_block"}, + }, + "services_secondary_range_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ConflictsWith: []string{"config.0.node_config.0.ip_allocation_policy.0.services_ipv4_cidr_block"}, + }, + "cluster_ipv4_cidr_block": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: cidrOrSizeDiffSuppress, + ConflictsWith: []string{"config.0.node_config.0.ip_allocation_policy.0.cluster_secondary_range_name"}, + }, + "services_ipv4_cidr_block": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: cidrOrSizeDiffSuppress, + ConflictsWith: []string{"config.0.node_config.0.ip_allocation_policy.0.services_secondary_range_name"}, + }, + }, + }, + }, }, }, }, @@ -193,6 +237,28 @@ func resourceComposerEnvironment() *schema.Resource { }, }, }, + "private_environment_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_private_endpoint": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + }, + "master_ipv4_cidr_block": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "172.16.0.0/28", + }, + }, + }, + }, "airflow_uri": { Type: schema.TypeString, Computed: true, @@ -527,6 +593,19 @@ func flattenComposerEnvironmentConfig(envCfg *composer.EnvironmentConfig) interf transformed["airflow_uri"] = envCfg.AirflowUri transformed["node_config"] = flattenComposerEnvironmentConfigNodeConfig(envCfg.NodeConfig) transformed["software_config"] = flattenComposerEnvironmentConfigSoftwareConfig(envCfg.SoftwareConfig) + transformed["private_environment_config"] = flattenComposerEnvironmentConfigPrivateEnvironmentConfig(envCfg.PrivateEnvironmentConfig) + + return []interface{}{transformed} +} + +func flattenComposerEnvironmentConfigPrivateEnvironmentConfig(envCfg *composer.PrivateEnvironmentConfig) interface{} { + if envCfg == nil { + return nil + } + + transformed := make(map[string]interface{}) + transformed["enable_private_endpoint"] = envCfg.PrivateClusterConfig.EnablePrivateEndpoint + transformed["master_ipv4_cidr_block"] = envCfg.PrivateClusterConfig.MasterIpv4CidrBlock return []interface{}{transformed} } @@ -544,6 +623,21 @@ func flattenComposerEnvironmentConfigNodeConfig(nodeCfg *composer.NodeConfig) in transformed["service_account"] = nodeCfg.ServiceAccount transformed["oauth_scopes"] = flattenComposerEnvironmentConfigNodeConfigOauthScopes(nodeCfg.OauthScopes) transformed["tags"] = flattenComposerEnvironmentConfigNodeConfigTags(nodeCfg.Tags) + transformed["ip_allocation_policy"] = flattenComposerEnvironmentConfigNodeConfigIPAllocationPolicy(nodeCfg.IpAllocationPolicy) + return []interface{}{transformed} +} + +func flattenComposerEnvironmentConfigNodeConfigIPAllocationPolicy(ipPolicy *composer.IPAllocationPolicy) interface{} { + if ipPolicy == nil { + return nil + } + transformed := make(map[string]interface{}) + transformed["use_ip_aliases"] = ipPolicy.UseIpAliases + transformed["cluster_ipv4_cidr_block"] = ipPolicy.ClusterIpv4CidrBlock + transformed["cluster_secondary_range_name"] = ipPolicy.ClusterSecondaryRangeName + transformed["services_ipv4_cidr_block"] = ipPolicy.ServicesIpv4CidrBlock + transformed["services_secondary_range_name"] = ipPolicy.ServicesSecondaryRangeName + return []interface{}{transformed} } @@ -601,6 +695,13 @@ func expandComposerEnvironmentConfig(v interface{}, d *schema.ResourceData, conf return nil, err } transformed.SoftwareConfig = transformedSoftwareConfig + + transformedPrivateEnvironmentConfig, err := expandComposerEnvironmentConfigPrivateEnvironmentConfig(original["private_environment_config"], d, config) + if err != nil { + return nil, err + } + transformed.PrivateEnvironmentConfig = transformedPrivateEnvironmentConfig + return transformed, nil } @@ -611,6 +712,32 @@ func expandComposerEnvironmentConfigNodeCount(v interface{}, d *schema.ResourceD return int64(v.(int)), nil } +func expandComposerEnvironmentConfigPrivateEnvironmentConfig(v interface{}, d *schema.ResourceData, config *Config) (*composer.PrivateEnvironmentConfig, error) { + l := v.([]interface{}) + if len(l) == 0 { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := &composer.PrivateEnvironmentConfig{ + EnablePrivateEnvironment: true, + } + + subBlock := &composer.PrivateClusterConfig{} + + if v, ok := original["enable_private_endpoint"]; ok { + subBlock.EnablePrivateEndpoint = v.(bool) + } + + if v, ok := original["master_ipv4_cidr_block"]; ok { + subBlock.MasterIpv4CidrBlock = v.(string) + } + + transformed.PrivateClusterConfig = subBlock + + return transformed, nil +} + func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.ResourceData, config *Config) (*composer.NodeConfig, error) { l := v.([]interface{}) if len(l) == 0 { @@ -665,6 +792,11 @@ func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.Resource } transformed.Subnetwork = transformedSubnetwork } + transformedIPAllocationPolicy, err := expandComposerEnvironmentIPAllocationPolicy(original["ip_allocation_policy"], d, config) + if err != nil { + return nil, err + } + transformed.IpAllocationPolicy = transformedIPAllocationPolicy transformedOauthScopes, err := expandComposerEnvironmentSetList(original["oauth_scopes"], d, config) if err != nil { @@ -677,9 +809,42 @@ func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.Resource return nil, err } transformed.Tags = transformedTags + return transformed, nil } +func expandComposerEnvironmentIPAllocationPolicy(v interface{}, d *schema.ResourceData, config *Config) (*composer.IPAllocationPolicy, error) { + l := v.([]interface{}) + if len(l) == 0 { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := &composer.IPAllocationPolicy{} + + if v, ok := original["use_ip_aliases"]; ok { + transformed.UseIpAliases = v.(bool) + } + + if v, ok := original["cluster_ipv4_cidr_block"]; ok { + transformed.ClusterIpv4CidrBlock = v.(string) + } + + if v, ok := original["cluster_secondary_range_name"]; ok { + transformed.ClusterSecondaryRangeName = v.(string) + } + + if v, ok := original["services_ipv4_cidr_block"]; ok { + transformed.ServicesIpv4CidrBlock = v.(string) + } + + if v, ok := original["services_secondary_range_name"]; ok { + transformed.ServicesSecondaryRangeName = v.(string) + } + return transformed, nil + +} + func expandComposerEnvironmentServiceAccount(v interface{}, d *schema.ResourceData, config *Config) (string, error) { serviceAccount := v.(string) if len(serviceAccount) == 0 { diff --git a/google-beta/resource_composer_environment_test.go b/google-beta/resource_composer_environment_test.go index 81def5931c..486d003e3c 100644 --- a/google-beta/resource_composer_environment_test.go +++ b/google-beta/resource_composer_environment_test.go @@ -118,6 +118,38 @@ func TestAccComposerEnvironment_update(t *testing.T) { }) } +// Checks environment creation with minimum required information. +func TestAccComposerEnvironment_private(t *testing.T) { + t.Parallel() + + envName := acctest.RandomWithPrefix(testComposerEnvironmentPrefix) + + var env composer.Environment + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccComposerEnvironmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironment_private(envName), + Check: testAccCheckComposerEnvironmentExists("google_composer_environment.test", &env), + }, + { + ResourceName: "google_composer_environment.test", + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_composer_environment.test", + ImportState: true, + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/environments/%s", getTestProjectFromEnv(), "us-central1", envName), + ImportStateVerify: true, + }, + }, + }) +} + // Checks behavior of node config, including dependencies on Compute resources. func TestAccComposerEnvironment_withNodeConfig(t *testing.T) { t.Parallel() @@ -280,6 +312,28 @@ resource "google_composer_environment" "test" { `, name) } +func testAccComposerEnvironment_private(name string) string { + return fmt.Sprintf(` +resource "google_composer_environment" "test" { + name = "%s" + region = "us-central1" + + config { + node_config { + zone = "us-central1-a" + ip_allocation_policy { + use_ip_aliases = true + cluster_ipv4_cidr_block = "10.0.0.0/16" + } + } + private_environment_config { + enable_private_endpoint = true + } + } +} +`, name) +} + func testAccComposerEnvironment_update(name string) string { return fmt.Sprintf(` data "google_composer_image_versions" "all" { diff --git a/website/docs/r/composer_environment.html.markdown b/website/docs/r/composer_environment.html.markdown index 062195279c..2c63d941ca 100644 --- a/website/docs/r/composer_environment.html.markdown +++ b/website/docs/r/composer_environment.html.markdown @@ -164,6 +164,11 @@ The `config` block supports: (Optional) The configuration settings for software inside the environment. Structure is documented below. +* `private_environment_config` - + (Optional) + The configuration used for the Private IP Cloud Composer environment. Structure is documented below. + + The `node_config` block supports: * `zone` - @@ -222,6 +227,12 @@ The `node_config` block supports: firewalls. Each tag within the list must comply with RFC1035. Cannot be updated. +* `ip_allocation_policy` - + (Optional) + Configuration for controlling how IPs are allocated in the GKE cluster. + Structure is documented below. + Cannot be updated. + The `software_config` block supports: * `airflow_config_overrides` - @@ -278,6 +289,57 @@ The `software_config` block supports: The major version of Python used to run the Apache Airflow scheduler, worker, and webserver processes. Can be set to '2' or '3'. If not specified, the default is '2'. Cannot be updated. +The `private_environment_config` block supports: + +* `enable_private_endpoint` - + If true, access to the public endpoint of the GKE cluster is denied. + +* `master_ipv4_cidr_block` - + (Optional) + The IP range in CIDR notation to use for the hosted master network. This range is used + for assigning internal IP addresses to the cluster master or set of masters and to the + internal load balancer virtual IP. This range must not overlap with any other ranges + in use within the cluster's network. + If left blank, the default value of '172.16.0.0/28' is used. + +The `ip_allocation_policy` block supports: + +* `use_ap_aliases` - + (Optional) + Whether or not to enable Alias IPs in the GKE cluster. If true, a VPC-native cluster is created. + +* `cluster_secondary_range_name` - + (Optional) + The name of the cluster's secondary range used to allocate IP addresses to pods. + Specify either `cluster_secondary_range_name` or `cluster_ipv4_cidr_block` but not both. + This field is applicable only when `use_ip_aliases` is true. + +* `services_secondary_range_name` - + (Optional) + The name of the services' secondary range used to allocate IP addresses to the cluster. + Specify either `services_secondary_range_name` or `services_ipv4_cidr_block` but not both. + This field is applicable only when `use_ip_aliases` is true. + +* `cluster_ipv4_cidr_block` - + (Optional) + The IP address range used to allocate IP addresses to pods in the cluster. + Set to blank to have GKE choose a range with the default size. + Set to /netmask (e.g. /14) to have GKE choose a range with a specific netmask. + Set to a CIDR notation (e.g. 10.96.0.0/14) from the RFC-1918 private networks + (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use. + Specify either `cluster_secondary_range_name` or `cluster_ipv4_cidr_block` but not both. + +* `services_ipv4_cidr_block` - + (Optional) + The IP address range used to allocate IP addresses in this cluster. + Set to blank to have GKE choose a range with the default size. + Set to /netmask (e.g. /14) to have GKE choose a range with a specific netmask. + Set to a CIDR notation (e.g. 10.96.0.0/14) from the RFC-1918 private networks + (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use. + Specify either `services_secondary_range_name` or `services_ipv4_cidr_block` but not both. + + + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: