mirror of
https://github.com/kubevela/kubevela.git
synced 2026-05-09 02:47:04 +00:00
* Refactor: use createOrUpdateNamespace as a common util function
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Feat: add ENV webservice handelr
* Fix: fix Env usecase logic
* Feat: Add Delete Env API
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: filter empty addon data
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Feat: split makefiels and make it clear
* Feat: add k8s utils test
* Feat: Add env update interface
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Feat: change env implementation
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Fix: minor fix
* Revert "Fix: minor fix"
This reverts commit 9cafefa65a.
* Fix: use appusecase as parameter
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Refactor: align CLI vela env with new env design
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: minor fix
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Feat: add page index and alias of env
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: fix tests and licence header
* Fix: fix makefile and add default target
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: update build swagger.json
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: change update env api
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Feat: list env with alias
* Feat: add log to env delete
* Fix: can not get app status
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Feat: support update workflow and refactor code
* Fix: lint
* Fix: remove swagger check
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: fix cli vela delete
* Fix: update test
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: update test
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
* Fix: app deploy unit test case
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Fix: SortOrderDescending is not effective
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Fix: e2e test case
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Feat: support default project/target/env
* Fix: make test and add swagger
* Fix: use separated datasource for unit test
* Fix: app rollback bug
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Fix: fix e2e test
* Fix: kubeapi driver sort bug
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Fix: e2e test
* Fix: api e2e test
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
* Fix: e2e test fix
* Fix: try fix e2e test
* Fix: api e2e test
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
188 lines
5.8 KiB
Go
188 lines
5.8 KiB
Go
/*
|
|
Copyright 2021 The KubeVela Authors.
|
|
|
|
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 envbinding
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/imdario/mergo"
|
|
"github.com/pkg/errors"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
|
"github.com/oam-dev/kubevela/pkg/oam/util"
|
|
errors2 "github.com/oam-dev/kubevela/pkg/utils/errors"
|
|
)
|
|
|
|
// MergeRawExtension merge two raw extension
|
|
func MergeRawExtension(base *runtime.RawExtension, patch *runtime.RawExtension) (*runtime.RawExtension, error) {
|
|
patchParameter, err := util.RawExtension2Map(patch)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to convert patch parameters to map")
|
|
}
|
|
baseParameter, err := util.RawExtension2Map(base)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to convert base parameters to map")
|
|
}
|
|
if baseParameter == nil {
|
|
baseParameter = make(map[string]interface{})
|
|
}
|
|
err = mergo.Merge(&baseParameter, patchParameter, mergo.WithOverride)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to do merge with override")
|
|
}
|
|
bs, err := json.Marshal(baseParameter)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to marshal merged properties")
|
|
}
|
|
return &runtime.RawExtension{Raw: bs}, nil
|
|
}
|
|
|
|
// MergeComponent merge two component, it will first merge their properties and then merge their traits
|
|
func MergeComponent(base *common.ApplicationComponent, patch *v1alpha1.EnvComponentPatch) (*common.ApplicationComponent, error) {
|
|
newComponent := base.DeepCopy()
|
|
var err error
|
|
|
|
// merge component properties
|
|
newComponent.Properties, err = MergeRawExtension(base.Properties, patch.Properties)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed to merge component properties")
|
|
}
|
|
|
|
// prepare traits
|
|
traitMaps := map[string]*common.ApplicationTrait{}
|
|
var traitOrders []string
|
|
for _, trait := range base.Traits {
|
|
traitMaps[trait.Type] = trait.DeepCopy()
|
|
traitOrders = append(traitOrders, trait.Type)
|
|
}
|
|
|
|
// patch traits
|
|
var errs errors2.ErrorList
|
|
for _, trait := range patch.Traits {
|
|
if baseTrait, exists := traitMaps[trait.Type]; exists {
|
|
if trait.Disable {
|
|
delete(traitMaps, trait.Type)
|
|
continue
|
|
}
|
|
baseTrait.Properties, err = MergeRawExtension(baseTrait.Properties, trait.Properties)
|
|
if err != nil {
|
|
errs = append(errs, errors.Wrapf(err, "failed to merge trait %s", trait.Type))
|
|
}
|
|
} else {
|
|
if trait.Disable {
|
|
continue
|
|
}
|
|
traitMaps[trait.Type] = trait.ToApplicationTrait()
|
|
traitOrders = append(traitOrders, trait.Type)
|
|
}
|
|
}
|
|
if errs.HasError() {
|
|
return nil, errors.Wrapf(err, "failed to merge component traits")
|
|
}
|
|
|
|
// fill in traits
|
|
newComponent.Traits = []common.ApplicationTrait{}
|
|
for _, traitType := range traitOrders {
|
|
if _, exists := traitMaps[traitType]; exists {
|
|
newComponent.Traits = append(newComponent.Traits, *traitMaps[traitType])
|
|
}
|
|
}
|
|
return newComponent, nil
|
|
}
|
|
|
|
func filterComponents(components []string, selector *v1alpha1.EnvSelector) []string {
|
|
if selector != nil {
|
|
filter := map[string]bool{}
|
|
for _, compName := range selector.Components {
|
|
filter[compName] = true
|
|
}
|
|
var _comps []string
|
|
for _, compName := range components {
|
|
if _, ok := filter[compName]; ok {
|
|
_comps = append(_comps, compName)
|
|
}
|
|
}
|
|
return _comps
|
|
}
|
|
return components
|
|
}
|
|
|
|
// PatchApplication patch base application with patch and selector
|
|
func PatchApplication(base *v1beta1.Application, patch *v1alpha1.EnvPatch, selector *v1alpha1.EnvSelector) (*v1beta1.Application, error) {
|
|
newApp := base.DeepCopy()
|
|
|
|
// init components
|
|
compMaps := map[string]*common.ApplicationComponent{}
|
|
var compOrders []string
|
|
for _, comp := range base.Spec.Components {
|
|
compMaps[comp.Name] = comp.DeepCopy()
|
|
compOrders = append(compOrders, comp.Name)
|
|
}
|
|
|
|
// patch components
|
|
var errs errors2.ErrorList
|
|
var err error
|
|
for _, comp := range patch.Components {
|
|
if baseComp, exists := compMaps[comp.Name]; exists {
|
|
if baseComp.Type != comp.Type {
|
|
compMaps[comp.Name] = comp.ToApplicationComponent()
|
|
} else {
|
|
compMaps[comp.Name], err = MergeComponent(baseComp, comp.DeepCopy())
|
|
if err != nil {
|
|
errs = append(errs, errors.Wrapf(err, "failed to merge component %s", comp.Name))
|
|
}
|
|
}
|
|
} else {
|
|
compMaps[comp.Name] = comp.ToApplicationComponent()
|
|
compOrders = append(compOrders, comp.Name)
|
|
}
|
|
}
|
|
if errs.HasError() {
|
|
return nil, errors.Wrapf(err, "failed to merge application components")
|
|
}
|
|
newApp.Spec.Components = []common.ApplicationComponent{}
|
|
|
|
// if selector is enabled, filter
|
|
compOrders = filterComponents(compOrders, selector)
|
|
|
|
// fill in new application
|
|
for _, compName := range compOrders {
|
|
newApp.Spec.Components = append(newApp.Spec.Components, *compMaps[compName])
|
|
}
|
|
return newApp, nil
|
|
}
|
|
|
|
// PatchApplicationByEnvBindingEnv get patched application directly through policyName and envName
|
|
func PatchApplicationByEnvBindingEnv(app *v1beta1.Application, policyName string, envName string) (*v1beta1.Application, error) {
|
|
policy, err := GetEnvBindingPolicy(app, policyName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if policy != nil {
|
|
for _, env := range policy.Envs {
|
|
if env.Name == envName {
|
|
return PatchApplication(app, &env.Patch, env.Selector)
|
|
}
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("target env %s in policy %s not found", envName, policyName)
|
|
}
|