mirror of https://github.com/kubevela/kubevela.git
refactor: parse trait & scope (#6017)
Signed-off-by: yyzxw <1020938856@qq.com>
This commit is contained in:
parent
338703baf5
commit
3cb0f7b330
|
|
@ -96,7 +96,7 @@ type Workload struct {
|
|||
SkipApplyWorkload bool
|
||||
}
|
||||
|
||||
// EvalContext eval workload template and set result to context
|
||||
// EvalContext eval workload template and set the result to context
|
||||
func (wl *Workload) EvalContext(ctx process.Context) error {
|
||||
return wl.engine.Complete(ctx, wl.FullTemplate.TemplateStr, wl.Params)
|
||||
}
|
||||
|
|
@ -125,7 +125,7 @@ func (wl *Workload) EvalStatus(templateContext map[string]interface{}) (string,
|
|||
|
||||
// EvalHealth eval workload health check
|
||||
func (wl *Workload) EvalHealth(templateContext map[string]interface{}) (bool, error) {
|
||||
// if health of template is not set or standard workload is managed by trait always return true
|
||||
// if the health of template is not set or standard workload is managed by trait always return true
|
||||
if wl.SkipApplyWorkload {
|
||||
return true, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -582,22 +582,38 @@ func (p *Parser) parseWorkload(ctx context.Context, comp common.ApplicationCompo
|
|||
}
|
||||
workload.ExternalRevision = comp.ExternalRevision
|
||||
|
||||
if err = p.parseTraits(ctx, workload, comp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = p.parseScopes(ctx, workload, comp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return workload, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseTraits(ctx context.Context, workload *Workload, comp common.ApplicationComponent) error {
|
||||
for _, traitValue := range comp.Traits {
|
||||
properties, err := util.RawExtension2Map(traitValue.Properties)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, comp.Name)
|
||||
return errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, comp.Name)
|
||||
}
|
||||
trait, err := p.parseTrait(ctx, traitValue.Type, properties)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "component(%s) parse trait(%s)", comp.Name, traitValue.Type)
|
||||
return errors.WithMessagef(err, "component(%s) parse trait(%s)", comp.Name, traitValue.Type)
|
||||
}
|
||||
|
||||
workload.Traits = append(workload.Traits, trait)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseScopes(ctx context.Context, workload *Workload, comp common.ApplicationComponent) error {
|
||||
for scopeType, instanceName := range comp.Scopes {
|
||||
sd, gvk, err := GetScopeDefAndGVK(ctx, p.client, p.dm, scopeType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
workload.Scopes = append(workload.Scopes, Scope{
|
||||
Name: instanceName,
|
||||
|
|
@ -606,7 +622,7 @@ func (p *Parser) parseWorkload(ctx context.Context, comp common.ApplicationCompo
|
|||
})
|
||||
workload.ScopeDefinition = append(workload.ScopeDefinition, sd)
|
||||
}
|
||||
return workload, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseWorkloadFromRevision resolve an ApplicationComponent and generate a Workload
|
||||
|
|
@ -618,22 +634,38 @@ func (p *Parser) ParseWorkloadFromRevision(comp common.ApplicationComponent, app
|
|||
}
|
||||
workload.ExternalRevision = comp.ExternalRevision
|
||||
|
||||
if err = p.parseTraitsFromRevision(comp, appRev, workload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = p.parseScopesFromRevision(comp, appRev, workload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return workload, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseTraitsFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision, workload *Workload) error {
|
||||
for _, traitValue := range comp.Traits {
|
||||
properties, err := util.RawExtension2Map(traitValue.Properties)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, comp.Name)
|
||||
return errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, comp.Name)
|
||||
}
|
||||
trait, err := p.parseTraitFromRevision(traitValue.Type, properties, appRev)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "component(%s) parse trait(%s)", comp.Name, traitValue.Type)
|
||||
return errors.WithMessagef(err, "component(%s) parse trait(%s)", comp.Name, traitValue.Type)
|
||||
}
|
||||
|
||||
workload.Traits = append(workload.Traits, trait)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseScopesFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision, workload *Workload) error {
|
||||
for scopeType, instanceName := range comp.Scopes {
|
||||
sd, gvk, err := GetScopeDefAndGVKFromRevision(scopeType, appRev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
workload.Scopes = append(workload.Scopes, Scope{
|
||||
Name: instanceName,
|
||||
|
|
@ -642,7 +674,7 @@ func (p *Parser) ParseWorkloadFromRevision(comp common.ApplicationComponent, app
|
|||
})
|
||||
workload.ScopeDefinition = append(workload.ScopeDefinition, sd)
|
||||
}
|
||||
return workload, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseWorkloadFromRevisionAndClient resolve an ApplicationComponent and generate a Workload
|
||||
|
|
@ -728,7 +760,7 @@ func (p *Parser) convertTemplate2Trait(name string, properties map[string]interf
|
|||
}, nil
|
||||
}
|
||||
|
||||
// ValidateComponentNames validate all component name whether repeat in cluster and template
|
||||
// ValidateComponentNames validate all component names whether repeat in cluster and template
|
||||
func (p *Parser) ValidateComponentNames(app *v1beta1.Application) (int, error) {
|
||||
compNames := map[string]struct{}{}
|
||||
for idx, comp := range app.Spec.Components {
|
||||
|
|
@ -740,7 +772,7 @@ func (p *Parser) ValidateComponentNames(app *v1beta1.Application) (int, error) {
|
|||
return 0, nil
|
||||
}
|
||||
|
||||
// GetScopeDefAndGVK get grouped API version of the given scope
|
||||
// GetScopeDefAndGVK get grouped an API version of the given scope
|
||||
func GetScopeDefAndGVK(ctx context.Context, cli client.Reader, dm discoverymapper.DiscoveryMapper,
|
||||
name string) (*v1beta1.ScopeDefinition, metav1.GroupVersionKind, error) {
|
||||
var gvk metav1.GroupVersionKind
|
||||
|
|
|
|||
|
|
@ -21,17 +21,24 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/pkg/test"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/stretchr/testify/assert"
|
||||
errors2 "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
workflowv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
common2 "github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
|
|
@ -234,7 +241,7 @@ var _ = Describe("Test application parser", func() {
|
|||
err := yaml.Unmarshal([]byte(appfileYaml), &o)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
// Create mock client
|
||||
// Create a mock client
|
||||
tclient := test.MockClient{
|
||||
MockGet: func(ctx context.Context, key client.ObjectKey, obj client.Object) error {
|
||||
if strings.Contains(key.Name, "notexist") {
|
||||
|
|
@ -499,3 +506,362 @@ patch: spec: replicas: parameter.replicas
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
func TestParser_parseTraits(t *testing.T) {
|
||||
type args struct {
|
||||
workload *Workload
|
||||
comp common.ApplicationComponent
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
mockTemplateLoaderFn TemplateLoaderFn
|
||||
validateFunc func(w *Workload) bool
|
||||
}{
|
||||
{
|
||||
name: "test empty traits",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "test parse trait properties error",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Traits: []common.ApplicationTrait{
|
||||
{
|
||||
Type: "expose",
|
||||
Properties: &runtime.RawExtension{
|
||||
Raw: []byte("invalid properties"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "test parse trait error",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Traits: []common.ApplicationTrait{
|
||||
{
|
||||
Type: "expose",
|
||||
Properties: &runtime.RawExtension{
|
||||
Raw: []byte(`{"unsupported": "{\"key\":\"value\"}"}`),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
mockTemplateLoaderFn: func(context.Context, discoverymapper.DiscoveryMapper, client.Reader, string, types.CapType) (*Template, error) {
|
||||
return nil, fmt.Errorf("unsupported key not found")
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "test parse trait success",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Traits: []common.ApplicationTrait{
|
||||
{
|
||||
Type: "expose",
|
||||
Properties: &runtime.RawExtension{
|
||||
Raw: []byte(`{"annotation": "{\"key\":\"value\"}"}`),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
mockTemplateLoaderFn: func(ctx context.Context, mapper discoverymapper.DiscoveryMapper, reader client.Reader, s string, capType types.CapType) (*Template, error) {
|
||||
return &Template{
|
||||
TemplateStr: "template",
|
||||
CapabilityCategory: "network",
|
||||
Health: "true",
|
||||
CustomStatus: "healthy",
|
||||
}, nil
|
||||
},
|
||||
validateFunc: func(w *Workload) bool {
|
||||
return w != nil && len(w.Traits) != 0 && w.Traits[0].Name == "expose" && w.Traits[0].Template == "template"
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
p := NewApplicationParser(nil, dm, pd)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p.tmplLoader = tt.mockTemplateLoaderFn
|
||||
err := p.parseTraits(context.Background(), tt.args.workload, tt.args.comp)
|
||||
tt.wantErr(t, err, fmt.Sprintf("parseTraits(%v, %v)", tt.args.workload, tt.args.comp))
|
||||
if tt.validateFunc != nil {
|
||||
assert.True(t, tt.validateFunc(tt.args.workload))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParser_parseScopes(t *testing.T) {
|
||||
type args struct {
|
||||
workload *Workload
|
||||
comp common.ApplicationComponent
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
mockTemplateLoaderFn TemplateLoaderFn
|
||||
mockGetFunc test.MockGetFn
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
validateFunc func(w *Workload) bool
|
||||
}{
|
||||
{
|
||||
name: "test empty scope",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{},
|
||||
workload: &Workload{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
validateFunc: func(w *Workload) bool {
|
||||
return w != nil && len(w.Scopes) == 0
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test get gvk error",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Scopes: map[string]string{
|
||||
"cluster1": "namespace1",
|
||||
"cluster2": "namespace2",
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
},
|
||||
mockGetFunc: func(ctx context.Context, key client.ObjectKey, obj client.Object) error {
|
||||
return fmt.Errorf("not exist")
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "test parse scopes success",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Scopes: map[string]string{
|
||||
"cluster1": "namespace1",
|
||||
"cluster2": "namespace2",
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
},
|
||||
mockGetFunc: func(ctx context.Context, key client.ObjectKey, obj client.Object) error {
|
||||
return nil
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
validateFunc: func(w *Workload) bool {
|
||||
return w != nil && len(w.Scopes) == 2 && w.Scopes[0].Name == "namespace1" && w.Scopes[1].Name == "namespace2"
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := NewApplicationParser(&test.MockClient{MockGet: tt.mockGetFunc}, dm, pd)
|
||||
p.tmplLoader = tt.mockTemplateLoaderFn
|
||||
err := p.parseScopes(context.Background(), tt.args.workload, tt.args.comp)
|
||||
if !tt.wantErr(t, err, fmt.Sprintf("parseScopes(%v, %v)", tt.args.workload, tt.args.comp)) {
|
||||
return
|
||||
}
|
||||
if tt.validateFunc != nil {
|
||||
assert.True(t, tt.validateFunc(tt.args.workload))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParser_parseTraitsFromRevision(t *testing.T) {
|
||||
type args struct {
|
||||
comp common.ApplicationComponent
|
||||
appRev *v1beta1.ApplicationRevision
|
||||
workload *Workload
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
validateFunc func(w *Workload) bool
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "test empty traits",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "test parse traits properties error",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Traits: []common.ApplicationTrait{
|
||||
{
|
||||
Type: "expose",
|
||||
Properties: &runtime.RawExtension{Raw: []byte("invalid")},
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "test parse traits from revision failed",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Traits: []common.ApplicationTrait{
|
||||
{
|
||||
Type: "expose",
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"appRevisionName": "appRevName"}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
appRev: &v1beta1.ApplicationRevision{
|
||||
Spec: v1beta1.ApplicationRevisionSpec{
|
||||
ApplicationRevisionCompressibleFields: v1beta1.ApplicationRevisionCompressibleFields{
|
||||
TraitDefinitions: map[string]*v1beta1.TraitDefinition{},
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "test parse traits from revision success",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Traits: []common.ApplicationTrait{
|
||||
{
|
||||
Type: "expose",
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"appRevisionName": "appRevName"}`)},
|
||||
},
|
||||
},
|
||||
},
|
||||
appRev: &v1beta1.ApplicationRevision{
|
||||
Spec: v1beta1.ApplicationRevisionSpec{
|
||||
ApplicationRevisionCompressibleFields: v1beta1.ApplicationRevisionCompressibleFields{
|
||||
TraitDefinitions: map[string]*v1beta1.TraitDefinition{
|
||||
"expose": {
|
||||
Spec: v1beta1.TraitDefinitionSpec{
|
||||
RevisionEnabled: true,
|
||||
AppliesToWorkloads: []string{"*"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
validateFunc: func(w *Workload) bool {
|
||||
return w != nil && len(w.Traits) == 1 && w.Traits[0].Name == "expose"
|
||||
},
|
||||
},
|
||||
}
|
||||
p := NewApplicationParser(nil, dm, pd)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.wantErr(t, p.parseTraitsFromRevision(tt.args.comp, tt.args.appRev, tt.args.workload), fmt.Sprintf("parseTraitsFromRevision(%v, %v, %v)", tt.args.comp, tt.args.appRev, tt.args.workload))
|
||||
if tt.validateFunc != nil {
|
||||
assert.True(t, tt.validateFunc(tt.args.workload))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParser_parseScopesFromRevision(t *testing.T) {
|
||||
type args struct {
|
||||
comp common.ApplicationComponent
|
||||
appRev *v1beta1.ApplicationRevision
|
||||
workload *Workload
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
validateFunc func(w *Workload) bool
|
||||
}{
|
||||
{
|
||||
name: "test empty scopes",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "test get scope definition from revision failed",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Scopes: map[string]string{
|
||||
"cluster": "namespace",
|
||||
},
|
||||
},
|
||||
appRev: &v1beta1.ApplicationRevision{
|
||||
Spec: v1beta1.ApplicationRevisionSpec{
|
||||
ApplicationRevisionCompressibleFields: v1beta1.ApplicationRevisionCompressibleFields{
|
||||
ScopeDefinitions: map[string]v1beta1.ScopeDefinition{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "test parse scopes from revision success",
|
||||
args: args{
|
||||
comp: common.ApplicationComponent{
|
||||
Scopes: map[string]string{
|
||||
"cluster": "namespace",
|
||||
},
|
||||
},
|
||||
appRev: &v1beta1.ApplicationRevision{
|
||||
Spec: v1beta1.ApplicationRevisionSpec{
|
||||
ApplicationRevisionCompressibleFields: v1beta1.ApplicationRevisionCompressibleFields{
|
||||
ScopeDefinitions: map[string]v1beta1.ScopeDefinition{
|
||||
"cluster": {
|
||||
Spec: v1beta1.ScopeDefinitionSpec{
|
||||
AllowComponentOverlap: true,
|
||||
Reference: common.DefinitionReference{
|
||||
Name: "cluster",
|
||||
Version: "v1alpha2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ScopeGVK: map[string]metav1.GroupVersionKind{
|
||||
"cluster/v1alpha2": {
|
||||
Group: "core.oam.dev",
|
||||
Version: "v1alpha2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
validateFunc: func(w *Workload) bool {
|
||||
return w != nil && len(w.Scopes) == 1 && w.Scopes[0].ResourceVersion == "cluster/v1alpha2"
|
||||
},
|
||||
},
|
||||
}
|
||||
p := NewApplicationParser(nil, dm, pd)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt.wantErr(t, p.parseScopesFromRevision(tt.args.comp, tt.args.appRev, tt.args.workload), fmt.Sprintf("parseScopesFromRevision(%v, %v, %v)", tt.args.comp, tt.args.appRev, tt.args.workload))
|
||||
if tt.validateFunc != nil {
|
||||
assert.True(t, tt.validateFunc(tt.args.workload))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ type Template struct {
|
|||
// processing.
|
||||
func LoadTemplate(ctx context.Context, dm discoverymapper.DiscoveryMapper, cli client.Reader, capName string, capType types.CapType) (*Template, error) {
|
||||
ctx = multicluster.WithCluster(ctx, multicluster.Local)
|
||||
// Application Controller only load template from ComponentDefinition and TraitDefinition
|
||||
// Application Controller only loads template from ComponentDefinition and TraitDefinition
|
||||
switch capType {
|
||||
case types.TypeComponentDefinition, types.TypeWorkload:
|
||||
cd := new(v1beta1.ComponentDefinition)
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ func GetDefinitionNamespaceWithCtx(ctx context.Context) string {
|
|||
}
|
||||
|
||||
// SetNamespaceInCtx set app namespace in context,
|
||||
// Sometimes webhook handler may receive request that appNs is empty string, and will cause error when search definition
|
||||
// Sometimes webhook handler may receive a request that appNs is empty string, and will cause error when search definition
|
||||
// So if namespace is empty, it will use `default` namespace by default.
|
||||
func SetNamespaceInCtx(ctx context.Context, namespace string) context.Context {
|
||||
if namespace == "" {
|
||||
|
|
@ -302,18 +302,23 @@ func GetDefinition(ctx context.Context, cli client.Reader, definition client.Obj
|
|||
appNs := GetDefinitionNamespaceWithCtx(ctx)
|
||||
if err := cli.Get(ctx, types.NamespacedName{Name: definitionName, Namespace: appNs}, definition); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
if err = cli.Get(ctx, types.NamespacedName{Name: definitionName, Namespace: oam.SystemDefinitionNamespace}, definition); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
// compatibility code for old clusters those definition crd is cluster scope
|
||||
var newErr error
|
||||
if newErr = cli.Get(ctx, types.NamespacedName{Name: definitionName}, definition); checkRequestNamespaceError(newErr) {
|
||||
return err
|
||||
}
|
||||
return newErr
|
||||
}
|
||||
return GetDefinitionFromNamespace(ctx, cli, definition, definitionName, oam.SystemDefinitionNamespace)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDefinitionFromNamespace get definition from namespace.
|
||||
func GetDefinitionFromNamespace(ctx context.Context, cli client.Reader, definition client.Object, definitionName, namespace string) error {
|
||||
if err := cli.Get(ctx, types.NamespacedName{Name: definitionName, Namespace: namespace}, definition); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
// compatibility code for old clusters those definition crd is cluster scope
|
||||
var newErr error
|
||||
if newErr = cli.Get(ctx, types.NamespacedName{Name: definitionName}, definition); checkRequestNamespaceError(newErr) {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
return newErr
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -383,7 +388,7 @@ func ConvertDefinitionRevName(definitionName string) (string, error) {
|
|||
return defRevName, nil
|
||||
}
|
||||
|
||||
// when get a namespaced scope object without namespace, would get an error request namespace
|
||||
// when get a namespaced scope object without namespace, would get an error request namespace
|
||||
func checkRequestNamespaceError(err error) bool {
|
||||
return err != nil && err.Error() == "an empty namespace may not be set when a resource name is provided"
|
||||
}
|
||||
|
|
@ -461,7 +466,7 @@ func EndReconcileWithNegativeCondition(ctx context.Context, r client.StatusClien
|
|||
return errors.Errorf(ErrReconcileErrInCondition, condition[0].Type, condition[0].Message)
|
||||
}
|
||||
|
||||
// PatchCondition will patch status with condition and return, it generally used by cases which don't want reconcile after patch
|
||||
// PatchCondition will patch status with condition and return, it generally used by cases which don't want to reconcile after patch
|
||||
func PatchCondition(ctx context.Context, r client.StatusClient, workload ConditionedObject,
|
||||
condition ...condition.Condition) error {
|
||||
if len(condition) == 0 {
|
||||
|
|
@ -472,7 +477,7 @@ func PatchCondition(ctx context.Context, r client.StatusClient, workload Conditi
|
|||
return r.Status().Patch(ctx, workload, workloadPatch, client.FieldOwner(workload.GetUID()))
|
||||
}
|
||||
|
||||
// IsConditionChanged will check if conditions in workload is changed compare to newCondition
|
||||
// IsConditionChanged will check if conditions in workload are changed compare to newCondition
|
||||
func IsConditionChanged(newCondition []condition.Condition, workload ConditionedObject) bool {
|
||||
var conditionIsChanged bool
|
||||
for _, newCond := range newCondition {
|
||||
|
|
|
|||
Loading…
Reference in New Issue