Skip to content

Commit

Permalink
azurerm_kubernetes_cluster_node_pool - support for the `source_snap…
Browse files Browse the repository at this point in the history
…shot_id` property (#21511)

* `azurerm_kubernetes_cluster_node_pool` - `source_snapshot_id`

* update

* update
  • Loading branch information
ms-henglu authored May 3, 2023
1 parent 66c530b commit 18d72e1
Show file tree
Hide file tree
Showing 25 changed files with 1,583 additions and 0 deletions.
6 changes: 6 additions & 0 deletions internal/services/containers/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/agentpools"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/maintenanceconfigurations"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/managedclusters"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/snapshots"
"github.com/hashicorp/go-azure-sdk/resource-manager/kubernetesconfiguration/2022-11-01/extensions"
"github.com/hashicorp/go-azure-sdk/sdk/client/resourcemanager"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
Expand All @@ -24,6 +25,7 @@ type Client struct {
KubernetesExtensionsClient *extensions.ExtensionsClient
MaintenanceConfigurationsClient *maintenanceconfigurations.MaintenanceConfigurationsClient
ServicesClient *containerservices.ContainerServicesClient
SnapshotClient *snapshots.SnapshotsClient
Environment azure.Environment
}

Expand Down Expand Up @@ -61,6 +63,9 @@ func NewContainersClient(o *common.ClientOptions) (*Client, error) {
servicesClient := containerservices.NewContainerServicesClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&servicesClient.Client, o.ResourceManagerAuthorizer)

snapshotClient := snapshots.NewSnapshotsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&snapshotClient.Client, o.ResourceManagerAuthorizer)

return &Client{
AgentPoolsClient: &agentPoolsClient,
ContainerInstanceClient: &containerInstanceClient,
Expand All @@ -70,6 +75,7 @@ func NewContainersClient(o *common.ClientOptions) (*Client, error) {
KubernetesExtensionsClient: &kubernetesExtensionsClient,
MaintenanceConfigurationsClient: &maintenanceConfigurationsClient,
ServicesClient: &servicesClient,
SnapshotClient: &snapshotClient,
Environment: o.AzureEnvironment,
}, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/compute/2022-03-01/proximityplacementgroups"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/agentpools"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/managedclusters"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/snapshots"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
Expand Down Expand Up @@ -294,6 +295,13 @@ func resourceKubernetesClusterNodePool() *pluginsdk.Resource {
ValidateFunc: proximityplacementgroups.ValidateProximityPlacementGroupID,
},

"snapshot_id": {
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: snapshots.ValidateSnapshotID,
},

"spot_max_price": {
Type: pluginsdk.TypeFloat,
Optional: true,
Expand Down Expand Up @@ -582,6 +590,12 @@ func resourceKubernetesClusterNodePoolCreate(d *pluginsdk.ResourceData, meta int
profile.NetworkProfile = expandAgentPoolNetworkProfile(networkProfile)
}

if snapshotId := d.Get("snapshot_id").(string); snapshotId != "" {
profile.CreationData = &agentpools.CreationData{
SourceResourceId: utils.String(snapshotId),
}
}

parameters := agentpools.AgentPool{
Name: utils.String(id.AgentPoolName),
Properties: &profile,
Expand Down Expand Up @@ -812,6 +826,10 @@ func resourceKubernetesClusterNodePoolRead(d *pluginsdk.ResourceData, meta inter
d.Set("kubelet_disk_type", string(*v))
}

if props.CreationData != nil {
d.Set("snapshot_id", props.CreationData.SourceResourceId)
}

scaleDownMode := string(managedclusters.ScaleDownModeDelete)
if v := props.ScaleDownMode; v != nil {
scaleDownMode = string(*v)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/agentpools"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/managedclusters"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/snapshots"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
Expand Down Expand Up @@ -955,6 +957,65 @@ func TestAccKubernetesClusterNodePool_nodeIPTags(t *testing.T) {
})
}

func TestAccKubernetesClusterNodePool_snapshotId(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster_node_pool", "test")
r := KubernetesClusterNodePoolResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.snapshotSource(data),
Check: acceptance.ComposeTestCheckFunc(
data.CheckWithClientForResource(func(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) error {
client := clients.Containers.SnapshotClient
poolId, err := agentpools.ParseAgentPoolID(state.ID)
if err != nil {
return err
}
id := snapshots.NewSnapshotID(poolId.SubscriptionId, poolId.ResourceGroupName, data.RandomString)
snapshot := snapshots.Snapshot{
Location: data.Locations.Primary,
Properties: &snapshots.SnapshotProperties{
CreationData: &snapshots.CreationData{
SourceResourceId: utils.String(poolId.ID()),
},
},
}
_, err = client.CreateOrUpdate(ctx, id, snapshot)
if err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}
return nil
}, "azurerm_kubernetes_cluster_node_pool.source"),
),
},
{
Config: r.snapshotRestore(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.snapshotSource(data),
Check: acceptance.ComposeTestCheckFunc(
data.CheckWithClientForResource(func(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) error {
client := clients.Containers.SnapshotClient
poolId, err := agentpools.ParseAgentPoolID(state.ID)
if err != nil {
return err
}
id := snapshots.NewSnapshotID(poolId.SubscriptionId, poolId.ResourceGroupName, data.RandomString)
_, err = client.Delete(ctx, id)
if err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}
return nil
}, "azurerm_kubernetes_cluster_node_pool.source"),
),
},
})
}

func (t KubernetesClusterNodePoolResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := agentpools.ParseAgentPoolID(state.ID)
if err != nil {
Expand Down Expand Up @@ -2544,3 +2605,87 @@ resource "azurerm_kubernetes_cluster_node_pool" "test" {
}
`, data.Locations.Primary, data.RandomInteger)
}

func (KubernetesClusterNodePoolResource) snapshotSource(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%[2]d"
location = "%[1]s"
}
resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%[2]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%[2]d"
default_node_pool {
name = "default"
node_count = 1
vm_size = "Standard_D2s_v3"
}
identity {
type = "SystemAssigned"
}
}
resource "azurerm_kubernetes_cluster_node_pool" "source" {
name = "source"
kubernetes_cluster_id = azurerm_kubernetes_cluster.test.id
vm_size = "Standard_D2s_v3"
}
`, data.Locations.Primary, data.RandomInteger)
}

func (KubernetesClusterNodePoolResource) snapshotRestore(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%[2]d"
location = "%[1]s"
}
resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%[2]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%[2]d"
default_node_pool {
name = "default"
node_count = 1
vm_size = "Standard_D2s_v3"
}
identity {
type = "SystemAssigned"
}
}
resource "azurerm_kubernetes_cluster_node_pool" "source" {
name = "source"
kubernetes_cluster_id = azurerm_kubernetes_cluster.test.id
vm_size = "Standard_D2s_v3"
}
data "azurerm_kubernetes_snapshot" "test" {
name = "%[3]s"
resource_group_name = azurerm_resource_group.test.name
}
resource "azurerm_kubernetes_cluster_node_pool" "test" {
name = "new"
kubernetes_cluster_id = azurerm_kubernetes_cluster.test.id
vm_size = "Standard_DS2_v2"
node_count = 1
snapshot_id = data.azurerm_kubernetes_snapshot.test.id
depends_on = [
azurerm_kubernetes_cluster_node_pool.source
]
}
`, data.Locations.Primary, data.RandomInteger, data.RandomString)
}
108 changes: 108 additions & 0 deletions internal/services/containers/kubernetes_snapshot_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package containers

import (
"context"
"fmt"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/agentpools"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2023-02-02-preview/snapshots"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tags"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

type KubernetesSnapshotDataSourceModel struct {
Name string `tfschema:"name"`
ResourceGroup string `tfschema:"resource_group_name"`
SourceResourceId string `tfschema:"source_resource_id"`
Tags map[string]string `tfschema:"tags"`
}

type KubernetesSnapshotDataSource struct{}

var _ sdk.DataSource = KubernetesSnapshotDataSource{}

func (r KubernetesSnapshotDataSource) ResourceType() string {
return "azurerm_kubernetes_snapshot"
}

func (r KubernetesSnapshotDataSource) ModelObject() interface{} {
return &KubernetesSnapshotDataSourceModel{}
}

func (r KubernetesSnapshotDataSource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return snapshots.ValidateSnapshotID
}

func (r KubernetesSnapshotDataSource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"resource_group_name": commonschema.ResourceGroupNameForDataSource(),
}
}

func (r KubernetesSnapshotDataSource) Attributes() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"source_resource_id": {
Type: pluginsdk.TypeString,
Computed: true,
},

"tags": tags.SchemaDataSource(),
}
}

func (r KubernetesSnapshotDataSource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.Containers.SnapshotClient
subscriptionId := metadata.Client.Account.SubscriptionId

var state KubernetesSnapshotDataSourceModel
if err := metadata.Decode(&state); err != nil {
return fmt.Errorf("decoding: %+v", err)
}

id := snapshots.NewSnapshotID(subscriptionId, state.ResourceGroup, state.Name)

resp, err := client.Get(ctx, id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return fmt.Errorf("%s was not found", id)
}
return fmt.Errorf("retrieving %s: %v", id, err)
}

state.Name = id.SnapshotName

if model := resp.Model; model != nil {
state.Tags = pointer.From(model.Tags)

if props := model.Properties; props != nil {
if props.CreationData != nil && props.CreationData.SourceResourceId != nil {
nodePoolId, err := agentpools.ParseAgentPoolIDInsensitively(*props.CreationData.SourceResourceId)
if err != nil {
return err
}
state.SourceResourceId = nodePoolId.ID()
}
}
}

metadata.SetID(id)

return metadata.Encode(&state)
},
}
}
Loading

0 comments on commit 18d72e1

Please sign in to comment.