Skip to content

Commit

Permalink
Preflight update and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
BCarvalheira authored and cadenmarchese committed Jul 18, 2024
1 parent ce31826 commit e7b3fe6
Show file tree
Hide file tree
Showing 4 changed files with 402 additions and 129 deletions.
15 changes: 2 additions & 13 deletions pkg/api/preflight.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,8 @@ type PreflightRequest struct {

// ValidationResult is the validation result to return in the deployment preflight response body
type ValidationResult struct {
Status ValidationStatus `json:"status"`
Error *ManagementErrorWithDetails `json:"error,omitempty"`
}

type ManagementErrorWithDetails struct {
// Code - The error code returned from the server.
Code *string `json:"code,omitempty"`
// Message - The error message returned from the server.
Message *string `json:"message,omitempty"`
// Target - The target of the error.
Target *string `json:"target,omitempty"`
// Details - Validation error.
Details *[]ManagementErrorWithDetails `json:"details,omitempty"`
Status ValidationStatus `json:"status"`
Error *CloudErrorBody `json:"error,omitempty"`
}

// ResourceTypeMeta is the Typemeta inside request body of preflight
Expand Down
16 changes: 16 additions & 0 deletions pkg/api/subscriptiondocument_example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package api

// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.

func ExampleSubscriptionDocument() *SubscriptionDocument {
return &SubscriptionDocument{
ID: "00000000-0000-0000-0000-000000000000",
Subscription: &Subscription{
State: SubscriptionStateRegistered,
Properties: &SubscriptionProperties{
TenantID: "11111111-1111-1111-1111-111111111111",
},
},
}
}
84 changes: 56 additions & 28 deletions pkg/frontend/openshiftcluster_preflightvalidation.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"net/http"
"strings"

"github.com/Azure/go-autorest/autorest/to"
"github.com/sirupsen/logrus"

"github.com/Azure/ARO-RP/pkg/api"
"github.com/Azure/ARO-RP/pkg/database/cosmosdb"
"github.com/Azure/ARO-RP/pkg/env"
"github.com/Azure/ARO-RP/pkg/frontend/middleware"
)
Expand All @@ -36,8 +36,8 @@ func (f *frontend) preflightValidation(w http.ResponseWriter, r *http.Request) {
if err != nil {
b = marshalValidationResult(api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.ManagementErrorWithDetails{
Message: to.StringPtr(err.Error()),
Error: &api.CloudErrorBody{
Message: err.Error(),
},
})
reply(log, w, header, b, statusCodeError(http.StatusOK))
Expand All @@ -48,13 +48,20 @@ func (f *frontend) preflightValidation(w http.ResponseWriter, r *http.Request) {
typeMeta := api.ResourceTypeMeta{}
if err := json.Unmarshal(raw, &typeMeta); err != nil {
// failing to parse the preflight body is not considered a validation failure. continue
log.Warningf("bad request. Failed to unmarshal ResourceTypeMeta: %s", err)
continue
log.Warningf("preflight validation failed with bad request. Failed to unmarshal ResourceTypeMeta: %s", err)
b = marshalValidationResult(api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.CloudErrorBody{
Message: err.Error(),
},
})
reply(log, w, header, b, statusCodeError(http.StatusOK))
return
}
if strings.EqualFold(typeMeta.Type, "Microsoft.RedHatOpenShift/openShiftClusters") {
res := f._preflightValidation(ctx, log, raw, typeMeta.APIVersion, typeMeta.Id)
res := f._preflightValidation(ctx, log, raw, typeMeta.APIVersion, strings.ToLower(typeMeta.Id))
if res.Status == api.ValidationStatusFailed {
log.Warningf("preflight validation failed")
log.Warningf("preflight validation failed with err: '%s'", res.Error.Message)
b = marshalValidationResult(res)
reply(log, w, header, b, statusCodeError(http.StatusOK))
return
Expand All @@ -68,6 +75,18 @@ func (f *frontend) preflightValidation(w http.ResponseWriter, r *http.Request) {
}

func (f *frontend) _preflightValidation(ctx context.Context, log *logrus.Entry, raw json.RawMessage, apiVersion string, resourceID string) api.ValidationResult {
log.Infof("running preflight validation on resource: %s", resourceID)
doc, err := f.dbOpenShiftClusters.Get(ctx, resourceID)

Check failure on line 79 in pkg/frontend/openshiftcluster_preflightvalidation.go

View workflow job for this annotation

GitHub Actions / golangci-lint

f.dbOpenShiftClusters undefined (type *frontend has no field or method dbOpenShiftClusters)) (typecheck)

Check failure on line 79 in pkg/frontend/openshiftcluster_preflightvalidation.go

View workflow job for this annotation

GitHub Actions / golangci-lint

f.dbOpenShiftClusters undefined (type *frontend has no field or method dbOpenShiftClusters) (typecheck)
isCreate := cosmosdb.IsErrorStatusCode(err, http.StatusNotFound)
if err != nil && !isCreate {
log.Warning(err.Error())
return api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.CloudErrorBody{
Message: "400: Cluster not found for resourceID: " + resourceID,
},
}
}
// unmarshal raw to OpenShiftCluster type
oc := &api.OpenShiftCluster{}
oc.Properties.ProvisioningState = api.ProvisioningStateSucceeded
Expand All @@ -79,35 +98,44 @@ func (f *frontend) _preflightValidation(ctx context.Context, log *logrus.Entry,
converter := f.apis[apiVersion].OpenShiftClusterConverter
staticValidator := f.apis[apiVersion].OpenShiftClusterStaticValidator
ext := converter.ToExternal(oc)
if err := json.Unmarshal(raw, &ext); err != nil {
if err = json.Unmarshal(raw, &ext); err != nil {
log.Warning(err.Error())
return api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.ManagementErrorWithDetails{
Message: to.StringPtr(err.Error()),
Error: &api.CloudErrorBody{
Message: api.CloudErrorCodeInternalServerError,
},
}
}

converter.ToInternal(ext, oc)
if err := staticValidator.Static(ext, nil, f.env.Location(), f.env.Domain(), f.env.FeatureIsSet(env.FeatureRequireD2sV3Workers), resourceID); err != nil {
return api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.ManagementErrorWithDetails{
Message: to.StringPtr(err.Error()),
},
if isCreate {
converter.ToInternal(ext, oc)
if err = staticValidator.Static(ext, nil, f.env.Location(), f.env.Domain(), f.env.FeatureIsSet(env.FeatureRequireD2sV3Workers), resourceID); err != nil {
return api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.CloudErrorBody{
Message: err.Error(),
},
}
}
}

if err := f.validateInstallVersion(ctx, oc); err != nil {
return api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.ManagementErrorWithDetails{
Code: to.StringPtr(api.CloudErrorCodeInvalidParameter),
Message: to.StringPtr(err.Error()),
},
if err := f.validateInstallVersion(ctx, oc); err != nil {
return api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.CloudErrorBody{
Code: api.CloudErrorCodeInvalidParameter,
Message: err.Error(),
},
}
}
} else {
if err := staticValidator.Static(ext, doc.OpenShiftCluster, f.env.Location(), f.env.Domain(), f.env.FeatureIsSet(env.FeatureRequireD2sV3Workers), resourceID); err != nil {
return api.ValidationResult{
Status: api.ValidationStatusFailed,
Error: &api.CloudErrorBody{
Message: err.Error(),
},
}
}
}

return validationSuccess
}

Expand Down
Loading

0 comments on commit e7b3fe6

Please sign in to comment.