ARO-RP/pkg/frontend/openshiftcluster_putorpatch.go

165 строки
5.2 KiB
Go
Исходник Обычный вид История

2019-10-16 06:29:17 +03:00
package frontend
import (
"encoding/json"
2019-11-28 19:31:37 +03:00
"fmt"
2019-10-16 06:29:17 +03:00
"net/http"
"github.com/Azure/go-autorest/autorest/azure"
2019-10-16 06:29:17 +03:00
"github.com/gorilla/mux"
uuid "github.com/satori/go.uuid"
"github.com/sirupsen/logrus"
"github.com/jim-minter/rp/pkg/api"
"github.com/jim-minter/rp/pkg/database/cosmosdb"
)
func (f *frontend) putOrPatchOpenShiftCluster(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(contextKeyLog).(*logrus.Entry)
vars := mux.Vars(r)
2019-12-03 00:57:05 +03:00
var err error
r, err = readBody(w, r)
2019-10-16 06:29:17 +03:00
if err != nil {
2019-12-03 00:57:05 +03:00
api.WriteCloudError(w, err.(*api.CloudError))
2019-10-16 06:29:17 +03:00
return
}
var b []byte
2019-11-12 19:34:18 +03:00
var created bool
2019-10-16 06:29:17 +03:00
err = cosmosdb.RetryOnPreconditionFailed(func() error {
2019-12-03 00:57:05 +03:00
b, created, err = f._putOrPatchOpenShiftCluster(r, api.APIs[vars["api-version"]]["OpenShiftCluster"].(api.OpenShiftClusterToInternal), api.APIs[vars["api-version"]]["OpenShiftCluster"].(api.OpenShiftClusterToExternal))
2019-10-16 06:29:17 +03:00
return err
})
2019-12-03 00:57:05 +03:00
if err == nil && created {
2019-11-12 19:34:18 +03:00
w.WriteHeader(http.StatusCreated)
}
2019-12-03 00:57:05 +03:00
reply(log, w, b, err)
2019-10-16 06:29:17 +03:00
}
2019-12-03 00:57:05 +03:00
func (f *frontend) _putOrPatchOpenShiftCluster(r *http.Request, internal api.OpenShiftClusterToInternal, external api.OpenShiftClusterToExternal) ([]byte, bool, error) {
vars := mux.Vars(r)
2019-12-03 00:57:05 +03:00
body := r.Context().Value(contextKeyBody).([]byte)
subdoc, err := f.validateSubscriptionState(api.Key(r.URL.Path), api.SubscriptionStateRegistered)
2019-11-29 03:24:09 +03:00
if err != nil {
return nil, false, err
}
2019-12-03 00:57:05 +03:00
doc, err := f.db.OpenShiftClusters.Get(api.Key(r.URL.Path))
if err != nil && !cosmosdb.IsErrorStatusCode(err, http.StatusNotFound) {
2019-11-12 19:34:18 +03:00
return nil, false, err
2019-10-16 06:29:17 +03:00
}
isCreate := doc == nil
if isCreate {
originalPath := r.Context().Value(contextKeyOriginalPath).(string)
originalR, err := azure.ParseResourceID(originalPath)
2019-10-16 06:29:17 +03:00
if err != nil {
2019-11-12 19:34:18 +03:00
return nil, false, err
2019-10-16 06:29:17 +03:00
}
doc = &api.OpenShiftClusterDocument{
ID: uuid.NewV4().String(),
Key: api.Key(r.URL.Path),
OpenShiftCluster: &api.OpenShiftCluster{
ID: originalPath,
Name: originalR.ResourceName,
2019-12-05 16:18:47 +03:00
Type: fmt.Sprintf("%s/%s", originalR.Provider, originalR.ResourceType),
2019-10-16 06:29:17 +03:00
Properties: api.Properties{
ProvisioningState: api.ProvisioningStateSucceeded,
// TODO: ResourceGroup should be exposed in external API
ResourceGroup: vars["resourceName"],
ServicePrincipalProfile: api.ServicePrincipalProfile{
TenantID: subdoc.Subscription.Properties.TenantID,
},
2019-10-16 06:29:17 +03:00
},
},
}
}
2019-10-16 06:29:17 +03:00
err = validateTerminalProvisioningState(doc.OpenShiftCluster.Properties.ProvisioningState)
if err != nil {
return nil, false, err
}
if doc.OpenShiftCluster.Properties.ProvisioningState == api.ProvisioningStateFailed {
switch doc.OpenShiftCluster.Properties.FailedProvisioningState {
case api.ProvisioningStateCreating:
return nil, false, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeRequestNotAllowed, "", "Request is not allowed on cluster whose creation failed. Delete the cluster.")
case api.ProvisioningStateUpdating:
// allow
case api.ProvisioningStateDeleting:
return nil, false, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeRequestNotAllowed, "", "Request is not allowed on cluster whose deletion failed. Delete the cluster.")
default:
return nil, false, fmt.Errorf("unexpected failedProvisioningState %q", doc.OpenShiftCluster.Properties.FailedProvisioningState)
2019-10-16 06:29:17 +03:00
}
}
var ext interface{}
switch r.Method {
case http.MethodPut:
ext = external.OpenShiftClusterToExternal(&api.OpenShiftCluster{
ID: doc.OpenShiftCluster.ID,
Name: doc.OpenShiftCluster.Name,
Type: doc.OpenShiftCluster.Type,
Properties: api.Properties{
ProvisioningState: doc.OpenShiftCluster.Properties.ProvisioningState,
},
})
case http.MethodPatch:
ext = external.OpenShiftClusterToExternal(doc.OpenShiftCluster)
}
2019-12-03 00:57:05 +03:00
err = json.Unmarshal(body, &ext)
2019-10-16 06:29:17 +03:00
if err != nil {
2019-11-12 19:34:18 +03:00
return nil, false, api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidRequestContent, "", "The request content was invalid and could not be deserialized: %q.", err)
2019-10-16 06:29:17 +03:00
}
if isCreate {
err = internal.ValidateOpenShiftCluster(f.env.Location(), r.URL.Path, ext, nil)
} else {
err = internal.ValidateOpenShiftCluster(f.env.Location(), r.URL.Path, ext, doc.OpenShiftCluster)
}
2019-10-16 06:29:17 +03:00
if err != nil {
2019-11-12 19:34:18 +03:00
return nil, false, err
2019-10-16 06:29:17 +03:00
}
oldID, oldName, oldType := doc.OpenShiftCluster.ID, doc.OpenShiftCluster.Name, doc.OpenShiftCluster.Type
2019-12-03 00:57:05 +03:00
internal.OpenShiftClusterToInternal(ext, doc.OpenShiftCluster)
doc.OpenShiftCluster.ID, doc.OpenShiftCluster.Name, doc.OpenShiftCluster.Type = oldID, oldName, oldType
2019-12-03 06:14:00 +03:00
if isCreate {
doc.OpenShiftCluster.Properties.ProvisioningState = api.ProvisioningStateCreating
} else {
doc.OpenShiftCluster.Properties.ProvisioningState = api.ProvisioningStateUpdating
doc.Dequeues = 0
}
2019-12-03 00:57:05 +03:00
err = internal.ValidateOpenShiftClusterDynamic(r.Context(), f.fpAuthorizer, doc.OpenShiftCluster)
if err != nil {
return nil, false, err
}
if isCreate {
doc, err = f.db.OpenShiftClusters.Create(doc)
} else {
2019-11-28 00:39:22 +03:00
doc, err = f.db.OpenShiftClusters.Update(doc)
2019-10-16 06:29:17 +03:00
}
if err != nil {
2019-11-12 19:34:18 +03:00
return nil, false, err
2019-10-16 06:29:17 +03:00
}
2019-11-18 06:07:44 +03:00
doc.OpenShiftCluster.Properties.ServicePrincipalProfile.ClientSecret = ""
2019-10-16 06:29:17 +03:00
2019-12-04 00:53:11 +03:00
b, err := json.MarshalIndent(external.OpenShiftClusterToExternal(doc.OpenShiftCluster), "", " ")
2019-11-12 19:34:18 +03:00
if err != nil {
return nil, false, err
}
return b, isCreate, nil
2019-10-16 06:29:17 +03:00
}