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_fleet_manager - Add support for hub_profile property #28365

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 135 additions & 87 deletions internal/services/containers/kubernetes_fleet_manager_resource.go
Original file line number Diff line number Diff line change
@@ -1,80 +1,100 @@
package containers

// NOTE: this file is generated - manual changes will be overwritten.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See NOTICE.txt in the project root for license information.
import (
"context"
"fmt"
"regexp"
"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-helpers/resourcemanager/location"
"github.com/hashicorp/go-azure-helpers/resourcemanager/tags"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2024-04-01/fleets"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

var (
_ sdk.Resource = KubernetesFleetManagerResource{}
_ sdk.ResourceWithUpdate = KubernetesFleetManagerResource{}
)
type KubernetesFleetManagerModel struct {
Name string `tfschema:"name"`
ResourceGroupName string `tfschema:"resource_group_name"`
Location string `tfschema:"location"`
HubProfile []FleetHubProfileModel `tfschema:"hub_profile"`
Tags map[string]string `tfschema:"tags"`
}

type FleetHubProfileModel struct {
DnsPrefix string `tfschema:"dns_prefix"`
Fqdn string `tfschema:"fqdn"`
KubernetesVersion string `tfschema:"kubernetes_version"`
PortalFqdn string `tfschema:"portal_fqdn"`
}

type KubernetesFleetManagerResource struct{}

func (r KubernetesFleetManagerResource) ModelObject() interface{} {
return &KubernetesFleetManagerResourceSchema{}
var _ sdk.ResourceWithUpdate = KubernetesFleetManagerResource{}

func (r KubernetesFleetManagerResource) ResourceType() string {
return "azurerm_kubernetes_fleet_manager"
}

type KubernetesFleetManagerResourceSchema struct {
Location string `tfschema:"location"`
Name string `tfschema:"name"`
ResourceGroupName string `tfschema:"resource_group_name"`
Tags map[string]interface{} `tfschema:"tags"`
func (r KubernetesFleetManagerResource) ModelObject() interface{} {
return &KubernetesFleetManagerModel{}
}

func (r KubernetesFleetManagerResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return fleets.ValidateFleetID
}

func (r KubernetesFleetManagerResource) ResourceType() string {
return "azurerm_kubernetes_fleet_manager"
}

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

"resource_group_name": commonschema.ResourceGroupName(),

"location": commonschema.Location(),

"hub_profile": {
Deprecated: "The service team has indicated this field is now deprecated and not to be used, as such we are marking it as such and no longer sending it to the API, please see url: https://learn.microsoft.com/en-us/azure/kubernetes-fleet/architectural-overview",
Type: pluginsdk.TypeList,
Optional: true,
ForceNew: true,
MaxItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"dns_prefix": {
Required: true,
Type: pluginsdk.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.All(
validation.StringLenBetween(1, 54),
validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-]{0,52}[a-zA-Z0-9]$`), "must match the pattern ^[a-zA-Z0-9]$|^[a-zA-Z0-9][a-zA-Z0-9-]{0,52}[a-zA-Z0-9]$"),
),
},

"fqdn": {
Computed: true,
Type: pluginsdk.TypeString,
Computed: true,
},

"kubernetes_version": {
Type: pluginsdk.TypeString,
Computed: true,
},

"portal_fqdn": {
Type: pluginsdk.TypeString,
Computed: true,
},
},
},
ForceNew: true,
MaxItems: 1,
Optional: true,
Type: pluginsdk.TypeList,
},

"tags": commonschema.Tags(),
}
}
Expand All @@ -87,31 +107,34 @@ func (r KubernetesFleetManagerResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.ContainerService.V20231015.Fleets

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

client := metadata.Client.ContainerService.V20231015.Fleets
subscriptionId := metadata.Client.Account.SubscriptionId
Comment on lines +110 to 116
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be mindful of the ordering of calls here, boilerplate code should follow the same pattern and ordering as the rest of the provider.

Suggested change
var model KubernetesFleetManagerModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}
client := metadata.Client.ContainerService.V20231015.Fleets
subscriptionId := metadata.Client.Account.SubscriptionId
client := metadata.Client.ContainerService.V20231015.Fleets
subscriptionId := metadata.Client.Account.SubscriptionId
var model KubernetesFleetManagerModel
if err := metadata.Decode(&model); err != nil {
return fmt.Errorf("decoding: %+v", err)
}


id := fleets.NewFleetID(subscriptionId, config.ResourceGroupName, config.Name)
id := fleets.NewFleetID(subscriptionId, model.ResourceGroupName, model.Name)

existing, err := client.Get(ctx, id)
if err != nil {
if !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for the presence of an existing %s: %+v", id, err)
}
if err != nil && !response.WasNotFound(existing.HttpResponse) {
return fmt.Errorf("checking for existing %s: %+v", id, err)
}

if !response.WasNotFound(existing.HttpResponse) {
return metadata.ResourceRequiresImport(r.ResourceType(), id)
}

var payload fleets.Fleet
r.mapKubernetesFleetManagerResourceSchemaToFleet(config, &payload)
fleetResource := &fleets.Fleet{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is usually called params or payload

Location: location.Normalize(model.Location),
Tags: pointer.To(model.Tags),
Properties: &fleets.FleetProperties{
HubProfile: expandFleetHubProfileModel(model.HubProfile),
},
}

if err := client.CreateOrUpdateThenPoll(ctx, id, payload, fleets.DefaultCreateOrUpdateOperationOptions()); err != nil {
if err := client.CreateOrUpdateThenPoll(ctx, id, *fleetResource, fleets.DefaultCreateOrUpdateOperationOptions()); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}

Expand All @@ -121,40 +144,51 @@ func (r KubernetesFleetManagerResource) Create() sdk.ResourceFunc {
}
}

func (r KubernetesFleetManagerResource) Read() sdk.ResourceFunc {
func (r KubernetesFleetManagerResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.ContainerService.V20231015.Fleets
schema := KubernetesFleetManagerResourceSchema{}

id, err := fleets.ParseFleetID(metadata.ResourceData.Id())
if err != nil {
return err
}

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

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

if model := resp.Model; model != nil {
schema.Name = id.FleetName
schema.ResourceGroupName = id.ResourceGroupName
r.mapFleetToKubernetesFleetManagerResourceSchema(*model, &schema)
properties := resp.Model
if resp.Model == nil {
return fmt.Errorf("retrieving %s: `model` was nil", *id)
}
if resp.Model.Properties == nil {
return fmt.Errorf("retrieving %s: `properties` was nil", *id)
}

if metadata.ResourceData.HasChange("tags") {
properties.Tags = pointer.To(model.Tags)
}

if err := client.CreateOrUpdateThenPoll(ctx, *id, *properties, fleets.DefaultCreateOrUpdateOperationOptions()); err != nil {
return fmt.Errorf("updating %s: %+v", *id, err)
}

return metadata.Encode(&schema)
return nil
},
}
}

func (r KubernetesFleetManagerResource) Delete() sdk.ResourceFunc {
func (r KubernetesFleetManagerResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.ContainerService.V20231015.Fleets

Expand All @@ -163,16 +197,36 @@ func (r KubernetesFleetManagerResource) Delete() sdk.ResourceFunc {
return err
}

if err := client.DeleteThenPoll(ctx, *id, fleets.DefaultDeleteOperationOptions()); err != nil {
return fmt.Errorf("deleting %s: %+v", *id, err)
resp, err := client.Get(ctx, *id)
if err != nil {
if response.WasNotFound(resp.HttpResponse) {
return metadata.MarkAsGone(id)
}

return fmt.Errorf("retrieving %s: %+v", *id, err)
}

return nil
state := KubernetesFleetManagerModel{
Name: id.FleetName,
ResourceGroupName: id.ResourceGroupName,
}

if model := resp.Model; model != nil {
state.Location = location.Normalize(model.Location)

if properties := model.Properties; properties != nil {
state.HubProfile = flattenFleetHubProfileModel(properties.HubProfile)
}

state.Tags = pointer.From(model.Tags)
}

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

func (r KubernetesFleetManagerResource) Update() sdk.ResourceFunc {
func (r KubernetesFleetManagerResource) Delete() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 30 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
Expand All @@ -183,45 +237,39 @@ func (r KubernetesFleetManagerResource) Update() sdk.ResourceFunc {
return err
}

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

existing, err := client.Get(ctx, *id)
if err != nil {
return fmt.Errorf("retrieving existing %s: %+v", *id, err)
}
if existing.Model == nil {
return fmt.Errorf("retrieving existing %s: properties was nil", *id)
}
payload := *existing.Model

r.mapKubernetesFleetManagerResourceSchemaToFleet(config, &payload)

if err := client.CreateOrUpdateThenPoll(ctx, *id, payload, fleets.DefaultCreateOrUpdateOperationOptions()); err != nil {
return fmt.Errorf("updating %s: %+v", *id, err)
if err := client.DeleteThenPoll(ctx, *id, fleets.DefaultDeleteOperationOptions()); err != nil {
return fmt.Errorf("deleting %s: %+v", id, err)
}

return nil
},
}
}

func (r KubernetesFleetManagerResource) mapKubernetesFleetManagerResourceSchemaToFleet(input KubernetesFleetManagerResourceSchema, output *fleets.Fleet) {
output.Location = location.Normalize(input.Location)
output.Tags = tags.Expand(input.Tags)
func expandFleetHubProfileModel(inputList []FleetHubProfileModel) *fleets.FleetHubProfile {
if len(inputList) == 0 {
return nil
}

if output.Properties == nil {
output.Properties = &fleets.FleetProperties{}
input := inputList[0]
output := &fleets.FleetHubProfile{
DnsPrefix: pointer.To(input.DnsPrefix),
}

return output
}

func (r KubernetesFleetManagerResource) mapFleetToKubernetesFleetManagerResourceSchema(input fleets.Fleet, output *KubernetesFleetManagerResourceSchema) {
output.Location = location.Normalize(input.Location)
output.Tags = tags.Flatten(input.Tags)
func flattenFleetHubProfileModel(input *fleets.FleetHubProfile) []FleetHubProfileModel {
if input == nil {
return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should return an empty hub profile model here

Suggested change
return nil
return []FleetHubProfileModel

}

if input.Properties == nil {
input.Properties = &fleets.FleetProperties{}
output := FleetHubProfileModel{
DnsPrefix: pointer.From(input.DnsPrefix),
Fqdn: pointer.From(input.Fqdn),
KubernetesVersion: pointer.From(input.KubernetesVersion),
PortalFqdn: pointer.From(input.PortalFqdn),
}

return []FleetHubProfileModel{output}
}
Loading
Loading