diff options
author | Eric Multanen <eric.w.multanen@intel.com> | 2020-07-22 14:11:05 -0700 |
---|---|---|
committer | Eric Multanen <eric.w.multanen@intel.com> | 2020-08-03 15:40:09 -0700 |
commit | b2c23afb03b393b05fe38dd7c54b1de3c42deaf3 (patch) | |
tree | 5e845ad676a62e4bde17a6c4a846544164b0ad40 /src/orchestrator | |
parent | d6f900721c81a2c03cb1a21a3d2064e9a69fc4b7 (diff) |
Add StateInfo structure synced resources
Add a StateInfo structure to the Cluster and
Deployment-Intent-Group resources to keep track of
the lifecycle state of these resources. Moved the
appcontext id that was being kept into this structure
as well. Enabled the approve state (and API) for
the deployment intent group.
Issue-ID: MULTICLOUD-1042
Signed-off-by: Eric Multanen <eric.w.multanen@intel.com>
Change-Id: I36602d8a0658d9d6d37b8799f9a372a7d1042496
Diffstat (limited to 'src/orchestrator')
-rw-r--r-- | src/orchestrator/api/api.go | 2 | ||||
-rw-r--r-- | src/orchestrator/api/instantiation_handler.go | 17 | ||||
-rw-r--r-- | src/orchestrator/go.mod | 1 | ||||
-rw-r--r-- | src/orchestrator/pkg/module/deployment_intent_groups.go | 44 | ||||
-rw-r--r-- | src/orchestrator/pkg/module/instantiation.go | 111 | ||||
-rw-r--r-- | src/orchestrator/pkg/state/state_helper.go | 29 | ||||
-rw-r--r-- | src/orchestrator/pkg/state/types.go | 42 |
7 files changed, 207 insertions, 39 deletions
diff --git a/src/orchestrator/api/api.go b/src/orchestrator/api/api.go index 03afee28..72b444b7 100644 --- a/src/orchestrator/api/api.go +++ b/src/orchestrator/api/api.go @@ -189,6 +189,8 @@ func NewRouter(projectClient moduleLib.ProjectManager, client: instantiationClient, } + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/approve", instantiationHandler.approveHandler).Methods("POST") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/terminate", instantiationHandler.terminateHandler).Methods("POST") router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/instantiate", instantiationHandler.instantiateHandler).Methods("POST") router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/terminate", instantiationHandler.terminateHandler).Methods("POST") router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/status", instantiationHandler.statusHandler).Methods("GET") diff --git a/src/orchestrator/api/instantiation_handler.go b/src/orchestrator/api/instantiation_handler.go index ce50e5b8..eeac8a00 100644 --- a/src/orchestrator/api/instantiation_handler.go +++ b/src/orchestrator/api/instantiation_handler.go @@ -31,6 +31,23 @@ type instantiationHandler struct { client moduleLib.InstantiationManager } +func (h instantiationHandler) approveHandler(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + p := vars["project-name"] + ca := vars["composite-app-name"] + v := vars["composite-app-version"] + di := vars["deployment-intent-group-name"] + + iErr := h.client.Approve(p, ca, v, di) + if iErr != nil { + http.Error(w, iErr.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusAccepted) + +} + func (h instantiationHandler) instantiateHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) diff --git a/src/orchestrator/go.mod b/src/orchestrator/go.mod index 22e1aba1..f05343cd 100644 --- a/src/orchestrator/go.mod +++ b/src/orchestrator/go.mod @@ -16,7 +16,6 @@ require ( github.com/lib/pq v1.6.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mitchellh/copystructure v1.0.0 // indirect - github.com/onap/multicloud-k8s/src/clm v0.0.0-00010101000000-000000000000 github.com/onap/multicloud-k8s/src/monitor v0.0.0-20200630152613-7c20f73e7c5d github.com/onap/multicloud-k8s/src/ncm v0.0.0-20200515060444-c77850a75eee github.com/onap/multicloud-k8s/src/rsync v0.0.0-20200630152613-7c20f73e7c5d diff --git a/src/orchestrator/pkg/module/deployment_intent_groups.go b/src/orchestrator/pkg/module/deployment_intent_groups.go index 35b03564..d017c1e9 100644 --- a/src/orchestrator/pkg/module/deployment_intent_groups.go +++ b/src/orchestrator/pkg/module/deployment_intent_groups.go @@ -20,8 +20,8 @@ import ( "encoding/json" "reflect" - appcontext "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext" "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db" + "github.com/onap/multicloud-k8s/src/orchestrator/pkg/state" pkgerrors "github.com/pkg/errors" ) @@ -62,7 +62,7 @@ type OverrideValues struct { type DeploymentIntentGroupManager interface { CreateDeploymentIntentGroup(d DeploymentIntentGroup, p string, ca string, v string) (DeploymentIntentGroup, error) GetDeploymentIntentGroup(di string, p string, ca string, v string) (DeploymentIntentGroup, error) - GetDeploymentIntentGroupContext(di string, p string, ca string, v string) (appcontext.AppContext, string, error) + GetDeploymentIntentGroupState(di string, p string, ca string, v string) (state.StateInfo, error) DeleteDeploymentIntentGroup(di string, p string, ca string, v string) error GetAllDeploymentIntentGroups(p string, ca string, v string) ([]DeploymentIntentGroup, error) } @@ -89,7 +89,7 @@ func (dk DeploymentIntentGroupKey) String() string { type DeploymentIntentGroupClient struct { storeName string tagMetaData string - tagContext string + tagState string } // NewDeploymentIntentGroupClient return an instance of DeploymentIntentGroupClient which implements DeploymentIntentGroupManager @@ -97,7 +97,7 @@ func NewDeploymentIntentGroupClient() *DeploymentIntentGroupClient { return &DeploymentIntentGroupClient{ storeName: "orchestrator", tagMetaData: "deploymentintentgroupmetadata", - tagContext: "contextid", + tagState: "stateInfo", } } @@ -134,6 +134,17 @@ func (c *DeploymentIntentGroupClient) CreateDeploymentIntentGroup(d DeploymentIn return DeploymentIntentGroup{}, pkgerrors.Wrap(err, "Create DB entry error") } + // Add the stateInfo record + stateInfo := state.StateInfo{ + State: state.StateEnum.Created, + ContextId: "", + } + + err = db.DBconn.Insert(c.storeName, gkey, nil, c.tagState, stateInfo) + if err != nil { + return DeploymentIntentGroup{}, pkgerrors.Wrap(err, "Error updating the stateInfo of the DeploymentIntentGroup: "+d.MetaData.Name) + } + return d, nil } @@ -205,8 +216,8 @@ func (c *DeploymentIntentGroupClient) GetAllDeploymentIntentGroups(p string, ca } -// GetDeploymentIntentGroupContext returns the AppContent with a given DeploymentIntentname, project, compositeAppName and version of compositeApp -func (c *DeploymentIntentGroupClient) GetDeploymentIntentGroupContext(di string, p string, ca string, v string) (appcontext.AppContext, string, error) { +// GetDeploymentIntentGroupState returns the AppContent with a given DeploymentIntentname, project, compositeAppName and version of compositeApp +func (c *DeploymentIntentGroupClient) GetDeploymentIntentGroupState(di string, p string, ca string, v string) (state.StateInfo, error) { key := DeploymentIntentGroupKey{ Name: di, @@ -215,22 +226,21 @@ func (c *DeploymentIntentGroupClient) GetDeploymentIntentGroupContext(di string, Version: v, } - result, err := db.DBconn.Find(c.storeName, key, c.tagContext) + result, err := db.DBconn.Find(c.storeName, key, c.tagState) if err != nil { - return appcontext.AppContext{}, "", pkgerrors.Wrap(err, "Get DeploymentIntentGroup Context error") + return state.StateInfo{}, pkgerrors.Wrap(err, "Get DeploymentIntentGroup StateInfo error") } if result != nil { - ctxVal := string(result[0]) - var cc appcontext.AppContext - _, err = cc.LoadAppContext(ctxVal) + s := state.StateInfo{} + err = db.DBconn.Unmarshal(result[0], &s) if err != nil { - return appcontext.AppContext{}, "", pkgerrors.Wrap(err, "Error loading DeploymentIntentGroup Appcontext") + return state.StateInfo{}, pkgerrors.Wrap(err, "Unmarshalling DeploymentIntentGroup StateInfo") } - return cc, ctxVal, nil + return s, nil } - return appcontext.AppContext{}, "", pkgerrors.New("Error getting DeploymentIntentGroup AppContext") + return state.StateInfo{}, pkgerrors.New("Error getting DeploymentIntentGroup StateInfo") } // DeleteDeploymentIntentGroup deletes a DeploymentIntentGroup @@ -241,9 +251,9 @@ func (c *DeploymentIntentGroupClient) DeleteDeploymentIntentGroup(di string, p s CompositeApp: ca, Version: v, } - _, _, err := c.GetDeploymentIntentGroupContext(di, p, ca, v) - if err == nil { - return pkgerrors.New("DeploymentIntentGroup must be terminated before it can be deleted " + di) + s, err := c.GetDeploymentIntentGroupState(di, p, ca, v) + if err == nil && s.State == state.StateEnum.Instantiated { + return pkgerrors.Errorf("DeploymentIntentGroup must be terminated before it can be deleted " + di) } err = db.DBconn.Remove(c.storeName, k) diff --git a/src/orchestrator/pkg/module/instantiation.go b/src/orchestrator/pkg/module/instantiation.go index f4e75861..9c0c9e31 100644 --- a/src/orchestrator/pkg/module/instantiation.go +++ b/src/orchestrator/pkg/module/instantiation.go @@ -25,6 +25,7 @@ import ( gpic "github.com/onap/multicloud-k8s/src/orchestrator/pkg/gpic" "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db" log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils" + "github.com/onap/multicloud-k8s/src/orchestrator/pkg/state" "github.com/onap/multicloud-k8s/src/orchestrator/utils/helm" pkgerrors "github.com/pkg/errors" ) @@ -71,32 +72,67 @@ type InstantiationKey struct { // InstantiationManager is an interface which exposes the // InstantiationManager functionalities type InstantiationManager interface { - //ApproveInstantiation(p string, ca string, v string, di string) (error) + Approve(p string, ca string, v string, di string) error Instantiate(p string, ca string, v string, di string) error Status(p string, ca string, v string, di string) (StatusData, error) Terminate(p string, ca string, v string, di string) error } -// InstantiationClientDbInfo consists of storeName and tagContext +// InstantiationClientDbInfo consists of storeName and tagState type InstantiationClientDbInfo struct { - storeName string // name of the mongodb collection to use for Instantiationclient documents - tagContext string // attribute key name for context object in App Context + storeName string // name of the mongodb collection to use for Instantiationclient documents + tagState string // attribute key name for context object in App Context } // NewInstantiationClient returns an instance of InstantiationClient func NewInstantiationClient() *InstantiationClient { return &InstantiationClient{ db: InstantiationClientDbInfo{ - storeName: "orchestrator", - tagContext: "contextid", + storeName: "orchestrator", + tagState: "stateInfo", }, } } -// TODO -//ApproveInstantiation approves an instantiation -// func (c InstantiationClient) ApproveInstantiation(p string, ca string, v string, di string) (error){ -// } +//Approve approves an instantiation +func (c InstantiationClient) Approve(p string, ca string, v string, di string) error { + s, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroupState(di, p, ca, v) + if err != nil { + return pkgerrors.Wrap(err, "DeploymentIntentGroup has no state info: "+di) + } + switch s.State { + case state.StateEnum.Approved: + return nil + case state.StateEnum.Terminated: + break + case state.StateEnum.Created: + break + case state.StateEnum.Applied: + return pkgerrors.Errorf("DeploymentIntentGroup is in an invalid state" + s.State) + case state.StateEnum.Instantiated: + return pkgerrors.Errorf("DeploymentIntentGroup has already been instantiated" + di) + default: + return pkgerrors.Errorf("DeploymentIntentGroup is in an unknown state" + s.State) + } + + key := DeploymentIntentGroupKey{ + Name: di, + Project: p, + CompositeApp: ca, + Version: v, + } + stateInfo := state.StateInfo{ + State: state.StateEnum.Approved, + ContextId: "", + } + + err = db.DBconn.Insert(c.db.storeName, key, nil, c.db.tagState, stateInfo) + if err != nil { + return pkgerrors.Wrap(err, "Error updating the stateInfo of the DeploymentIntentGroup: "+di) + } + + return nil +} func getOverrideValuesByAppName(ov []OverrideValues, a string) map[string]string { for _, eachOverrideVal := range ov { @@ -189,9 +225,23 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin return pkgerrors.Wrap(err, "Not finding the deploymentIntentGroup") } - _, _, err = NewDeploymentIntentGroupClient().GetDeploymentIntentGroupContext(di, p, ca, v) - if err == nil { - return pkgerrors.Errorf("DeploymentIntentGroup has already been instantiated: " + di) + s, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroupState(di, p, ca, v) + if err != nil { + return pkgerrors.Errorf("Error retrieving DeploymentIntentGroup stateInfo: " + di) + } + switch s.State { + case state.StateEnum.Approved: + break + case state.StateEnum.Terminated: + break // TODO - ideally, should check that all resources have completed being terminated + case state.StateEnum.Created: + return pkgerrors.Errorf("DeploymentIntentGroup must be Approved before instantiating" + di) + case state.StateEnum.Applied: + return pkgerrors.Errorf("DeploymentIntentGroup is in an invalid state" + di) + case state.StateEnum.Instantiated: + return pkgerrors.Errorf("DeploymentIntentGroup has already been instantiated" + di) + default: + return pkgerrors.Errorf("DeploymentIntentGroup is in an unknown state" + s.State) } rName := dIGrp.Spec.Version //rName is releaseName @@ -292,8 +342,11 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin CompositeApp: ca, Version: v, } - - err = db.DBconn.Insert(c.db.storeName, key, nil, c.db.tagContext, ctxval) + stateInfo := state.StateInfo{ + State: state.StateEnum.Instantiated, + ContextId: ctxval.(string), + } + err = db.DBconn.Insert(c.db.storeName, key, nil, c.db.tagState, stateInfo) if err != nil { cleanuperr := context.DeleteCompositeApp() if cleanuperr != nil { @@ -348,11 +401,16 @@ the deployment, which is made available in the appcontext. */ func (c InstantiationClient) Status(p string, ca string, v string, di string) (StatusData, error) { - ac, _, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroupContext(di, p, ca, v) + s, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroupState(di, p, ca, v) if err != nil { return StatusData{}, pkgerrors.Wrap(err, "deploymentIntentGroup not found: "+di) } + ac, err := state.GetAppContextFromStateInfo(s) + if err != nil { + return StatusData{}, pkgerrors.Wrap(err, "AppContext for deploymentIntentGroup not found: "+di) + } + // Get all apps in this composite app allApps, err := NewAppClient().GetApps(p, ca, v) if err != nil { @@ -409,12 +467,19 @@ DeploymentIntentName and calls rsync to terminate. */ func (c InstantiationClient) Terminate(p string, ca string, v string, di string) error { - ac, ctxval, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroupContext(di, p, ca, v) + s, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroupState(di, p, ca, v) + if err != nil { + return pkgerrors.Wrap(err, "DeploymentIntentGroup has no state info: "+di) + } else if s.State != state.StateEnum.Instantiated { + return pkgerrors.Errorf("DeploymentIntentGroup is not instantiated" + di) + } + + ac, err := state.GetAppContextFromStateInfo(s) if err != nil { - return pkgerrors.Wrap(err, "DeploymentIntentGroup has no app context: "+di) + return pkgerrors.Wrap(err, "AppContext for deploymentIntentGroup not found: "+di) } - err = callRsyncUninstall(ctxval) + err = callRsyncUninstall(s.ContextId) if err != nil { return err } @@ -430,10 +495,14 @@ func (c InstantiationClient) Terminate(p string, ca string, v string, di string) CompositeApp: ca, Version: v, } + stateInfo := state.StateInfo{ + State: state.StateEnum.Terminated, + ContextId: "", + } - err = db.DBconn.RemoveTag(c.db.storeName, key, c.db.tagContext) + err = db.DBconn.Insert(c.db.storeName, key, nil, c.db.tagState, stateInfo) if err != nil { - return pkgerrors.Wrap(err, "Error removing the app context tag from DeploymentIntentGroup: "+di) + return pkgerrors.Wrap(err, "Error updating the stateInfo of the DeploymentIntentGroup: "+di) } return nil diff --git a/src/orchestrator/pkg/state/state_helper.go b/src/orchestrator/pkg/state/state_helper.go new file mode 100644 index 00000000..a65cea8d --- /dev/null +++ b/src/orchestrator/pkg/state/state_helper.go @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Intel Corporation, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package state + +import "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext" + +// GetAppContextFromStateInfo loads the appcontext present in the StateInfo input +func GetAppContextFromStateInfo(s StateInfo) (appcontext.AppContext, error) { + var cc appcontext.AppContext + _, err := cc.LoadAppContext(s.ContextId) + if err != nil { + return appcontext.AppContext{}, err + } + return cc, nil +} diff --git a/src/orchestrator/pkg/state/types.go b/src/orchestrator/pkg/state/types.go new file mode 100644 index 00000000..25fb60d2 --- /dev/null +++ b/src/orchestrator/pkg/state/types.go @@ -0,0 +1,42 @@ +/* + * Copyright 2020 Intel Corporation, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package state + +// StateInfo struct is used to maintain the values for state, contextid, (and other) +// information about resources which can be instantiated via rsync. +type StateInfo struct { + State StateValue + ContextId string +} + +type StateValue = string + +type states struct { + Created StateValue + Approved StateValue + Applied StateValue + Instantiated StateValue + Terminated StateValue +} + +var StateEnum = &states{ + Created: "Created", + Approved: "Approved", + Applied: "Applied", + Instantiated: "Instantiated", + Terminated: "Terminated", +} |