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

appservice - update to go-azure-sdk and API version 2023-01-01 #24688

Merged
merged 24 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1d23b8f
migrate to 2023-01-01 - pre rebase commit for new SDK version
jackofallops Jan 23, 2024
8e6f4eb
finish refactor for go-azure-sdk first pass
jackofallops Jan 23, 2024
81d76a3
fixup error messages
jackofallops Jan 23, 2024
01b6509
fix crash in import check
jackofallops Jan 23, 2024
59db752
fixup first round of test fails
jackofallops Jan 23, 2024
1ddd01e
fixup logging and imports
jackofallops Jan 24, 2024
df6e3b2
found half migrated resource in legacy web folder
jackofallops Jan 24, 2024
047b334
linting
jackofallops Jan 24, 2024
0a452f5
tidy and fixup broken slot test
jackofallops Jan 26, 2024
a14634d
workaround for ListCredentials not really being an LRO
jackofallops Jan 29, 2024
da8dfa0
fix crash in flattenbackup for last executed
jackofallops Jan 29, 2024
c4beee9
fix construction of relayid
jackofallops Jan 29, 2024
7ed1528
fixup some docker tests
jackofallops Jan 29, 2024
57f5fde
set explicit delete opts as service defaults to true and SDK defaults…
jackofallops Jan 29, 2024
9131ece
set explicit delete opts for slots as service defaults to true and SD…
jackofallops Jan 29, 2024
00cc9a0
remove erroneous replace
jackofallops Jan 29, 2024
cac79b2
address timing issue in credentials read
jackofallops Jan 30, 2024
c2372a1
fix vendoring
jackofallops Jan 30, 2024
5998079
review feedback
jackofallops Jan 31, 2024
123caf3
gofmt
jackofallops Jan 31, 2024
f288a13
fixup activeslot custom poller
jackofallops Jan 31, 2024
a0eecb0
remove zone redundancy from test as not available subscription
jackofallops Jan 31, 2024
f5ca374
ignore change on sitecredentials pw due to salting bug only occuring …
jackofallops Jan 31, 2024
9bf1f8a
ignore change on sitecredentials pw due to salting bug only occuring …
jackofallops Jan 31, 2024
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
25 changes: 18 additions & 7 deletions internal/services/appservice/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ import (
"fmt"

"github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/appserviceplans"
_ "github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/resourceproviders"
_ "github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/webapps"
"github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/resourceproviders"
"github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/webapps"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
"github.com/tombuildsstuff/kermit/sdk/web/2022-09-01/web"
)

type Client struct {
AppServiceEnvironmentClient *web.AppServiceEnvironmentsClient
BaseClient *web.BaseClient
ResourceProvidersClient *resourceproviders.ResourceProvidersClient
ServicePlanClient *appserviceplans.AppServicePlansClient
WebAppsClient *web.AppsClient
WebAppsClient *webapps.WebAppsClient
}

func NewClient(o *common.ClientOptions) (*Client, error) {
Expand All @@ -27,19 +28,29 @@ func NewClient(o *common.ClientOptions) (*Client, error) {
baseClient := web.NewWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&baseClient.Client, o.ResourceManagerAuthorizer)

webAppServiceClient := web.NewAppsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&webAppServiceClient.Client, o.ResourceManagerAuthorizer)
webAppServiceClient, err := webapps.NewWebAppsClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building WebApps client: %+v", err)
}
o.Configure(webAppServiceClient.Client, o.Authorizers.ResourceManager)

resourceProvidersClient, err := resourceproviders.NewResourceProvidersClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building ResourceProviders client: %+v", err)
}
o.Configure(resourceProvidersClient.Client, o.Authorizers.ResourceManager)

servicePlanClient, err := appserviceplans.NewAppServicePlansClientWithBaseURI(o.Environment.ResourceManager)
if err != nil {
return nil, fmt.Errorf("building Api client: %+v", err)
return nil, fmt.Errorf("building ServicePlan client: %+v", err)
}
o.Configure(servicePlanClient.Client, o.Authorizers.ResourceManager)

return &Client{
AppServiceEnvironmentClient: &appServiceEnvironmentClient,
BaseClient: &baseClient,
ResourceProvidersClient: resourceProvidersClient,
ServicePlanClient: servicePlanClient,
WebAppsClient: &webAppServiceClient,
WebAppsClient: webAppServiceClient,
}, nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package custompollers

import (
"context"
"fmt"
"time"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
"github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/webapps"
"github.com/hashicorp/go-azure-sdk/sdk/client/pollers"
)

var _ pollers.PollerType = &appServiceActiveSlotPoller{}

type appServiceActiveSlotPoller struct {
client *webapps.WebAppsClient
id webapps.SlotId
appId commonids.AppServiceId
}

var (
pollingSuccess = pollers.PollResult{
Status: pollers.PollingStatusSucceeded,
PollInterval: 10 * time.Second,
}
pollingInProgress = pollers.PollResult{
Status: pollers.PollingStatusInProgress,
PollInterval: 10 * time.Second,
}
)

func NewAppServiceActiveSlotPoller(client *webapps.WebAppsClient, id commonids.AppServiceId, slotId webapps.SlotId) *appServiceActiveSlotPoller {
return &appServiceActiveSlotPoller{
client: client,
id: slotId,
appId: id,
}
}

func (p appServiceActiveSlotPoller) Poll(ctx context.Context) (*pollers.PollResult, error) {
resp, err := p.client.Get(ctx, p.appId)
if err == nil {
if resp.Model != nil && resp.Model.Properties != nil {
swapStatus := resp.Model.Properties.SlotSwapStatus
if swapStatus == nil || pointer.From(swapStatus.SourceSlotName) != p.id.SlotName {
return &pollingInProgress, err
}
return &pollingSuccess, nil
}
}
return nil, fmt.Errorf("retrieving %s: %+v", p.appId, err)
}
51 changes: 27 additions & 24 deletions internal/services/appservice/function_app_active_slot_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (
"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/commonids"
"github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/webapps"
"github.com/hashicorp/go-azure-sdk/sdk/client/pollers"
"github.com/hashicorp/terraform-provider-azurerm/internal/locks"
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/appservice/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/appservice/validate"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/appservice/custompollers"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
"github.com/tombuildsstuff/kermit/sdk/web/2022-09-01/web"
)

type FunctionAppActiveSlotResource struct{}
Expand All @@ -36,7 +38,7 @@ func (r FunctionAppActiveSlotResource) ResourceType() string {
}

func (r FunctionAppActiveSlotResource) IDValidationFunc() pluginsdk.SchemaValidateFunc {
return validate.FunctionAppID
return commonids.ValidateFunctionAppID
}

func (r FunctionAppActiveSlotResource) Arguments() map[string]*pluginsdk.Schema {
Expand All @@ -45,7 +47,7 @@ func (r FunctionAppActiveSlotResource) Arguments() map[string]*pluginsdk.Schema
Type: pluginsdk.TypeString,
Required: true,
Description: "The ID of the Slot to swap with `Production`.",
ValidateFunc: validate.FunctionAppSlotID,
ValidateFunc: webapps.ValidateSlotID,
},

"overwrite_network_config": {
Expand Down Expand Up @@ -79,35 +81,36 @@ func (r FunctionAppActiveSlotResource) Create() sdk.ResourceFunc {
}

client := metadata.Client.AppService.WebAppsClient
id, err := parse.FunctionAppSlotID(activeSlot.SlotID)
appId := parse.NewWebAppID(id.SubscriptionId, id.ResourceGroup, id.SiteName)
id, err := webapps.ParseSlotID(activeSlot.SlotID)
if err != nil {
return fmt.Errorf("parsing App ID: %+v", err)
}
appId := commonids.NewAppServiceID(id.SubscriptionId, id.ResourceGroupName, id.SiteName)

app, err := client.Get(ctx, id.ResourceGroup, id.SiteName)
app, err := client.Get(ctx, appId)
if err != nil {
if utils.ResponseWasNotFound(app.Response) {
if response.WasNotFound(app.HttpResponse) {
return fmt.Errorf("%s was not found", id)
}
return fmt.Errorf("reading %s: %+v", id, err)
}

csmSlotEntity := web.CsmSlotEntity{
TargetSlot: &id.SlotName,
PreserveVnet: &activeSlot.OverwriteNetworking,
csmSlotEntity := webapps.CsmSlotEntity{
TargetSlot: id.SlotName,
PreserveVnet: activeSlot.OverwriteNetworking,
}

locks.ByID(appId.ID())
defer locks.UnlockByID(appId.ID())

future, err := client.SwapSlotWithProduction(ctx, id.ResourceGroup, id.SiteName, csmSlotEntity)
if err != nil {
if _, err := client.SwapSlotWithProduction(ctx, appId, csmSlotEntity); err != nil {
return fmt.Errorf("making %s the active slot: %+v", id.SlotName, err)
}

if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for slot swap to complete: %+v", err)
pollerType := custompollers.NewAppServiceActiveSlotPoller(client, appId, *id)
poller := pollers.NewPoller(pollerType, 10*time.Second, pollers.DefaultNumberOfDroppedConnectionsToAllow)
if err := poller.PollUntilDone(ctx); err != nil {
return err
}

metadata.SetID(appId)
Expand All @@ -123,29 +126,29 @@ func (r FunctionAppActiveSlotResource) Read() sdk.ResourceFunc {
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
client := metadata.Client.AppService.WebAppsClient

id, err := parse.FunctionAppID(metadata.ResourceData.Id())
id, err := commonids.ParseFunctionAppID(metadata.ResourceData.Id())
if err != nil {
return err
}

app, err := client.Get(ctx, id.ResourceGroup, id.SiteName)
app, err := client.Get(ctx, *id)
if err != nil {
if utils.ResponseWasNotFound(app.Response) {
if response.WasNotFound(app.HttpResponse) {
return metadata.MarkAsGone(id)
}
return fmt.Errorf("reading active slot for %s: %+v", id.SiteName, err)
}

if app.SiteProperties == nil || app.SiteProperties.SlotSwapStatus == nil {
if app.Model == nil || app.Model.Properties == nil || app.Model.Properties.SlotSwapStatus == nil {
return fmt.Errorf("reading site properties to determine active slot status: %+v", err)
}

activeSlot := FunctionAppActiveSlotModel{
LastSwap: app.SiteProperties.SlotSwapStatus.TimestampUtc.String(),
LastSwap: pointer.From(app.Model.Properties.SlotSwapStatus.TimestampUtc),
}

if slotName := app.SiteProperties.SlotSwapStatus.SourceSlotName; slotName != nil {
activeSlot.SlotID = parse.NewWebAppSlotID(id.SubscriptionId, id.ResourceGroup, id.SiteName, *slotName).ID()
if slotName := app.Model.Properties.SlotSwapStatus.SourceSlotName; slotName != nil {
activeSlot.SlotID = webapps.NewSlotID(id.SubscriptionId, id.ResourceGroupName, id.SiteName, *slotName).ID()
}

// Default value here for imports as this cannot be read from service as it's part of the swap request only and not stored
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import (
"fmt"
"testing"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
"github.com/hashicorp/go-azure-sdk/resource-manager/web/2023-01-01/webapps"
"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"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/appservice/parse"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

type FunctionApActiveSlotResource struct{}
Expand Down Expand Up @@ -93,25 +94,25 @@ func TestAccFunctionAppActiveSlot_linuxUpdate(t *testing.T) {
}

func (r FunctionApActiveSlotResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
id, err := parse.FunctionAppID(state.ID)
id, err := commonids.ParseFunctionAppID(state.ID)
if err != nil {
return nil, err
}

slotId, err := parse.WebAppSlotID(state.Attributes["slot_id"])
slotId, err := webapps.ParseSlotID(state.Attributes["slot_id"])
if err != nil {
return nil, err
}

app, err := client.AppService.WebAppsClient.Get(ctx, id.ResourceGroup, id.SiteName)
app, err := client.AppService.WebAppsClient.Get(ctx, *id)
if err != nil {
return nil, fmt.Errorf("retreiving Function App %s for slot %s: %+v", id, slotId.SlotName, err)
}
if app.SiteProperties == nil || app.SiteProperties.SlotSwapStatus == nil || app.SiteProperties.SlotSwapStatus.SourceSlotName == nil {
if app.Model == nil || app.Model.Properties == nil || app.Model.Properties.SlotSwapStatus == nil || app.Model.Properties.SlotSwapStatus.SourceSlotName == nil {
return nil, fmt.Errorf("missing App Slot Properties for %s", id)
}

return utils.Bool(*app.SiteProperties.SlotSwapStatus.SourceSlotName == slotId.SlotName), nil
return pointer.To(*app.Model.Properties.SlotSwapStatus.SourceSlotName == slotId.SlotName), nil
}

func (r FunctionApActiveSlotResource) basicWindows(data acceptance.TestData) string {
Expand Down Expand Up @@ -256,15 +257,15 @@ resource "azurerm_storage_account" "test" {
}

resource "azurerm_service_plan" "test" {
name = "acctestASP-WAS-%[1]d"
name = "acctestASP-LAS-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
os_type = "Linux"
sku_name = "EP1"
}

resource "azurerm_linux_function_app" "test" {
name = "acctestWA-%[1]d"
name = "acctestLA-%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
service_plan_id = azurerm_service_plan.test.id
Expand Down
Loading
Loading