diff options
author | Lukasz Rajewski <lukasz.rajewski@orange.com> | 2022-02-03 19:18:07 +0100 |
---|---|---|
committer | Lukasz Rajewski <lukasz.rajewski@orange.com> | 2022-02-23 14:27:01 +0100 |
commit | 88ecb1f9dfeded36e7fd74c776daefcaf67f8ae2 (patch) | |
tree | 321eb34967dd32a43d7e3ac62b5fd664e5b2231b /src/k8splugin/internal/app/config_backend.go | |
parent | 1f92a0ec4ea037089b82e3f80bb030f34fab64f0 (diff) |
ConfigAPI and Query API improvements
- Config Template create from the definition content
- Missing CRUD Config handlers added
- Improved Rollback and Config delete
- Query API name filtering improved
Issue-ID: MULTICLOUD-1437
Signed-off-by: Lukasz Rajewski <lukasz.rajewski@orange.com>
Change-Id: Iec8ec6d03746085f294d9318a252f1ae45d3b9c8
Diffstat (limited to 'src/k8splugin/internal/app/config_backend.go')
-rw-r--r-- | src/k8splugin/internal/app/config_backend.go | 194 |
1 files changed, 130 insertions, 64 deletions
diff --git a/src/k8splugin/internal/app/config_backend.go b/src/k8splugin/internal/app/config_backend.go index c365363f..4dcbeb57 100644 --- a/src/k8splugin/internal/app/config_backend.go +++ b/src/k8splugin/internal/app/config_backend.go @@ -38,10 +38,10 @@ import ( //ConfigStore contains the values that will be stored in the database type configVersionDBContent struct { - ConfigNew Config `json:"config-new"` - ConfigPrev Config `json:"config-prev"` - Action string `json:"action"` // CRUD opration for this config - Resources []helm.KubernetesResource `json:"resources"` + ConfigNew Config `json:"config-new"` + ConfigPrev Config `json:"config-prev"` + Action string `json:"action"` // CRUD opration for this config + Resources []KubernetesConfigResource `json:"resources"` } //ConfigStore to Store the Config @@ -56,10 +56,15 @@ type ConfigVersionStore struct { configName string } +type KubernetesConfigResource struct { + Resource helm.KubernetesResource `json:"resource"` + Status string `json:"status"` +} + type configResourceList struct { resourceTemplates []helm.KubernetesResourceTemplate - resources []helm.KubernetesResource - updatedResources chan []helm.KubernetesResource + resources []KubernetesConfigResource + updatedResources chan []KubernetesConfigResource profile rb.Profile action string } @@ -181,7 +186,7 @@ func (c ConfigStore) getConfigList() ([]Config, error) { return []Config{}, pkgerrors.Wrap(err, "Retrieving model info") } cfgKey := constructKey(rbName, rbVersion, profileName, c.instanceID, tagConfig) - values, err := db.Etcd.GetAll(cfgKey) + values, err := db.Etcd.GetValues(cfgKey) if err != nil { return []Config{}, pkgerrors.Wrap(err, "Get Config DB List") } @@ -194,6 +199,9 @@ func (c ConfigStore) getConfigList() ([]Config, error) { if err != nil { return []Config{}, pkgerrors.Wrap(err, "Unmarshaling Config Value") } + if cfg.ConfigName == "" { + continue + } result = append(result, cfg) } return result, nil @@ -256,7 +264,7 @@ func (c ConfigVersionStore) cleanupIstanceTags(configName string) error { } // Create a version for the configuration. If previous config provided that is also stored -func (c ConfigVersionStore) createConfigVersion(configNew, configPrev Config, action string, resources []helm.KubernetesResource) (uint, error) { +func (c ConfigVersionStore) createConfigVersion(configNew, configPrev Config, action string, resources []KubernetesConfigResource) (uint, error) { configName := "" if configNew.ConfigName != "" { @@ -281,7 +289,7 @@ func (c ConfigVersionStore) createConfigVersion(configNew, configPrev Config, ac cs.Action = action cs.ConfigNew = configNew cs.ConfigPrev = configPrev - cs.Resources = resources //[]helm.KubernetesResource{} + cs.Resources = resources //[]KubernetesConfigResource{} configValue, err := db.Serialize(cs) if err != nil { @@ -321,27 +329,27 @@ func (c ConfigVersionStore) deleteConfigVersion(configName string) error { // Read the specified version of the configuration and return its prev and current value. // Also returns the action for the config version -func (c ConfigVersionStore) getConfigVersion(configName string, version uint) (Config, Config, string, []helm.KubernetesResource, error) { +func (c ConfigVersionStore) getConfigVersion(configName string, version uint) (Config, Config, string, []KubernetesConfigResource, error) { rbName, rbVersion, profileName, _, err := resolveModelFromInstance(c.instanceID) if err != nil { - return Config{}, Config{}, "", []helm.KubernetesResource{}, pkgerrors.Wrap(err, "Retrieving model info") + return Config{}, Config{}, "", []KubernetesConfigResource{}, pkgerrors.Wrap(err, "Retrieving model info") } versionKey := constructKey(rbName, rbVersion, profileName, c.instanceID, tagVersion, configName, strconv.Itoa(int(version))) configBytes, err := db.Etcd.Get(versionKey) if err != nil { - return Config{}, Config{}, "", []helm.KubernetesResource{}, pkgerrors.Wrap(err, "Get Config Version ") + return Config{}, Config{}, "", []KubernetesConfigResource{}, pkgerrors.Wrap(err, "Get Config Version ") } if configBytes != nil { pr := configVersionDBContent{} err = db.DeSerialize(string(configBytes), &pr) if err != nil { - return Config{}, Config{}, "", []helm.KubernetesResource{}, pkgerrors.Wrap(err, "DeSerialize Config Version") + return Config{}, Config{}, "", []KubernetesConfigResource{}, pkgerrors.Wrap(err, "DeSerialize Config Version") } return pr.ConfigNew, pr.ConfigPrev, pr.Action, pr.Resources, nil } - return Config{}, Config{}, "", []helm.KubernetesResource{}, pkgerrors.Wrap(err, "Invalid data ") + return Config{}, Config{}, "", []KubernetesConfigResource{}, pkgerrors.Wrap(err, "Invalid data ") } // Get the counter for the version @@ -419,6 +427,25 @@ func (c ConfigVersionStore) decrementVersion(configName string) error { return nil } +// Get tag list +func (c ConfigVersionStore) getTagList(configName string) ([]string, error) { + rbName, rbVersion, profileName, _, err := resolveModelFromInstance(c.instanceID) + if err != nil { + return []string{}, pkgerrors.Wrap(err, "Retrieving model info") + } + tagKey := constructKey(rbName, rbVersion, profileName, c.instanceID, tagName, configName) + + tagKeyList, err := db.Etcd.GetKeys(tagKey) + if err != nil { + return []string{}, pkgerrors.Wrap(err, "Config DB Entry Not found") + } + result := make([]string, 0) + for _, tag := range tagKeyList { + result = append(result, tag[len(tagKey):len(tag)-1]) + } + return result, nil +} + // Get tag version func (c ConfigVersionStore) getTagVersion(configName, tagNameValue string) (string, error) { rbName, rbVersion, profileName, _, err := resolveModelFromInstance(c.instanceID) @@ -444,28 +471,44 @@ func (c ConfigVersionStore) tagCurrentVersion(configName, tagNameValue string) e if err != nil { return pkgerrors.Wrap(err, "Retrieving model info") } + currentConfig, _, _, _, err := c.getConfigVersion(configName, currentVersion) + if err != nil { + return pkgerrors.Wrap(err, "Retrieving current configuration") + } + tagKey := constructKey(rbName, rbVersion, profileName, c.instanceID, tagName, configName, tagNameValue) err = db.Etcd.Put(tagKey, strconv.Itoa(int(currentVersion))) if err != nil { return pkgerrors.Wrap(err, "TagIt store DB") } + + currentConfig.ConfigTag = tagNameValue + configValue, err := db.Serialize(currentConfig) + if err != nil { + return pkgerrors.Wrap(err, "Serialize Config Value") + } + cfgKey := constructKey(rbName, rbVersion, profileName, c.instanceID, tagConfig, configName) + err = db.Etcd.Put(cfgKey, configValue) + if err != nil { + return pkgerrors.Wrap(err, "Config DB Entry") + } return nil } // Apply Config -func applyConfig(instanceID string, p Config, pChannel chan configResourceList, action string, resources []helm.KubernetesResource) ([]helm.KubernetesResource, error) { +func applyConfig(instanceID string, p Config, pChannel chan configResourceList, action string, resources []KubernetesConfigResource) ([]KubernetesConfigResource, error) { rbName, rbVersion, profileName, releaseName, err := resolveModelFromInstance(instanceID) if err != nil { - return []helm.KubernetesResource{}, pkgerrors.Wrap(err, "Retrieving model info") + return []KubernetesConfigResource{}, pkgerrors.Wrap(err, "Retrieving model info") } // Get Template and Resolve the template with values crl, err := resolve(rbName, rbVersion, profileName, instanceID, p, releaseName) if err != nil { - return []helm.KubernetesResource{}, pkgerrors.Wrap(err, "Resolve Config") + return []KubernetesConfigResource{}, pkgerrors.Wrap(err, "Resolve Config") } - var updatedResources (chan []helm.KubernetesResource) = make(chan []helm.KubernetesResource) + var updatedResources (chan []KubernetesConfigResource) = make(chan []KubernetesConfigResource) crl.action = action crl.resources = resources crl.updatedResources = updatedResources @@ -477,7 +520,7 @@ func applyConfig(instanceID string, p Config, pChannel chan configResourceList, default: } - var resultResources []helm.KubernetesResource = <-updatedResources + var resultResources []KubernetesConfigResource = <-updatedResources return resultResources, nil } @@ -492,14 +535,14 @@ func scheduleResources(c chan configResourceList) { resp, err := ic.Find(data.profile.RBName, data.profile.RBVersion, data.profile.ProfileName, nil) if (err != nil || len(resp) == 0) && data.action != "STOP" { log.Println("Error finding a running instance. Retrying later...") - data.updatedResources <- []helm.KubernetesResource{} + data.updatedResources <- []KubernetesConfigResource{} continue } breakThread := false switch { - case data.action == "POST": - log.Printf("[scheduleResources]: POST %v %v", data.profile, data.resourceTemplates) - var resources []helm.KubernetesResource + case data.action == "PUT" || data.action == "POST": + log.Printf("[scheduleResources]: %v %v %v", data.action, data.profile, data.resourceTemplates) + resources := []KubernetesConfigResource{} for _, inst := range resp { k8sClient := KubernetesClient{} err = k8sClient.Init(inst.Request.CloudRegion, inst.ID) @@ -508,36 +551,30 @@ func scheduleResources(c chan configResourceList) { //Move onto the next cloud region continue } - //assuming - the resource is not exist already - resources, err = k8sClient.createResources(data.resourceTemplates, inst.Namespace) - errCreate := err - if err != nil { - // assuming - the err represent the resource is already exist, so going for update - resources, err = k8sClient.updateResources(data.resourceTemplates, inst.Namespace) + for _, res := range data.resourceTemplates { + var resToCreateOrUpdate = []helm.KubernetesResourceTemplate{res} + resProceeded, err := k8sClient.createResources(resToCreateOrUpdate, inst.Namespace) + errCreate := err + var status string = "" if err != nil { - log.Printf("Error Creating resources: %s", errCreate.Error()) - log.Printf("Error Updating resources: %s", err.Error()) - continue + // assuming - the err represent the resource already exist, so going for update + resProceeded, err = k8sClient.updateResources(resToCreateOrUpdate, inst.Namespace) + if err != nil { + log.Printf("Error Creating resources: %s", errCreate.Error()) + log.Printf("Error Updating resources: %s", err.Error()) + break + } else { + status = "UPDATED" + } + } else { + status = "CREATED" + } + for _, resCreated := range resProceeded { + resource := KubernetesConfigResource{} + resource.Resource = resCreated + resource.Status = status + resources = append(resources, resource) } - } - } - data.updatedResources <- resources - case data.action == "PUT": - log.Printf("[scheduleResources]: PUT %v %v", data.profile, data.resourceTemplates) - var resources []helm.KubernetesResource - for _, inst := range resp { - k8sClient := KubernetesClient{} - err = k8sClient.Init(inst.Request.CloudRegion, inst.ID) - if err != nil { - log.Printf("Getting CloudRegion Information: %s", err.Error()) - //Move onto the next cloud region - continue - } - - resources, err = k8sClient.updateResources(data.resourceTemplates, inst.Namespace) - if err != nil { - log.Printf("Error Updating resources: %s", err.Error()) - continue } } data.updatedResources <- resources @@ -551,13 +588,17 @@ func scheduleResources(c chan configResourceList) { //Move onto the next cloud region continue } - err = k8sClient.deleteResources(helm.GetReverseK8sResources(data.resources), inst.Namespace) + var tmpResources []helm.KubernetesResource = []helm.KubernetesResource{} + for _, res := range data.resources { + tmpResources = append(tmpResources, res.Resource) + } + err = k8sClient.deleteResources(helm.GetReverseK8sResources(tmpResources), inst.Namespace) if err != nil { log.Printf("Error Deleting resources: %s", err.Error()) continue } } - data.updatedResources <- []helm.KubernetesResource{} + data.updatedResources <- []KubernetesConfigResource{} case data.action == "STOP": breakThread = true @@ -581,17 +622,40 @@ var resolve = func(rbName, rbVersion, profileName, instanceId string, p Config, return configResourceList{}, pkgerrors.Wrap(err, "Reading Profile Data") } - t, err := rb.NewConfigTemplateClient().Get(rbName, rbVersion, p.TemplateName) - if err != nil { - return configResourceList{}, pkgerrors.Wrap(err, "Getting Template") - } - if t.ChartName == "" { - return configResourceList{}, pkgerrors.New("Invalid template no Chart.yaml file found") + var t rb.ConfigTemplate + if p.TemplateName == "" && p.ConfigName == "" { + //for rollback to base definition + t = rb.ConfigTemplate{} + t.HasContent = false + } else { + t, err = rb.NewConfigTemplateClient().Get(rbName, rbVersion, p.TemplateName) + if err != nil { + return configResourceList{}, pkgerrors.Wrap(err, "Getting Template") + } + if t.ChartName == "" { + return configResourceList{}, pkgerrors.New("Invalid template no Chart.yaml file found") + } } - def, err := rb.NewConfigTemplateClient().Download(rbName, rbVersion, p.TemplateName) - if err != nil { - return configResourceList{}, pkgerrors.Wrap(err, "Downloading Template") + var def []byte + + if t.HasContent { + def, err = rb.NewConfigTemplateClient().Download(rbName, rbVersion, p.TemplateName) + if err != nil { + return configResourceList{}, pkgerrors.Wrap(err, "Downloading Template") + } + } else { + log.Printf("Using Definition Template as a Configuration Template") + defClient := rb.NewDefinitionClient() + definition, err := defClient.Get(rbName, rbVersion) + if err != nil { + return configResourceList{}, pkgerrors.Wrap(err, "Get RB Definition") + } + def, err = defClient.Download(rbName, rbVersion) + if err != nil { + return configResourceList{}, pkgerrors.Wrap(err, "Downloading RB Definition Template") + } + t.ChartName = definition.ChartName } ic := NewInstanceClient() @@ -625,8 +689,10 @@ var resolve = func(rbName, rbVersion, profileName, instanceId string, p Config, return configResourceList{}, pkgerrors.Wrap(err, "Processing values") } - for k, v := range p.Values { - rawValues[k] = v + if p.Values != nil { + for k, v := range p.Values { + rawValues[k] = v + } } //Create a temp file in the system temp folder for values input b, err := json.Marshal(rawValues) |