diff --git a/azurerm/internal/services/containers/resource_arm_kubernetes_cluster.go b/azurerm/internal/services/containers/resource_arm_kubernetes_cluster.go index 4ffd5332901b..78bb40131795 100644 --- a/azurerm/internal/services/containers/resource_arm_kubernetes_cluster.go +++ b/azurerm/internal/services/containers/resource_arm_kubernetes_cluster.go @@ -295,6 +295,18 @@ func resourceArmKubernetesCluster() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "outbound_ports_allocated": { + Type: schema.TypeInt, + Optional: true, + Default: 0, + ValidateFunc: validation.IntBetween(0, 64000), + }, + "idle_timeout_in_minutes": { + Type: schema.TypeInt, + Optional: true, + Default: 30, + ValidateFunc: validation.IntBetween(4, 120), + }, "managed_outbound_ip_count": { Type: schema.TypeInt, Optional: true, @@ -1171,29 +1183,31 @@ func expandLoadBalancerProfile(d []interface{}, loadBalancerType string) (*conta config := d[0].(map[string]interface{}) - var managedOutboundIps *containerservice.ManagedClusterLoadBalancerProfileManagedOutboundIPs - var outboundIpPrefixes *containerservice.ManagedClusterLoadBalancerProfileOutboundIPPrefixes - var outboundIps *containerservice.ManagedClusterLoadBalancerProfileOutboundIPs + profile := &containerservice.ManagedClusterLoadBalancerProfile{} + + if port, ok := config["outbound_ports_allocated"].(int); ok { + profile.AllocatedOutboundPorts = utils.Int32(int32(port)) + } + + if idleTimeout, ok := config["idle_timeout_in_minutes"].(int); ok { + profile.IdleTimeoutInMinutes = utils.Int32(int32(idleTimeout)) + } if ipCount := config["managed_outbound_ip_count"]; ipCount != nil { if c := int32(ipCount.(int)); c > 0 { - managedOutboundIps = &containerservice.ManagedClusterLoadBalancerProfileManagedOutboundIPs{Count: &c} + profile.ManagedOutboundIPs = &containerservice.ManagedClusterLoadBalancerProfileManagedOutboundIPs{Count: &c} } } if ipPrefixes := idsToResourceReferences(config["outbound_ip_prefix_ids"]); ipPrefixes != nil { - outboundIpPrefixes = &containerservice.ManagedClusterLoadBalancerProfileOutboundIPPrefixes{PublicIPPrefixes: ipPrefixes} + profile.OutboundIPPrefixes = &containerservice.ManagedClusterLoadBalancerProfileOutboundIPPrefixes{PublicIPPrefixes: ipPrefixes} } if outIps := idsToResourceReferences(config["outbound_ip_address_ids"]); outIps != nil { - outboundIps = &containerservice.ManagedClusterLoadBalancerProfileOutboundIPs{PublicIPs: outIps} + profile.OutboundIPs = &containerservice.ManagedClusterLoadBalancerProfileOutboundIPs{PublicIPs: outIps} } - return &containerservice.ManagedClusterLoadBalancerProfile{ - ManagedOutboundIPs: managedOutboundIps, - OutboundIPPrefixes: outboundIpPrefixes, - OutboundIPs: outboundIps, - }, nil + return profile, nil } func idsToResourceReferences(set interface{}) *[]containerservice.ResourceReference { @@ -1265,6 +1279,14 @@ func flattenKubernetesClusterNetworkProfile(profile *containerservice.NetworkPro if lbp := profile.LoadBalancerProfile; lbp != nil { lb := make(map[string]interface{}) + if v := lbp.AllocatedOutboundPorts; v != nil { + lb["outbound_ports_allocated"] = v + } + + if v := lbp.IdleTimeoutInMinutes; v != nil { + lb["idle_timeout_in_minutes"] = v + } + if ips := lbp.ManagedOutboundIPs; ips != nil { if count := ips.Count; count != nil { lb["managed_outbound_ip_count"] = count diff --git a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go index 6329ebdd9002..2c4a683d1dd4 100644 --- a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go +++ b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go @@ -458,6 +458,8 @@ func testAccAzureRMKubernetesCluster_standardLoadBalancerProfile(t *testing.T) { resource.TestCheckResourceAttr(data.ResourceName, "network_profile.0.load_balancer_sku", "Standard"), resource.TestCheckResourceAttr(data.ResourceName, "network_profile.0.load_balancer_profile.0.managed_outbound_ip_count", "3"), resource.TestCheckResourceAttr(data.ResourceName, "network_profile.0.load_balancer_profile.0.effective_outbound_ips.#", "3"), + resource.TestCheckResourceAttr(data.ResourceName, "network_profile.0.load_balancer_profile.0.idle_timeout_in_minutes", "30"), + resource.TestCheckResourceAttr(data.ResourceName, "network_profile.0.load_balancer_profile.0.outbound_ports_allocated", "0"), ), }, }, @@ -492,6 +494,34 @@ func testAccAzureRMKubernetesCluster_standardLoadBalancerProfileComplete(t *test }) } +func TestAccAzureRMKubernetesCluster_standardLoadBalancerProfileWithPortAndTimeout(t *testing.T) { + checkIfShouldRunTestsIndividually(t) + testAccAzureRMKubernetesCluster_standardLoadBalancerProfileWithPortAndTimeout(t) +} + +func testAccAzureRMKubernetesCluster_standardLoadBalancerProfileWithPortAndTimeout(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test") + clientId := os.Getenv("ARM_CLIENT_ID") + clientSecret := os.Getenv("ARM_CLIENT_SECRET") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMKubernetesClusterDestroy, + PreventPostDestroyRefresh: true, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMKubernetesCluster_standardLoadBalancerProfileWithPortAndTimeoutConfig(data, clientId, clientSecret), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKubernetesClusterExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "network_profile.0.load_balancer_profile.0.outbound_ports_allocated", "8000"), + resource.TestCheckResourceAttr(data.ResourceName, "network_profile.0.load_balancer_profile.0.idle_timeout_in_minutes", "10"), + ), + }, + }, + }) +} + func TestAccAzureRMKubernetesCluster_basicLoadBalancerProfile(t *testing.T) { checkIfShouldRunTestsIndividually(t) testAccAzureRMKubernetesCluster_basicLoadBalancerProfile(t) @@ -1261,6 +1291,56 @@ resource "azurerm_kubernetes_cluster" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, currentKubernetesVersion, data.RandomInteger, clientId, clientSecret) } +func testAccAzureRMKubernetesCluster_standardLoadBalancerProfileWithPortAndTimeoutConfig(data acceptance.TestData, clientId string, clientSecret string) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-aks-%d" + location = "%s" +} + +resource "azurerm_kubernetes_cluster" "test" { + name = "acctestaks%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + dns_prefix = "acctestaks%d" + kubernetes_version = "%s" + + linux_profile { + admin_username = "acctestuser%d" + + ssh_key { + key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqaZoyiz1qbdOQ8xEf6uEu1cCwYowo5FHtsBhqLoDnnp7KUTEBN+L2NxRIfQ781rxV6Iq5jSav6b2Q8z5KiseOlvKA/RF2wqU0UPYqQviQhLmW6THTpmrv/YkUCuzxDpsH7DUDhZcwySLKVVe0Qm3+5N2Ta6UYH3lsDf9R9wTP2K/+vAnflKebuypNlmocIvakFWoZda18FOmsOoIVXQ8HWFNCuw9ZCunMSN62QGamCe3dL5cXlkgHYv7ekJE15IA9aOJcM7e90oeTqo+7HTcWfdu0qQqPWY5ujyMw/llas8tsXY85LFqRnr3gJ02bAscjc477+X+j/gkpFoN1QEmt terraform@demo.tld" + } + } + + default_node_pool { + name = "default" + node_count = 1 + vm_size = "Standard_DS2_v2" + } + + service_principal { + client_id = "%s" + client_secret = "%s" + } + + network_profile { + network_plugin = "kubenet" + load_balancer_sku = "Standard" + load_balancer_profile { + managed_outbound_ip_count = 2 + outbound_ports_allocated = 8000 + idle_timeout_in_minutes = 10 + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, currentKubernetesVersion, data.RandomInteger, clientId, clientSecret) +} + func testAccAzureRMKubernetesCluster_basicLoadBalancerProfileConfig(data acceptance.TestData, clientId string, clientSecret string) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_test.go b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_test.go index 30514c91b31f..594b05261c11 100644 --- a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_test.go +++ b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_test.go @@ -38,23 +38,24 @@ func TestAccAzureRMKubernetes_all(t *testing.T) { "roleBasedAccessControlAAD": testAccAzureRMKubernetesCluster_roleBasedAccessControlAAD, }, "network": { - "advancedNetworkingKubenet": testAccAzureRMKubernetesCluster_advancedNetworkingKubenet, - "advancedNetworkingKubenetComplete": testAccAzureRMKubernetesCluster_advancedNetworkingKubenetComplete, - "advancedNetworkingAzure": testAccAzureRMKubernetesCluster_advancedNetworkingAzure, - "advancedNetworkingAzureComplete": testAccAzureRMKubernetesCluster_advancedNetworkingAzureComplete, - "advancedNetworkingAzureCalicoPolicy": testAccAzureRMKubernetesCluster_advancedNetworkingAzureCalicoPolicy, - "advancedNetworkingAzureCalicoPolicyComplete": testAccAzureRMKubernetesCluster_advancedNetworkingAzureCalicoPolicyComplete, - "advancedNetworkingAzureNPMPolicy": testAccAzureRMKubernetesCluster_advancedNetworkingAzureNPMPolicy, - "advancedNetworkingAzureNPMPolicyComplete": testAccAzureRMKubernetesCluster_advancedNetworkingAzureNPMPolicyComplete, - "enableNodePublicIP": testAccAzureRMKubernetesCluster_enableNodePublicIP, - "internalNetwork": testAccAzureRMKubernetesCluster_internalNetwork, - "basicLoadBalancerProfile": testAccAzureRMKubernetesCluster_basicLoadBalancerProfile, - "conflictingLoadBalancerProfile": testAccAzureRMKubernetesCluster_conflictingLoadBalancerProfile, - "prefixedLoadBalancerProfile": testAccAzureRMKubernetesCluster_prefixedLoadBalancerProfile, - "standardLoadBalancer": testAccAzureRMKubernetesCluster_standardLoadBalancer, - "standardLoadBalancerComplete": testAccAzureRMKubernetesCluster_standardLoadBalancerComplete, - "standardLoadBalancerProfile": testAccAzureRMKubernetesCluster_standardLoadBalancerProfile, - "standardLoadBalancerProfileComplete": testAccAzureRMKubernetesCluster_standardLoadBalancerProfileComplete, + "advancedNetworkingKubenet": testAccAzureRMKubernetesCluster_advancedNetworkingKubenet, + "advancedNetworkingKubenetComplete": testAccAzureRMKubernetesCluster_advancedNetworkingKubenetComplete, + "advancedNetworkingAzure": testAccAzureRMKubernetesCluster_advancedNetworkingAzure, + "advancedNetworkingAzureComplete": testAccAzureRMKubernetesCluster_advancedNetworkingAzureComplete, + "advancedNetworkingAzureCalicoPolicy": testAccAzureRMKubernetesCluster_advancedNetworkingAzureCalicoPolicy, + "advancedNetworkingAzureCalicoPolicyComplete": testAccAzureRMKubernetesCluster_advancedNetworkingAzureCalicoPolicyComplete, + "advancedNetworkingAzureNPMPolicy": testAccAzureRMKubernetesCluster_advancedNetworkingAzureNPMPolicy, + "advancedNetworkingAzureNPMPolicyComplete": testAccAzureRMKubernetesCluster_advancedNetworkingAzureNPMPolicyComplete, + "enableNodePublicIP": testAccAzureRMKubernetesCluster_enableNodePublicIP, + "internalNetwork": testAccAzureRMKubernetesCluster_internalNetwork, + "basicLoadBalancerProfile": testAccAzureRMKubernetesCluster_basicLoadBalancerProfile, + "conflictingLoadBalancerProfile": testAccAzureRMKubernetesCluster_conflictingLoadBalancerProfile, + "prefixedLoadBalancerProfile": testAccAzureRMKubernetesCluster_prefixedLoadBalancerProfile, + "standardLoadBalancer": testAccAzureRMKubernetesCluster_standardLoadBalancer, + "standardLoadBalancerComplete": testAccAzureRMKubernetesCluster_standardLoadBalancerComplete, + "standardLoadBalancerProfile": testAccAzureRMKubernetesCluster_standardLoadBalancerProfile, + "standardLoadBalancerProfileComplete": testAccAzureRMKubernetesCluster_standardLoadBalancerProfileComplete, + "standardLoadBalancerProfileWithPortAndTimeout": testAccAzureRMKubernetesCluster_standardLoadBalancerProfileWithPortAndTimeout, }, "nodePool": { "autoScale": testAccAzureRMKubernetesClusterNodePool_autoScale, diff --git a/website/docs/r/kubernetes_cluster.html.markdown b/website/docs/r/kubernetes_cluster.html.markdown index 8be56328e6ae..256db541dbe4 100644 --- a/website/docs/r/kubernetes_cluster.html.markdown +++ b/website/docs/r/kubernetes_cluster.html.markdown @@ -281,7 +281,11 @@ A `load_balancer_profile` block supports the following: ~> **NOTE:** These options are mutually exclusive. Note that when specifying `outbound_ip_address_ids` ([azurerm_public_ip](/docs/providers/azurerm/r/public_ip.html)) the SKU must be `Standard`. -* `managed_outbound_ip_count` - (Optional) Count of desired managed outbound IPs for the cluster load balancer. Must be in the range of [1, 100]. +* `outbound_ports_allocated` - (Optional) Number of desired SNAT port for each VM in the clusters load balancer. Must be between `0` and `64000` inclusive. Defaults to `0`. + +* `idle_timeout_in_minutes` - (Optional) Desired outbound flow idle timeout in minutes for the cluster load balancer. Must be between `4` and `120` inclusive. Defaults to `30`. + +* `managed_outbound_ip_count` - (Optional) Count of desired managed outbound IPs for the cluster load balancer. Must be between `1` and `100` inclusive. * `outbound_ip_prefix_ids` - (Optional) The ID of the outbound Public IP Address Prefixes which should be used for the cluster load balancer.