/* * Copyright 2018 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 rb import ( "bytes" "encoding/base64" "k8splugin/internal/db" "log" uuid "github.com/hashicorp/go-uuid" pkgerrors "github.com/pkg/errors" ) // Definition contains the parameters needed for resource bundle (rb) definitions // It implements the interface for managing the definitions type Definition struct { UUID string `json:"uuid,omitempty"` Name string `json:"name"` ChartName string `json:"chart-name"` Description string `json:"description"` ServiceType string `json:"service-type"` } // DefinitionManager is an interface exposes the resource bundle definition functionality type DefinitionManager interface { Create(def Definition) (Definition, error) List() ([]Definition, error) Get(resID string) (Definition, error) Delete(resID string) error Upload(resID string, inp []byte) error } // DefinitionClient implements the DefinitionManager // It will also be used to maintain some localized state type DefinitionClient struct { storeName string tagMeta, tagContent string } // NewDefinitionClient returns an instance of the DefinitionClient // which implements the DefinitionManager // Uses rbdef collection in underlying db func NewDefinitionClient() *DefinitionClient { return &DefinitionClient{ storeName: "rbdef", tagMeta: "metadata", tagContent: "content", } } // Create an entry for the resource in the database func (v *DefinitionClient) Create(def Definition) (Definition, error) { // If UUID is empty, we will generate one if def.UUID == "" { def.UUID, _ = uuid.GenerateUUID() } key := def.UUID err := db.DBconn.Create(v.storeName, key, v.tagMeta, def) if err != nil { return Definition{}, pkgerrors.Wrap(err, "Creating DB Entry") } return def, nil } // List all resource entries in the database func (v *DefinitionClient) List() ([]Definition, error) { res, err := db.DBconn.ReadAll(v.storeName, v.tagMeta) if err != nil || len(res) == 0 { return []Definition{}, pkgerrors.Wrap(err, "Listing Resource Bundle Definitions") } var results []Definition for key, value := range res { //value is a byte array if len(value) > 0 { def := Definition{} err = db.DBconn.Unmarshal(value, &def) if err != nil { log.Printf("[Definition] Error Unmarshaling value for: %s", key) continue } results = append(results, def) } } return results, nil } // Get returns the Resource Bundle Definition for corresponding ID func (v *DefinitionClient) Get(id string) (Definition, error) { value, err := db.DBconn.Read(v.storeName, id, v.tagMeta) if err != nil { return Definition{}, pkgerrors.Wrap(err, "Get Resource Bundle definition") } //value is a byte array if value != nil { def := Definition{} err = db.DBconn.Unmarshal(value, &def) if err != nil { return Definition{}, pkgerrors.Wrap(err, "Unmarshaling Value") } return def, nil } return Definition{}, pkgerrors.New("Error getting Resource Bundle Definition") } // Delete the Resource Bundle definition from database func (v *DefinitionClient) Delete(id string) error { err := db.DBconn.Delete(v.storeName, id, v.tagMeta) if err != nil { return pkgerrors.Wrap(err, "Delete Resource Bundle Definition") } //Delete the content when the delete operation happens err = db.DBconn.Delete(v.storeName, id, v.tagContent) if err != nil { return pkgerrors.Wrap(err, "Delete Resource Bundle Definition Content") } return nil } // Upload the contents of resource bundle into database func (v *DefinitionClient) Upload(id string, inp []byte) error { //ignore the returned data here _, err := v.Get(id) if err != nil { return pkgerrors.Errorf("Invalid Definition ID provided: %s", err.Error()) } err = isTarGz(bytes.NewBuffer(inp)) if err != nil { return pkgerrors.Errorf("Error in file format: %s", err.Error()) } //Encode given byte stream to text for storage encodedStr := base64.StdEncoding.EncodeToString(inp) err = db.DBconn.Create(v.storeName, id, v.tagContent, encodedStr) if err != nil { return pkgerrors.Errorf("Error uploading data to db: %s", err.Error()) } return nil }