Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_kubernetes_cluster - add support for private link #5161

Merged
merged 9 commits into from
Dec 18, 2019
31 changes: 30 additions & 1 deletion azurerm/data_source_kubernetes_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-06-01/containerservice"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-10-01/containerservice"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/kubernetes"
Expand Down Expand Up @@ -199,6 +199,24 @@ func dataSourceArmKubernetesCluster() *schema.Resource {
Computed: true,
},

"api_server_authorized_ip_ranges": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},

"private_link_enabled": {
Type: schema.TypeBool,
Computed: true,
},

"private_fqdn": {
Type: schema.TypeString,
Computed: true,
},

"kubernetes_version": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -459,9 +477,20 @@ func dataSourceArmKubernetesClusterRead(d *schema.ResourceData, meta interface{}
if props := resp.ManagedClusterProperties; props != nil {
d.Set("dns_prefix", props.DNSPrefix)
d.Set("fqdn", props.Fqdn)
d.Set("private_fqdn", props.PrivateFQDN)
d.Set("kubernetes_version", props.KubernetesVersion)
d.Set("node_resource_group", props.NodeResourceGroup)

// TODO: 2.0 we should introduce a access_profile block to match the new API design,
if accessProfile := props.APIServerAccessProfile; accessProfile != nil {
apiServerAuthorizedIPRanges := utils.FlattenStringSlice(accessProfile.AuthorizedIPRanges)
if err := d.Set("api_server_authorized_ip_ranges", apiServerAuthorizedIPRanges); err != nil {
return fmt.Errorf("Error setting `api_server_authorized_ip_ranges`: %+v", err)
}

d.Set("private_link_enabled", accessProfile.EnablePrivateCluster)
}
jlpedrosa marked this conversation as resolved.
Show resolved Hide resolved

addonProfiles := flattenKubernetesClusterDataSourceAddonProfiles(props.AddonProfiles)
if err := d.Set("addon_profile", addonProfiles); err != nil {
return fmt.Errorf("Error setting `addon_profile`: %+v", err)
Expand Down
32 changes: 32 additions & 0 deletions azurerm/data_source_kubernetes_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,38 @@ func testAccDataSourceAzureRMKubernetesCluster_basic(t *testing.T) {
})
}

func testAccDataSourceAzureRMKubernetesCluster_privateLink(t *testing.T) {
resourceName := "azurerm_kubernetes_cluster.test"
ri := tf.AccRandTimeInt()
clientId := os.Getenv("ARM_CLIENT_ID")
clientSecret := os.Getenv("ARM_CLIENT_SECRET")
location := testLocation()

privateIpAddressCdir := "10.0.0.0/8"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMKubernetesClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMKubernetesCluster_privateLinkConfig(ri, clientId, clientSecret, location, privateIpAddressCdir, true),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMKubernetesClusterExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "private_fqdn"),
resource.TestCheckResourceAttr(resourceName, "api_server_authorized_ip_ranges.#", "1"),
resource.TestCheckResourceAttr(resourceName, "private_link_enabled", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"service_principal.0.client_secret"},
},
},
})
}

func testAccDataSourceAzureRMKubernetesCluster_roleBasedAccessControl(t *testing.T) {
dataSourceName := "data.azurerm_kubernetes_cluster.test"
ri := tf.AccRandTimeInt()
Expand Down
2 changes: 1 addition & 1 deletion azurerm/internal/services/containers/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package client
import (
"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
"github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2018-09-01/containerregistry"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-06-01/containerservice"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-10-01/containerservice"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common"
)

Expand Down
2 changes: 1 addition & 1 deletion azurerm/internal/services/containers/kubernetes_addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package containers
import (
"strings"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-06-01/containerservice"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-10-01/containerservice"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package containers
import (
"fmt"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-06-01/containerservice"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-10-01/containerservice"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
Expand Down
2 changes: 1 addition & 1 deletion azurerm/resource_arm_container_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-06-01/containerservice"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-10-01/containerservice"
"github.com/hashicorp/terraform-plugin-sdk/helper/hashcode"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down
64 changes: 46 additions & 18 deletions azurerm/resource_arm_kubernetes_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-06-01/containerservice"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-10-01/containerservice"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
Expand Down Expand Up @@ -268,6 +268,17 @@ func resourceArmKubernetesCluster() *schema.Resource {
},
},

"private_link_enabled": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},

"private_fqdn": {
Type: schema.TypeString,
Computed: true,
},

// TODO: remove Computed in 2.0
"enable_pod_security_policy": {
Type: schema.TypeBool,
Expand Down Expand Up @@ -636,6 +647,13 @@ func resourceArmKubernetesClusterCreate(d *schema.ResourceData, meta interface{}
apiServerAuthorizedIPRangesRaw := d.Get("api_server_authorized_ip_ranges").(*schema.Set).List()
apiServerAuthorizedIPRanges := utils.ExpandStringSlice(apiServerAuthorizedIPRangesRaw)

enablePrivateLink := d.Get("private_link_enabled").(bool)

apiAccesProfile := containerservice.ManagedClusterAPIServerAccessProfile{
EnablePrivateCluster: &enablePrivateLink,
AuthorizedIPRanges: apiServerAuthorizedIPRanges,
}

nodeResourceGroup := d.Get("node_resource_group").(string)

enablePodSecurityPolicy := d.Get("enable_pod_security_policy").(bool)
Expand All @@ -644,19 +662,19 @@ func resourceArmKubernetesClusterCreate(d *schema.ResourceData, meta interface{}
Name: &name,
Location: &location,
ManagedClusterProperties: &containerservice.ManagedClusterProperties{
APIServerAuthorizedIPRanges: apiServerAuthorizedIPRanges,
AadProfile: azureADProfile,
AddonProfiles: addonProfiles,
AgentPoolProfiles: agentProfiles,
DNSPrefix: utils.String(dnsPrefix),
EnableRBAC: utils.Bool(rbacEnabled),
KubernetesVersion: utils.String(kubernetesVersion),
LinuxProfile: linuxProfile,
WindowsProfile: windowsProfile,
NetworkProfile: networkProfile,
ServicePrincipalProfile: servicePrincipalProfile,
NodeResourceGroup: utils.String(nodeResourceGroup),
EnablePodSecurityPolicy: utils.Bool(enablePodSecurityPolicy),
APIServerAccessProfile: &apiAccesProfile,
AadProfile: azureADProfile,
AddonProfiles: addonProfiles,
AgentPoolProfiles: agentProfiles,
DNSPrefix: utils.String(dnsPrefix),
EnableRBAC: utils.Bool(rbacEnabled),
KubernetesVersion: utils.String(kubernetesVersion),
LinuxProfile: linuxProfile,
WindowsProfile: windowsProfile,
NetworkProfile: networkProfile,
ServicePrincipalProfile: servicePrincipalProfile,
NodeResourceGroup: utils.String(nodeResourceGroup),
EnablePodSecurityPolicy: utils.Bool(enablePodSecurityPolicy),
},
Tags: tags.Expand(t),
}
Expand Down Expand Up @@ -748,7 +766,11 @@ func resourceArmKubernetesClusterUpdate(d *schema.ResourceData, meta interface{}
if d.HasChange("api_server_authorized_ip_ranges") {
updateCluster = true
apiServerAuthorizedIPRangesRaw := d.Get("api_server_authorized_ip_ranges").(*schema.Set).List()
existing.APIServerAuthorizedIPRanges = utils.ExpandStringSlice(apiServerAuthorizedIPRangesRaw)
enablePrivateCluster := d.Get("private_link_enabled").(bool)
existing.ManagedClusterProperties.APIServerAccessProfile = &containerservice.ManagedClusterAPIServerAccessProfile{
AuthorizedIPRanges: utils.ExpandStringSlice(apiServerAuthorizedIPRangesRaw),
EnablePrivateCluster: &enablePrivateCluster,
}
}

if d.HasChange("enable_pod_security_policy") {
Expand Down Expand Up @@ -903,13 +925,19 @@ func resourceArmKubernetesClusterRead(d *schema.ResourceData, meta interface{})
if props := resp.ManagedClusterProperties; props != nil {
d.Set("dns_prefix", props.DNSPrefix)
d.Set("fqdn", props.Fqdn)
d.Set("private_fqdn", props.PrivateFQDN)
d.Set("kubernetes_version", props.KubernetesVersion)
d.Set("node_resource_group", props.NodeResourceGroup)
d.Set("enable_pod_security_policy", props.EnablePodSecurityPolicy)

apiServerAuthorizedIPRanges := utils.FlattenStringSlice(props.APIServerAuthorizedIPRanges)
if err := d.Set("api_server_authorized_ip_ranges", apiServerAuthorizedIPRanges); err != nil {
return fmt.Errorf("Error setting `api_server_authorized_ip_ranges`: %+v", err)
// TODO: 2.0 we should introduce a access_profile block to match the new API design,
if accessProfile := props.APIServerAccessProfile; accessProfile != nil {
apiServerAuthorizedIPRanges := utils.FlattenStringSlice(accessProfile.AuthorizedIPRanges)
if err := d.Set("api_server_authorized_ip_ranges", apiServerAuthorizedIPRanges); err != nil {
return fmt.Errorf("Error setting `api_server_authorized_ip_ranges`: %+v", err)
}

d.Set("private_link_enabled", accessProfile.EnablePrivateCluster)
}
tombuildsstuff marked this conversation as resolved.
Show resolved Hide resolved

addonProfiles := containers.FlattenKubernetesAddOnProfiles(props.AddonProfiles)
Expand Down
2 changes: 1 addition & 1 deletion azurerm/resource_arm_kubernetes_cluster_node_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"log"
"time"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-06-01/containerservice"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-10-01/containerservice"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
Expand Down
126 changes: 126 additions & 0 deletions azurerm/resource_arm_kubernetes_cluster_other_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,89 @@ func testAccAzureRMKubernetesCluster_basicVMSS(t *testing.T) {
})
}

func testAccAzureRMKubernetesCluster_privateLinkOn(t *testing.T) {
resourceName := "azurerm_kubernetes_cluster.test"
ri := tf.AccRandTimeInt()
clientId := os.Getenv("ARM_CLIENT_ID")
clientSecret := os.Getenv("ARM_CLIENT_SECRET")
location := testLocation()

initialPrivateIpAddressCdir := "10.0.0.0/8"
modifiedPrivateIpAddressCdir := "10.230.0.0/16"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMKubernetesClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMKubernetesCluster_privateLinkConfig(ri, clientId, clientSecret, location, initialPrivateIpAddressCdir, true),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMKubernetesClusterExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "private_fqdn"),
resource.TestCheckResourceAttr(resourceName, "api_server_authorized_ip_ranges.#", "1"),
resource.TestCheckResourceAttr(resourceName, "private_link_enabled", "true"),
),
},
{
Config: testAccAzureRMKubernetesCluster_privateLinkConfig(ri, clientId, clientSecret, location, modifiedPrivateIpAddressCdir, true),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMKubernetesClusterExists(resourceName),
resource.TestCheckResourceAttrSet(resourceName, "private_fqdn"),
resource.TestCheckResourceAttr(resourceName, "api_server_authorized_ip_ranges.#", "1"),
resource.TestCheckResourceAttr(resourceName, "private_link_enabled", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"service_principal.0.client_secret"},
},
},
})
}

func testAccAzureRMKubernetesCluster_privateLinkOff(t *testing.T) {
resourceName := "azurerm_kubernetes_cluster.test"
ri := tf.AccRandTimeInt()
clientId := os.Getenv("ARM_CLIENT_ID")
clientSecret := os.Getenv("ARM_CLIENT_SECRET")
location := testLocation()

initialPrivateIpAddressCdir := "10.0.0.0/8"
modifiedPrivateIpAddressCdir := "10.230.0.0/16"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMKubernetesClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMKubernetesCluster_privateLinkConfig(ri, clientId, clientSecret, location, initialPrivateIpAddressCdir, false),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMKubernetesClusterExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "api_server_authorized_ip_ranges.#", "1"),
resource.TestCheckResourceAttr(resourceName, "private_link_enabled", "false"),
),
},
{
Config: testAccAzureRMKubernetesCluster_privateLinkConfig(ri, clientId, clientSecret, location, modifiedPrivateIpAddressCdir, false),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "api_server_authorized_ip_ranges.#", "1"),
resource.TestCheckResourceAttr(resourceName, "private_link_enabled", "false"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"service_principal.0.client_secret"},
},
},
})
}

func testAccAzureRMKubernetesCluster_requiresImport(t *testing.T) {
if !features.ShouldResourcesBeImported() {
t.Skip("Skipping since resources aren't required to be imported")
Expand Down Expand Up @@ -378,6 +461,49 @@ resource "azurerm_kubernetes_cluster" "test" {
`, rInt, location, rInt, rInt, clientId, clientSecret)
}

func testAccAzureRMKubernetesCluster_privateLinkConfig(rInt int, clientId string, clientSecret string, location string, cdir string, enablePrivateLink bool) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%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"

linux_profile {
admin_username = "acctestuser%d"

ssh_key {
key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqaZoyiz1qbdOQ8xEf6uEu1cCwYowo5FHtsBhqLoDnnp7KUTEBN+L2NxRIfQ781rxV6Iq5jSav6b2Q8z5KiseOlvKA/RF2wqU0UPYqQviQhLmW6THTpmrv/YkUCuzxDpsH7DUDhZcwySLKVVe0Qm3+5N2Ta6UYH3lsDf9R9wTP2K/+vAnflKebuypNlmocIvakFWoZda18FOmsOoIVXQ8HWFNCuw9ZCunMSN62QGamCe3dL5cXlkgHYv7ekJE15IA9aOJcM7e90oeTqo+7HTcWfdu0qQqPWY5ujyMw/llas8tsXY85LFqRnr3gJ02bAscjc477+X+j/gkpFoN1QEmt [email protected]"
}
}

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"
}

api_server_authorized_ip_ranges = [ "%s"]
private_link_enabled = %t
}
`, rInt, location, rInt, rInt, rInt, clientId, clientSecret, cdir, enablePrivateLink)
}

func testAccAzureRMKubernetesCluster_requiresImportConfig(rInt int, clientId, clientSecret, location string) string {
template := testAccAzureRMKubernetesCluster_basicVMSSConfig(rInt, clientId, clientSecret, location)
return fmt.Sprintf(`
Expand Down
Loading