From c3d27acbe3a7bdfc5e4bc72200e9e38a1d17d634 Mon Sep 17 00:00:00 2001 From: German Date: Tue, 1 Aug 2023 13:22:19 -0300 Subject: [PATCH] fix: Refresh and destroy on DeploymentSettings fails with 404 if there is an out of band deletion #146 --- .../pkg/internal/pulumiapi/deployment_settings.go | 9 +++++---- provider/pkg/internal/pulumiapi/error.go | 15 +++++++++++++-- provider/pkg/internal/pulumiapi/teams.go | 4 ++-- provider/pkg/provider/deployment_settings.go | 9 +++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/provider/pkg/internal/pulumiapi/deployment_settings.go b/provider/pkg/internal/pulumiapi/deployment_settings.go index f097cb7f..46f09ae5 100644 --- a/provider/pkg/internal/pulumiapi/deployment_settings.go +++ b/provider/pkg/internal/pulumiapi/deployment_settings.go @@ -2,7 +2,6 @@ package pulumiapi import ( "context" - "errors" "fmt" "net/http" "path" @@ -81,9 +80,11 @@ func (c *Client) GetDeploymentSettings(ctx context.Context, stack StackName) (*D var ds DeploymentSettings _, err := c.do(ctx, http.MethodGet, apiPath, nil, &ds) if err != nil { - var errResp *errorResponse - if errors.As(err, &errResp) && errResp.StatusCode == http.StatusNotFound { - return nil, fmt.Errorf("deployment settings for stack (%s) not found", stack.String()) + statusCode := GetErrorStatusCode(err) + if statusCode == http.StatusNotFound { + // Important: do now wrap this error so the provider knows to handle it as a + // deleted resource + return nil, err } return nil, fmt.Errorf("failed to get deployment settings for stack (%s): %w", stack.String(), err) } diff --git a/provider/pkg/internal/pulumiapi/error.go b/provider/pkg/internal/pulumiapi/error.go index 9bb051fc..15c32ef9 100644 --- a/provider/pkg/internal/pulumiapi/error.go +++ b/provider/pkg/internal/pulumiapi/error.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,10 @@ // limitations under the License. package pulumiapi -import "fmt" +import ( + "errors" + "fmt" +) // errorResponse is returned from pulumi service api when there's been an error type errorResponse struct { @@ -24,3 +27,11 @@ type errorResponse struct { func (err *errorResponse) Error() string { return fmt.Sprintf("%d API error: %s", err.StatusCode, err.Message) } + +func GetErrorStatusCode(err error) int { + var errResp *errorResponse + if errors.As(err, &errResp) { + return errResp.StatusCode + } + return 0 +} diff --git a/provider/pkg/internal/pulumiapi/teams.go b/provider/pkg/internal/pulumiapi/teams.go index 8ab22ec1..beb967bf 100644 --- a/provider/pkg/internal/pulumiapi/teams.go +++ b/provider/pkg/internal/pulumiapi/teams.go @@ -227,8 +227,8 @@ func (c *Client) updateTeamMembership(ctx context.Context, orgName, teamName, us func (c *Client) AddMemberToTeam(ctx context.Context, orgName, teamName, userName string) error { err := c.updateTeamMembership(ctx, orgName, teamName, userName, "add") if err != nil { - var errResp *errorResponse - if errors.As(err, &errResp) && errResp.StatusCode == http.StatusConflict { + statusCode := GetErrorStatusCode(err) + if statusCode == http.StatusConflict { // ignore 409 since that means the team member is already added return nil } diff --git a/provider/pkg/provider/deployment_settings.go b/provider/pkg/provider/deployment_settings.go index 9cf1852a..c5597040 100644 --- a/provider/pkg/provider/deployment_settings.go +++ b/provider/pkg/provider/deployment_settings.go @@ -3,6 +3,7 @@ package provider import ( "context" "fmt" + "net/http" "path" pbempty "github.com/golang/protobuf/ptypes/empty" @@ -529,7 +530,15 @@ func (ds *PulumiServiceDeploymentSettingsResource) Read(req *pulumirpc.ReadReque } settings, err := ds.client.GetDeploymentSettings(ctx, stack) if err != nil { + statusCode := pulumiapi.GetErrorStatusCode(err) + if statusCode == http.StatusNotFound { + // deleteResponse causes the resource to be deleted from the state. + var deleteResponse = &pulumirpc.ReadResponse{Id: "", Properties: nil} + // If it's a 404 error, this resource was probably deleted. + return deleteResponse, nil + } return nil, err + } dsInput := PulumiServiceDeploymentSettingsInput{