diff --git a/apis/core.oam.dev/v1alpha2/appdeploy_types.go b/apis/core.oam.dev/v1alpha2/appdeploy_types.go index 9a9901562..280d02a52 100644 --- a/apis/core.oam.dev/v1alpha2/appdeploy_types.go +++ b/apis/core.oam.dev/v1alpha2/appdeploy_types.go @@ -29,8 +29,8 @@ type ApplicationDeploymentSpec struct { TargetApplicationName string `json:"targetApplicationName"` // SourceApplicationName contains the name of the application that we need to upgrade from. - // it can be omitted only when it's the first time to deploy the application - SourceApplicationName *string `json:"sourceApplicationName,omitempty"` + // it can be empty only when it's the first time to deploy the application + SourceApplicationName string `json:"sourceApplicationName"` // The list of component to upgrade in the application. // We only support single component application so far diff --git a/apis/core.oam.dev/v1alpha2/zz_generated.deepcopy.go b/apis/core.oam.dev/v1alpha2/zz_generated.deepcopy.go index 0d2dae272..3daf780b8 100644 --- a/apis/core.oam.dev/v1alpha2/zz_generated.deepcopy.go +++ b/apis/core.oam.dev/v1alpha2/zz_generated.deepcopy.go @@ -321,11 +321,6 @@ func (in *ApplicationDeploymentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationDeploymentSpec) DeepCopyInto(out *ApplicationDeploymentSpec) { *out = *in - if in.SourceApplicationName != nil { - in, out := &in.SourceApplicationName, &out.SourceApplicationName - *out = new(string) - **out = **in - } if in.ComponentList != nil { in, out := &in.ComponentList, &out.ComponentList *out = make([]string, len(*in)) diff --git a/charts/vela-core/crds/core.oam.dev_applicationdeployments.yaml b/charts/vela-core/crds/core.oam.dev_applicationdeployments.yaml index 06b229074..625f6b90e 100644 --- a/charts/vela-core/crds/core.oam.dev_applicationdeployments.yaml +++ b/charts/vela-core/crds/core.oam.dev_applicationdeployments.yaml @@ -251,13 +251,14 @@ spec: type: integer type: object sourceApplicationName: - description: SourceApplicationName contains the name of the application that we need to upgrade from. it can be omitted only when it's the first time to deploy the application + description: SourceApplicationName contains the name of the application that we need to upgrade from. it can be empty only when it's the first time to deploy the application type: string targetApplicationName: description: TargetApplicationName contains the name of the application that we need to upgrade to. We assume that an application is immutable, thus the name alone is suffice type: string required: - rolloutPlan + - sourceApplicationName - targetApplicationName type: object status: diff --git a/design/vela-core/rollout-design.md b/design/vela-core/rollout-design.md index f817eaeca..b943296a0 100644 --- a/design/vela-core/rollout-design.md +++ b/design/vela-core/rollout-design.md @@ -174,7 +174,7 @@ We will use a pre-defined annotation "app.oam.dev/rollout" that equals to "true" utilizes an appDeployment object to follow this rule. - Upon creation, the appDeployment controller marks itself as the owner of the application. The application controller will have built-in logic to ignore any applications that has the - "app.oam.dev/rollout" annotation set to true. + "app.oam.dev/rollout-template" annotation set to true. - The appDeployment controller can change the target application fields. For example, - It might remove all the conflict traits, such as HPA during upgrade. - It might modify the label selectors fields in the services to make sure there are ways to diff --git a/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationdeployments.yaml b/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationdeployments.yaml index 4f1de1a7c..631cd76b4 100644 --- a/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationdeployments.yaml +++ b/legacy/charts/vela-core-legacy/crds/core.oam.dev_applicationdeployments.yaml @@ -251,13 +251,14 @@ spec: type: integer type: object sourceApplicationName: - description: SourceApplicationName contains the name of the application that we need to upgrade from. it can be omitted only when it's the first time to deploy the application + description: SourceApplicationName contains the name of the application that we need to upgrade from. it can be empty only when it's the first time to deploy the application type: string targetApplicationName: description: TargetApplicationName contains the name of the application that we need to upgrade to. We assume that an application is immutable, thus the name alone is suffice type: string required: - rolloutPlan + - sourceApplicationName - targetApplicationName type: object status: diff --git a/pkg/controller/common/rollout/rollout_plan_init.go b/pkg/controller/common/rollout/rollout_plan_init.go new file mode 100644 index 000000000..321238ed8 --- /dev/null +++ b/pkg/controller/common/rollout/rollout_plan_init.go @@ -0,0 +1,19 @@ +package rollout + +import ( + "context" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1" +) + +// ReconcileRolloutPlan generates the rollout plan and reconcile it +func ReconcileRolloutPlan(ctx context.Context, client client.Client, rolloutSpec *v1alpha1.RolloutPlan, + targetWorkload, sourceWorkload *unstructured.Unstructured) error { + klog.InfoS("generate the rollout plan", "rollout Spec", rolloutSpec, + "target workload", klog.KObj(targetWorkload)) + return nil +} diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go index 51a67a1fe..29050fa9d 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go @@ -36,7 +36,8 @@ import ( "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" ) -const rolloutReconcileWaitTime = time.Second * 30 +// RolloutReconcileWaitTime is the time to wait before reconcile again an application still in rollout phase +const RolloutReconcileWaitTime = time.Second * 3 // Reconciler reconciles a Application object type Reconciler struct { @@ -75,7 +76,7 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { app.Status.Phase = v1alpha2.ApplicationRollingOut app.Status.SetConditions(readyCondition("Rolling")) // do not process apps still in rolling out - return ctrl.Result{RequeueAfter: rolloutReconcileWaitTime}, r.Status().Update(ctx, app) + return ctrl.Result{RequeueAfter: RolloutReconcileWaitTime}, r.Status().Update(ctx, app) } applog.Info("Start Rendering") diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go index 8cf1bde9d..6f5938ad1 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go @@ -679,7 +679,7 @@ var _ = Describe("Test Application Controller", func() { Namespace: app.Namespace, } result, err := reconciler.Reconcile(reconcile.Request{NamespacedName: appKey}) - Expect(result).To(BeIdenticalTo(ctrl.Result{RequeueAfter: rolloutReconcileWaitTime})) + Expect(result).To(BeIdenticalTo(ctrl.Result{RequeueAfter: RolloutReconcileWaitTime})) Expect(err).ToNot(HaveOccurred()) By("Check App status is rollingout") checkApp := &v1alpha2.Application{} diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-template.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-template.go new file mode 100644 index 000000000..d4763cb60 --- /dev/null +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-template.go @@ -0,0 +1,27 @@ +package applicationdeployment + +import ( + "context" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/klog/v2" + + corev1alpha2 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" + "github.com/oam-dev/kubevela/pkg/oam" +) + +// adjustTargetApplicationTemplate makes sure that the target template is in compliance before handing it over to +// the application controller +func (r *Reconciler) adjustTargetApplicationTemplate(ctx context.Context, targetWorkload *unstructured.Unstructured, + targetApp *corev1alpha2.Application) error { + klog.InfoS("Start to adjust the target application template", + "application", klog.KObj(targetApp), "target workload", targetWorkload) + + // TODO: adjust the target workload if needed + + // update the template without the rollout annotation so that the application controller can take over + anno := targetApp.GetAnnotations() + delete(anno, oam.AnnotationAppRollout) + targetApp.SetAnnotations(anno) + return r.Update(ctx, targetApp) +} diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/workload.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-workload.go similarity index 52% rename from pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/workload.go rename to pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-workload.go index 088b806ce..5a8c2a7bd 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/workload.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-workload.go @@ -7,22 +7,23 @@ import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/klog/v2" corev1alpha2 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" oamutil "github.com/oam-dev/kubevela/pkg/oam/util" appUtil "github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment" ) -// extractWorkload extracts the workload -func (r *Reconciler) extractWorkload(componentList []string, targetApp, - sourceApp *corev1alpha2.Application) (*unstructured.Unstructured, *unstructured.Unstructured, error) { +// extractWorkloadTypeAndGVK extracts the workload type and gvk +func (r *Reconciler) extractWorkloadTypeAndGVK(ctx context.Context, componentList []string, targetApp, + sourceApp *corev1alpha2.Application) (string, *schema.GroupVersionKind, error) { var componentType string // assume that the validator webhook has already guaranteed that there is no more than one component for now if len(componentList) == 0 { // we need to find a default component commons := appUtil.FindCommonComponent(targetApp, sourceApp) if len(commons) != 1 { - return nil, nil, fmt.Errorf("cannot find a default component, too many common components: %+v", commons) + return "", nil, fmt.Errorf("cannot find a default component, too many common components: %+v", commons) } componentType = commons[0] } else { @@ -30,33 +31,44 @@ func (r *Reconciler) extractWorkload(componentList []string, targetApp, } // get the workload definition // the validator webhook has checked that source and the target are the same type - wd, err := oamutil.GetWorkloadDefinition(r, componentType) + wd, err := oamutil.GetWorkloadDefinition(ctx, r, componentType) if err != nil { - return nil, nil, errors.Wrap(err, fmt.Sprintf("failed to get workload definition %s", componentType)) + return "", nil, errors.Wrap(err, fmt.Sprintf("failed to get workload definition %s", componentType)) } // get the CR kind from the definitionRef gvk, err := oamutil.GetGVKFromDefinition(r.dm, wd.Spec.Reference) if err != nil { - return nil, nil, errors.Wrap(err, fmt.Sprintf("failed to get workload GVK from definition ref %s", + return "", nil, errors.Wrap(err, fmt.Sprintf("failed to get workload GVK from definition ref %s", wd.Spec.Reference)) } - targetWorkload, err := r.fetchWorkload(targetApp, componentType, gvk) + return componentType, &gvk, nil +} + +// fetchWorkload based on the component type and the application and its gvk +func (r *Reconciler) fetchWorkloads(ctx context.Context, targetApp, sourceApp *corev1alpha2.Application, workloadType string, + workloadGVK *schema.GroupVersionKind) (*unstructured.Unstructured, *unstructured.Unstructured, error) { + targetWorkload, err := r.fetchWorkload(ctx, targetApp, workloadType, *workloadGVK) if err != nil { return nil, nil, err } + klog.InfoS("get the target workload we need to work on", "targetWorkload", klog.KObj(targetWorkload)) + if sourceApp == nil { return targetWorkload, nil, nil } - // get the component definition in the app, - sourceWorkload, err := r.fetchWorkload(sourceApp, componentType, gvk) + sourceWorkload, err := r.fetchWorkload(ctx, sourceApp, workloadType, *workloadGVK) if err != nil { return nil, nil, err } + if sourceWorkload != nil { + klog.InfoS("get the source workload we need to work on", "sourceWorkload", klog.KObj(sourceWorkload)) + } + return targetWorkload, sourceWorkload, nil } // fetchWorkload based on the component type and the application and its gvk -func (r *Reconciler) fetchWorkload(app *corev1alpha2.Application, componentType string, +func (r *Reconciler) fetchWorkload(ctx context.Context, app *corev1alpha2.Application, componentType string, gvk schema.GroupVersionKind) (*unstructured.Unstructured, error) { // get the component definition in the app, comp := app.GetComponent(componentType) @@ -64,8 +76,7 @@ func (r *Reconciler) fetchWorkload(app *corev1alpha2.Application, componentType return nil, fmt.Errorf("cannot find the component %s in the application", componentType) } // get the workload given GVK and name - workload, err := oamutil.GetObjectGivenGVKAndName(context.Background(), r, gvk, app.GetNamespace(), - comp.Name) + workload, err := oamutil.GetObjectGivenGVKAndName(ctx, r, gvk, app.GetNamespace(), comp.Name) if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("failed to get workload %s with gvk %+v ", componentType, gvk)) } diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go index 2b13f2410..898e34e82 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go @@ -3,6 +3,7 @@ package applicationdeployment import ( "context" "fmt" + "time" "github.com/crossplane/crossplane-runtime/pkg/event" "github.com/crossplane/crossplane-runtime/pkg/logging" @@ -15,11 +16,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" corev1alpha2 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" + "github.com/oam-dev/kubevela/pkg/controller/common/rollout" controller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev" + "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application" + "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" ) -const appDeployfinalizer = "finalizers.applicationdeployment.oam.dev" +const appDeployFinalizer = "finalizers.applicationdeployment.oam.dev" +const reconcileTimeOut = 10 * time.Second // Reconciler reconciles an ApplicationDeployment object type Reconciler struct { @@ -29,13 +34,16 @@ type Reconciler struct { Scheme *runtime.Scheme } -// Reconcile is the main logic of applicationdeployment controller // +kubebuilder:rbac:groups=core.oam.dev,resources=applicationdeployments,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core.oam.dev,resources=applicationdeployments/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=core.oam.dev,resources=applicationconfigurations,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core.oam.dev,resources=applications,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core.oam.dev,resources=applications/status,verbs=get;update;patch + +// Reconcile is the main logic of applicationdeployment controller func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - ctx := context.Background() var appDeploy corev1alpha2.ApplicationDeployment + ctx, cancel := context.WithTimeout(context.TODO(), reconcileTimeOut) + defer cancel() if err := r.Get(ctx, req.NamespacedName, &appDeploy); err != nil { if apierrors.IsNotFound(err) { klog.InfoS("application deployment does not exist", "appDeploy", klog.KRef(req.Namespace, req.Name)) @@ -47,7 +55,8 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { r.handleFinalizer(&appDeploy) // Get the target application - var targetApp, sourceApp corev1alpha2.Application + var targetApp corev1alpha2.Application + var sourceApp *corev1alpha2.Application targetAppName := appDeploy.Spec.TargetApplicationName if err := r.Get(ctx, ktypes.NamespacedName{Namespace: req.Namespace, Name: targetAppName}, &targetApp); err != nil { @@ -55,37 +64,66 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { klog.KRef(req.Namespace, targetAppName)) return ctrl.Result{}, err } + // Get the source application sourceAppName := appDeploy.Spec.SourceApplicationName - if sourceAppName == nil { + if sourceAppName == "" { klog.Info("source app fields not filled, we assume it is deployed for the first time") - } else if err := r.Get(ctx, ktypes.NamespacedName{Namespace: req.Namespace, Name: *sourceAppName}, - &sourceApp); err != nil { + } else if err := r.Get(ctx, ktypes.NamespacedName{Namespace: req.Namespace, Name: sourceAppName}, sourceApp); err != nil { klog.ErrorS(err, "cannot locate source application", "source application", klog.KRef(req.Namespace, - *sourceAppName)) + sourceAppName)) return ctrl.Result{}, err } // Get the kubernetes workloads to upgrade from the application - targetWorkload, sourceWorkload, err := r.extractWorkload(appDeploy.Spec.ComponentList, &targetApp, &sourceApp) + workloadType, workloadGVK, err := r.extractWorkloadTypeAndGVK(ctx, + appDeploy.Spec.ComponentList, &targetApp, sourceApp) if err != nil { - klog.Error(err, "cannot locate the workloads object") + klog.ErrorS(err, "cannot extract the workloadType and GVK", + "component list", appDeploy.Spec.ComponentList, "target app", klog.KObj(&targetApp)) return ctrl.Result{}, err } + + targetWorkload, sourceWorkload, err := r.fetchWorkloads(ctx, &targetApp, sourceApp, workloadType, workloadGVK) + if err != nil { + klog.ErrorS(err, "cannot fetch the workloads to upgrade", "workload Type", workloadType, + "workload GVK", *workloadGVK, "target application", klog.KRef(req.Namespace, targetAppName), + "source application", klog.KRef(req.Namespace, sourceAppName)) + return ctrl.Result{}, client.IgnoreNotFound(err) + } klog.InfoS("get the target workload we need to work on", "targetWorkload", klog.KObj(targetWorkload)) + + // check if the target application is still in rolling + if _, exist := targetApp.GetAnnotations()[oam.AnnotationAppRollout]; exist { + // adjust the target workload if it's still a template + if err := r.adjustTargetApplicationTemplate(ctx, targetWorkload, &targetApp); err != nil { + klog.ErrorS(err, "cannot adjust the target workload", "target workload", klog.KObj(targetWorkload)) + return ctrl.Result{}, err + } + // requeue it to process hopefully after the application controller takes over + return ctrl.Result{RequeueAfter: 2 * application.RolloutReconcileWaitTime}, nil + } + if sourceWorkload != nil { klog.InfoS("get the source workload we need to work on", "sourceWorkload", klog.KObj(sourceWorkload)) } - // TODO: pass these two object to the rollout plan + + // reconcile the rollout part of the spec given the target and source workload + err = rollout.ReconcileRolloutPlan(ctx, r, &appDeploy.Spec.RolloutPlan, targetWorkload, sourceWorkload) + if err != nil { + klog.ErrorS(err, "cannot reconcile the rollout plan", "rollout spec", appDeploy.Spec.RolloutPlan) + return ctrl.Result{}, err + } + return ctrl.Result{}, nil } func (r *Reconciler) handleFinalizer(appDeploy *corev1alpha2.ApplicationDeployment) { if appDeploy.DeletionTimestamp.IsZero() { - if !slice.ContainsString(appDeploy.Finalizers, appDeployfinalizer, nil) { + if !slice.ContainsString(appDeploy.Finalizers, appDeployFinalizer, nil) { // TODO: add finalizer klog.Info("add finalizer") } - } else if slice.ContainsString(appDeploy.Finalizers, appDeployfinalizer, nil) { + } else if slice.ContainsString(appDeploy.Finalizers, appDeployFinalizer, nil) { // TODO: perform finalize klog.Info("perform clean up") } diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/workloads/clonetset.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/workloads/clonetset.go new file mode 100644 index 000000000..3c7413caa --- /dev/null +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/workloads/clonetset.go @@ -0,0 +1 @@ +package workloads diff --git a/pkg/oam/util/helper.go b/pkg/oam/util/helper.go index da37206b0..a9e44410f 100644 --- a/pkg/oam/util/helper.go +++ b/pkg/oam/util/helper.go @@ -182,7 +182,7 @@ func FetchTraitDefinition(ctx context.Context, r client.Reader, dm discoverymapp return nil, err } // Fetch the corresponding traitDefinition CR - traitDefinition, err := GetTraitDefinition(r, trName) + traitDefinition, err := GetTraitDefinition(ctx, r, trName) if err != nil { return nil, err } @@ -198,7 +198,7 @@ func FetchWorkloadDefinition(ctx context.Context, r client.Reader, dm discoverym return nil, err } // Fetch the corresponding workloadDefinition CR - workloadDefinition, err := GetWorkloadDefinition(r, wldName) + workloadDefinition, err := GetWorkloadDefinition(ctx, r, wldName) if err != nil { return nil, err } @@ -214,18 +214,19 @@ func GenNamespacedDefinitionName(dn string) types.NamespacedName { } // GetWorkloadDefinition Get WorkloadDefinition -func GetWorkloadDefinition(cli client.Reader, workitemName string) (*v1alpha2.WorkloadDefinition, error) { +func GetWorkloadDefinition(ctx context.Context, cli client.Reader, + workitemName string) (*v1alpha2.WorkloadDefinition, error) { wd := new(v1alpha2.WorkloadDefinition) - if err := cli.Get(context.Background(), GenNamespacedDefinitionName(workitemName), wd); err != nil { + if err := cli.Get(ctx, GenNamespacedDefinitionName(workitemName), wd); err != nil { return nil, err } return wd, nil } // GetTraitDefinition Get TraitDefinition -func GetTraitDefinition(cli client.Reader, traitName string) (*v1alpha2.TraitDefinition, error) { +func GetTraitDefinition(ctx context.Context, cli client.Reader, traitName string) (*v1alpha2.TraitDefinition, error) { td := new(v1alpha2.TraitDefinition) - if err := cli.Get(context.Background(), GenNamespacedDefinitionName(traitName), td); err != nil { + if err := cli.Get(ctx, GenNamespacedDefinitionName(traitName), td); err != nil { return nil, err } return td, nil diff --git a/pkg/oam/util/template.go b/pkg/oam/util/template.go index c42b93c47..3149c3a37 100644 --- a/pkg/oam/util/template.go +++ b/pkg/oam/util/template.go @@ -38,7 +38,7 @@ func GetScopeGVK(cli client.Client, dm discoverymapper.DiscoveryMapper, func LoadTemplate(cli client.Reader, key string, kd types.CapType) (*Template, error) { switch kd { case types.TypeWorkload: - wd, err := GetWorkloadDefinition(cli, key) + wd, err := GetWorkloadDefinition(context.TODO(), cli, key) if err != nil { return nil, errors.WithMessagef(err, "LoadTemplate [%s] ", key) } @@ -57,7 +57,7 @@ func LoadTemplate(cli client.Reader, key string, kd types.CapType) (*Template, e return tmpl, nil case types.TypeTrait: - td, err := GetTraitDefinition(cli, key) + td, err := GetTraitDefinition(context.TODO(), cli, key) if err != nil { return nil, errors.WithMessagef(err, "LoadTemplate [%s] ", key) } diff --git a/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/common.go b/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/common.go index 4fea333d5..88523efb7 100644 --- a/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/common.go +++ b/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/common.go @@ -15,7 +15,7 @@ func FindCommonComponent(targetApp, sourceApp *v1alpha2.Application) []string { return commonComponents } // find the common components in both the source and target application - // write an O(N) algorithm just for fun, totally doesn't worth the extra effort + // write an O(N) algorithm just for fun, totally doesn't worth the extra space targetComponents := make(map[string]bool) for _, comp := range targetApp.Spec.Components { targetComponents[comp.WorkloadType] = true @@ -26,5 +26,4 @@ func FindCommonComponent(targetApp, sourceApp *v1alpha2.Application) []string { } } return commonComponents - } diff --git a/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/validation.go b/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/validation.go index 34053b904..14079673d 100644 --- a/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/validation.go +++ b/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment/validation.go @@ -39,12 +39,12 @@ func (h *ValidatingHandler) ValidateCreate(appDeploy *v1alpha2.ApplicationDeploy return allErrs } sourceAppName := appDeploy.Spec.SourceApplicationName - if sourceAppName != nil { - if err := h.Get(context.Background(), ktypes.NamespacedName{Namespace: appDeploy.Namespace, Name: *sourceAppName}, + if sourceAppName != "" { + if err := h.Get(context.Background(), ktypes.NamespacedName{Namespace: appDeploy.Namespace, Name: sourceAppName}, &sourceApp); err != nil { klog.ErrorS(err, "cannot locate source application", "source application", - klog.KRef(appDeploy.Namespace, *sourceAppName)) - allErrs = append(allErrs, field.NotFound(fldPath.Child("sourceApplicationName"), *sourceAppName)) + klog.KRef(appDeploy.Namespace, sourceAppName)) + allErrs = append(allErrs, field.NotFound(fldPath.Child("sourceApplicationName"), sourceAppName)) } }