aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Multanen <eric.w.multanen@intel.com>2020-07-22 14:11:05 -0700
committerEric Multanen <eric.w.multanen@intel.com>2020-08-03 15:40:09 -0700
commitb2c23afb03b393b05fe38dd7c54b1de3c42deaf3 (patch)
tree5e845ad676a62e4bde17a6c4a846544164b0ad40 /src
parentd6f900721c81a2c03cb1a21a3d2064e9a69fc4b7 (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')
-rw-r--r--src/clm/api/clusterhandler_test.go10
-rw-r--r--src/clm/go.mod15
-rw-r--r--src/clm/pkg/cluster/cluster.go47
-rw-r--r--src/ncm/pkg/module/types/module_definitions.go2
-rw-r--r--src/ncm/pkg/networkintents/network.go40
-rw-r--r--src/ncm/pkg/networkintents/providernet.go48
-rw-r--r--src/ncm/pkg/scheduler/scheduler.go82
-rw-r--r--src/orchestrator/api/api.go2
-rw-r--r--src/orchestrator/api/instantiation_handler.go17
-rw-r--r--src/orchestrator/go.mod1
-rw-r--r--src/orchestrator/pkg/module/deployment_intent_groups.go44
-rw-r--r--src/orchestrator/pkg/module/instantiation.go111
-rw-r--r--src/orchestrator/pkg/state/state_helper.go29
-rw-r--r--src/orchestrator/pkg/state/types.go42
14 files changed, 386 insertions, 104 deletions
diff --git a/src/clm/api/clusterhandler_test.go b/src/clm/api/clusterhandler_test.go
index 4bbc91b1..076718df 100644
--- a/src/clm/api/clusterhandler_test.go
+++ b/src/clm/api/clusterhandler_test.go
@@ -28,8 +28,8 @@ import (
"testing"
"github.com/onap/multicloud-k8s/src/clm/pkg/cluster"
- "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
types "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/state"
pkgerrors "github.com/pkg/errors"
)
@@ -43,7 +43,7 @@ type mockClusterManager struct {
ClusterProviderItems []cluster.ClusterProvider
ClusterItems []cluster.Cluster
ClusterContentItems []cluster.ClusterContent
- ClusterContextItems []appcontext.AppContext
+ ClusterStateInfo []state.StateInfo
ClusterLabelItems []cluster.ClusterLabel
ClusterKvPairsItems []cluster.ClusterKvPairs
ClusterList []string
@@ -102,12 +102,12 @@ func (m *mockClusterManager) GetClusterContent(provider, name string) (cluster.C
return m.ClusterContentItems[0], nil
}
-func (m *mockClusterManager) GetClusterContext(provider, name string) (appcontext.AppContext, string, error) {
+func (m *mockClusterManager) GetClusterState(provider, name string) (state.StateInfo, error) {
if m.Err != nil {
- return appcontext.AppContext{}, "", m.Err
+ return state.StateInfo{}, m.Err
}
- return m.ClusterContextItems[0], "", nil
+ return m.ClusterStateInfo[0], nil
}
func (m *mockClusterManager) GetClusters(provider string) ([]cluster.Cluster, error) {
diff --git a/src/clm/go.mod b/src/clm/go.mod
index 0e655566..1d174b12 100644
--- a/src/clm/go.mod
+++ b/src/clm/go.mod
@@ -2,25 +2,24 @@ module github.com/onap/multicloud-k8s/src/clm
require (
github.com/ghodss/yaml v1.0.0
- github.com/go-stack/stack v1.8.0 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/gorilla/handlers v1.3.0
- github.com/gorilla/mux v1.6.2
+ github.com/gorilla/mux v1.7.3
github.com/k8snetworkplumbingwg/network-attachment-definition-client v0.0.0-20200127152046-0ee521d56061
- github.com/onap/multicloud-k8s/src/orchestrator v0.0.0-20200601021239-7959bd4c6fd4
+ github.com/onap/multicloud-k8s/src/orchestrator v0.0.0-20200721211210-783ed87fb39a
github.com/opencontainers/go-digest v1.0.0 // indirect
- github.com/pkg/errors v0.8.1
- github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect
- github.com/xdg/stringprep v1.0.0 // indirect
- google.golang.org/grpc v1.27.1
+ github.com/pkg/errors v0.9.1
+ google.golang.org/grpc v1.28.0
gopkg.in/yaml.v2 v2.2.8
k8s.io/api v0.0.0-20190831074750-7364b6bdad65
- k8s.io/apimachinery v0.0.0-20190831074630-461753078381
+ k8s.io/apimachinery v0.18.2
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
k8s.io/kubernetes v1.14.1
)
replace (
+ github.com/onap/multicloud-k8s/src/orchestrator => ../orchestrator
+ github.com/onap/multicloud-k8s/src/clm => ../clm
k8s.io/api => k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d
diff --git a/src/clm/pkg/cluster/cluster.go b/src/clm/pkg/cluster/cluster.go
index ac7f31f7..9505bd97 100644
--- a/src/clm/pkg/cluster/cluster.go
+++ b/src/clm/pkg/cluster/cluster.go
@@ -17,9 +17,9 @@
package cluster
import (
- appcontext "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
mtypes "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/state"
pkgerrors "github.com/pkg/errors"
)
@@ -28,7 +28,7 @@ type clientDbInfo struct {
storeName string // name of the mongodb collection to use for client documents
tagMeta string // attribute key name for the json data of a client document
tagContent string // attribute key name for the file data of a client document
- tagContext string // attribute key name for context object in App Context
+ tagState string // attribute key name for StateInfo object in the cluster
}
// ClusterProvider contains the parameters needed for ClusterProviders
@@ -101,7 +101,7 @@ type ClusterManager interface {
CreateCluster(provider string, pr Cluster, qr ClusterContent) (Cluster, error)
GetCluster(provider, name string) (Cluster, error)
GetClusterContent(provider, name string) (ClusterContent, error)
- GetClusterContext(provider, name string) (appcontext.AppContext, string, error)
+ GetClusterState(provider, name string) (state.StateInfo, error)
GetClusters(provider string) ([]Cluster, error)
GetClustersWithLabel(provider, label string) ([]string, error)
DeleteCluster(provider, name string) error
@@ -129,7 +129,7 @@ func NewClusterClient() *ClusterClient {
storeName: "cluster",
tagMeta: "clustermetadata",
tagContent: "clustercontent",
- tagContext: "clustercontext",
+ tagState: "stateInfo",
},
}
}
@@ -254,6 +254,17 @@ func (v *ClusterClient) CreateCluster(provider string, p Cluster, q ClusterConte
return Cluster{}, pkgerrors.Wrap(err, "Creating DB Entry")
}
+ // Add the stateInfo record
+ stateInfo := state.StateInfo{
+ State: state.StateEnum.Created,
+ ContextId: "",
+ }
+
+ err = db.DBconn.Insert(v.db.storeName, key, nil, v.db.tagState, stateInfo)
+ if err != nil {
+ return Cluster{}, pkgerrors.Wrap(err, "Creating cluster StateInfo")
+ }
+
return p, nil
}
@@ -309,31 +320,29 @@ func (v *ClusterClient) GetClusterContent(provider, name string) (ClusterContent
return ClusterContent{}, pkgerrors.New("Error getting Cluster Content")
}
-// GetClusterContext returns the AppContext for corresponding provider and name
-func (v *ClusterClient) GetClusterContext(provider, name string) (appcontext.AppContext, string, error) {
+// GetClusterState returns the StateInfo structure for corresponding cluster provider and cluster
+func (v *ClusterClient) GetClusterState(provider, name string) (state.StateInfo, error) {
//Construct key and tag to select the entry
key := ClusterKey{
ClusterProviderName: provider,
ClusterName: name,
}
- value, err := db.DBconn.Find(v.db.storeName, key, v.db.tagContext)
+ result, err := db.DBconn.Find(v.db.storeName, key, v.db.tagState)
if err != nil {
- return appcontext.AppContext{}, "", pkgerrors.Wrap(err, "Get Cluster Context")
+ return state.StateInfo{}, pkgerrors.Wrap(err, "Get Cluster StateInfo")
}
- //value is a byte array
- if value != nil {
- ctxVal := string(value[0])
- var cc appcontext.AppContext
- _, err = cc.LoadAppContext(ctxVal)
+ if result != nil {
+ s := state.StateInfo{}
+ err = db.DBconn.Unmarshal(result[0], &s)
if err != nil {
- return appcontext.AppContext{}, "", pkgerrors.Wrap(err, "Reinitializing Cluster AppContext")
+ return state.StateInfo{}, pkgerrors.Wrap(err, "Unmarshalling Cluster StateInfo")
}
- return cc, ctxVal, nil
+ return s, nil
}
- return appcontext.AppContext{}, "", pkgerrors.New("Error getting Cluster AppContext")
+ return state.StateInfo{}, pkgerrors.New("Error getting Cluster StateInfo")
}
// GetClusters returns all the Clusters for corresponding provider
@@ -393,9 +402,9 @@ func (v *ClusterClient) DeleteCluster(provider, name string) error {
ClusterProviderName: provider,
ClusterName: name,
}
- _, _, err := v.GetClusterContext(provider, name)
- if err == nil {
- return pkgerrors.Errorf("Cannot delete cluster until context is deleted: %v, %v", provider, name)
+ s, err := v.GetClusterState(provider, name)
+ if err == nil && s.State == state.StateEnum.Applied {
+ return pkgerrors.Errorf("Cluster network intents must be terminated before it can be deleted: " + name)
}
err = db.DBconn.Remove(v.db.storeName, key)
diff --git a/src/ncm/pkg/module/types/module_definitions.go b/src/ncm/pkg/module/types/module_definitions.go
index 0dd657ac..0c85cdb1 100644
--- a/src/ncm/pkg/module/types/module_definitions.go
+++ b/src/ncm/pkg/module/types/module_definitions.go
@@ -20,5 +20,5 @@ type ClientDbInfo struct {
StoreName string // name of the mongodb collection to use for client documents
TagMeta string // attribute key name for the json data of a client document
TagContent string // attribute key name for the file data of a client document
- TagContext string // attribute key name for context object in App Context
+ TagState string // attribute key name for context object in App Context
}
diff --git a/src/ncm/pkg/networkintents/network.go b/src/ncm/pkg/networkintents/network.go
index de8ee504..58480cc8 100644
--- a/src/ncm/pkg/networkintents/network.go
+++ b/src/ncm/pkg/networkintents/network.go
@@ -22,6 +22,7 @@ import (
nettypes "github.com/onap/multicloud-k8s/src/ncm/pkg/networkintents/types"
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
mtypes "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/state"
pkgerrors "github.com/pkg/errors"
)
@@ -89,11 +90,25 @@ func (v *NetworkClient) CreateNetwork(p Network, clusterProvider, cluster string
NetworkName: p.Metadata.Name,
}
- //Check if cluster exists
- _, err := clusterPkg.NewClusterClient().GetCluster(clusterProvider, cluster)
+ //Check if cluster exists and in a state for adding network intents
+ s, err := clusterPkg.NewClusterClient().GetClusterState(clusterProvider, cluster)
if err != nil {
return Network{}, pkgerrors.New("Unable to find the cluster")
}
+ switch s.State {
+ case state.StateEnum.Approved:
+ return Network{}, pkgerrors.Errorf("Cluster is in an invalid state: " + cluster + " " + state.StateEnum.Approved)
+ case state.StateEnum.Terminated:
+ break
+ case state.StateEnum.Created:
+ break
+ case state.StateEnum.Applied:
+ return Network{}, pkgerrors.Errorf("Existing cluster network intents must be terminated before creating: " + cluster)
+ case state.StateEnum.Instantiated:
+ return Network{}, pkgerrors.Errorf("Cluster is in an invalid state: " + cluster + " " + state.StateEnum.Instantiated)
+ default:
+ return Network{}, pkgerrors.Errorf("Cluster is in an invalid state: " + cluster + " " + s.State)
+ }
//Check if this Network already exists
_, err = v.GetNetwork(p.Metadata.Name, clusterProvider, cluster)
@@ -167,6 +182,25 @@ func (v *NetworkClient) GetNetworks(clusterProvider, cluster string) ([]Network,
// Delete the Network from database
func (v *NetworkClient) DeleteNetwork(name, clusterProvider, cluster string) error {
+ // verify cluster is in a state where network intent can be deleted
+ s, err := clusterPkg.NewClusterClient().GetClusterState(clusterProvider, cluster)
+ if err != nil {
+ return pkgerrors.New("Unable to find the cluster")
+ }
+ switch s.State {
+ case state.StateEnum.Approved:
+ return pkgerrors.Errorf("Cluster is in an invalid state: " + cluster + " " + state.StateEnum.Approved)
+ case state.StateEnum.Terminated:
+ break
+ case state.StateEnum.Created:
+ break
+ case state.StateEnum.Applied:
+ return pkgerrors.Errorf("Cluster network intents must be terminated before deleting: " + cluster)
+ case state.StateEnum.Instantiated:
+ return pkgerrors.Errorf("Cluster is in an invalid state: " + cluster + " " + state.StateEnum.Instantiated)
+ default:
+ return pkgerrors.Errorf("Cluster is in an invalid state: " + cluster + " " + s.State)
+ }
//Construct key and tag to select the entry
key := NetworkKey{
@@ -175,7 +209,7 @@ func (v *NetworkClient) DeleteNetwork(name, clusterProvider, cluster string) err
NetworkName: name,
}
- err := db.DBconn.Remove(v.db.StoreName, key)
+ err = db.DBconn.Remove(v.db.StoreName, key)
if err != nil {
return pkgerrors.Wrap(err, "Delete Network Entry;")
}
diff --git a/src/ncm/pkg/networkintents/providernet.go b/src/ncm/pkg/networkintents/providernet.go
index 072e07f6..dbe6e46c 100644
--- a/src/ncm/pkg/networkintents/providernet.go
+++ b/src/ncm/pkg/networkintents/providernet.go
@@ -22,6 +22,7 @@ import (
nettypes "github.com/onap/multicloud-k8s/src/ncm/pkg/networkintents/types"
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
mtypes "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/types"
+ "github.com/onap/multicloud-k8s/src/orchestrator/pkg/state"
pkgerrors "github.com/pkg/errors"
)
@@ -84,6 +85,26 @@ func NewProviderNetClient() *ProviderNetClient {
// CreateProviderNet - create a new ProviderNet
func (v *ProviderNetClient) CreateProviderNet(p ProviderNet, clusterProvider, cluster string, exists bool) (ProviderNet, error) {
+ // verify cluster exists and in state to add provider networks
+ s, err := clusterPkg.NewClusterClient().GetClusterState(clusterProvider, cluster)
+ if err != nil {
+ return ProviderNet{}, pkgerrors.New("Unable to find the cluster")
+ }
+ switch s.State {
+ case state.StateEnum.Approved:
+ return ProviderNet{}, pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Approved)
+ case state.StateEnum.Terminated:
+ break
+ case state.StateEnum.Created:
+ break
+ case state.StateEnum.Applied:
+ return ProviderNet{}, pkgerrors.Wrap(err, "Existing cluster provider network intents must be terminated before creating: "+cluster)
+ case state.StateEnum.Instantiated:
+ return ProviderNet{}, pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Instantiated)
+ default:
+ return ProviderNet{}, pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+s.State)
+ }
+
//Construct key and tag to select the entry
key := ProviderNetKey{
ClusterProviderName: clusterProvider,
@@ -91,12 +112,6 @@ func (v *ProviderNetClient) CreateProviderNet(p ProviderNet, clusterProvider, cl
ProviderNetName: p.Metadata.Name,
}
- //Check if cluster exists
- _, err := clusterPkg.NewClusterClient().GetCluster(clusterProvider, cluster)
- if err != nil {
- return ProviderNet{}, pkgerrors.New("Unable to find the cluster")
- }
-
//Check if this ProviderNet already exists
_, err = v.GetProviderNet(p.Metadata.Name, clusterProvider, cluster)
if err == nil && !exists {
@@ -169,6 +184,25 @@ func (v *ProviderNetClient) GetProviderNets(clusterProvider, cluster string) ([]
// Delete the ProviderNet from database
func (v *ProviderNetClient) DeleteProviderNet(name, clusterProvider, cluster string) error {
+ // verify cluster is in a state where provider network intent can be deleted
+ s, err := clusterPkg.NewClusterClient().GetClusterState(clusterProvider, cluster)
+ if err != nil {
+ return pkgerrors.New("Unable to find the cluster")
+ }
+ switch s.State {
+ case state.StateEnum.Approved:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Approved)
+ case state.StateEnum.Terminated:
+ break
+ case state.StateEnum.Created:
+ break
+ case state.StateEnum.Applied:
+ return pkgerrors.Wrap(err, "Cluster provider network intents must be terminated before deleting: "+cluster)
+ case state.StateEnum.Instantiated:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Instantiated)
+ default:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+s.State)
+ }
//Construct key and tag to select the entry
key := ProviderNetKey{
@@ -177,7 +211,7 @@ func (v *ProviderNetClient) DeleteProviderNet(name, clusterProvider, cluster str
ProviderNetName: name,
}
- err := db.DBconn.Remove(v.db.StoreName, key)
+ err = db.DBconn.Remove(v.db.StoreName, key)
if err != nil {
return pkgerrors.Wrap(err, "Delete ProviderNet Entry;")
}
diff --git a/src/ncm/pkg/scheduler/scheduler.go b/src/ncm/pkg/scheduler/scheduler.go
index 4886a67e..8ced68b8 100644
--- a/src/ncm/pkg/scheduler/scheduler.go
+++ b/src/ncm/pkg/scheduler/scheduler.go
@@ -27,6 +27,7 @@ import (
"github.com/onap/multicloud-k8s/src/orchestrator/pkg/grpc/installappclient"
"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"
pkgerrors "github.com/pkg/errors"
)
@@ -51,7 +52,7 @@ func NewSchedulerClient() *SchedulerClient {
StoreName: "cluster",
TagMeta: "clustermetadata",
TagContent: "clustercontent",
- TagContext: "clustercontext",
+ TagState: "stateInfo",
},
}
}
@@ -59,9 +60,23 @@ func NewSchedulerClient() *SchedulerClient {
// Apply Network Intents associated with a cluster
func (v *SchedulerClient) ApplyNetworkIntents(clusterProvider, cluster string) error {
- _, _, err := clusterPkg.NewClusterClient().GetClusterContext(clusterProvider, cluster)
- if err == nil {
- return pkgerrors.Errorf("Cluster network intents have already been applied: %v, %v", clusterProvider, cluster)
+ s, err := clusterPkg.NewClusterClient().GetClusterState(clusterProvider, cluster)
+ if err != nil {
+ return pkgerrors.Errorf("Error finding cluster: %v %v", clusterProvider, cluster)
+ }
+ switch s.State {
+ case state.StateEnum.Approved:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Approved)
+ case state.StateEnum.Terminated:
+ break
+ case state.StateEnum.Created:
+ break
+ case state.StateEnum.Applied:
+ return nil
+ case state.StateEnum.Instantiated:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Instantiated)
+ default:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+s.State)
}
// Make an app context for the network intent resources
@@ -135,12 +150,17 @@ func (v *SchedulerClient) ApplyNetworkIntents(clusterProvider, cluster string) e
return pkgerrors.Wrap(err, "Error adding Cluster to AppContext")
}
- // save the context in the cluster db record
+ // update the StateInfo in the cluster db record
key := clusterPkg.ClusterKey{
ClusterProviderName: clusterProvider,
ClusterName: cluster,
}
- err = db.DBconn.Insert(v.db.StoreName, key, nil, v.db.TagContext, ctxVal)
+ stateInfo := state.StateInfo{
+ State: state.StateEnum.Applied,
+ ContextId: ctxVal.(string),
+ }
+
+ err = db.DBconn.Insert(v.db.StoreName, key, nil, v.db.TagState, stateInfo)
if err != nil {
cleanuperr := ac.DeleteCompositeApp()
if cleanuperr != nil {
@@ -149,7 +169,7 @@ func (v *SchedulerClient) ApplyNetworkIntents(clusterProvider, cluster string) e
"cluster": cluster,
})
}
- return pkgerrors.Wrap(err, "Error adding AppContext to DB")
+ return pkgerrors.Wrap(err, "Error updating the stateInfo of cluster: "+cluster)
}
// call resource synchronizer to instantiate the CRs in the cluster
@@ -163,37 +183,55 @@ func (v *SchedulerClient) ApplyNetworkIntents(clusterProvider, cluster string) e
// Terminate Network Intents associated with a cluster
func (v *SchedulerClient) TerminateNetworkIntents(clusterProvider, cluster string) error {
- context, ctxVal, err := clusterPkg.NewClusterClient().GetClusterContext(clusterProvider, cluster)
+ s, err := clusterPkg.NewClusterClient().GetClusterState(clusterProvider, cluster)
if err != nil {
- return pkgerrors.Wrapf(err, "Error finding AppContext for cluster: %v, %v", clusterProvider, cluster)
+ return pkgerrors.Wrapf(err, "Error finding StateInfo for cluster: %v, %v", clusterProvider, cluster)
+ }
+ switch s.State {
+ case state.StateEnum.Approved:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Approved)
+ case state.StateEnum.Terminated:
+ return nil
+ case state.StateEnum.Created:
+ return pkgerrors.Wrap(err, "Cluster network intents have not been applied: "+cluster)
+ case state.StateEnum.Applied:
+ break
+ case state.StateEnum.Instantiated:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+state.StateEnum.Instantiated)
+ default:
+ return pkgerrors.Wrap(err, "Cluster is in an invalid state: "+cluster+" "+s.State)
}
// call resource synchronizer to terminate the CRs in the cluster
- err = installappclient.InvokeUninstallApp(ctxVal)
+ err = installappclient.InvokeUninstallApp(s.ContextId)
if err != nil {
return err
}
// remove the app context
- cleanuperr := context.DeleteCompositeApp()
- if cleanuperr != nil {
- log.Warn("Error deleted AppContext", log.Fields{
- "cluster-provider": clusterProvider,
- "cluster": cluster,
- })
+ context, err := state.GetAppContextFromStateInfo(s)
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error getting appcontext from cluster StateInfo : "+clusterProvider+" "+cluster)
+ }
+ err = context.DeleteCompositeApp()
+ if err != nil {
+ return pkgerrors.Wrap(err, "Error deleting appcontext of cluster : "+clusterProvider+" "+cluster)
}
- // remove the app context field from the cluster db record
+ // update StateInfo
key := clusterPkg.ClusterKey{
ClusterProviderName: clusterProvider,
ClusterName: cluster,
}
- err = db.DBconn.RemoveTag(v.db.StoreName, key, v.db.TagContext)
+ stateInfo := state.StateInfo{
+ State: state.StateEnum.Terminated,
+ ContextId: "",
+ }
+
+ err = db.DBconn.Insert(v.db.StoreName, key, nil, v.db.TagState, stateInfo)
if err != nil {
- log.Warn("Error removing AppContext from Cluster document", log.Fields{
- "cluster-provider": clusterProvider,
- "cluster": cluster,
- })
+ return pkgerrors.Wrap(err, "Error updating the stateInfo of cluster: "+cluster)
}
+
return nil
}
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",
+}