X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fk8splugin%2Finternal%2Fapp%2Fconfig.go;fp=src%2Fk8splugin%2Finternal%2Fapp%2Fconfig.go;h=fce163fc1e9f64bcf842e241c6716d0d65fc0294;hb=88ecb1f9dfeded36e7fd74c776daefcaf67f8ae2;hp=8952c16dc53cffabf1a1dc6e57f32d1296dc719b;hpb=1f92a0ec4ea037089b82e3f80bb030f34fab64f0;p=multicloud%2Fk8s.git diff --git a/src/k8splugin/internal/app/config.go b/src/k8splugin/internal/app/config.go index 8952c16d..fce163fc 100644 --- a/src/k8splugin/internal/app/config.go +++ b/src/k8splugin/internal/app/config.go @@ -22,17 +22,17 @@ import ( "strconv" "strings" - "github.com/onap/multicloud-k8s/src/k8splugin/internal/helm" - pkgerrors "github.com/pkg/errors" ) // Config contains the parameters needed for configuration type Config struct { - ConfigName string `json:"config-name"` - TemplateName string `json:"template-name"` - Description string `json:"description"` - Values map[string]interface{} `json:"values"` + ConfigName string `json:"config-name"` + TemplateName string `json:"template-name"` + Description string `json:"description"` + Values map[string]interface{} `json:"values"` + ConfigVersion uint `json:"config-version"` + ConfigTag string `json:"config-tag"` } //ConfigResult output for Create, Update and delete @@ -54,6 +54,12 @@ type ConfigRollback struct { } `json:"anyOf"` } +//ConfigRollback input +type ConfigTag struct { + ConfigVersion uint `json:"config-version"` + ConfigTag string `json:"config-tag"` +} + //ConfigTagit for Tagging configurations type ConfigTagit struct { TagName string `json:"tag-name"` @@ -63,14 +69,18 @@ type ConfigTagit struct { type ConfigManager interface { Create(instanceID string, p Config) (ConfigResult, error) Get(instanceID, configName string) (Config, error) + GetVersion(instanceID, configName, version string) (Config, error) + GetTag(instanceID, configName, tagName string) (Config, error) List(instanceID string) ([]Config, error) + VersionList(instanceID, configName string) ([]Config, error) Help() map[string]string Update(instanceID, configName string, p Config) (ConfigResult, error) Delete(instanceID, configName string) (ConfigResult, error) - DeleteAll(instanceID, configName string) error - Rollback(instanceID string, configName string, p ConfigRollback) error + DeleteAll(instanceID, configName string, deleteConfigOnly bool) error + Rollback(instanceID string, configName string, p ConfigRollback, acceptRevert bool) (ConfigResult, error) Cleanup(instanceID string) error - Tagit(instanceID string, configName string, p ConfigTagit) error + Tagit(instanceID string, configName string, p ConfigTagit) (ConfigTag, error) + TagList(instanceID, configName string) ([]ConfigTag, error) } // ConfigClient implements the ConfigManager @@ -99,7 +109,7 @@ func (v *ConfigClient) Help() map[string]string { func (v *ConfigClient) Create(instanceID string, p Config) (ConfigResult, error) { log.Printf("[Config Create] Instance %s", instanceID) // Check required fields - if p.ConfigName == "" || p.TemplateName == "" || len(p.Values) == 0 { + if p.ConfigName == "" || p.TemplateName == "" { return ConfigResult{}, pkgerrors.New("Incomplete Configuration Provided") } // Resolving rbName, Version, etc. not to break response @@ -123,7 +133,7 @@ func (v *ConfigClient) Create(instanceID string, p Config) (ConfigResult, error) // Acquire per profile Mutex lock.Lock() defer lock.Unlock() - var appliedResources ([]helm.KubernetesResource) + var appliedResources ([]KubernetesConfigResource) appliedResources, err = applyConfig(instanceID, p, profileChannel, "POST", nil) if err != nil { return ConfigResult{}, pkgerrors.Wrap(err, "Apply Config failed") @@ -160,10 +170,6 @@ func (v *ConfigClient) Create(instanceID string, p Config) (ConfigResult, error) // Update an entry for the config in the database func (v *ConfigClient) Update(instanceID, configName string, p Config) (ConfigResult, error) { log.Printf("[Config Update] Instance %s Config %s", instanceID, configName) - // Check required fields - if len(p.Values) == 0 { - return ConfigResult{}, pkgerrors.New("Incomplete Configuration Provided") - } // Resolving rbName, Version, etc. not to break response rbName, rbVersion, profileName, _, err := resolveModelFromInstance(instanceID) if err != nil { @@ -182,7 +188,7 @@ func (v *ConfigClient) Update(instanceID, configName string, p Config) (ConfigRe // Acquire per profile Mutex lock.Lock() defer lock.Unlock() - var appliedResources ([]helm.KubernetesResource) + var appliedResources ([]KubernetesConfigResource) appliedResources, err = applyConfig(instanceID, p, profileChannel, "PUT", nil) if err != nil { return ConfigResult{}, pkgerrors.Wrap(err, "Apply Config failed") @@ -232,6 +238,59 @@ func (v *ConfigClient) Get(instanceID, configName string) (Config, error) { if err != nil { return Config{}, pkgerrors.Wrap(err, "Get Config DB Entry") } + + cvs := ConfigVersionStore{ + instanceID: instanceID, + configName: configName, + } + currentVersion, err := cvs.getCurrentVersion(configName) + if err != nil { + return Config{}, pkgerrors.Wrap(err, "Get Config Version Entry") + } + cfg.ConfigVersion = currentVersion + return cfg, nil +} + +// Get version config entry in the database +func (v *ConfigClient) GetTag(instanceID, configName, tagName string) (Config, error) { + cvs := ConfigVersionStore{ + instanceID: instanceID, + configName: configName, + } + version, err := cvs.getTagVersion(configName, tagName) + if err != nil { + return Config{}, pkgerrors.Wrap(err, "Get Config Tag Version Entry") + } + return v.GetVersion(instanceID, configName, version) +} + +// Get version config entry in the database +func (v *ConfigClient) GetVersion(instanceID, configName, version string) (Config, error) { + + // Acquire per profile Mutex + lock, _ := getProfileData(instanceID) + lock.Lock() + defer lock.Unlock() + // Read Config DB + cs := ConfigStore{ + instanceID: instanceID, + configName: configName, + } + cfg, err := cs.getConfig() + + cvs := ConfigVersionStore{ + instanceID: instanceID, + configName: configName, + } + versionInt, err := strconv.ParseUint(version, 0, 32) + if err != nil { + return Config{}, pkgerrors.Wrap(err, "Parsint version string") + } + _, _, _, _, err = cvs.getConfigVersion(configName, uint(versionInt)) + if err != nil { + return Config{}, pkgerrors.Wrap(err, "Get Config Version Entry") + } + cfg.ConfigVersion = uint(versionInt) return cfg, nil } @@ -247,14 +306,100 @@ func (v *ConfigClient) List(instanceID string) ([]Config, error) { instanceID: instanceID, } cfg, err := cs.getConfigList() + result := make([]Config, 0) + for _, config := range cfg { + cvs := ConfigVersionStore{ + instanceID: instanceID, + configName: config.ConfigName, + } + currentVersion, err := cvs.getCurrentVersion(config.ConfigName) + if err != nil { + return []Config{}, pkgerrors.Wrap(err, "Get Current Config Version ") + } + config.ConfigVersion = currentVersion + result = append(result, config) + } if err != nil { return []Config{}, pkgerrors.Wrap(err, "Get Config DB Entry") } - return cfg, nil + return result, nil +} + +// Version List config entry in the database +func (v *ConfigClient) VersionList(instanceID string, configName string) ([]Config, error) { + + // Acquire per profile Mutex + lock, _ := getProfileData(instanceID) + lock.Lock() + defer lock.Unlock() + + cvs := ConfigVersionStore{ + instanceID: instanceID, + configName: configName, + } + currentVersion, err := cvs.getCurrentVersion(configName) + if err != nil { + return []Config{}, pkgerrors.Wrap(err, "Get Current Config Version ") + } + //Get all configurations + var i uint + cfgList := make([]Config, 0) + for i = 1; i <= currentVersion; i++ { + config, _, _, _, err := cvs.getConfigVersion(configName, i) + config.ConfigVersion = i + if err != nil { + return []Config{}, pkgerrors.Wrap(err, "Get Config Version") + } + cfgList = append(cfgList, config) + } + + return cfgList, nil +} + +func (v *ConfigClient) TagList(instanceID, configName string) ([]ConfigTag, error) { + + // Acquire per profile Mutex + lock, _ := getProfileData(instanceID) + lock.Lock() + defer lock.Unlock() + // Read Config DB + cs := ConfigStore{ + instanceID: instanceID, + configName: configName, + } + _, err := cs.getConfig() + if err != nil { + return []ConfigTag{}, pkgerrors.Wrap(err, "Get Config DB Entry") + } + cvs := ConfigVersionStore{ + instanceID: instanceID, + configName: configName, + } + + tagList, err := cvs.getTagList(configName) + if err != nil { + return []ConfigTag{}, pkgerrors.Wrap(err, "Get Tag list") + } + result := make([]ConfigTag, 0) + for _, tag := range tagList { + tagData := ConfigTag{} + version, err := cvs.getTagVersion(configName, tag) + if err != nil { + return []ConfigTag{}, pkgerrors.Wrap(err, "Get Tag version") + } + versionInt, err := strconv.ParseUint(version, 0, 32) + if err != nil { + return []ConfigTag{}, pkgerrors.Wrap(err, "Parsint version string") + } + tagData.ConfigTag = tag + tagData.ConfigVersion = uint(versionInt) + result = append(result, tagData) + } + return result, nil } // Delete the Config from database -func (v *ConfigClient) DeleteAll(instanceID, configName string) error { +func (v *ConfigClient) DeleteAll(instanceID, configName string, deleteConfigOnly bool) error { log.Printf("[Config Delete All] Instance %s Config %s", instanceID, configName) // Check if Config exists cs := ConfigStore{ @@ -270,19 +415,13 @@ func (v *ConfigClient) DeleteAll(instanceID, configName string) error { instanceID: instanceID, configName: configName, } - currentVersion, err := cvs.getCurrentVersion(configName) - if err != nil { - return pkgerrors.Wrap(err, "Current version get failed") - } - _, _, action, _, err := cvs.getConfigVersion(configName, currentVersion) - if err != nil { - return pkgerrors.Wrap(err, "Config version get failed") - } - if action != "DELETE" { - _, err = v.Delete(instanceID, configName) + if !deleteConfigOnly { + var rollbackConfig = ConfigRollback{} + rollbackConfig.AnyOf.ConfigVersion = "0" + _, err = v.Rollback(instanceID, configName, rollbackConfig, true) if err != nil { - return pkgerrors.Wrap(err, "Config DELETE version failed") + return pkgerrors.Wrap(err, "Rollback to base version") } } // Delete Config from DB @@ -339,7 +478,7 @@ func (v *ConfigClient) Delete(instanceID, configName string) (ConfigResult, erro if err != nil { return ConfigResult{}, pkgerrors.Wrap(err, "Update Config DB Entry") } - version, err := cvs.createConfigVersion(p, configPrev, "DELETE", []helm.KubernetesResource{}) + version, err := cvs.createConfigVersion(p, configPrev, "DELETE", []KubernetesConfigResource{}) if err != nil { return ConfigResult{}, pkgerrors.Wrap(err, "Create Delete Config Version DB Entry") } @@ -358,25 +497,28 @@ func (v *ConfigClient) Delete(instanceID, configName string) (ConfigResult, erro } // Rollback starts from current version and rollbacks to the version desired -func (v *ConfigClient) Rollback(instanceID string, configName string, rback ConfigRollback) error { +func (v *ConfigClient) Rollback(instanceID string, configName string, rback ConfigRollback, acceptRevert bool) (ConfigResult, error) { log.Printf("[Config Rollback] Instance %s Config %s", instanceID, configName) var reqVersion string var err error - + rbName, rbVersion, profileName, _, err := resolveModelFromInstance(instanceID) + if err != nil { + return ConfigResult{}, pkgerrors.Wrap(err, "Retrieving model info") + } if rback.AnyOf.ConfigTag != "" { reqVersion, err = v.GetTagVersion(instanceID, configName, rback.AnyOf.ConfigTag) if err != nil { - return pkgerrors.Wrap(err, "Rollback Invalid tag") + return ConfigResult{}, pkgerrors.Wrap(err, "Rollback Invalid tag") } } else if rback.AnyOf.ConfigVersion != "" { reqVersion = rback.AnyOf.ConfigVersion } else { - return pkgerrors.Errorf("No valid Index for Rollback") + return ConfigResult{}, pkgerrors.Errorf("No valid Index for Rollback") } index, err := strconv.Atoi(reqVersion) if err != nil { - return pkgerrors.Wrap(err, "Rollback Invalid Index") + return ConfigResult{}, pkgerrors.Wrap(err, "Rollback Invalid Index") } rollbackIndex := uint(index) @@ -391,62 +533,114 @@ func (v *ConfigClient) Rollback(instanceID string, configName string, rback Conf } currentVersion, err := cvs.getCurrentVersion(configName) if err != nil { - return pkgerrors.Wrap(err, "Rollback Get Current Config Version ") + return ConfigResult{}, pkgerrors.Wrap(err, "Rollback Get Current Config Version ") + } + + if (rollbackIndex < 1 && !acceptRevert) || rollbackIndex >= currentVersion { + return ConfigResult{}, pkgerrors.Wrap(err, "Rollback Invalid Config Version") } - if rollbackIndex < 1 && rollbackIndex >= currentVersion { - return pkgerrors.Wrap(err, "Rollback Invalid Config Version") + if rollbackIndex < 1 && acceptRevert { + rollbackIndex = 0 } //Rollback all the intermettinent configurations for i := currentVersion; i > rollbackIndex; i-- { configNew, configPrev, _, resources, err := cvs.getConfigVersion(configName, i) if err != nil { - return pkgerrors.Wrap(err, "Rollback Get Config Version") + return ConfigResult{}, pkgerrors.Wrap(err, "Rollback Get Config Version") + } + var prevAction string + if i == 1 { + prevAction = "POST" + configPrev.ConfigName = "" + configPrev.TemplateName = "" + configPrev.Values = make(map[string]interface{}) + } else { + _, _, prevAction, _, err = cvs.getConfigVersion(configName, i-1) } - _, _, prevAction, _, err := cvs.getConfigVersion(configName, i-1) + log.Printf("ROLLBACK to version: %d", i-1) if err != nil { - return pkgerrors.Wrap(err, "Rollback Get Prev Config Version") + return ConfigResult{}, pkgerrors.Wrap(err, "Rollback Get Prev Config Version") } cs := ConfigStore{ instanceID: instanceID, configName: configNew.ConfigName, } if prevAction != "DELETE" { + var resourcesToDelete = make([]KubernetesConfigResource, 0) + for _, res := range resources { + if res.Status == "CREATED" { + resourcesToDelete = append(resourcesToDelete, res) + } + } + if len(resourcesToDelete) > 0 { + _, err := applyConfig(instanceID, configPrev, profileChannel, "DELETE", resources) + if err != nil { + return ConfigResult{}, pkgerrors.Wrap(err, "Apply Config failed") + } + } appliedResources, err := applyConfig(instanceID, configPrev, profileChannel, prevAction, nil) if err != nil { - return pkgerrors.Wrap(err, "Apply Config failed") + return ConfigResult{}, pkgerrors.Wrap(err, "Apply Config failed") } log.Printf("%s result: %s", prevAction, appliedResources) _, err = cs.updateConfig(configPrev) if err != nil { - return pkgerrors.Wrap(err, "Update Config DB Entry") + return ConfigResult{}, pkgerrors.Wrap(err, "Update Config DB Entry") } } else { // POST is always preceeded by Config not existing - _, err := applyConfig(instanceID, configNew, profileChannel, prevAction, resources) + _, err := applyConfig(instanceID, configPrev, profileChannel, prevAction, resources) if err != nil { - return pkgerrors.Wrap(err, "Delete Config failed") + return ConfigResult{}, pkgerrors.Wrap(err, "Delete Config failed") } log.Printf("DELETE resources: %s", resources) _, err = cs.updateConfig(configPrev) if err != nil { - return pkgerrors.Wrap(err, "Update Config DB Entry") + return ConfigResult{}, pkgerrors.Wrap(err, "Update Config DB Entry") } } } + if rollbackIndex == 0 { + //this is used only for delete config and remianing configuration 1 will be removed there + rollbackIndex = 1 + } for i := currentVersion; i > rollbackIndex; i-- { // Delete rolled back items err = cvs.deleteConfigVersion(configName) if err != nil { - return pkgerrors.Wrap(err, "Delete Config Version ") + return ConfigResult{}, pkgerrors.Wrap(err, "Delete Config Version ") } } - return nil + currentVersion, err = cvs.getCurrentVersion(configName) + if err != nil { + return ConfigResult{}, pkgerrors.Wrap(err, "Rollback Get Current Config Version ") + } + // Check if Config exists + cs := ConfigStore{ + instanceID: instanceID, + configName: configName, + } + currentConfig, err := cs.getConfig() + if err != nil { + return ConfigResult{}, pkgerrors.Wrap(err, "Update Error - Config doesn't exist") + } + // Create Result structure + cfgRes := ConfigResult{ + InstanceName: instanceID, + DefinitionName: rbName, + DefinitionVersion: rbVersion, + ProfileName: profileName, + ConfigName: configName, + TemplateName: currentConfig.TemplateName, + ConfigVersion: currentVersion, + } + return cfgRes, nil } // Tagit tags the current version with the tag provided -func (v *ConfigClient) Tagit(instanceID string, configName string, tag ConfigTagit) error { +func (v *ConfigClient) Tagit(instanceID string, configName string, tag ConfigTagit) (ConfigTag, error) { log.Printf("[Config Tag It] Instance %s Config %s", instanceID, configName) lock, _ := getProfileData(instanceID) // Acquire per profile Mutex @@ -459,9 +653,17 @@ func (v *ConfigClient) Tagit(instanceID string, configName string, tag ConfigTag } err := cvs.tagCurrentVersion(configName, tag.TagName) if err != nil { - return pkgerrors.Wrap(err, "Tag of current version failed") + return ConfigTag{}, pkgerrors.Wrap(err, "Tag of current version failed") } - return nil + currentVersion, err := cvs.getCurrentVersion(configName) + if err != nil { + return ConfigTag{}, pkgerrors.Wrap(err, "Rollback Get Current Config Version ") + } + + var tagResult = ConfigTag{} + tagResult.ConfigVersion = currentVersion + tagResult.ConfigTag = tag.TagName + return tagResult, nil } // GetTagVersion returns the version associated with the tag @@ -489,7 +691,11 @@ func (v *ConfigClient) Cleanup(instanceID string) error { } for _, config := range configs { - err = v.DeleteAll(instanceID, config.ConfigName) + _, err = v.Delete(instanceID, config.ConfigName) + if err != nil { + log.Printf("Config %s delete failed: %s", config.ConfigName, err.Error()) + } + err = v.DeleteAll(instanceID, config.ConfigName, true) if err != nil { log.Printf("Config %s delete failed: %s", config.ConfigName, err.Error()) } @@ -529,7 +735,7 @@ func (v *ConfigClient) ApplyAllConfig(instanceID string, configName string) erro if action != "DELETE" { resources = nil } - var appliedResources ([]helm.KubernetesResource) + var appliedResources ([]KubernetesConfigResource) appliedResources, err = applyConfig(instanceID, configNew, profileChannel, action, resources) if err != nil { return pkgerrors.Wrap(err, "Apply Config failed")