-
Notifications
You must be signed in to change notification settings - Fork 196
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
add Preflight Validate API support #4329
base: main
Are you sure you want to change the base?
Changes from all commits
4b4f6a3
4c267fd
1dd2246
24bef4f
7392da7
5fd5d08
4531513
d955428
59c65f0
e17c1db
932cba3
4ae5dc1
7bab2e2
5ad148b
0aba62a
ca49e0d
3264e88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,13 @@ import ( | |
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
|
||
"github.com/Azure/azure-sdk-for-go/sdk/azcore" | ||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" | ||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" | ||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to" | ||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" | ||
"github.com/azure/azure-dev/cli/azd/pkg/account" | ||
|
@@ -688,3 +691,129 @@ func convertFromStandardProvisioningState(state armresources.ProvisioningState) | |
|
||
return DeploymentProvisioningState("") | ||
} | ||
|
||
func (ds *StandardDeployments) ValidatePreflightToSubscription( | ||
ctx context.Context, | ||
subscriptionId string, | ||
location string, | ||
deploymentName string, | ||
armTemplate azure.RawArmTemplate, | ||
parameters azure.ArmParameters, | ||
tags map[string]*string, | ||
options map[string]any, | ||
) error { | ||
deploymentClient, err := ds.createDeploymentsClient(ctx, subscriptionId) | ||
if err != nil { | ||
return fmt.Errorf("creating deployments client: %w", err) | ||
} | ||
|
||
var rawResponse *http.Response | ||
ctxWithResp := runtime.WithCaptureResponse(ctx, &rawResponse) | ||
|
||
validate, err := deploymentClient.BeginValidateAtSubscriptionScope( | ||
ctxWithResp, deploymentName, | ||
armresources.Deployment{ | ||
Properties: &armresources.DeploymentProperties{ | ||
Template: armTemplate, | ||
Parameters: parameters, | ||
Mode: to.Ptr(armresources.DeploymentModeIncremental), | ||
}, | ||
Location: to.Ptr(location), | ||
Tags: tags, | ||
}, nil) | ||
if err != nil { | ||
return validatePreflightError(rawResponse, err, "subscription") | ||
} | ||
|
||
_, err = validate.PollUntilDone(ctx, nil) | ||
if err != nil { | ||
preflightError := createDeploymentError(err) | ||
return fmt.Errorf( | ||
"validating preflight to subscription:\n\nPreflight Error Details:\n%w", | ||
preflightError, | ||
) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type PreflightErrorResponse struct { | ||
Error struct { | ||
Code string `json:"code"` | ||
Message string `json:"message"` | ||
Details []struct { | ||
Code string `json:"code"` | ||
Message string `json:"message"` | ||
} `json:"details"` | ||
} `json:"error"` | ||
} | ||
Comment on lines
+740
to
+749
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like this basically captures the same ARM errors that we use in the |
||
|
||
func validatePreflightError( | ||
rawResponse *http.Response, | ||
err error, | ||
typeMessage string, | ||
) error { | ||
if rawResponse == nil || rawResponse.StatusCode != 400 { | ||
return fmt.Errorf("calling preflight validate api failing to %s: %w", typeMessage, err) | ||
} | ||
|
||
defer rawResponse.Body.Close() | ||
body, errOnRawResponse := io.ReadAll(rawResponse.Body) | ||
if errOnRawResponse != nil { | ||
return fmt.Errorf("failed to read response error body from preflight api to %s: %w", typeMessage, errOnRawResponse) | ||
} | ||
|
||
var errPreflight PreflightErrorResponse | ||
errOnRawResponse = json.Unmarshal(body, &errPreflight) | ||
if errOnRawResponse != nil { | ||
return fmt.Errorf("failed to unmarshal preflight error response to %s: %w", typeMessage, errOnRawResponse) | ||
} | ||
|
||
if len(errPreflight.Error.Details) > 0 { | ||
detailMessage := errPreflight.Error.Details[0].Message | ||
return fmt.Errorf("calling preflight validate api failing to %s: %s", typeMessage, detailMessage) | ||
} else { | ||
return fmt.Errorf("calling preflight validate api failing to %s: %w", typeMessage, err) | ||
} | ||
} | ||
|
||
func (ds *StandardDeployments) ValidatePreflightToResourceGroup( | ||
ctx context.Context, | ||
subscriptionId, resourceGroup, deploymentName string, | ||
armTemplate azure.RawArmTemplate, | ||
parameters azure.ArmParameters, | ||
tags map[string]*string, | ||
options map[string]any, | ||
) error { | ||
deploymentClient, err := ds.createDeploymentsClient(ctx, subscriptionId) | ||
if err != nil { | ||
return fmt.Errorf("creating deployments client: %w", err) | ||
} | ||
|
||
var rawResponse *http.Response | ||
ctxWithResp := runtime.WithCaptureResponse(ctx, &rawResponse) | ||
|
||
validate, err := deploymentClient.BeginValidate(ctxWithResp, resourceGroup, deploymentName, | ||
armresources.Deployment{ | ||
Properties: &armresources.DeploymentProperties{ | ||
Template: armTemplate, | ||
Parameters: parameters, | ||
Mode: to.Ptr(armresources.DeploymentModeIncremental), | ||
}, | ||
Tags: tags, | ||
}, nil) | ||
if err != nil { | ||
return validatePreflightError(rawResponse, err, "resource group") | ||
} | ||
|
||
_, err = validate.PollUntilDone(ctx, nil) | ||
if err != nil { | ||
deploymentError := createDeploymentError(err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should use this same |
||
return fmt.Errorf( | ||
"validating preflight to resource group:\n\nDeployment Error Details:\n%w", | ||
deploymentError, | ||
) | ||
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to do this? If we get an HttpError we should be able to case the error to ARM http error to parse the error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a workaround for a related bug here: Azure/azure-sdk-for-go#23350