Skip to content
Merged
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
10 changes: 8 additions & 2 deletions pkg/asset/installconfig/gcp/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net"
"net/http"
"slices"
"strings"

Expand Down Expand Up @@ -201,11 +202,16 @@ func validateDiskTypeAvailability(client API, fieldPath *field.Path, project, re

dt, dtZones, err := client.GetDiskTypeWithZones(context.TODO(), project, region, diskType)
if err != nil {
// Reading a disk type is not required to install, so a service account
// holding only the minimum set of install permissions is denied here. That
// says nothing about the configured disk type, so skip the check rather
// than report a bad value.
var gerr *googleapi.Error
if errors.As(err, &gerr) {
if errors.As(err, &gerr) && gerr.Code < 500 && gerr.Code != http.StatusForbidden {
return append(allErrs, field.Invalid(fieldPath.Child("diskType"), diskType, err.Error()))
}
return append(allErrs, field.InternalError(fieldPath.Child("diskType"), err))
logrus.Warnf("could not verify disk type %s availability in %s, skipping API check: %v", diskType, region, err)
return allErrs
}

if dt == nil {
Expand Down
31 changes: 24 additions & 7 deletions pkg/asset/installconfig/gcp/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,7 @@ func TestValidateDiskTypeAvailability(t *testing.T) {
mockErr error
expectedError bool
expectedErrMsg string
expectedWarn string
}{
{
name: "Empty disk type is a no-op",
Expand Down Expand Up @@ -1509,21 +1510,33 @@ func TestValidateDiskTypeAvailability(t *testing.T) {
{
name: "GCP API error returns field error",
diskType: "pd-ssd",
mockErr: &googleapi.Error{Code: http.StatusForbidden, Message: "forbidden"},
mockErr: &googleapi.Error{Code: http.StatusBadRequest, Message: "bad request"},
expectedError: true,
expectedErrMsg: `forbidden`,
expectedErrMsg: `bad request`,
},
{
name: "Non-API error returns internal error",
diskType: "pd-ssd",
mockErr: fmt.Errorf("network timeout"),
expectedError: true,
expectedErrMsg: `network timeout`,
name: "GCP 403 permission denied degrades gracefully",
diskType: "pd-ssd",
mockErr: &googleapi.Error{Code: http.StatusForbidden, Message: "Required 'compute.diskTypes.get' permission"},
expectedWarn: `could not verify disk type pd-ssd availability`,
},
{
name: "GCP 503 server error degrades gracefully",
diskType: "pd-ssd",
mockErr: &googleapi.Error{Code: http.StatusServiceUnavailable, Message: "backend error"},
expectedWarn: `could not verify disk type pd-ssd availability`,
},
{
name: "Non-API error degrades gracefully",
diskType: "pd-ssd",
mockErr: fmt.Errorf("network timeout"),
expectedWarn: `could not verify disk type pd-ssd availability`,
},
}

for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
hook := logrusTest.NewGlobal()
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
gcpClient := mock.NewMockAPI(mockCtrl)
Expand All @@ -1539,6 +1552,10 @@ func TestValidateDiskTypeAvailability(t *testing.T) {
} else {
assert.Empty(t, errs)
}
if test.expectedWarn != "" {
assert.NotEmpty(t, hook.Entries)
assert.Regexp(t, test.expectedWarn, hook.LastEntry().Message)
}
})
}
}
Expand Down