diff options
Diffstat (limited to 'src/orchestrator')
18 files changed, 253 insertions, 773 deletions
diff --git a/src/orchestrator/api/api.go b/src/orchestrator/api/api.go index de69d163..07f8fe34 100644 --- a/src/orchestrator/api/api.go +++ b/src/orchestrator/api/api.go @@ -128,13 +128,13 @@ func NewRouter(projectClient moduleLib.ProjectManager, genericPlacementIntentHandler := genericPlacementIntentHandler{ client: genericPlacementIntentClient, } - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents", genericPlacementIntentHandler.createGenericPlacementIntentHandler).Methods("POST") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents", genericPlacementIntentHandler.createGenericPlacementIntentHandler).Methods("POST") - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}", genericPlacementIntentHandler.getGenericPlacementHandler).Methods("GET") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents/{intent-name}", genericPlacementIntentHandler.getGenericPlacementHandler).Methods("GET") - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents", genericPlacementIntentHandler.getAllGenericPlacementIntentsHandler).Methods("GET") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents", genericPlacementIntentHandler.getAllGenericPlacementIntentsHandler).Methods("GET") - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}", genericPlacementIntentHandler.deleteGenericPlacementHandler).Methods("DELETE") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents/{intent-name}", genericPlacementIntentHandler.deleteGenericPlacementHandler).Methods("DELETE") //setting routes for AppIntent if appIntentClient == nil { @@ -145,11 +145,11 @@ func NewRouter(projectClient moduleLib.ProjectManager, client: appIntentClient, } - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}/app-intents", appIntentHandler.createAppIntentHandler).Methods("POST") - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}/app-intents/{app-intent-name}", appIntentHandler.getAppIntentHandler).Methods("GET") - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}/app-intents", appIntentHandler.getAllAppIntentsHandler).Methods("GET") - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}/app-intents/", appIntentHandler.getAllIntentsByAppHandler).Queries("app-name", "{app-name}") - router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/generic-placement-intents/{intent-name}/app-intents/{app-intent-name}", appIntentHandler.deleteAppIntentHandler).Methods("DELETE") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents/{intent-name}/app-intents", appIntentHandler.createAppIntentHandler).Methods("POST") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents/{intent-name}/app-intents/{app-intent-name}", appIntentHandler.getAppIntentHandler).Methods("GET") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents/{intent-name}/app-intents", appIntentHandler.getAllAppIntentsHandler).Methods("GET") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents/{intent-name}/app-intents/", appIntentHandler.getAllIntentsByAppHandler).Queries("app-name", "{app-name}") + router.HandleFunc("/projects/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intents/{intent-name}/app-intents/{app-intent-name}", appIntentHandler.deleteAppIntentHandler).Methods("DELETE") //setting routes for deploymentIntentGroup if deploymentIntentGrpClient == nil { deploymentIntentGrpClient = moduleClient.DeploymentIntentGroup diff --git a/src/orchestrator/api/app_intent_handler.go b/src/orchestrator/api/app_intent_handler.go index 1d48f8a6..3d0d5bad 100644 --- a/src/orchestrator/api/app_intent_handler.go +++ b/src/orchestrator/api/app_intent_handler.go @@ -62,8 +62,9 @@ func (h appIntentHandler) createAppIntentHandler(w http.ResponseWriter, r *http. compositeAppName := vars["composite-app-name"] version := vars["composite-app-version"] intent := vars["intent-name"] + digName := vars["deployment-intent-group-name"] - appIntent, createErr := h.client.CreateAppIntent(a, projectName, compositeAppName, version, intent) + appIntent, createErr := h.client.CreateAppIntent(a, projectName, compositeAppName, version, intent, digName) if createErr != nil { http.Error(w, createErr.Error(), http.StatusInternalServerError) return @@ -104,13 +105,19 @@ func (h appIntentHandler) getAppIntentHandler(w http.ResponseWriter, r *http.Req return } + dig := vars["deployment-intent-group-name"] + if dig == "" { + http.Error(w, "Missing deploymentIntentGroupName in GET request", http.StatusBadRequest) + return + } + ai := vars["app-intent-name"] if ai == "" { http.Error(w, "Missing appIntentName in GET request", http.StatusBadRequest) return } - appIntent, err := h.client.GetAppIntent(ai, p, ca, v, i) + appIntent, err := h.client.GetAppIntent(ai, p, ca, v, i,dig) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -128,7 +135,7 @@ func (h appIntentHandler) getAppIntentHandler(w http.ResponseWriter, r *http.Req /* getAllIntentsByAppHandler handles the URL: -/v2/project/{project-name}/composite-apps/{composite-app-name}/{version}/generic-placement-intent/{intent-name}/app-intents?app-name=<app-name> +/v2/project/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intent/{intent-name}/app-intents?app-name=<app-name> */ func (h appIntentHandler) getAllIntentsByAppHandler(w http.ResponseWriter, r *http.Request) { @@ -142,13 +149,15 @@ func (h appIntentHandler) getAllIntentsByAppHandler(w http.ResponseWriter, r *ht ca := vars["composite-app-name"] v := vars["composite-app-version"] i := vars["intent-name"] + digName := vars["deployment-intent-group-name"] + aN := r.URL.Query().Get("app-name") if aN == "" { http.Error(w, "Missing appName in GET request", http.StatusBadRequest) return } - specData, err := h.client.GetAllIntentsByApp(aN, p, ca, v, i) + specData, err := h.client.GetAllIntentsByApp(aN, p, ca, v, i, digName) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -166,7 +175,7 @@ func (h appIntentHandler) getAllIntentsByAppHandler(w http.ResponseWriter, r *ht /* getAllAppIntentsHandler handles the URL: -/v2/project/{project-name}/composite-apps/{composite-app-name}/{version}/generic-placement-intent/{intent-name}/app-intents +/v2/project/{project-name}/composite-apps/{composite-app-name}/{composite-app-version}/deployment-intent-groups/{deployment-intent-group-name}/generic-placement-intent/{intent-name}/app-intents */ func (h appIntentHandler) getAllAppIntentsHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) @@ -179,8 +188,9 @@ func (h appIntentHandler) getAllAppIntentsHandler(w http.ResponseWriter, r *http ca := vars["composite-app-name"] v := vars["composite-app-version"] i := vars["intent-name"] + digName := vars["deployment-intent-group-name"] - applicationsAndClusterInfo, err := h.client.GetAllAppIntents(p, ca, v, i) + applicationsAndClusterInfo, err := h.client.GetAllAppIntents(p, ca, v, i, digName) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -205,8 +215,10 @@ func (h appIntentHandler) deleteAppIntentHandler(w http.ResponseWriter, r *http. v := vars["composite-app-version"] i := vars["intent-name"] ai := vars["app-intent-name"] + digName := vars["deployment-intent-group-name"] + - err := h.client.DeleteAppIntent(ai, p, ca, v, i) + err := h.client.DeleteAppIntent(ai, p, ca, v, i, digName) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return diff --git a/src/orchestrator/api/generic_placement_intent_handler.go b/src/orchestrator/api/generic_placement_intent_handler.go index 2415ae2c..cb23776a 100644 --- a/src/orchestrator/api/generic_placement_intent_handler.go +++ b/src/orchestrator/api/generic_placement_intent_handler.go @@ -62,8 +62,9 @@ func (h genericPlacementIntentHandler) createGenericPlacementIntentHandler(w htt projectName := vars["project-name"] compositeAppName := vars["composite-app-name"] version := vars["composite-app-version"] + digName := vars["deployment-intent-group-name"] - gPIntent, createErr := h.client.CreateGenericPlacementIntent(g, projectName, compositeAppName, version) + gPIntent, createErr := h.client.CreateGenericPlacementIntent(g, projectName, compositeAppName, version, digName) if createErr != nil { http.Error(w, createErr.Error(), http.StatusInternalServerError) return @@ -103,7 +104,13 @@ func (h genericPlacementIntentHandler) getGenericPlacementHandler(w http.Respons return } - gPIntent, err := h.client.GetGenericPlacementIntent(intentName, projectName, compositeAppName, version) + dig := vars["deployment-intent-group-name"] + if dig == "" { + http.Error(w, "Missing deploymentIntentGroupName in GET request", http.StatusBadRequest) + return + } + + gPIntent, err := h.client.GetGenericPlacementIntent(intentName, projectName, compositeAppName, version, dig) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -128,8 +135,9 @@ func (h genericPlacementIntentHandler) getAllGenericPlacementIntentsHandler(w ht p := vars["project-name"] ca := vars["composite-app-name"] v := vars["composite-app-version"] + digName := vars["deployment-intent-group-name"] - gpList, err := h.client.GetAllGenericPlacementIntents(p, ca, v) + gpList, err := h.client.GetAllGenericPlacementIntents(p, ca, v, digName) if err != nil { http.Error(w, err.Error(), http.StatusNotFound) return @@ -150,8 +158,9 @@ func (h genericPlacementIntentHandler) deleteGenericPlacementHandler(w http.Resp p := vars["project-name"] ca := vars["composite-app-name"] v := vars["composite-app-version"] + digName := vars["deployment-intent-group-name"] - err := h.client.DeleteGenericPlacementIntent(i, p, ca, v) + err := h.client.DeleteGenericPlacementIntent(i, p, ca, v, digName) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return diff --git a/src/orchestrator/json-schemas/deployment-group-intent.json b/src/orchestrator/json-schemas/deployment-group-intent.json index 2740747b..00b1f32f 100644 --- a/src/orchestrator/json-schemas/deployment-group-intent.json +++ b/src/orchestrator/json-schemas/deployment-group-intent.json @@ -5,7 +5,8 @@ "spec": { "required": [ "profile", - "version" + "version", + "logical-cloud" ], "type": "object", "description": "DepSpecData has profile, version, OverrideValuesObj", @@ -42,6 +43,16 @@ "type": "string", "maxLength": 128, "pattern": "[-_0-9a-zA-Z]+$" + }, + "logical-cloud": { + "description": "Logical Cloud to use for this intent", + "required": [ + "logical-cloud" + ], + "type": "string", + "example": "cloud1", + "maxLength": 128, + "pattern": "[-_0-9a-zA-Z]+$" } } }, diff --git a/src/orchestrator/json-schemas/generic-placement-intent.json b/src/orchestrator/json-schemas/generic-placement-intent.json index 44df9087..b1d8e229 100644 --- a/src/orchestrator/json-schemas/generic-placement-intent.json +++ b/src/orchestrator/json-schemas/generic-placement-intent.json @@ -2,21 +2,6 @@ "$schema": "http://json-schema.org/schema#", "type": "object", "properties": { - "spec": { - "type": "object", - "description": "Spec", - "properties": { - "logical-cloud": { - "description": "Logical Cloud to use for this intent", - "required": [ - "logical-cloud" - ], - "type": "string", - "example": "cloud1", - "maxLength": 128 - } - } - }, "metadata": { "required": ["name"], "properties": { diff --git a/src/orchestrator/pkg/appcontext/appcontext.go b/src/orchestrator/pkg/appcontext/appcontext.go index d77672db..d0935d82 100644 --- a/src/orchestrator/pkg/appcontext/appcontext.go +++ b/src/orchestrator/pkg/appcontext/appcontext.go @@ -67,10 +67,11 @@ var AppContextStatusEnum = &statuses{ // CompositeAppVersion, ReleaseName. This shall be used for // instantiation of a compositeApp type CompositeAppMeta struct { - Project string `json:"Project"` - CompositeApp string `json:"CompositeApp"` - Version string `json:"Version"` - Release string `json:"Release"` + Project string `json:"Project"` + CompositeApp string `json:"CompositeApp"` + Version string `json:"Version"` + Release string `json:"Release"` + DeploymentIntentGroup string `json:"DeploymentIntentGroup"` } // Init app context @@ -565,6 +566,7 @@ func (ac *AppContext) GetCompositeAppMeta() (CompositeAppMeta, error) { ca := fmt.Sprintf("%v", datamap["CompositeApp"]) v := fmt.Sprintf("%v", datamap["Version"]) rn := fmt.Sprintf("%v", datamap["Release"]) + dig := fmt.Sprintf("%v", datamap["DeploymentIntentGroup"]) - return CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rn}, nil + return CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rn, DeploymentIntentGroup: dig}, nil } diff --git a/src/orchestrator/pkg/infra/db/mock.go b/src/orchestrator/pkg/infra/db/mock.go index e43be8fb..cc3af718 100644 --- a/src/orchestrator/pkg/infra/db/mock.go +++ b/src/orchestrator/pkg/infra/db/mock.go @@ -41,18 +41,10 @@ func (m *MockDB) HealthCheck() error { return m.Err } -func (m *MockDB) Create(table string, key Key, tag string, data interface{}) error { - return m.Err -} - func (m *MockDB) Insert(table string, key Key, query interface{}, tag string, data interface{}) error { return m.Err } -func (m *MockDB) Update(table string, key Key, tag string, data interface{}) error { - return m.Err -} - // MockDB uses simple JSON and not BSON func (m *MockDB) Unmarshal(inp []byte, out interface{}) error { err := json.Unmarshal(inp, out) @@ -62,21 +54,6 @@ func (m *MockDB) Unmarshal(inp []byte, out interface{}) error { return nil } -func (m *MockDB) Read(table string, key Key, tag string) ([]byte, error) { - if m.Err != nil { - return nil, m.Err - } - - str := fmt.Sprintf("%v", key) - for k, v := range m.Items { - if k == str { - return v[tag], nil - } - } - - return nil, m.Err -} - func (m *MockDB) Find(table string, key Key, tag string) ([][]byte, error) { if m.Err != nil { return nil, m.Err @@ -93,10 +70,6 @@ func (m *MockDB) Find(table string, key Key, tag string) ([][]byte, error) { return nil, m.Err } -func (m *MockDB) Delete(table string, key Key, tag string) error { - return m.Err -} - func (m *MockDB) Remove(table string, key Key) error { return m.Err } diff --git a/src/orchestrator/pkg/infra/db/mongo.go b/src/orchestrator/pkg/infra/db/mongo.go index a3fdc570..cae57e1d 100644 --- a/src/orchestrator/pkg/infra/db/mongo.go +++ b/src/orchestrator/pkg/infra/db/mongo.go @@ -18,7 +18,6 @@ package db import ( "encoding/json" - "log" "sort" "golang.org/x/net/context" @@ -135,88 +134,6 @@ func (m *MongoStore) validateParams(args ...interface{}) bool { return true } -// Create is used to create a DB entry -func (m *MongoStore) Create(coll string, key Key, tag string, data interface{}) error { - if data == nil || !m.validateParams(coll, key, tag) { - return pkgerrors.New("No Data to store") - } - - c := getCollection(coll, m) - ctx := context.Background() - - //Insert the data and then add the objectID to the masterTable - res, err := c.InsertOne(ctx, bson.D{ - {tag, data}, - }) - if err != nil { - return pkgerrors.Errorf("Error inserting into database: %s", err.Error()) - } - - //Add objectID of created data to masterKey document - //Create masterkey document if it does not exist - filter := bson.D{{"key", key}} - - _, err = decodeBytes( - c.FindOneAndUpdate( - ctx, - filter, - bson.D{ - {"$set", bson.D{ - {tag, res.InsertedID}, - }}, - }, - options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After))) - - if err != nil { - return pkgerrors.Errorf("Error updating master table: %s", err.Error()) - } - - return nil -} - -// Update is used to update a DB entry -func (m *MongoStore) Update(coll string, key Key, tag string, data interface{}) error { - if data == nil || !m.validateParams(coll, key, tag) { - return pkgerrors.New("No Data to update") - } - - c := getCollection(coll, m) - ctx := context.Background() - - //Get the masterkey document based on given key - filter := bson.D{{"key", key}} - keydata, err := decodeBytes(c.FindOne(context.Background(), filter)) - if err != nil { - return pkgerrors.Errorf("Error finding master table: %s", err.Error()) - } - - //Read the tag objectID from document - tagoid, ok := keydata.Lookup(tag).ObjectIDOK() - if !ok { - return pkgerrors.Errorf("Error finding objectID for tag %s", tag) - } - - //Update the document with new data - filter = bson.D{{"_id", tagoid}} - - _, err = decodeBytes( - c.FindOneAndUpdate( - ctx, - filter, - bson.D{ - {"$set", bson.D{ - {tag, data}, - }}, - }, - options.FindOneAndUpdate().SetReturnDocument(options.After))) - - if err != nil { - return pkgerrors.Errorf("Error updating record: %s", err.Error()) - } - - return nil -} - // Unmarshal implements an unmarshaler for bson data that // is produced from the mongo database func (m *MongoStore) Unmarshal(inp []byte, out interface{}) error { @@ -227,126 +144,6 @@ func (m *MongoStore) Unmarshal(inp []byte, out interface{}) error { return nil } -// Read method returns the data stored for this key and for this particular tag -func (m *MongoStore) Read(coll string, key Key, tag string) ([]byte, error) { - if !m.validateParams(coll, key, tag) { - return nil, pkgerrors.New("Mandatory fields are missing") - } - - c := getCollection(coll, m) - ctx := context.Background() - - //Get the masterkey document based on given key - filter := bson.D{{"key", key}} - keydata, err := decodeBytes(c.FindOne(context.Background(), filter)) - if err != nil { - return nil, pkgerrors.Errorf("Error finding master table: %s", err.Error()) - } - - //Read the tag objectID from document - tagoid, ok := keydata.Lookup(tag).ObjectIDOK() - if !ok { - return nil, pkgerrors.Errorf("Error finding objectID for tag %s", tag) - } - - //Use tag objectID to read the data from store - filter = bson.D{{"_id", tagoid}} - tagdata, err := decodeBytes(c.FindOne(ctx, filter)) - if err != nil { - return nil, pkgerrors.Errorf("Error reading found object: %s", err.Error()) - } - - //Return the data as a byte array - //Convert string data to byte array using the built-in functions - switch tagdata.Lookup(tag).Type { - case bson.TypeString: - return []byte(tagdata.Lookup(tag).StringValue()), nil - default: - return tagdata.Lookup(tag).Value, nil - } -} - -// Helper function that deletes an object by its ID -func (m *MongoStore) deleteObjectByID(coll string, objID primitive.ObjectID) error { - - c := getCollection(coll, m) - ctx := context.Background() - - _, err := c.DeleteOne(ctx, bson.D{{"_id", objID}}) - if err != nil { - return pkgerrors.Errorf("Error Deleting from database: %s", err.Error()) - } - - log.Printf("Deleted Obj with ID %s", objID.String()) - return nil -} - -// Delete method removes a document from the Database that matches key -// TODO: delete all referenced docs if tag is empty string -func (m *MongoStore) Delete(coll string, key Key, tag string) error { - if !m.validateParams(coll, key, tag) { - return pkgerrors.New("Mandatory fields are missing") - } - - c := getCollection(coll, m) - ctx := context.Background() - - //Get the masterkey document based on given key - filter := bson.D{{"key", key}} - //Remove the tag ID entry from masterkey table - update := bson.D{ - { - "$unset", bson.D{ - {tag, ""}, - }, - }, - } - keydata, err := decodeBytes(c.FindOneAndUpdate(ctx, filter, update, - options.FindOneAndUpdate().SetReturnDocument(options.Before))) - if err != nil { - //No document was found. Return nil. - if err == mongo.ErrNoDocuments { - return nil - } - //Return any other error that was found. - return pkgerrors.Errorf("Error decoding master table after update: %s", - err.Error()) - } - - //Read the tag objectID from document - elems, err := keydata.Elements() - if err != nil { - return pkgerrors.Errorf("Error reading elements from database: %s", err.Error()) - } - - tagoid, ok := keydata.Lookup(tag).ObjectIDOK() - if !ok { - return pkgerrors.Errorf("Error finding objectID for tag %s", tag) - } - - //Use tag objectID to read the data from store - err = m.deleteObjectByID(coll, tagoid) - if err != nil { - return pkgerrors.Errorf("Error deleting from database: %s", err.Error()) - } - - //Delete master table if no more tags left - //_id, key and tag should be elements in before doc - //if master table needs to be removed too - if len(elems) == 3 { - keyid, ok := keydata.Lookup("_id").ObjectIDOK() - if !ok { - return pkgerrors.Errorf("Error finding objectID for key %s", key) - } - err = m.deleteObjectByID(coll, keyid) - if err != nil { - return pkgerrors.Errorf("Error deleting master table from database: %s", err.Error()) - } - } - - return nil -} - func (m *MongoStore) findFilter(key Key) (primitive.M, error) { var bsonMap bson.M diff --git a/src/orchestrator/pkg/infra/db/mongo_test.go b/src/orchestrator/pkg/infra/db/mongo_test.go index d57c19dd..3e14e755 100644 --- a/src/orchestrator/pkg/infra/db/mongo_test.go +++ b/src/orchestrator/pkg/infra/db/mongo_test.go @@ -17,13 +17,8 @@ package db import ( - "bytes" "context" - "strings" - "testing" - pkgerrors "github.com/pkg/errors" - "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) @@ -83,388 +78,3 @@ func (c *mockCollection) CountDocuments(ctx context.Context, filter interface{}, opts ...*options.CountOptions) (int64, error) { return 1, c.Err } - -func TestCreate(t *testing.T) { - testCases := []struct { - label string - input map[string]interface{} - mockColl *mockCollection - bson bson.Raw - expectedError string - }{ - { - label: "Successfull creation of entry", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "tagName", - "data": "Data In String Format", - }, - bson: bson.Raw{'\x08', '\x00', '\x00', '\x00', '\x0A', 'x', '\x00', '\x00'}, - mockColl: &mockCollection{}, - }, - { - label: "UnSuccessfull creation of entry", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "tagName", - "data": "Data In String Format", - }, - mockColl: &mockCollection{ - Err: pkgerrors.New("DB Error"), - }, - expectedError: "DB Error", - }, - { - label: "Missing input fields", - input: map[string]interface{}{ - "coll": "", - "key": MockKey{Key: ""}, - "tag": "", - "data": "", - }, - expectedError: "No Data to store", - mockColl: &mockCollection{}, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.label, func(t *testing.T) { - m, _ := NewMongoStore("name", &mongo.Database{}) - // Override the getCollection function with our mocked version - getCollection = func(coll string, m *MongoStore) MongoCollection { - return testCase.mockColl - } - - decodeBytes = func(sr *mongo.SingleResult) (bson.Raw, error) { - return testCase.bson, testCase.mockColl.Err - } - - err := m.Create(testCase.input["coll"].(string), testCase.input["key"].(Key), - testCase.input["tag"].(string), testCase.input["data"]) - if err != nil { - if testCase.expectedError == "" { - t.Fatalf("Create method returned an un-expected (%s)", err) - } - if !strings.Contains(string(err.Error()), testCase.expectedError) { - t.Fatalf("Create method returned an error (%s)", err) - } - } - }) - } -} - -func TestUpdate(t *testing.T) { - testCases := []struct { - label string - input map[string]interface{} - mockColl *mockCollection - bson bson.Raw - expectedError string - }{ - { - label: "Successfull update of entry", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "metadata", - "data": "Data In String Format", - }, - // Binary form of - // { - // "_id" : ObjectId("5c115156777ff85654248ae1"), - // "key" : bson.D{{"name","testdef"},{"version","v1"}}, - // "metadata" : ObjectId("5c115156c9755047e318bbfd") - // } - bson: bson.Raw{ - '\x58', '\x00', '\x00', '\x00', '\x03', '\x6b', '\x65', '\x79', - '\x00', '\x27', '\x00', '\x00', '\x00', '\x02', '\x6e', '\x61', - '\x6d', '\x65', '\x00', '\x08', '\x00', '\x00', '\x00', '\x74', - '\x65', '\x73', '\x74', '\x64', '\x65', '\x66', '\x00', '\x02', - '\x76', '\x65', '\x72', '\x73', '\x69', '\x6f', '\x6e', '\x00', - '\x03', '\x00', '\x00', '\x00', '\x76', '\x31', '\x00', '\x00', - '\x07', '\x6d', '\x65', '\x74', '\x61', '\x64', '\x61', '\x74', - '\x61', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', '\x7f', - '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x07', '\x5f', - '\x69', '\x64', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', - '\x7f', '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x00', - }, - mockColl: &mockCollection{}, - }, - { - label: "Entry does not exist", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "tagName", - "data": "Data In String Format", - }, - mockColl: &mockCollection{ - Err: pkgerrors.New("DB Error"), - }, - expectedError: "DB Error", - }, - } - - for _, testCase := range testCases { - t.Run(testCase.label, func(t *testing.T) { - m, _ := NewMongoStore("name", &mongo.Database{}) - // Override the getCollection function with our mocked version - getCollection = func(coll string, m *MongoStore) MongoCollection { - return testCase.mockColl - } - - decodeBytes = func(sr *mongo.SingleResult) (bson.Raw, error) { - return testCase.bson, testCase.mockColl.Err - } - - err := m.Update(testCase.input["coll"].(string), testCase.input["key"].(Key), - testCase.input["tag"].(string), testCase.input["data"]) - if err != nil { - if testCase.expectedError == "" { - t.Fatalf("Create method returned an un-expected (%s)", err) - } - if !strings.Contains(string(err.Error()), testCase.expectedError) { - t.Fatalf("Create method returned an error (%s)", err) - } - } - }) - } -} - -func TestRead(t *testing.T) { - testCases := []struct { - label string - input map[string]interface{} - mockColl *mockCollection - bson bson.Raw - expectedError string - expected []byte - }{ - { - label: "Successfull Read of entry", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "metadata", - }, - // Binary form of - // { - // "_id" : ObjectId("5c115156777ff85654248ae1"), - // "key" : bson.D{{"name","testdef"},{"version","v1"}}, - // "metadata" : ObjectId("5c115156c9755047e318bbfd") - // } - bson: bson.Raw{ - '\x58', '\x00', '\x00', '\x00', '\x03', '\x6b', '\x65', '\x79', - '\x00', '\x27', '\x00', '\x00', '\x00', '\x02', '\x6e', '\x61', - '\x6d', '\x65', '\x00', '\x08', '\x00', '\x00', '\x00', '\x74', - '\x65', '\x73', '\x74', '\x64', '\x65', '\x66', '\x00', '\x02', - '\x76', '\x65', '\x72', '\x73', '\x69', '\x6f', '\x6e', '\x00', - '\x03', '\x00', '\x00', '\x00', '\x76', '\x31', '\x00', '\x00', - '\x07', '\x6d', '\x65', '\x74', '\x61', '\x64', '\x61', '\x74', - '\x61', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', '\x7f', - '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x07', '\x5f', - '\x69', '\x64', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', - '\x7f', '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x00', - }, - mockColl: &mockCollection{}, - // This is not the document because we are mocking decodeBytes - expected: []byte{92, 17, 81, 86, 119, 127, 248, 86, 84, 36, 138, 225}, - }, - { - label: "UnSuccessfull Read of entry: object not found", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "badtag", - }, - // Binary form of - // { - // "_id" : ObjectId("5c115156777ff85654248ae1"), - // "key" : bson.D{{"name","testdef"},{"version","v1"}}, - // "metadata" : ObjectId("5c115156c9755047e318bbfd") - // } - bson: bson.Raw{ - '\x58', '\x00', '\x00', '\x00', '\x03', '\x6b', '\x65', '\x79', - '\x00', '\x27', '\x00', '\x00', '\x00', '\x02', '\x6e', '\x61', - '\x6d', '\x65', '\x00', '\x08', '\x00', '\x00', '\x00', '\x74', - '\x65', '\x73', '\x74', '\x64', '\x65', '\x66', '\x00', '\x02', - '\x76', '\x65', '\x72', '\x73', '\x69', '\x6f', '\x6e', '\x00', - '\x03', '\x00', '\x00', '\x00', '\x76', '\x31', '\x00', '\x00', - '\x07', '\x6d', '\x65', '\x74', '\x61', '\x64', '\x61', '\x74', - '\x61', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', '\x7f', - '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x07', '\x5f', - '\x69', '\x64', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', - '\x7f', '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x00', - }, - mockColl: &mockCollection{}, - expectedError: "Error finding objectID", - }, - { - label: "UnSuccessfull Read of entry", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "tagName", - }, - mockColl: &mockCollection{ - Err: pkgerrors.New("DB Error"), - }, - expectedError: "DB Error", - }, - { - label: "Missing input fields", - input: map[string]interface{}{ - "coll": "", - "key": MockKey{Key: ""}, - "tag": "", - }, - expectedError: "Mandatory fields are missing", - mockColl: &mockCollection{}, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.label, func(t *testing.T) { - m, _ := NewMongoStore("name", &mongo.Database{}) - // Override the getCollection function with our mocked version - getCollection = func(coll string, m *MongoStore) MongoCollection { - return testCase.mockColl - } - - decodeBytes = func(sr *mongo.SingleResult) (bson.Raw, error) { - return testCase.bson, testCase.mockColl.Err - } - got, err := m.Read(testCase.input["coll"].(string), testCase.input["key"].(Key), - testCase.input["tag"].(string)) - if err != nil { - if testCase.expectedError == "" { - t.Fatalf("Read method returned an un-expected (%s)", err) - } - if !strings.Contains(string(err.Error()), testCase.expectedError) { - t.Fatalf("Read method returned an error (%s)", err) - } - } else { - if bytes.Compare(got, testCase.expected) != 0 { - t.Fatalf("Read returned unexpected data: %v, expected: %v", - string(got), testCase.expected) - } - } - }) - } -} - -func TestDelete(t *testing.T) { - testCases := []struct { - label string - input map[string]interface{} - mockColl *mockCollection - bson bson.Raw - expectedError string - }{ - { - label: "Successfull Delete of entry", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "metadata", - }, - // Binary form of - // { - // "_id" : ObjectId("5c115156777ff85654248ae1"), - // "key" : bson.D{{"name","testdef"},{"version","v1"}}, - // "metadata" : ObjectId("5c115156c9755047e318bbfd") - // } - bson: bson.Raw{ - '\x58', '\x00', '\x00', '\x00', '\x03', '\x6b', '\x65', '\x79', - '\x00', '\x27', '\x00', '\x00', '\x00', '\x02', '\x6e', '\x61', - '\x6d', '\x65', '\x00', '\x08', '\x00', '\x00', '\x00', '\x74', - '\x65', '\x73', '\x74', '\x64', '\x65', '\x66', '\x00', '\x02', - '\x76', '\x65', '\x72', '\x73', '\x69', '\x6f', '\x6e', '\x00', - '\x03', '\x00', '\x00', '\x00', '\x76', '\x31', '\x00', '\x00', - '\x07', '\x6d', '\x65', '\x74', '\x61', '\x64', '\x61', '\x74', - '\x61', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', '\x7f', - '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x07', '\x5f', - '\x69', '\x64', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', - '\x7f', '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x00', - }, - mockColl: &mockCollection{}, - }, - { - label: "UnSuccessfull Delete of entry", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "tagName", - }, - mockColl: &mockCollection{ - Err: pkgerrors.New("DB Error"), - }, - expectedError: "DB Error", - }, - { - label: "UnSuccessfull Delete, key not found", - input: map[string]interface{}{ - "coll": "collname", - "key": MockKey{Key: "keyvalue"}, - "tag": "tagName", - }, - // Binary form of - // { - // "_id" : ObjectId("5c115156777ff85654248ae1"), - // "key" : bson.D{{"name","testdef"},{"version","v1"}}, - // "metadata" : ObjectId("5c115156c9755047e318bbfd") - // } - bson: bson.Raw{ - '\x58', '\x00', '\x00', '\x00', '\x03', '\x6b', '\x65', '\x79', - '\x00', '\x27', '\x00', '\x00', '\x00', '\x02', '\x6e', '\x61', - '\x6d', '\x65', '\x00', '\x08', '\x00', '\x00', '\x00', '\x74', - '\x65', '\x73', '\x74', '\x64', '\x65', '\x66', '\x00', '\x02', - '\x76', '\x65', '\x72', '\x73', '\x69', '\x6f', '\x6e', '\x00', - '\x03', '\x00', '\x00', '\x00', '\x76', '\x31', '\x00', '\x00', - '\x07', '\x6d', '\x65', '\x74', '\x61', '\x64', '\x61', '\x74', - '\x61', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', '\x7f', - '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x07', '\x5f', - '\x69', '\x64', '\x00', '\x5c', '\x11', '\x51', '\x56', '\x77', - '\x7f', '\xf8', '\x56', '\x54', '\x24', '\x8a', '\xe1', '\x00', - }, - mockColl: &mockCollection{}, - expectedError: "Error finding objectID", - }, - { - label: "Missing input fields", - input: map[string]interface{}{ - "coll": "", - "key": MockKey{Key: ""}, - "tag": "", - }, - expectedError: "Mandatory fields are missing", - mockColl: &mockCollection{}, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.label, func(t *testing.T) { - m, _ := NewMongoStore("name", &mongo.Database{}) - // Override the getCollection function with our mocked version - getCollection = func(coll string, m *MongoStore) MongoCollection { - return testCase.mockColl - } - - decodeBytes = func(sr *mongo.SingleResult) (bson.Raw, error) { - return testCase.bson, testCase.mockColl.Err - } - err := m.Delete(testCase.input["coll"].(string), testCase.input["key"].(Key), - testCase.input["tag"].(string)) - if err != nil { - if testCase.expectedError == "" { - t.Fatalf("Delete method returned an un-expected (%s)", err) - } - if !strings.Contains(string(err.Error()), testCase.expectedError) { - t.Fatalf("Delete method returned an error (%s)", err) - } - } - }) - } -} diff --git a/src/orchestrator/pkg/infra/db/store.go b/src/orchestrator/pkg/infra/db/store.go index a332fcda..d6ed6022 100644 --- a/src/orchestrator/pkg/infra/db/store.go +++ b/src/orchestrator/pkg/infra/db/store.go @@ -39,20 +39,6 @@ type Store interface { // Unmarshal implements any unmarshaling needed for the database Unmarshal(inp []byte, out interface{}) error - // Creates a new master document with key and links data with tag and - // creates a pointer(row) to the newly added data in the master table - Create(table string, key Key, tag string, data interface{}) error - - // Reads data for a particular key with specific tag. - Read(table string, key Key, tag string) ([]byte, error) - - // Update data for particular key with specific tag - Update(table string, key Key, tag string, data interface{}) error - - // Deletes a specific tag data for key. - // TODO: If tag is empty, it will delete all tags under key. - Delete(table string, key Key, tag string) error - // Inserts and Updates a tag with key and also adds query fields if provided Insert(coll string, key Key, query interface{}, tag string, data interface{}) error diff --git a/src/orchestrator/pkg/module/app_intent.go b/src/orchestrator/pkg/module/app_intent.go index 9da252e5..6b394513 100644 --- a/src/orchestrator/pkg/module/app_intent.go +++ b/src/orchestrator/pkg/module/app_intent.go @@ -53,11 +53,11 @@ type SpecData struct { // AppIntentManager is an interface which exposes the // AppIntentManager functionalities type AppIntentManager interface { - CreateAppIntent(a AppIntent, p string, ca string, v string, i string) (AppIntent, error) - GetAppIntent(ai string, p string, ca string, v string, i string) (AppIntent, error) - GetAllIntentsByApp(aN, p, ca, v, i string) (SpecData, error) - GetAllAppIntents(p, ca, v, i string) (ApplicationsAndClusterInfo, error) - DeleteAppIntent(ai string, p string, ca string, v string, i string) error + CreateAppIntent(a AppIntent, p string, ca string, v string, i string, digName string) (AppIntent, error) + GetAppIntent(ai string, p string, ca string, v string, i string, digName string) (AppIntent, error) + GetAllIntentsByApp(aN, p, ca, v, i, digName string) (SpecData, error) + GetAllAppIntents(p, ca, v, i, digName string) (ApplicationsAndClusterInfo, error) + DeleteAppIntent(ai string, p string, ca string, v string, i string, digName string) error } //AppIntentQueryKey required for query @@ -67,20 +67,22 @@ type AppIntentQueryKey struct { // AppIntentKey is used as primary key type AppIntentKey struct { - Name string `json:"appintent"` - Project string `json:"project"` - CompositeApp string `json:"compositeapp"` - Version string `json:"compositeappversion"` - Intent string `json:"genericplacement"` + Name string `json:"appintent"` + Project string `json:"project"` + CompositeApp string `json:"compositeapp"` + Version string `json:"compositeappversion"` + Intent string `json:"genericplacement"` + DeploymentIntentGroupName string `json:"deploymentintentgroup"` } // AppIntentFindByAppKey required for query type AppIntentFindByAppKey struct { - Project string `json:"project"` - CompositeApp string `json:"compositeapp"` - CompositeAppVersion string `json:"compositeappversion"` - Intent string `json:"genericplacement"` - AppName string `json:"app-name"` + Project string `json:"project"` + CompositeApp string `json:"compositeapp"` + CompositeAppVersion string `json:"compositeappversion"` + Intent string `json:"genericplacement"` + DeploymentIntentGroupName string `json:"deploymentintentgroup"` + AppName string `json:"app-name"` } // ApplicationsAndClusterInfo type represents the list of @@ -121,11 +123,11 @@ func NewAppIntentClient() *AppIntentClient { } // CreateAppIntent creates an entry for AppIntent in the db. -// Other input parameters for it - projectName, compositeAppName, version, intentName. -func (c *AppIntentClient) CreateAppIntent(a AppIntent, p string, ca string, v string, i string) (AppIntent, error) { +// Other input parameters for it - projectName, compositeAppName, version, intentName and deploymentIntentGroupName. +func (c *AppIntentClient) CreateAppIntent(a AppIntent, p string, ca string, v string, i string, digName string) (AppIntent, error) { //Check for the AppIntent already exists here. - res, err := c.GetAppIntent(a.MetaData.Name, p, ca, v, i) + res, err := c.GetAppIntent(a.MetaData.Name, p, ca, v, i, digName) if !reflect.DeepEqual(res, AppIntent{}) { return AppIntent{}, pkgerrors.New("AppIntent already exists") } @@ -143,17 +145,24 @@ func (c *AppIntentClient) CreateAppIntent(a AppIntent, p string, ca string, v st } // check if Intent exists - _, err = NewGenericPlacementIntentClient().GetGenericPlacementIntent(i, p, ca, v) + _, err = NewGenericPlacementIntentClient().GetGenericPlacementIntent(i, p, ca, v, digName) if err != nil { return AppIntent{}, pkgerrors.New("Unable to find the intent") } + // check if the deploymentIntentGrpName exists + _, err = NewDeploymentIntentGroupClient().GetDeploymentIntentGroup(digName, p, ca, v) + if err != nil { + return AppIntent{}, pkgerrors.New("Unable to find the deployment-intent-group-name") + } + akey := AppIntentKey{ - Name: a.MetaData.Name, - Project: p, - CompositeApp: ca, - Version: v, - Intent: i, + Name: a.MetaData.Name, + Project: p, + CompositeApp: ca, + Version: v, + Intent: i, + DeploymentIntentGroupName: digName, } qkey := AppIntentQueryKey{ @@ -168,15 +177,16 @@ func (c *AppIntentClient) CreateAppIntent(a AppIntent, p string, ca string, v st return a, nil } -// GetAppIntent shall take arguments - name of the app intent, name of the project, name of the composite app, version of the composite app and intent name. It shall return the AppIntent -func (c *AppIntentClient) GetAppIntent(ai string, p string, ca string, v string, i string) (AppIntent, error) { +// GetAppIntent shall take arguments - name of the app intent, name of the project, name of the composite app, version of the composite app,intent name and deploymentIntentGroupName. It shall return the AppIntent +func (c *AppIntentClient) GetAppIntent(ai string, p string, ca string, v string, i string, digName string) (AppIntent, error) { k := AppIntentKey{ - Name: ai, - Project: p, - CompositeApp: ca, - Version: v, - Intent: i, + Name: ai, + Project: p, + CompositeApp: ca, + Version: v, + Intent: i, + DeploymentIntentGroupName: digName, } result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData) @@ -197,17 +207,18 @@ func (c *AppIntentClient) GetAppIntent(ai string, p string, ca string, v string, } /* -GetAllIntentsByApp takes in parameters AppName, CompositeAppName, CompositeNameVersion -and GenericPlacementIntentName. Returns SpecData which contains +GetAllIntentsByApp queries intent by AppName, it takes in parameters AppName, CompositeAppName, CompositeNameVersion, +GenericPlacementIntentName & DeploymentIntentGroupName. Returns SpecData which contains all the intents for the app. */ -func (c *AppIntentClient) GetAllIntentsByApp(aN, p, ca, v, i string) (SpecData, error) { +func (c *AppIntentClient) GetAllIntentsByApp(aN, p, ca, v, i, digName string) (SpecData, error) { k := AppIntentFindByAppKey{ - Project: p, - CompositeApp: ca, - CompositeAppVersion: v, - Intent: i, - AppName: aN, + Project: p, + CompositeApp: ca, + CompositeAppVersion: v, + Intent: i, + DeploymentIntentGroupName: digName, + AppName: aN, } result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData) if err != nil { @@ -224,15 +235,16 @@ func (c *AppIntentClient) GetAllIntentsByApp(aN, p, ca, v, i string) (SpecData, /* GetAllAppIntents takes in paramaters ProjectName, CompositeAppName, CompositeNameVersion -and GenericPlacementIntentName. Returns the ApplicationsAndClusterInfo Object - an array of AppClusterInfo +and GenericPlacementIntentName,DeploymentIntentGroupName. Returns the ApplicationsAndClusterInfo Object - an array of AppClusterInfo */ -func (c *AppIntentClient) GetAllAppIntents(p, ca, v, i string) (ApplicationsAndClusterInfo, error) { +func (c *AppIntentClient) GetAllAppIntents(p, ca, v, i, digName string) (ApplicationsAndClusterInfo, error) { k := AppIntentKey{ - Name: "", - Project: p, - CompositeApp: ca, - Version: v, - Intent: i, + Name: "", + Project: p, + CompositeApp: ca, + Version: v, + Intent: i, + DeploymentIntentGroupName: digName, } result, err := db.DBconn.Find(c.storeName, k, c.tagMetaData) if err != nil { @@ -262,13 +274,14 @@ func (c *AppIntentClient) GetAllAppIntents(p, ca, v, i string) (ApplicationsAndC } // DeleteAppIntent delete an AppIntent -func (c *AppIntentClient) DeleteAppIntent(ai string, p string, ca string, v string, i string) error { +func (c *AppIntentClient) DeleteAppIntent(ai string, p string, ca string, v string, i string, digName string) error { k := AppIntentKey{ - Name: ai, - Project: p, - CompositeApp: ca, - Version: v, - Intent: i, + Name: ai, + Project: p, + CompositeApp: ca, + Version: v, + Intent: i, + DeploymentIntentGroupName: digName, } err := db.DBconn.Remove(c.storeName, k) diff --git a/src/orchestrator/pkg/module/app_intent_test.go b/src/orchestrator/pkg/module/app_intent_test.go index 089f09ff..a2e295ea 100644 --- a/src/orchestrator/pkg/module/app_intent_test.go +++ b/src/orchestrator/pkg/module/app_intent_test.go @@ -33,6 +33,7 @@ func TestCreateAppIntent(t *testing.T) { inputCompositeApp string inputCompositeAppVersion string inputGenericPlacementIntent string + inputDeploymentIntentGrpName string expectedError string mockdb *db.MockDB expected AppIntent @@ -81,6 +82,7 @@ func TestCreateAppIntent(t *testing.T) { inputCompositeApp: "testCompositeApp", inputCompositeAppVersion: "testCompositeAppVersion", inputGenericPlacementIntent: "testIntent", + inputDeploymentIntentGrpName: "testDeploymentIntentGroup", expected: AppIntent{ MetaData: MetaData{ Name: "testAppIntent", @@ -142,6 +144,7 @@ func TestCreateAppIntent(t *testing.T) { Project: "testProject", CompositeApp: "testCompositeApp", Version: "testCompositeAppVersion", + DigName: "testDeploymentIntentGroup", }.String(): { "genericplacementintentmetadata": []byte( "{\"metadata\":{\"Name\":\"testIntent\"," + @@ -150,6 +153,39 @@ func TestCreateAppIntent(t *testing.T) { "\"UserData2\": \"userData2\"}," + "\"spec\":{\"Logical-Cloud\": \"logicalCloud1\"}}"), }, + DeploymentIntentGroupKey{ + Name: "testDeploymentIntentGroup", + Project: "testProject", + CompositeApp: "testCompositeApp", + Version: "testCompositeAppVersion", + }.String(): { + "deploymentintentgroupmetadata": []byte( + "{\"metadata\":{\"name\":\"testDeploymentIntentGroup\"," + + "\"description\":\"DescriptionTestDeploymentIntentGroup\"," + + "\"userData1\": \"userData1\"," + + "\"userData2\": \"userData2\"}," + + "\"spec\":{\"profile\": \"Testprofile\"," + + "\"version\": \"version of deployment\"," + + "\"override-values\":[" + + "{" + + "\"app-name\": \"TestAppName\"," + + "\"values\": " + + "{" + + "\"imageRepository\":\"registry.hub.docker.com\"" + + "}" + + "}," + + "{" + + "\"app-name\": \"TestAppName\"," + + "\"values\": " + + "{" + + "\"imageRepository\":\"registry.hub.docker.com\"" + + "}" + + "}" + + "]," + + "\"logical-cloud\": \"cloud1\"" + + "}"+ + "}"), + }, }, }, }, @@ -158,7 +194,7 @@ func TestCreateAppIntent(t *testing.T) { t.Run(testCase.label, func(t *testing.T) { db.DBconn = testCase.mockdb appIntentCli := NewAppIntentClient() - got, err := appIntentCli.CreateAppIntent(testCase.inputAppIntent, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion, testCase.inputGenericPlacementIntent) + got, err := appIntentCli.CreateAppIntent(testCase.inputAppIntent, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion, testCase.inputGenericPlacementIntent, testCase.inputDeploymentIntentGrpName) if err != nil { if testCase.expectedError == "" { t.Fatalf("CreateAppIntent returned an unexpected error %s, ", err) @@ -186,6 +222,7 @@ func TestGetAppIntent(t *testing.T) { compositeAppName string compositeAppVersion string genericPlacementIntent string + deploymentIntentgrpName string }{ { label: "Get Intent", @@ -194,6 +231,7 @@ func TestGetAppIntent(t *testing.T) { compositeAppName: "testCompositeApp", compositeAppVersion: "testCompositeAppVersion", genericPlacementIntent: "testIntent", + deploymentIntentgrpName: "testDeploymentIntentGroup", expected: AppIntent{ MetaData: MetaData{ Name: "testAppIntent", @@ -234,6 +272,7 @@ func TestGetAppIntent(t *testing.T) { CompositeApp: "testCompositeApp", Version: "testCompositeAppVersion", Intent: "testIntent", + DeploymentIntentGroupName: "testDeploymentIntentGroup", }.String(): { "appintentmetadata": []byte( "{\"metadata\":{\"Name\":\"testAppIntent\"," + @@ -270,7 +309,7 @@ func TestGetAppIntent(t *testing.T) { db.DBconn = testCase.mockdb appIntentCli := NewAppIntentClient() got, err := appIntentCli.GetAppIntent(testCase.appIntentName, testCase.projectName, testCase.compositeAppName, testCase.compositeAppVersion, - testCase.genericPlacementIntent) + testCase.genericPlacementIntent, testCase.deploymentIntentgrpName) if err != nil { if testCase.expectedError == "" { t.Fatalf("GetAppIntent returned an unexpected error: %s", err) diff --git a/src/orchestrator/pkg/module/deployment_intent_groups.go b/src/orchestrator/pkg/module/deployment_intent_groups.go index dec6391f..f8e434f4 100644 --- a/src/orchestrator/pkg/module/deployment_intent_groups.go +++ b/src/orchestrator/pkg/module/deployment_intent_groups.go @@ -47,6 +47,7 @@ type DepSpecData struct { Profile string `json:"profile"` Version string `json:"version"` OverrideValuesObj []OverrideValues `json:"override-values"` + LogicalCloud string `json:"logical-cloud"` } // OverrideValues has appName and ValuesObj diff --git a/src/orchestrator/pkg/module/deployment_intent_groups_test.go b/src/orchestrator/pkg/module/deployment_intent_groups_test.go index 0fdeb4a1..86ae49df 100644 --- a/src/orchestrator/pkg/module/deployment_intent_groups_test.go +++ b/src/orchestrator/pkg/module/deployment_intent_groups_test.go @@ -57,6 +57,7 @@ func TestCreateDeploymentIntentGroup(t *testing.T) { "imageRepository": "registry.hub.docker.com", }}, }, + LogicalCloud: "cloud1", }, }, inputProject: "testProject", @@ -82,6 +83,7 @@ func TestCreateDeploymentIntentGroup(t *testing.T) { "imageRepository": "registry.hub.docker.com", }}, }, + LogicalCloud: "cloud1", }, }, expectedError: "", @@ -167,6 +169,7 @@ func TestGetDeploymentIntentGroup(t *testing.T) { "imageRepository": "registry.hub.docker.com", }}, }, + LogicalCloud: "cloud1", }, }, expectedError: "", @@ -200,7 +203,10 @@ func TestGetDeploymentIntentGroup(t *testing.T) { "\"imageRepository\":\"registry.hub.docker.com\"" + "}" + "}" + - "]}}"), + "]," + + "\"logical-cloud\": \"cloud1\"" + + "}"+ + "}"), }, }, }, diff --git a/src/orchestrator/pkg/module/generic_placement_intent.go b/src/orchestrator/pkg/module/generic_placement_intent.go index fb00a6ab..3ff1c7dc 100644 --- a/src/orchestrator/pkg/module/generic_placement_intent.go +++ b/src/orchestrator/pkg/module/generic_placement_intent.go @@ -18,6 +18,7 @@ package module import ( "encoding/json" + "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db" pkgerrors "github.com/pkg/errors" @@ -26,7 +27,6 @@ import ( // GenericPlacementIntent shall have 2 fields - metadata and spec type GenericPlacementIntent struct { MetaData GenIntentMetaData `json:"metadata"` - Spec GenIntentSpecData `json:"spec"` } // GenIntentMetaData has name, description, userdata1, userdata2 @@ -37,21 +37,16 @@ type GenIntentMetaData struct { UserData2 string `json:"userData2"` } -// GenIntentSpecData has logical-cloud-name -type GenIntentSpecData struct { - LogicalCloud string `json:"logical-cloud"` -} - // GenericPlacementIntentManager is an interface which exposes the GenericPlacementIntentManager functionality type GenericPlacementIntentManager interface { CreateGenericPlacementIntent(g GenericPlacementIntent, p string, ca string, - v string) (GenericPlacementIntent, error) + v string, digName string) (GenericPlacementIntent, error) GetGenericPlacementIntent(intentName string, projectName string, - compositeAppName string, version string) (GenericPlacementIntent, error) + compositeAppName string, version string, digName string) (GenericPlacementIntent, error) DeleteGenericPlacementIntent(intentName string, projectName string, - compositeAppName string, version string) error + compositeAppName string, version string, digName string) error - GetAllGenericPlacementIntents(p string, ca string, v string) ([]GenericPlacementIntent, error) + GetAllGenericPlacementIntents(p string, ca string, v string, digName string) ([]GenericPlacementIntent, error) } // GenericPlacementIntentKey is used as the primary key @@ -60,6 +55,7 @@ type GenericPlacementIntentKey struct { Project string `json:"project"` CompositeApp string `json:"compositeapp"` Version string `json:"compositeappversion"` + DigName string `json:"deploymentintentgroup"` } // We will use json marshalling to convert to string to @@ -86,12 +82,12 @@ func NewGenericPlacementIntentClient() *GenericPlacementIntentClient { } } -// CreateGenericPlacementIntent creates an entry for GenericPlacementIntent in the database. Other Input parameters for it - projectName, compositeAppName, version +// CreateGenericPlacementIntent creates an entry for GenericPlacementIntent in the database. Other Input parameters for it - projectName, compositeAppName, version and deploymentIntentGroupName func (c *GenericPlacementIntentClient) CreateGenericPlacementIntent(g GenericPlacementIntent, p string, ca string, - v string) (GenericPlacementIntent, error) { + v string, digName string) (GenericPlacementIntent, error) { // check if the genericPlacement already exists. - res, err := c.GetGenericPlacementIntent(g.MetaData.Name, p, ca, v) + res, err := c.GetGenericPlacementIntent(g.MetaData.Name, p, ca, v, digName) if res != (GenericPlacementIntent{}) { return GenericPlacementIntent{}, pkgerrors.New("Intent already exists") } @@ -108,11 +104,18 @@ func (c *GenericPlacementIntentClient) CreateGenericPlacementIntent(g GenericPla return GenericPlacementIntent{}, pkgerrors.New("Unable to find the composite-app") } + // check if the deploymentIntentGrpName exists + _, err = NewDeploymentIntentGroupClient().GetDeploymentIntentGroup(digName, p, ca, v) + if err != nil { + return GenericPlacementIntent{}, pkgerrors.New("Unable to find the deployment-intent-group-name") + } + gkey := GenericPlacementIntentKey{ Name: g.MetaData.Name, Project: p, CompositeApp: ca, Version: v, + DigName: digName, } err = db.DBconn.Insert(c.storeName, gkey, nil, c.tagMetaData, g) @@ -123,13 +126,14 @@ func (c *GenericPlacementIntentClient) CreateGenericPlacementIntent(g GenericPla return g, nil } -// GetGenericPlacementIntent shall take arguments - name of the intent, name of the project, name of the composite app and version of the composite app. It shall return the genericPlacementIntent if its present. -func (c *GenericPlacementIntentClient) GetGenericPlacementIntent(i string, p string, ca string, v string) (GenericPlacementIntent, error) { +// GetGenericPlacementIntent shall take arguments - name of the intent, name of the project, name of the composite app, version of the composite app and deploymentIntentGroupName. It shall return the genericPlacementIntent if its present. +func (c *GenericPlacementIntentClient) GetGenericPlacementIntent(i string, p string, ca string, v string, digName string) (GenericPlacementIntent, error) { key := GenericPlacementIntentKey{ Name: i, Project: p, CompositeApp: ca, Version: v, + DigName: digName, } result, err := db.DBconn.Find(c.storeName, key, c.tagMetaData) @@ -150,8 +154,8 @@ func (c *GenericPlacementIntentClient) GetGenericPlacementIntent(i string, p str } -// GetAllGenericPlacementIntents returns all the generic placement intents for a given compsoite app name, composite app version and project. -func (c *GenericPlacementIntentClient) GetAllGenericPlacementIntents(p string, ca string, v string) ([]GenericPlacementIntent, error) { +// GetAllGenericPlacementIntents returns all the generic placement intents for a given compsoite app name, composite app version, project and deploymentIntentGroupName +func (c *GenericPlacementIntentClient) GetAllGenericPlacementIntents(p string, ca string, v string, digName string) ([]GenericPlacementIntent, error) { //Check if project exists _, err := NewProjectClient().GetProject(p) @@ -170,6 +174,7 @@ func (c *GenericPlacementIntentClient) GetAllGenericPlacementIntents(p string, c Project: p, CompositeApp: ca, Version: v, + DigName: digName, } var gpList []GenericPlacementIntent @@ -192,12 +197,13 @@ func (c *GenericPlacementIntentClient) GetAllGenericPlacementIntents(p string, c } // DeleteGenericPlacementIntent the intent from the database -func (c *GenericPlacementIntentClient) DeleteGenericPlacementIntent(i string, p string, ca string, v string) error { +func (c *GenericPlacementIntentClient) DeleteGenericPlacementIntent(i string, p string, ca string, v string, digName string) error { key := GenericPlacementIntentKey{ Name: i, Project: p, CompositeApp: ca, Version: v, + DigName: digName, } err := db.DBconn.Remove(c.storeName, key) diff --git a/src/orchestrator/pkg/module/generic_placement_intent_test.go b/src/orchestrator/pkg/module/generic_placement_intent_test.go index d779e81f..59c1cac5 100644 --- a/src/orchestrator/pkg/module/generic_placement_intent_test.go +++ b/src/orchestrator/pkg/module/generic_placement_intent_test.go @@ -31,6 +31,7 @@ func TestCreateGenericPlacementIntent(t *testing.T) { inputProject string inputCompositeApp string inputCompositeAppVersion string + inputDepIntGrpName string expectedError string mockdb *db.MockDB expected GenericPlacementIntent @@ -44,13 +45,11 @@ func TestCreateGenericPlacementIntent(t *testing.T) { UserData1: "userData1", UserData2: "userData2", }, - Spec: GenIntentSpecData{ - LogicalCloud: "logicalCloud1", - }, }, inputProject: "testProject", inputCompositeApp: "testCompositeApp", inputCompositeAppVersion: "testCompositeAppVersion", + inputDepIntGrpName: "testDeploymentIntentGroup", expected: GenericPlacementIntent{ MetaData: GenIntentMetaData{ Name: "testGenericPlacement", @@ -58,9 +57,6 @@ func TestCreateGenericPlacementIntent(t *testing.T) { UserData1: "userData1", UserData2: "userData2", }, - Spec: GenIntentSpecData{ - LogicalCloud: "logicalCloud1", - }, }, expectedError: "", mockdb: &db.MockDB{ @@ -82,6 +78,40 @@ func TestCreateGenericPlacementIntent(t *testing.T) { "\"spec\":{" + "\"version\":\"version of the composite app\"}}"), }, + DeploymentIntentGroupKey{ + Name: "testDeploymentIntentGroup", + Project: "testProject", + CompositeApp: "testCompositeApp", + Version: "testCompositeAppVersion", + }.String(): { + "deploymentintentgroupmetadata": []byte( + "{\"metadata\":{\"name\":\"testDeploymentIntentGroup\"," + + "\"description\":\"DescriptionTestDeploymentIntentGroup\"," + + "\"userData1\": \"userData1\"," + + "\"userData2\": \"userData2\"}," + + "\"spec\":{\"profile\": \"Testprofile\"," + + "\"version\": \"version of deployment\"," + + "\"override-values\":[" + + "{" + + "\"app-name\": \"TestAppName\"," + + "\"values\": " + + "{" + + "\"imageRepository\":\"registry.hub.docker.com\"" + + "}" + + "}," + + "{" + + "\"app-name\": \"TestAppName\"," + + "\"values\": " + + "{" + + "\"imageRepository\":\"registry.hub.docker.com\"" + + "}" + + "}" + + "]," + + "\"logical-cloud\": \"cloud1\"" + + "}"+ + "}"), + }, + }, }, }, @@ -91,7 +121,7 @@ func TestCreateGenericPlacementIntent(t *testing.T) { t.Run(testCase.label, func(t *testing.T) { db.DBconn = testCase.mockdb intentCli := NewGenericPlacementIntentClient() - got, err := intentCli.CreateGenericPlacementIntent(testCase.inputIntent, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion) + got, err := intentCli.CreateGenericPlacementIntent(testCase.inputIntent, testCase.inputProject, testCase.inputCompositeApp, testCase.inputCompositeAppVersion, testCase.inputDepIntGrpName) if err != nil { if testCase.expectedError == "" { t.Fatalf("CreateGenericPlacementIntent returned an unexpected error %s", err) @@ -120,6 +150,7 @@ func TestGetGenericPlacementIntent(t *testing.T) { projectName string compositeAppName string compositeAppVersion string + deploymentIntentGroupName string }{ { label: "Get Intent", @@ -127,6 +158,7 @@ func TestGetGenericPlacementIntent(t *testing.T) { projectName: "testProject", compositeAppName: "testCompositeApp", compositeAppVersion: "testVersion", + deploymentIntentGroupName: "testDeploymentIntentGroup", expected: GenericPlacementIntent{ MetaData: GenIntentMetaData{ Name: "testIntent", @@ -134,9 +166,6 @@ func TestGetGenericPlacementIntent(t *testing.T) { UserData1: "userData1", UserData2: "userData2", }, - Spec: GenIntentSpecData{ - LogicalCloud: "logicalCloud1", - }, }, expectedError: "", mockdb: &db.MockDB{ @@ -146,13 +175,14 @@ func TestGetGenericPlacementIntent(t *testing.T) { Project: "testProject", CompositeApp: "testCompositeApp", Version: "testVersion", + DigName: "testDeploymentIntentGroup", }.String(): { "genericplacementintentmetadata": []byte( "{\"metadata\":{\"Name\":\"testIntent\"," + "\"Description\":\"A sample intent for testing\"," + "\"UserData1\": \"userData1\"," + - "\"UserData2\": \"userData2\"}," + - "\"spec\":{\"Logical-Cloud\": \"logicalCloud1\"}}"), + "\"UserData2\": \"userData2\"}" + + "}"), }, }, }, @@ -163,7 +193,7 @@ func TestGetGenericPlacementIntent(t *testing.T) { t.Run(testCase.label, func(t *testing.T) { db.DBconn = testCase.mockdb intentCli := NewGenericPlacementIntentClient() - got, err := intentCli.GetGenericPlacementIntent(testCase.intentName, testCase.projectName, testCase.compositeAppName, testCase.compositeAppVersion) + got, err := intentCli.GetGenericPlacementIntent(testCase.intentName, testCase.projectName, testCase.compositeAppName, testCase.compositeAppVersion, testCase.deploymentIntentGroupName) if err != nil { if testCase.expectedError == "" { t.Fatalf("GetGenericPlacementIntent returned an unexpected error: %s", err) diff --git a/src/orchestrator/pkg/module/instantiation.go b/src/orchestrator/pkg/module/instantiation.go index 0ae76006..d703af7f 100644 --- a/src/orchestrator/pkg/module/instantiation.go +++ b/src/orchestrator/pkg/module/instantiation.go @@ -99,12 +99,12 @@ func NewInstantiationClient() *InstantiationClient { func (c InstantiationClient) Approve(p string, ca string, v string, di string) error { s, err := NewDeploymentIntentGroupClient().GetDeploymentIntentGroupState(di, p, ca, v) if err != nil { - log.Info("DeploymentIntentGroup has no state info ", log.Fields{"DeploymentIntentGroup: ":di}) + log.Info("DeploymentIntentGroup has no state info ", log.Fields{"DeploymentIntentGroup: ": di}) return pkgerrors.Wrap(err, "DeploymentIntentGroup has no state info: "+di) } stateVal, err := state.GetCurrentStateFromStateInfo(s) if err != nil { - log.Info("Error getting current state from DeploymentIntentGroup stateInfo", log.Fields{"DeploymentIntentGroup ":di}) + log.Info("Error getting current state from DeploymentIntentGroup stateInfo", log.Fields{"DeploymentIntentGroup ": di}) return pkgerrors.Errorf("Error getting current state from DeploymentIntentGroup stateInfo: " + di) } switch stateVal { @@ -222,24 +222,24 @@ func GetSortedTemplateForApp(appName, p, ca, v, rName, cp string, overrideValues return sortedTemplates, err } -func calculateDirPath(fp string) string { +func calculateDirPath(fp string) string { sa := strings.Split(fp, "/") return "/" + sa[1] + "/" + sa[2] + "/" } func cleanTmpfiles(sortedTemplates []helm.KubernetesResourceTemplate) error { dp := calculateDirPath(sortedTemplates[0].FilePath) - for _, st := range sortedTemplates{ + for _, st := range sortedTemplates { log.Info("Clean up ::", log.Fields{"file: ": st.FilePath}) err := os.Remove(st.FilePath) if err != nil { - log.Error("Error while deleting file", log.Fields{"file: ":st.FilePath}) + log.Error("Error while deleting file", log.Fields{"file: ": st.FilePath}) return err } } err := os.RemoveAll(dp) if err != nil { - log.Error("Error while deleting dir", log.Fields{"Dir: ":dp}) + log.Error("Error while deleting dir", log.Fields{"Dir: ": dp}) return err } log.Info("Clean up temp-dir::", log.Fields{"Dir: ": dp}) @@ -298,7 +298,7 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin return pkgerrors.Wrap(err, "Not finding the apps") } - cca, err := makeAppContextForCompositeApp(p, ca, v, rName) + cca, err := makeAppContextForCompositeApp(p, ca, v, rName, di) if err != nil { return err } @@ -338,7 +338,7 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin defer cleanTmpfiles(sortedTemplates) - specData, err := NewAppIntentClient().GetAllIntentsByApp(eachApp.Metadata.Name, p, ca, v, gIntent) + specData, err := NewAppIntentClient().GetAllIntentsByApp(eachApp.Metadata.Name, p, ca, v, gIntent, di) if err != nil { deleteAppContext(context) return pkgerrors.Wrap(err, "Unable to get the intents for app") @@ -369,7 +369,7 @@ func (c InstantiationClient) Instantiate(p string, ca string, v string, di strin deleteAppContext(context) return pkgerrors.Wrap(err, "Error while verifying resources in app: ") } - + } jappOrderInstr, err := json.Marshal(appOrderInstr) if err != nil { diff --git a/src/orchestrator/pkg/module/instantiation_appcontext_helper.go b/src/orchestrator/pkg/module/instantiation_appcontext_helper.go index 692cdf1e..06e025c7 100644 --- a/src/orchestrator/pkg/module/instantiation_appcontext_helper.go +++ b/src/orchestrator/pkg/module/instantiation_appcontext_helper.go @@ -46,7 +46,7 @@ type contextForCompositeApp struct { } // makeAppContext creates an appContext for a compositeApp and returns the output as contextForCompositeApp -func makeAppContextForCompositeApp(p, ca, v, rName string) (contextForCompositeApp, error) { +func makeAppContextForCompositeApp(p, ca, v, rName, dig string) (contextForCompositeApp, error) { context := appcontext.AppContext{} ctxval, err := context.InitAppContext() if err != nil { @@ -56,14 +56,14 @@ func makeAppContextForCompositeApp(p, ca, v, rName string) (contextForCompositeA if err != nil { return contextForCompositeApp{}, pkgerrors.Wrap(err, "Error creating CompositeApp handle") } - err = context.AddCompositeAppMeta(appcontext.CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rName}) + err = context.AddCompositeAppMeta(appcontext.CompositeAppMeta{Project: p, CompositeApp: ca, Version: v, Release: rName, DeploymentIntentGroup: dig}) if err != nil { return contextForCompositeApp{}, pkgerrors.Wrap(err, "Error Adding CompositeAppMeta") } m, err := context.GetCompositeAppMeta() - log.Info(":: The meta data stored in the runtime context :: ", log.Fields{"Project": m.Project, "CompositeApp": m.CompositeApp, "Version": m.Version, "Release": m.Release}) + log.Info(":: The meta data stored in the runtime context :: ", log.Fields{"Project": m.Project, "CompositeApp": m.CompositeApp, "Version": m.Version, "Release": m.Release, "DeploymentIntentGroup": m.DeploymentIntentGroup}) cca := contextForCompositeApp{context: context, ctxval: ctxval, compositeAppHandle: compositeHandle} |