Skip to content

Commit

Permalink
AKS (azurerm_kubernetes_cluster, `azurerm_kubernetes_cluster_node_p…
Browse files Browse the repository at this point in the history
…ool`): add support for version aliases (#17084)

* Migrate to containerservice 2022-03-02-preview

* Add support for AKS version alias

- Allow alias version;
- Do not rely on CurrentKubernetesVersion in resourceKubernetesClusterRead to avoid state drift.

* make generate

* Update docs

* Add an acceptance test for cluster upgrades with version aliases

* Migrate off deprecated test method
  • Loading branch information
weisdd authored Jun 28, 2022
1 parent 43c020e commit 16b9fa0
Show file tree
Hide file tree
Showing 65 changed files with 4,521 additions and 278 deletions.
2 changes: 1 addition & 1 deletion internal/services/containers/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
legacy "github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2019-08-01/containerservice"
legacyacr "github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/mgmt/2019-06-01-preview/containerregistry"
"github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/mgmt/2021-08-01-preview/containerregistry"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)
Expand Down
2 changes: 1 addition & 1 deletion internal/services/containers/kubernetes_addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"strings"

"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/Azure/go-autorest/autorest/azure"
commonValidate "github.com/hashicorp/terraform-provider-azurerm/helpers/validate"
containerValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/containers/validate"
Expand Down
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/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/identity"
"github.com/hashicorp/go-azure-helpers/resourcemanager/zones"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/zones"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
Expand Down
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/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/zones"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -846,7 +846,9 @@ func resourceKubernetesClusterNodePoolDelete(d *pluginsdk.ResourceData, meta int
return err
}

future, err := client.Delete(ctx, id.ResourceGroup, id.ManagedClusterName, id.AgentPoolName)
ignorePodDisruptionBudget := true

future, err := client.Delete(ctx, id.ResourceGroup, id.ManagedClusterName, id.AgentPoolName, &ignorePodDisruptionBudget)
if err != nil {
return fmt.Errorf("deleting %s: %+v", *id, err)
}
Expand Down
11 changes: 4 additions & 7 deletions internal/services/containers/kubernetes_cluster_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/Azure/go-autorest/autorest/date"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/identity"
Expand Down Expand Up @@ -1723,12 +1723,7 @@ func resourceKubernetesClusterRead(d *pluginsdk.ResourceData, meta interface{})
d.Set("private_fqdn", props.PrivateFQDN)
d.Set("portal_fqdn", props.AzurePortalFQDN)
d.Set("disk_encryption_set_id", props.DiskEncryptionSetID)
// CurrentKubernetesVersion contains the actual version the Managed Cluster is running after upgrading
// KubernetesVersion now seems to contain the initial version the cluster was created with
d.Set("kubernetes_version", props.KubernetesVersion)
if v := props.CurrentKubernetesVersion; v != nil {
d.Set("kubernetes_version", v)
}
d.Set("node_resource_group", props.NodeResourceGroup)
d.Set("enable_pod_security_policy", props.EnablePodSecurityPolicy)
d.Set("local_account_disabled", props.DisableLocalAccounts)
Expand Down Expand Up @@ -1911,7 +1906,9 @@ func resourceKubernetesClusterDelete(d *pluginsdk.ResourceData, meta interface{}
}
}

future, err := client.Delete(ctx, id.ResourceGroup, id.ManagedClusterName)
ignorePodDisruptionBudget := true

future, err := client.Delete(ctx, id.ResourceGroup, id.ManagedClusterName, &ignorePodDisruptionBudget)
if err != nil {
return fmt.Errorf("deleting %s: %+v", *id, err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import (
type KubernetesClusterResource struct{}

var (
olderKubernetesVersion = "1.21.7"
currentKubernetesVersion = "1.22.4"
olderKubernetesVersion = "1.21.7"
currentKubernetesVersion = "1.22.4"
olderKubernetesVersionAlias = "1.22"
currentKubernetesVersionAlias = "1.23"
)

func TestAccKubernetesCluster_hostEncryption(t *testing.T) {
Expand Down
31 changes: 31 additions & 0 deletions internal/services/containers/kubernetes_cluster_upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,37 @@ func TestAccKubernetesCluster_upgradeCustomNodePoolBeforeControlPlaneFails(t *te
})
}

func TestAccKubernetesCluster_upgradeControlPlaneAndAllPoolsTogetherVersionAlias(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}
nodePoolName := "azurerm_kubernetes_cluster_node_pool.test"

data.ResourceTest(t, r, []acceptance.TestStep{
{
// all on the older version
Config: r.upgradeVersionsConfig(data, olderKubernetesVersionAlias, olderKubernetesVersionAlias, olderKubernetesVersionAlias),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("kubernetes_version").HasValue(olderKubernetesVersionAlias),
check.That(data.ResourceName).Key("default_node_pool.0.orchestrator_version").HasValue(olderKubernetesVersionAlias),
check.That(nodePoolName).Key("orchestrator_version").HasValue(olderKubernetesVersionAlias),
),
},
data.ImportStep(),
{
// upgrade control plane, default and custom node pools
Config: r.upgradeVersionsConfig(data, currentKubernetesVersionAlias, currentKubernetesVersionAlias, currentKubernetesVersionAlias),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
check.That(data.ResourceName).Key("kubernetes_version").HasValue(currentKubernetesVersionAlias),
check.That(data.ResourceName).Key("default_node_pool.0.orchestrator_version").HasValue(currentKubernetesVersionAlias),
check.That(nodePoolName).Key("orchestrator_version").HasValue(currentKubernetesVersionAlias),
),
},
data.ImportStep(),
})
}

func TestAccKubernetesCluster_upgradeSettings(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}
Expand Down
8 changes: 5 additions & 3 deletions internal/services/containers/kubernetes_cluster_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"net/http"
"strings"

"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/containers/client"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/containers/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
Expand Down Expand Up @@ -272,8 +272,10 @@ func validateNodePoolSupportsVersion(ctx context.Context, client *client.Client,
continue
}

supportedVersions = append(supportedVersions, *version.KubernetesVersion)
if *version.KubernetesVersion == desiredNodePoolVersion {
v := *version.KubernetesVersion
supportedVersions = append(supportedVersions, v)
// alias versions (major.minor) are also fine as the latest supported GA patch version is chosen automatically in this case
if v == desiredNodePoolVersion || v[:strings.LastIndex(v, ".")] == desiredNodePoolVersion {
versionExists = true
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/services/containers/kubernetes_nodepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"strconv"
"strings"

"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/zones"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"time"

"github.com/Azure/azure-sdk-for-go/services/machinelearningservices/mgmt/2021-07-01/machinelearningservices"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-01-02-preview/containerservice"
"github.com/Azure/azure-sdk-for-go/services/preview/containerservice/mgmt/2022-03-02-preview/containerservice"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
Expand Down
75 changes: 75 additions & 0 deletions internal/services/privatedns/parse/a_record.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"fmt"
"strings"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

type ARecordId struct {
SubscriptionId string
ResourceGroup string
PrivateDnsZoneName string
AName string
}

func NewARecordID(subscriptionId, resourceGroup, privateDnsZoneName, aName string) ARecordId {
return ARecordId{
SubscriptionId: subscriptionId,
ResourceGroup: resourceGroup,
PrivateDnsZoneName: privateDnsZoneName,
AName: aName,
}
}

func (id ARecordId) String() string {
segments := []string{
fmt.Sprintf("A Name %q", id.AName),
fmt.Sprintf("Private Dns Zone Name %q", id.PrivateDnsZoneName),
fmt.Sprintf("Resource Group %q", id.ResourceGroup),
}
segmentsStr := strings.Join(segments, " / ")
return fmt.Sprintf("%s: (%s)", "A Record", segmentsStr)
}

func (id ARecordId) ID() string {
fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/privateDnsZones/%s/A/%s"
return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.PrivateDnsZoneName, id.AName)
}

// ARecordID parses a ARecord ID into an ARecordId struct
func ARecordID(input string) (*ARecordId, error) {
id, err := resourceids.ParseAzureResourceID(input)
if err != nil {
return nil, err
}

resourceId := ARecordId{
SubscriptionId: id.SubscriptionID,
ResourceGroup: id.ResourceGroup,
}

if resourceId.SubscriptionId == "" {
return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
}

if resourceId.ResourceGroup == "" {
return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
}

if resourceId.PrivateDnsZoneName, err = id.PopSegment("privateDnsZones"); err != nil {
return nil, err
}
if resourceId.AName, err = id.PopSegment("A"); err != nil {
return nil, err
}

if err := id.ValidateNoEmptySegments(input); err != nil {
return nil, err
}

return &resourceId, nil
}
128 changes: 128 additions & 0 deletions internal/services/privatedns/parse/a_record_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package parse

// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten

import (
"testing"

"github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids"
)

var _ resourceids.Id = ARecordId{}

func TestARecordIDFormatter(t *testing.T) {
actual := NewARecordID("12345678-1234-9876-4563-123456789012", "resGroup1", "privateDnsZone1", "eh1").ID()
expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/privateDnsZones/privateDnsZone1/A/eh1"
if actual != expected {
t.Fatalf("Expected %q but got %q", expected, actual)
}
}

func TestARecordID(t *testing.T) {
testData := []struct {
Input string
Error bool
Expected *ARecordId
}{

{
// empty
Input: "",
Error: true,
},

{
// missing SubscriptionId
Input: "/",
Error: true,
},

{
// missing value for SubscriptionId
Input: "/subscriptions/",
Error: true,
},

{
// missing ResourceGroup
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
Error: true,
},

{
// missing value for ResourceGroup
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
Error: true,
},

{
// missing PrivateDnsZoneName
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
Error: true,
},

{
// missing value for PrivateDnsZoneName
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/privateDnsZones/",
Error: true,
},

{
// missing AName
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/privateDnsZones/privateDnsZone1/",
Error: true,
},

{
// missing value for AName
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/privateDnsZones/privateDnsZone1/A/",
Error: true,
},

{
// valid
Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/privateDnsZones/privateDnsZone1/A/eh1",
Expected: &ARecordId{
SubscriptionId: "12345678-1234-9876-4563-123456789012",
ResourceGroup: "resGroup1",
PrivateDnsZoneName: "privateDnsZone1",
AName: "eh1",
},
},

{
// upper-cased
Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/PRIVATEDNSZONES/PRIVATEDNSZONE1/A/EH1",
Error: true,
},
}

for _, v := range testData {
t.Logf("[DEBUG] Testing %q", v.Input)

actual, err := ARecordID(v.Input)
if err != nil {
if v.Error {
continue
}

t.Fatalf("Expect a value but got an error: %s", err)
}
if v.Error {
t.Fatal("Expect an error but didn't get one")
}

if actual.SubscriptionId != v.Expected.SubscriptionId {
t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
}
if actual.ResourceGroup != v.Expected.ResourceGroup {
t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
}
if actual.PrivateDnsZoneName != v.Expected.PrivateDnsZoneName {
t.Fatalf("Expected %q but got %q for PrivateDnsZoneName", v.Expected.PrivateDnsZoneName, actual.PrivateDnsZoneName)
}
if actual.AName != v.Expected.AName {
t.Fatalf("Expected %q but got %q for AName", v.Expected.AName, actual.AName)
}
}
}
Loading

0 comments on commit 16b9fa0

Please sign in to comment.