From bab5bb2caf4f7946f46c6a8249bd969282783002 Mon Sep 17 00:00:00 2001 From: qiaozp <47812250+chivalryq@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:41:20 +0800 Subject: [PATCH] Refactor: capabilities and workload in appfile parsing (#6250) --- apis/types/capability.go | 20 +- cmd/core/app/server.go | 4 +- hack/docgen/def/mods/component.go | 2 +- pkg/appfile/appfile.go | 181 ++++++------ pkg/appfile/appfile_test.go | 20 +- pkg/appfile/parser.go | 272 ++++++++++-------- pkg/appfile/parser_test.go | 35 +-- pkg/appfile/unit_test.go | 10 +- pkg/appfile/validate.go | 6 +- pkg/appfile/validate_test.go | 2 +- .../application/application_controller.go | 4 +- .../core.oam.dev/v1beta1/application/apply.go | 46 +-- .../v1beta1/application/dispatcher.go | 18 +- .../v1beta1/application/generator.go | 14 +- .../v1beta1/application/revision.go | 4 +- .../v1beta1/application/revision_test.go | 2 +- pkg/oam/labels.go | 26 -- pkg/workflow/providers/oam/apply.go | 2 +- .../providers/terraform/terraform_test.go | 6 +- references/appfile/addon.go | 6 +- references/cli/components.go | 4 +- references/cli/traits.go | 4 +- references/common/registry.go | 23 +- references/docgen/cluster.go | 17 +- references/docgen/cluster_test.go | 10 +- 25 files changed, 343 insertions(+), 395 deletions(-) diff --git a/apis/types/capability.go b/apis/types/capability.go index 92703253d..4c92432e5 100644 --- a/apis/types/capability.go +++ b/apis/types/capability.go @@ -32,22 +32,6 @@ type CRDInfo struct { Kind string `json:"kind"` } -// Chart defines all necessary information to install a whole chart -type Chart struct { - Repo string `json:"repo"` - URL string `json:"url"` - Name string `json:"name"` - Namespace string `json:"namespace,omitempty"` - Version string `json:"version"` - Values map[string]interface{} `json:"values"` -} - -// Installation defines the installation method for this Capability, currently only helm is supported -type Installation struct { - Helm Chart `json:"helm"` - // TODO(wonderflow) add raw yaml file support for install capability -} - // CapType defines the type of capability type CapType string @@ -107,7 +91,6 @@ type Capability struct { CueTemplateURI string `json:"templateURI,omitempty"` Parameters []Parameter `json:"parameters,omitempty"` CrdName string `json:"crdName,omitempty"` - Center string `json:"center,omitempty"` Status string `json:"status,omitempty"` Description string `json:"description,omitempty"` Example string `json:"example,omitempty"` @@ -121,8 +104,7 @@ type Capability struct { Namespace string `json:"namespace,omitempty"` // Plugin Source - Source *Source `json:"source,omitempty"` - CrdInfo *CRDInfo `json:"crdInfo,omitempty"` + Source *Source `json:"source,omitempty"` // Terraform TerraformConfiguration string `json:"terraformConfiguration,omitempty"` diff --git a/cmd/core/app/server.go b/cmd/core/app/server.go index f1ad68e74..41049fed2 100644 --- a/cmd/core/app/server.go +++ b/cmd/core/app/server.go @@ -47,7 +47,7 @@ import ( "github.com/oam-dev/kubevela/pkg/auth" "github.com/oam-dev/kubevela/pkg/cache" commonconfig "github.com/oam-dev/kubevela/pkg/controller/common" - oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1" + oamv1beta1 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1/application" "github.com/oam-dev/kubevela/pkg/features" "github.com/oam-dev/kubevela/pkg/monitor/watcher" @@ -227,7 +227,7 @@ func prepareRun(ctx context.Context, mgr manager.Manager, s *options.CoreOptions } } - if err := oamv1alpha2.Setup(mgr, *s.ControllerArgs); err != nil { + if err := oamv1beta1.Setup(mgr, *s.ControllerArgs); err != nil { klog.ErrorS(err, "Unable to setup the oam controller") return err } diff --git a/hack/docgen/def/mods/component.go b/hack/docgen/def/mods/component.go index bc306808e..c27b8d4b9 100644 --- a/hack/docgen/def/mods/component.go +++ b/hack/docgen/def/mods/component.go @@ -42,7 +42,7 @@ var ComponentDefDirs = []string{"./vela-templates/definitions/internal/component // CustomComponentHeaderEN . var CustomComponentHeaderEN = `--- -title: Built-in Component Type +title: Built-in ParsedComponents Type --- This documentation will walk through all the built-in component types sorted alphabetically. diff --git a/pkg/appfile/appfile.go b/pkg/appfile/appfile.go index 1507fd263..a1f43525f 100644 --- a/pkg/appfile/appfile.go +++ b/pkg/appfile/appfile.go @@ -74,8 +74,10 @@ const ( GitCredentialsSecretReferenceKey = "gitCredentialsSecretReference" ) -// Workload is component -type Workload struct { +// Component is an internal struct for component in application +// User-defined policies are parsed as a Component without any Traits because their purpose is dispatching some resources +// Internal policies are NOT parsed as a Component +type Component struct { Name string Type string CapabilityCategory types.CapabilityCategory @@ -89,39 +91,39 @@ type Workload struct { } // 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) +func (comp *Component) EvalContext(ctx process.Context) error { + return comp.engine.Complete(ctx, comp.FullTemplate.TemplateStr, comp.Params) } // GetTemplateContext get workload template context, it will be used to eval status and health -func (wl *Workload) GetTemplateContext(ctx process.Context, client client.Client, accessor util.NamespaceAccessor) (map[string]interface{}, error) { +func (comp *Component) GetTemplateContext(ctx process.Context, client client.Client, accessor util.NamespaceAccessor) (map[string]interface{}, error) { // if the standard workload is managed by trait, just return empty context - if wl.SkipApplyWorkload { + if comp.SkipApplyWorkload { return nil, nil } - templateContext, err := wl.engine.GetTemplateContext(ctx, client, accessor) + templateContext, err := comp.engine.GetTemplateContext(ctx, client, accessor) if templateContext != nil { - templateContext[velaprocess.ParameterFieldName] = wl.Params + templateContext[velaprocess.ParameterFieldName] = comp.Params } return templateContext, err } // EvalStatus eval workload status -func (wl *Workload) EvalStatus(templateContext map[string]interface{}) (string, error) { +func (comp *Component) EvalStatus(templateContext map[string]interface{}) (string, error) { // if the standard workload is managed by trait always return empty message - if wl.SkipApplyWorkload { + if comp.SkipApplyWorkload { return "", nil } - return wl.engine.Status(templateContext, wl.FullTemplate.CustomStatus, wl.Params) + return comp.engine.Status(templateContext, comp.FullTemplate.CustomStatus, comp.Params) } // EvalHealth eval workload health check -func (wl *Workload) EvalHealth(templateContext map[string]interface{}) (bool, error) { +func (comp *Component) EvalHealth(templateContext map[string]interface{}) (bool, error) { // if the health of template is not set or standard workload is managed by trait always return true - if wl.SkipApplyWorkload { + if comp.SkipApplyWorkload { return true, nil } - return wl.engine.HealthCheck(templateContext, wl.FullTemplate.Health, wl.Params) + return comp.engine.HealthCheck(templateContext, comp.FullTemplate.Health, comp.Params) } // Trait is ComponentTrait @@ -168,9 +170,10 @@ func (trait *Trait) EvalHealth(templateContext map[string]interface{}) (bool, er // Appfile describes application type Appfile struct { - Name string - Namespace string - Workloads []*Workload + Name string + Namespace string + ParsedComponents []*Component + ParsedPolicies []*Component AppRevision *v1beta1.ApplicationRevision AppRevisionName string @@ -183,19 +186,17 @@ type Appfile struct { RelatedComponentDefinitions map[string]*v1beta1.ComponentDefinition RelatedWorkflowStepDefinitions map[string]*v1beta1.WorkflowStepDefinition - Policies []v1beta1.AppPolicy - PolicyWorkloads []*Workload - Components []common.ApplicationComponent - Artifacts []*types.ComponentManifest - WorkflowSteps []workflowv1alpha1.WorkflowStep - WorkflowMode *workflowv1alpha1.WorkflowExecuteMode + Policies []v1beta1.AppPolicy + Components []common.ApplicationComponent + Artifacts []*types.ComponentManifest + WorkflowSteps []workflowv1alpha1.WorkflowStep + WorkflowMode *workflowv1alpha1.WorkflowExecuteMode ExternalPolicies map[string]*v1alpha1.Policy ExternalWorkflow *workflowv1alpha1.Workflow ReferredObjects []*unstructured.Unstructured - parser *Parser - app *v1beta1.Application + app *v1beta1.Application Debug bool } @@ -204,7 +205,7 @@ type Appfile struct { // internal policies like apply-once, topology, will not render manifests func (af *Appfile) GeneratePolicyManifests(ctx context.Context) ([]*unstructured.Unstructured, error) { var manifests []*unstructured.Unstructured - for _, policy := range af.PolicyWorkloads { + for _, policy := range af.ParsedPolicies { un, err := af.generatePolicyUnstructured(policy) if err != nil { return nil, err @@ -214,7 +215,7 @@ func (af *Appfile) GeneratePolicyManifests(ctx context.Context) ([]*unstructured return manifests, nil } -func (af *Appfile) generatePolicyUnstructured(workload *Workload) ([]*unstructured.Unstructured, error) { +func (af *Appfile) generatePolicyUnstructured(workload *Component) ([]*unstructured.Unstructured, error) { ctxData := GenerateContextDataFromAppFile(af, workload.Name) uns, err := generatePolicyUnstructuredFromCUEModule(workload, af.Artifacts, ctxData) if err != nil { @@ -231,16 +232,16 @@ func (af *Appfile) generatePolicyUnstructured(workload *Workload) ([]*unstructur return uns, nil } -func generatePolicyUnstructuredFromCUEModule(wl *Workload, artifacts []*types.ComponentManifest, ctxData velaprocess.ContextData) ([]*unstructured.Unstructured, error) { +func generatePolicyUnstructuredFromCUEModule(comp *Component, artifacts []*types.ComponentManifest, ctxData velaprocess.ContextData) ([]*unstructured.Unstructured, error) { pCtx := velaprocess.NewContext(ctxData) pCtx.PushData(velaprocess.ContextDataArtifacts, prepareArtifactsData(artifacts)) - if err := wl.EvalContext(pCtx); err != nil { + if err := comp.EvalContext(pCtx); err != nil { return nil, errors.Wrapf(err, "evaluate base template app=%s in namespace=%s", ctxData.AppName, ctxData.Namespace) } base, auxs := pCtx.Output() workload, err := base.Unstructured() if err != nil { - return nil, errors.Wrapf(err, "evaluate base template policy=%s app=%s", wl.Name, ctxData.AppName) + return nil, errors.Wrapf(err, "evaluate base template policy=%s app=%s", comp.Name, ctxData.AppName) } commonLabels := definition.GetCommonLabels(definition.GetBaseContextLabels(pCtx)) util.AddLabels(workload, commonLabels) @@ -249,7 +250,7 @@ func generatePolicyUnstructuredFromCUEModule(wl *Workload, artifacts []*types.Co for _, assist := range auxs { tr, err := assist.Ins.Unstructured() if err != nil { - return nil, errors.Wrapf(err, "evaluate auxiliary=%s template for policy=%s app=%s", assist.Name, wl.Name, ctxData.AppName) + return nil, errors.Wrapf(err, "evaluate auxiliary=%s template for policy=%s app=%s", assist.Name, comp.Name, ctxData.AppName) } util.AddLabels(tr, commonLabels) res = append(res, tr) @@ -283,10 +284,10 @@ func prepareArtifactsData(comps []*types.ComponentManifest) map[string]interface // GenerateComponentManifests converts an appFile to a slice of ComponentManifest func (af *Appfile) GenerateComponentManifests() ([]*types.ComponentManifest, error) { - compManifests := make([]*types.ComponentManifest, len(af.Workloads)) - af.Artifacts = make([]*types.ComponentManifest, len(af.Workloads)) - for i, wl := range af.Workloads { - cm, err := af.GenerateComponentManifest(wl, nil) + compManifests := make([]*types.ComponentManifest, len(af.ParsedComponents)) + af.Artifacts = make([]*types.ComponentManifest, len(af.ParsedComponents)) + for i, comp := range af.ParsedComponents { + cm, err := af.GenerateComponentManifest(comp, nil) if err != nil { return nil, err } @@ -301,21 +302,21 @@ func (af *Appfile) GenerateComponentManifests() ([]*types.ComponentManifest, err } // GenerateComponentManifest generate only one ComponentManifest -func (af *Appfile) GenerateComponentManifest(wl *Workload, mutate func(*velaprocess.ContextData)) (*types.ComponentManifest, error) { +func (af *Appfile) GenerateComponentManifest(comp *Component, mutate func(*velaprocess.ContextData)) (*types.ComponentManifest, error) { if af.Namespace == "" { af.Namespace = corev1.NamespaceDefault } - ctxData := GenerateContextDataFromAppFile(af, wl.Name) + ctxData := GenerateContextDataFromAppFile(af, comp.Name) if mutate != nil { mutate(&ctxData) } // generate context here to avoid nil pointer panic - wl.Ctx = NewBasicContext(ctxData, wl.Params) - switch wl.CapabilityCategory { + comp.Ctx = NewBasicContext(ctxData, comp.Params) + switch comp.CapabilityCategory { case types.TerraformCategory: - return generateComponentFromTerraformModule(wl, af.Name, af.Namespace) + return generateComponentFromTerraformModule(comp, af.Name, af.Namespace) default: - return generateComponentFromCUEModule(wl, ctxData) + return generateComponentFromCUEModule(comp, ctxData) } } @@ -393,15 +394,15 @@ func (af *Appfile) setNamespace(obj *unstructured.Unstructured) { } } -func (af *Appfile) assembleWorkload(wl *unstructured.Unstructured, compName string, labels map[string]string) { +func (af *Appfile) assembleWorkload(comp *unstructured.Unstructured, compName string, labels map[string]string) { // use component name as workload name if workload name is not specified // don't override the name set in render phase if exist - if len(wl.GetName()) == 0 { - wl.SetName(compName) + if len(comp.GetName()) == 0 { + comp.SetName(compName) } - af.setNamespace(wl) - af.setWorkloadLabels(wl, labels) - af.filterAndSetAnnotations(wl) + af.setNamespace(comp) + af.setWorkloadLabels(comp, labels) + af.filterAndSetAnnotations(comp) } /* @@ -416,10 +417,10 @@ func (af *Appfile) assembleWorkload(wl *unstructured.Unstructured, compName stri // Component Revision name was not added here (app.oam.dev/revision: mycomp-v2) */ -func (af *Appfile) setWorkloadLabels(wl *unstructured.Unstructured, commonLabels map[string]string) { +func (af *Appfile) setWorkloadLabels(comp *unstructured.Unstructured, commonLabels map[string]string) { // add more workload-specific labels here - util.AddLabels(wl, map[string]string{oam.LabelOAMResourceType: oam.ResourceTypeWorkload}) - util.AddLabels(wl, commonLabels) + util.AddLabels(comp, map[string]string{oam.LabelOAMResourceType: oam.ResourceTypeWorkload}) + util.AddLabels(comp, commonLabels) } func (af *Appfile) assembleTrait(trait *unstructured.Unstructured, compName string, labels map[string]string) { @@ -491,14 +492,14 @@ func IsNotFoundInAppFile(err error) bool { } // PrepareProcessContext prepares a DSL process Context -func PrepareProcessContext(wl *Workload, ctxData velaprocess.ContextData) (process.Context, error) { - if wl.Ctx == nil { - wl.Ctx = NewBasicContext(ctxData, wl.Params) +func PrepareProcessContext(comp *Component, ctxData velaprocess.ContextData) (process.Context, error) { + if comp.Ctx == nil { + comp.Ctx = NewBasicContext(ctxData, comp.Params) } - if err := wl.EvalContext(wl.Ctx); err != nil { + if err := comp.EvalContext(comp.Ctx); err != nil { return nil, errors.Wrapf(err, "evaluate base template app=%s in namespace=%s", ctxData.AppName, ctxData.Namespace) } - return wl.Ctx, nil + return comp.Ctx, nil } // NewBasicContext prepares a basic DSL process Context @@ -510,27 +511,27 @@ func NewBasicContext(contextData velaprocess.ContextData, params map[string]inte return pCtx } -func generateComponentFromCUEModule(wl *Workload, ctxData velaprocess.ContextData) (*types.ComponentManifest, error) { - pCtx, err := PrepareProcessContext(wl, ctxData) +func generateComponentFromCUEModule(comp *Component, ctxData velaprocess.ContextData) (*types.ComponentManifest, error) { + pCtx, err := PrepareProcessContext(comp, ctxData) if err != nil { return nil, err } - return baseGenerateComponent(pCtx, wl, ctxData.AppName, ctxData.Namespace) + return baseGenerateComponent(pCtx, comp, ctxData.AppName, ctxData.Namespace) } -func generateComponentFromTerraformModule(wl *Workload, appName, ns string) (*types.ComponentManifest, error) { - return baseGenerateComponent(wl.Ctx, wl, appName, ns) +func generateComponentFromTerraformModule(comp *Component, appName, ns string) (*types.ComponentManifest, error) { + return baseGenerateComponent(comp.Ctx, comp, appName, ns) } -func baseGenerateComponent(pCtx process.Context, wl *Workload, appName, ns string) (*types.ComponentManifest, error) { +func baseGenerateComponent(pCtx process.Context, comp *Component, appName, ns string) (*types.ComponentManifest, error) { var err error - pCtx.PushData(velaprocess.ContextComponentType, wl.Type) - for _, tr := range wl.Traits { + pCtx.PushData(velaprocess.ContextComponentType, comp.Type) + for _, tr := range comp.Traits { if err := tr.EvalContext(pCtx); err != nil { - return nil, errors.Wrapf(err, "evaluate template trait=%s app=%s", tr.Name, wl.Name) + return nil, errors.Wrapf(err, "evaluate template trait=%s app=%s", tr.Name, comp.Name) } } - if patcher := wl.Patch; patcher != nil { + if patcher := comp.Patch; patcher != nil { workload, auxiliaries := pCtx.Output() if p, err := patcher.LookupValue("workload"); err == nil { if err := workload.Unify(p.CueValue()); err != nil { @@ -545,43 +546,43 @@ func baseGenerateComponent(pCtx process.Context, wl *Workload, appName, ns strin } } } - compManifest, err := evalWorkloadWithContext(pCtx, wl, ns, appName) + compManifest, err := evalWorkloadWithContext(pCtx, comp, ns, appName) if err != nil { return nil, err } - compManifest.Name = wl.Name + compManifest.Name = comp.Name compManifest.Namespace = ns return compManifest, nil } // makeWorkloadWithContext evaluate the workload's template to unstructured resource. -func makeWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName string) (*unstructured.Unstructured, error) { +func makeWorkloadWithContext(pCtx process.Context, comp *Component, ns, appName string) (*unstructured.Unstructured, error) { var ( workload *unstructured.Unstructured err error ) base, _ := pCtx.Output() - switch wl.CapabilityCategory { + switch comp.CapabilityCategory { case types.TerraformCategory: - workload, err = generateTerraformConfigurationWorkload(wl, ns) + workload, err = generateTerraformConfigurationWorkload(comp, ns) if err != nil { - return nil, errors.Wrapf(err, "failed to generate Terraform Configuration workload for workload %s", wl.Name) + return nil, errors.Wrapf(err, "failed to generate Terraform Configuration workload for workload %s", comp.Name) } default: workload, err = base.Unstructured() if err != nil { - return nil, errors.Wrapf(err, "evaluate base template component=%s app=%s", wl.Name, appName) + return nil, errors.Wrapf(err, "evaluate base template component=%s app=%s", comp.Name, appName) } } commonLabels := definition.GetCommonLabels(definition.GetBaseContextLabels(pCtx)) - util.AddLabels(workload, util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.WorkloadTypeLabel: wl.Type})) + util.AddLabels(workload, util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.WorkloadTypeLabel: comp.Type})) return workload, nil } // evalWorkloadWithContext evaluate the workload's template to generate component manifest -func evalWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName string) (*types.ComponentManifest, error) { +func evalWorkloadWithContext(pCtx process.Context, comp *Component, ns, appName string) (*types.ComponentManifest, error) { compManifest := &types.ComponentManifest{} - workload, err := makeWorkloadWithContext(pCtx, wl, ns, appName) + workload, err := makeWorkloadWithContext(pCtx, comp, ns, appName) if err != nil { return nil, err } @@ -593,7 +594,7 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName str for i, assist := range assists { tr, err := assist.Ins.Unstructured() if err != nil { - return nil, errors.Wrapf(err, "evaluate trait=%s template for component=%s app=%s", assist.Name, wl.Name, appName) + return nil, errors.Wrapf(err, "evaluate trait=%s template for component=%s app=%s", assist.Name, comp.Name, appName) } labels := util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.TraitTypeLabel: assist.Type}) if assist.Name != "" { @@ -605,26 +606,26 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName str return compManifest, nil } -func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructured.Unstructured, error) { - if wl.FullTemplate == nil || wl.FullTemplate.Terraform == nil || wl.FullTemplate.Terraform.Configuration == "" { +func generateTerraformConfigurationWorkload(comp *Component, ns string) (*unstructured.Unstructured, error) { + if comp.FullTemplate == nil || comp.FullTemplate.Terraform == nil || comp.FullTemplate.Terraform.Configuration == "" { return nil, errors.New(errTerraformConfigurationIsNotSet) } - params, err := json.Marshal(wl.Params) + params, err := json.Marshal(comp.Params) if err != nil { return nil, errors.Wrap(err, errFailToConvertTerraformComponentProperties) } - if wl.FullTemplate.ComponentDefinition == nil || wl.FullTemplate.ComponentDefinition.Spec.Schematic == nil || - wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform == nil { + if comp.FullTemplate.ComponentDefinition == nil || comp.FullTemplate.ComponentDefinition.Spec.Schematic == nil || + comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform == nil { return nil, errors.New(errTerraformComponentDefinition) } configuration := terraformapi.Configuration{ TypeMeta: metav1.TypeMeta{APIVersion: "terraform.core.oam.dev/v1beta2", Kind: "Configuration"}, ObjectMeta: metav1.ObjectMeta{ - Name: wl.Name, + Name: comp.Name, Namespace: ns, - Annotations: wl.FullTemplate.ComponentDefinition.Annotations, + Annotations: comp.FullTemplate.ComponentDefinition.Annotations, }, } // 1. parse the spec of configuration @@ -635,26 +636,26 @@ func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructu configuration.Spec = spec if configuration.Spec.WriteConnectionSecretToReference == nil { - configuration.Spec.WriteConnectionSecretToReference = wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.WriteConnectionSecretToReference + configuration.Spec.WriteConnectionSecretToReference = comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.WriteConnectionSecretToReference } if configuration.Spec.WriteConnectionSecretToReference != nil && configuration.Spec.WriteConnectionSecretToReference.Namespace == "" { configuration.Spec.WriteConnectionSecretToReference.Namespace = ns } if configuration.Spec.ProviderReference == nil { - configuration.Spec.ProviderReference = wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.ProviderReference + configuration.Spec.ProviderReference = comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.ProviderReference } if configuration.Spec.GitCredentialsSecretReference == nil { - configuration.Spec.GitCredentialsSecretReference = wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.GitCredentialsSecretReference + configuration.Spec.GitCredentialsSecretReference = comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.GitCredentialsSecretReference } - switch wl.FullTemplate.Terraform.Type { + switch comp.FullTemplate.Terraform.Type { case "hcl": - configuration.Spec.HCL = wl.FullTemplate.Terraform.Configuration + configuration.Spec.HCL = comp.FullTemplate.Terraform.Configuration case "remote": - configuration.Spec.Remote = wl.FullTemplate.Terraform.Configuration - configuration.Spec.Path = wl.FullTemplate.Terraform.Path + configuration.Spec.Remote = comp.FullTemplate.Terraform.Configuration + configuration.Spec.Path = comp.FullTemplate.Terraform.Path } // 2. parse variable diff --git a/pkg/appfile/appfile_test.go b/pkg/appfile/appfile_test.go index fec17de69..5177fda9b 100644 --- a/pkg/appfile/appfile_test.go +++ b/pkg/appfile/appfile_test.go @@ -135,7 +135,7 @@ variable "password" { ` ) - wl := &Workload{ + wl := &Component{ Name: "sample-db", FullTemplate: &Template{ Terraform: &common.Terraform{ @@ -161,10 +161,10 @@ variable "password" { } af := &Appfile{ - Workloads: []*Workload{wl}, - Name: appName, - AppRevisionName: revision, - Namespace: ns, + ParsedComponents: []*Component{wl}, + Name: appName, + AppRevisionName: revision, + Namespace: ns, } variable := map[string]interface{}{"account_name": "oamtest"} @@ -319,13 +319,13 @@ var _ = Describe("Test evalWorkloadWithContext", func() { err error ) type appArgs struct { - wl *Workload + wl *Component appName string revision string } args := appArgs{ - wl: &Workload{ + wl: &Component{ Name: compName, FullTemplate: &Template{ Terraform: &common.Terraform{ @@ -595,7 +595,7 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) { } } - wl := &Workload{ + wl := &Component{ FullTemplate: template, Name: name, Params: tc.args.params, @@ -730,7 +730,7 @@ if context.componentType == "stateless" { publishVersion: context.publishVersion }`, } - wl := &Workload{Type: "stateful", Traits: []*Trait{tr}} + wl := &Component{Type: "stateful", Traits: []*Trait{tr}} cm, err := baseGenerateComponent(pContext, wl, appName, ns) assert.NoError(t, err) assert.Equal(t, cm.Traits[0].Object["kind"], "StatefulSet") @@ -751,7 +751,7 @@ var _ = Describe("Test use context.appLabels& context.appAnnotations in componen "ak1": "av1", "ak2": "av2", }, - Workloads: []*Workload{ + ParsedComponents: []*Component{ { Name: "comp1", Type: "deployment", diff --git a/pkg/appfile/parser.go b/pkg/appfile/parser.go index c48511a1c..16fbdd753 100644 --- a/pkg/appfile/parser.go +++ b/pkg/appfile/parser.go @@ -105,8 +105,6 @@ func (p *Parser) GenerateAppFile(ctx context.Context, app *v1beta1.Application) // GenerateAppFileFromApp converts an application to an Appfile func (p *Parser) GenerateAppFileFromApp(ctx context.Context, app *v1beta1.Application) (*Appfile, error) { - ns := app.Namespace - appName := app.Name for idx := range app.Spec.Policies { if app.Spec.Policies[idx].Name == "" { @@ -114,54 +112,32 @@ func (p *Parser) GenerateAppFileFromApp(ctx context.Context, app *v1beta1.Applic } } - appFile := p.newAppFile(appName, ns, app) + appFile := newAppFile(app) if app.Status.LatestRevision != nil { appFile.AppRevisionName = app.Status.LatestRevision.Name } var err error - var wds []*Workload - if wds, err = p.parseWorkloads(ctx, appFile); err != nil { - return nil, errors.Wrapf(err, "failed to parseWorkloads") + if err = p.parseComponents(ctx, appFile); err != nil { + return nil, errors.Wrap(err, "failed to parseComponents") } if err = p.parseWorkflowSteps(ctx, appFile); err != nil { - return nil, errors.Wrapf(err, "failed to parseWorkflowSteps") + return nil, errors.Wrap(err, "failed to parseWorkflowSteps") } if err = p.parsePolicies(ctx, appFile); err != nil { - return nil, errors.Wrapf(err, "failed to parsePolicies") + return nil, errors.Wrap(err, "failed to parsePolicies") } if err = p.parseReferredObjects(ctx, appFile); err != nil { - return nil, errors.Wrapf(err, "failed to parseReferredObjects") - } - - for _, w := range wds { - if w == nil { - continue - } - if w.FullTemplate.ComponentDefinition != nil { - cd := w.FullTemplate.ComponentDefinition.DeepCopy() - cd.Status = v1beta1.ComponentDefinitionStatus{} - appFile.RelatedComponentDefinitions[w.FullTemplate.ComponentDefinition.Name] = cd - } - for _, t := range w.Traits { - if t == nil { - continue - } - if t.FullTemplate.TraitDefinition != nil { - td := t.FullTemplate.TraitDefinition.DeepCopy() - td.Status = v1beta1.TraitDefinitionStatus{} - appFile.RelatedTraitDefinitions[t.FullTemplate.TraitDefinition.Name] = td - } - } + return nil, errors.Wrap(err, "failed to parseReferredObjects") } return appFile, nil } -func (p *Parser) newAppFile(appName, ns string, app *v1beta1.Application) *Appfile { +func newAppFile(app *v1beta1.Application) *Appfile { file := &Appfile{ - Name: appName, - Namespace: ns, + Name: app.Name, + Namespace: app.Namespace, AppLabels: make(map[string]string), AppAnnotations: make(map[string]string), @@ -171,8 +147,7 @@ func (p *Parser) newAppFile(appName, ns string, app *v1beta1.Application) *Appfi ExternalPolicies: make(map[string]*v1alpha1.Policy), - parser: p, - app: app, + app: app, } for k, v := range app.Annotations { file.AppAnnotations[k] = v @@ -238,10 +213,8 @@ func (p *Parser) GenerateAppFileFromRevision(appRev *v1beta1.ApplicationRevision inheritLabelAndAnnotationFromAppRev(appRev) - app := appRev.Spec.Application.DeepCopy() - ns := app.Namespace - appName := app.Name - appfile := p.newAppFile(appName, ns, app) + ctx := context.Background() + appfile := newAppFile(appRev.Spec.Application.DeepCopy()) appfile.AppRevision = appRev appfile.AppRevisionName = appRev.Name appfile.AppRevisionHash = appRev.Labels[oam.LabelAppRevisionHash] @@ -251,62 +224,52 @@ func (p *Parser) GenerateAppFileFromRevision(appRev *v1beta1.ApplicationRevision } appfile.ExternalWorkflow = appRev.Spec.Workflow - var wds []*Workload - for _, comp := range app.Spec.Components { - wd, err := p.ParseWorkloadFromRevision(comp, appRev) - if err != nil { - return nil, err - } - wds = append(wds, wd) + if err := p.parseComponentsFromRevision(appfile); err != nil { + return nil, errors.Wrap(err, "failed to parseComponentsFromRevision") } - appfile.Workloads = wds - appfile.Components = app.Spec.Components - if err := p.parseWorkflowStepsFromRevision(context.Background(), appfile); err != nil { - return nil, errors.Wrapf(err, "failed to parseWorkflowStepsFromRevision") + if err := p.parseWorkflowStepsFromRevision(ctx, appfile); err != nil { + return nil, errors.Wrap(err, "failed to parseWorkflowStepsFromRevision") } - if err := p.parsePoliciesFromRevision(context.Background(), appfile); err != nil { - return nil, errors.Wrapf(err, "failed to parsePolicies") + if err := p.parsePoliciesFromRevision(ctx, appfile); err != nil { + return nil, errors.Wrap(err, "failed to parsePolicies") } if err := p.parseReferredObjectsFromRevision(appfile); err != nil { - return nil, errors.Wrapf(err, "failed to parseReferredObjects") - } - - for k, v := range appRev.Spec.ComponentDefinitions { - appfile.RelatedComponentDefinitions[k] = v.DeepCopy() - } - for k, v := range appRev.Spec.TraitDefinitions { - appfile.RelatedTraitDefinitions[k] = v.DeepCopy() - } - for k, v := range appRev.Spec.WorkflowStepDefinitions { - appfile.RelatedWorkflowStepDefinitions[k] = v.DeepCopy() + return nil, errors.Wrap(err, "failed to parseReferredObjects") } // add compatible code for upgrading to v1.3 as the workflow steps were not recorded before v1.2 if len(appfile.RelatedWorkflowStepDefinitions) == 0 && len(appfile.WorkflowSteps) > 0 { - ctx := context.Background() - for _, workflowStep := range appfile.WorkflowSteps { - if step.IsBuiltinWorkflowStepType(workflowStep.Type) { - continue - } - if _, found := appfile.RelatedWorkflowStepDefinitions[workflowStep.Type]; found { - continue - } - def := &v1beta1.WorkflowStepDefinition{} - if err := util.GetCapabilityDefinition(ctx, p.client, def, workflowStep.Type); err != nil { - return nil, errors.Wrapf(err, "failed to get workflow step definition %s", workflowStep.Type) - } - appfile.RelatedWorkflowStepDefinitions[workflowStep.Type] = def - } - - appRev.Spec.WorkflowStepDefinitions = make(map[string]*v1beta1.WorkflowStepDefinition) - for name, def := range appfile.RelatedWorkflowStepDefinitions { - appRev.Spec.WorkflowStepDefinitions[name] = def + if err := p.parseWorkflowStepsForLegacyRevision(ctx, appfile); err != nil { + return nil, errors.Wrap(err, "failed to parseWorkflowStepsForLegacyRevision") } } return appfile, nil } +// parseWorkflowStepsForLegacyRevision compatible for upgrading to v1.3 as the workflow steps were not recorded before v1.2 +func (p *Parser) parseWorkflowStepsForLegacyRevision(ctx context.Context, af *Appfile) error { + for _, workflowStep := range af.WorkflowSteps { + if step.IsBuiltinWorkflowStepType(workflowStep.Type) { + continue + } + if _, found := af.RelatedWorkflowStepDefinitions[workflowStep.Type]; found { + continue + } + def := &v1beta1.WorkflowStepDefinition{} + if err := util.GetCapabilityDefinition(ctx, p.client, def, workflowStep.Type); err != nil { + return errors.Wrapf(err, "failed to get workflow step definition %s", workflowStep.Type) + } + af.RelatedWorkflowStepDefinitions[workflowStep.Type] = def + } + + af.AppRevision.Spec.WorkflowStepDefinitions = make(map[string]*v1beta1.WorkflowStepDefinition) + for name, def := range af.RelatedWorkflowStepDefinitions { + af.AppRevision.Spec.WorkflowStepDefinitions[name] = def + } + return nil +} + func (p *Parser) parseReferredObjectsFromRevision(af *Appfile) error { af.ReferredObjects = []*unstructured.Unstructured{} for _, obj := range af.AppRevision.Spec.ReferredObjects { @@ -381,11 +344,11 @@ func (p *Parser) parsePoliciesFromRevision(ctx context.Context, af *Appfile) (er case v1alpha1.DebugPolicyType: af.Debug = true default: - w, err := p.makeWorkloadFromRevision(policy.Name, policy.Type, types.TypePolicy, policy.Properties, af.AppRevision) + w, err := p.makeComponentFromRevision(policy.Name, policy.Type, types.TypePolicy, policy.Properties, af.AppRevision) if err != nil { return err } - af.PolicyWorkloads = append(af.PolicyWorkloads, w) + af.ParsedPolicies = append(af.ParsedPolicies, w) } } return nil @@ -424,11 +387,11 @@ func (p *Parser) parsePolicies(ctx context.Context, af *Appfile) (err error) { af.RelatedTraitDefinitions[def.Name] = def } default: - w, err := p.makeWorkload(ctx, policy.Name, policy.Type, types.TypePolicy, policy.Properties) + w, err := p.makeComponent(ctx, policy.Name, policy.Type, types.TypePolicy, policy.Properties) if err != nil { return err } - af.PolicyWorkloads = append(af.PolicyWorkloads, w) + af.ParsedPolicies = append(af.ParsedPolicies, w) } } return nil @@ -472,7 +435,14 @@ func (p *Parser) loadWorkflowToAppfile(ctx context.Context, af *Appfile) error { } func (p *Parser) parseWorkflowStepsFromRevision(ctx context.Context, af *Appfile) error { - return p.loadWorkflowToAppfile(ctx, af) + if err := p.loadWorkflowToAppfile(ctx, af); err != nil { + return err + } + // Definitions are already in AppRevision + for k, v := range af.AppRevision.Spec.WorkflowStepDefinitions { + af.RelatedWorkflowStepDefinitions[k] = v.DeepCopy() + } + return nil } func (p *Parser) parseWorkflowSteps(ctx context.Context, af *Appfile) error { @@ -480,14 +450,14 @@ func (p *Parser) parseWorkflowSteps(ctx context.Context, af *Appfile) error { return err } for _, workflowStep := range af.WorkflowSteps { - err := p.parseWorkflowStep(ctx, af, workflowStep.Type) + err := p.fetchAndSetWorkflowStepDefinition(ctx, af, workflowStep.Type) if err != nil { return err } if workflowStep.SubSteps != nil { for _, workflowSubStep := range workflowStep.SubSteps { - err := p.parseWorkflowStep(ctx, af, workflowSubStep.Type) + err := p.fetchAndSetWorkflowStepDefinition(ctx, af, workflowSubStep.Type) if err != nil { return err } @@ -497,7 +467,7 @@ func (p *Parser) parseWorkflowSteps(ctx context.Context, af *Appfile) error { return nil } -func (p *Parser) parseWorkflowStep(ctx context.Context, af *Appfile, workflowStepType string) error { +func (p *Parser) fetchAndSetWorkflowStepDefinition(ctx context.Context, af *Appfile, workflowStepType string) error { if step.IsBuiltinWorkflowStepType(workflowStepType) { return nil } @@ -512,36 +482,36 @@ func (p *Parser) parseWorkflowStep(ctx context.Context, af *Appfile, workflowSte return nil } -func (p *Parser) makeWorkload(ctx context.Context, name, typ string, capType types.CapType, props *runtime.RawExtension) (*Workload, error) { +func (p *Parser) makeComponent(ctx context.Context, name, typ string, capType types.CapType, props *runtime.RawExtension) (*Component, error) { templ, err := p.tmplLoader.LoadTemplate(ctx, p.client, typ, capType) if err != nil { return nil, errors.WithMessagef(err, "fetch component/policy type of %s", name) } - return p.convertTemplate2Workload(name, typ, props, templ) + return p.convertTemplate2Component(name, typ, props, templ) } -func (p *Parser) makeWorkloadFromRevision(name, typ string, capType types.CapType, props *runtime.RawExtension, appRev *v1beta1.ApplicationRevision) (*Workload, error) { +func (p *Parser) makeComponentFromRevision(name, typ string, capType types.CapType, props *runtime.RawExtension, appRev *v1beta1.ApplicationRevision) (*Component, error) { templ, err := LoadTemplateFromRevision(typ, capType, appRev, p.client.RESTMapper()) if err != nil { return nil, errors.WithMessagef(err, "fetch component/policy type of %s from revision", name) } - return p.convertTemplate2Workload(name, typ, props, templ) + return p.convertTemplate2Component(name, typ, props, templ) } -func (p *Parser) convertTemplate2Workload(name, typ string, props *runtime.RawExtension, templ *Template) (*Workload, error) { +func (p *Parser) convertTemplate2Component(name, typ string, props *runtime.RawExtension, templ *Template) (*Component, error) { settings, err := util.RawExtension2Map(props) if err != nil { return nil, errors.WithMessagef(err, "fail to parse settings for %s", name) } - wlType, err := util.ConvertDefinitionRevName(typ) + cpType, err := util.ConvertDefinitionRevName(typ) if err != nil { - wlType = typ + cpType = typ } - return &Workload{ + return &Component{ Traits: []*Trait{}, Name: name, - Type: wlType, + Type: cpType, CapabilityCategory: templ.CapabilityCategory, FullTemplate: templ, Params: settings, @@ -549,25 +519,61 @@ func (p *Parser) convertTemplate2Workload(name, typ string, props *runtime.RawEx }, nil } -// parseWorkloads resolve an Application Components and Traits to generate Workloads -func (p *Parser) parseWorkloads(ctx context.Context, af *Appfile) ([]*Workload, error) { - var wds []*Workload - for _, comp := range af.app.Spec.Components { - wd, err := p.parseWorkload(ctx, comp) +// parseComponents resolve an Application Components and Traits to generate Component +func (p *Parser) parseComponents(ctx context.Context, af *Appfile) error { + var comps []*Component + for _, c := range af.app.Spec.Components { + comp, err := p.parseComponent(ctx, c) if err != nil { - return nil, err + return err } - wds = append(wds, wd) + comps = append(comps, comp) } - af.Workloads = wds + + af.ParsedComponents = comps af.Components = af.app.Spec.Components - return wds, nil + setComponentDefinitions(af, comps) + + return nil } -// parseWorkload resolve an ApplicationComponent and generate a Workload +func setComponentDefinitions(af *Appfile, comps []*Component) { + for _, comp := range comps { + if comp == nil { + continue + } + if comp.FullTemplate.ComponentDefinition != nil { + cd := comp.FullTemplate.ComponentDefinition.DeepCopy() + cd.Status = v1beta1.ComponentDefinitionStatus{} + af.RelatedComponentDefinitions[comp.FullTemplate.ComponentDefinition.Name] = cd + } + for _, t := range comp.Traits { + if t == nil { + continue + } + if t.FullTemplate.TraitDefinition != nil { + td := t.FullTemplate.TraitDefinition.DeepCopy() + td.Status = v1beta1.TraitDefinitionStatus{} + af.RelatedTraitDefinitions[t.FullTemplate.TraitDefinition.Name] = td + } + } + } +} + +// setComponentDefinitionsFromRevision can set related definitions directly from app revision +func setComponentDefinitionsFromRevision(af *Appfile) { + for k, v := range af.AppRevision.Spec.ComponentDefinitions { + af.RelatedComponentDefinitions[k] = v.DeepCopy() + } + for k, v := range af.AppRevision.Spec.TraitDefinitions { + af.RelatedTraitDefinitions[k] = v.DeepCopy() + } +} + +// parseComponent resolve an ApplicationComponent and generate a Component // containing ALL information required by an Appfile. -func (p *Parser) parseWorkload(ctx context.Context, comp common.ApplicationComponent) (*Workload, error) { - workload, err := p.makeWorkload(ctx, comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties) +func (p *Parser) parseComponent(ctx context.Context, comp common.ApplicationComponent) (*Component, error) { + workload, err := p.makeComponent(ctx, comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties) if err != nil { return nil, err } @@ -578,7 +584,7 @@ func (p *Parser) parseWorkload(ctx context.Context, comp common.ApplicationCompo return workload, nil } -func (p *Parser) parseTraits(ctx context.Context, workload *Workload, comp common.ApplicationComponent) error { +func (p *Parser) parseTraits(ctx context.Context, workload *Component, comp common.ApplicationComponent) error { for _, traitValue := range comp.Traits { properties, err := util.RawExtension2Map(traitValue.Properties) if err != nil { @@ -594,10 +600,26 @@ func (p *Parser) parseTraits(ctx context.Context, workload *Workload, comp commo return nil } -// ParseWorkloadFromRevision resolve an ApplicationComponent and generate a Workload +func (p *Parser) parseComponentsFromRevision(af *Appfile) error { + var comps []*Component + for _, c := range af.app.Spec.Components { + comp, err := p.ParseComponentFromRevision(c, af.AppRevision) + if err != nil { + return err + } + comps = append(comps, comp) + } + af.ParsedComponents = comps + af.Components = af.app.Spec.Components + // Definitions are already in AppRevision + setComponentDefinitionsFromRevision(af) + return nil +} + +// ParseComponentFromRevision resolve an ApplicationComponent and generate a Component // containing ALL information required by an Appfile from app revision. -func (p *Parser) ParseWorkloadFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Workload, error) { - workload, err := p.makeWorkloadFromRevision(comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties, appRev) +func (p *Parser) ParseComponentFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Component, error) { + workload, err := p.makeComponentFromRevision(comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties, appRev) if err != nil { return nil, err } @@ -609,7 +631,7 @@ func (p *Parser) ParseWorkloadFromRevision(comp common.ApplicationComponent, app return workload, nil } -func (p *Parser) parseTraitsFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision, workload *Workload) error { +func (p *Parser) parseTraitsFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision, workload *Component) error { for _, traitValue := range comp.Traits { properties, err := util.RawExtension2Map(traitValue.Properties) if err != nil { @@ -625,35 +647,35 @@ func (p *Parser) parseTraitsFromRevision(comp common.ApplicationComponent, appRe return nil } -// ParseWorkloadFromRevisionAndClient resolve an ApplicationComponent and generate a Workload +// ParseComponentFromRevisionAndClient resolve an ApplicationComponent and generate a Component // containing ALL information required by an Appfile from app revision, and will fall back to // load external definitions if not found -func (p *Parser) ParseWorkloadFromRevisionAndClient(ctx context.Context, comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Workload, error) { - workload, err := p.makeWorkloadFromRevision(comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties, appRev) +func (p *Parser) ParseComponentFromRevisionAndClient(ctx context.Context, c common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Component, error) { + comp, err := p.makeComponentFromRevision(c.Name, c.Type, types.TypeComponentDefinition, c.Properties, appRev) if IsNotFoundInAppRevision(err) { - workload, err = p.makeWorkload(ctx, comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties) + comp, err = p.makeComponent(ctx, c.Name, c.Type, types.TypeComponentDefinition, c.Properties) } if err != nil { return nil, err } - for _, traitValue := range comp.Traits { + for _, traitValue := range c.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 nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, c.Name) } trait, err := p.parseTraitFromRevision(traitValue.Type, properties, appRev) if IsNotFoundInAppRevision(err) { 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 nil, errors.WithMessagef(err, "component(%s) parse trait(%s)", c.Name, traitValue.Type) } - workload.Traits = append(workload.Traits, trait) + comp.Traits = append(comp.Traits, trait) } - return workload, nil + return comp, nil } func (p *Parser) parseTrait(ctx context.Context, name string, properties map[string]interface{}) (*Trait, error) { @@ -692,7 +714,7 @@ func (p *Parser) convertTemplate2Trait(name string, properties map[string]interf }, nil } -// ValidateComponentNames validate all component names whether repeat in cluster and template +// ValidateComponentNames validate all component names whether repeat in app func (p *Parser) ValidateComponentNames(app *v1beta1.Application) (int, error) { compNames := map[string]struct{}{} for idx, comp := range app.Spec.Components { diff --git a/pkg/appfile/parser_test.go b/pkg/appfile/parser_test.go index f9925c3c2..672e183bf 100644 --- a/pkg/appfile/parser_test.go +++ b/pkg/appfile/parser_test.go @@ -46,7 +46,7 @@ import ( var expectedExceptApp = &Appfile{ Name: "application-sample", - Workloads: []*Workload{ + ParsedComponents: []*Component{ { Name: "myweb", Type: "worker", @@ -286,11 +286,11 @@ var _ = Describe("Test application parser", func() { }) func equal(af, dest *Appfile) bool { - if af.Name != dest.Name || len(af.Workloads) != len(dest.Workloads) { + if af.Name != dest.Name || len(af.ParsedComponents) != len(dest.ParsedComponents) { return false } - for i, wd := range af.Workloads { - destWd := dest.Workloads[i] + for i, wd := range af.ParsedComponents { + destWd := dest.ParsedComponents[i] if wd.Name != destWd.Name || len(wd.Traits) != len(destWd.Traits) { return false } @@ -327,7 +327,7 @@ var _ = Describe("Test application parser", func() { // prepare verify data expectedExceptAppfile = &Appfile{ Name: "backport-1-2-test-demo", - Workloads: []*Workload{ + ParsedComponents: []*Component{ { Name: "backport-1-2-test-demo", Type: "webservice", @@ -502,14 +502,17 @@ patch: spec: replicas: parameter.replicas _, err := NewApplicationParser(&mockClient, pd).GenerateAppFile(context.TODO(), &app) Expect(err).Should(HaveOccurred()) - Expect(err.Error() == "failed to get workflow step definition apply-application-unknown: not found").Should(BeTrue()) + Expect(err.Error()).Should(SatisfyAll( + ContainSubstring("failed to get workflow step definition apply-application-unknown: not found"), + ContainSubstring("failed to parseWorkflowStepsForLegacyRevision")), + ) }) }) }) func TestParser_parseTraits(t *testing.T) { type args struct { - workload *Workload + workload *Component comp common.ApplicationComponent } tests := []struct { @@ -517,7 +520,7 @@ func TestParser_parseTraits(t *testing.T) { args args wantErr assert.ErrorAssertionFunc mockTemplateLoaderFn TemplateLoaderFn - validateFunc func(w *Workload) bool + validateFunc func(w *Component) bool }{ { name: "test empty traits", @@ -574,7 +577,7 @@ func TestParser_parseTraits(t *testing.T) { }, }, }, - workload: &Workload{}, + workload: &Component{}, }, wantErr: assert.NoError, mockTemplateLoaderFn: func(ctx context.Context, reader client.Client, s string, capType types.CapType) (*Template, error) { @@ -585,7 +588,7 @@ func TestParser_parseTraits(t *testing.T) { CustomStatus: "healthy", }, nil }, - validateFunc: func(w *Workload) bool { + validateFunc: func(w *Component) bool { return w != nil && len(w.Traits) != 0 && w.Traits[0].Name == "expose" && w.Traits[0].Template == "template" }, }, @@ -608,12 +611,12 @@ func TestParser_parseTraitsFromRevision(t *testing.T) { type args struct { comp common.ApplicationComponent appRev *v1beta1.ApplicationRevision - workload *Workload + workload *Component } tests := []struct { name string args args - validateFunc func(w *Workload) bool + validateFunc func(w *Component) bool wantErr assert.ErrorAssertionFunc }{ { @@ -634,7 +637,7 @@ func TestParser_parseTraitsFromRevision(t *testing.T) { }, }, }, - workload: &Workload{}, + workload: &Component{}, }, wantErr: assert.Error, }, @@ -656,7 +659,7 @@ func TestParser_parseTraitsFromRevision(t *testing.T) { }, }, }, - workload: &Workload{}, + workload: &Component{}, }, wantErr: assert.Error, }, @@ -685,10 +688,10 @@ func TestParser_parseTraitsFromRevision(t *testing.T) { }, }, }, - workload: &Workload{}, + workload: &Component{}, }, wantErr: assert.NoError, - validateFunc: func(w *Workload) bool { + validateFunc: func(w *Component) bool { return w != nil && len(w.Traits) == 1 && w.Traits[0].Name == "expose" }, }, diff --git a/pkg/appfile/unit_test.go b/pkg/appfile/unit_test.go index 64200d8f8..297559c0e 100644 --- a/pkg/appfile/unit_test.go +++ b/pkg/appfile/unit_test.go @@ -38,7 +38,7 @@ func TestIsNotFoundInAppRevision(t *testing.T) { require.True(t, IsNotFoundInAppRevision(fmt.Errorf("ComponentDefinition XXX not found in app revision"))) } -func TestParseWorkloadFromRevisionAndClient(t *testing.T) { +func TestParseComponentFromRevisionAndClient(t *testing.T) { ctx := context.Background() cli := fake.NewClientBuilder().WithScheme(scheme).Build() p := &Parser{ @@ -63,21 +63,21 @@ func TestParseWorkloadFromRevisionAndClient(t *testing.T) { require.NoError(t, cli.Create(ctx, cd)) require.NoError(t, cli.Create(ctx, td)) appRev.Spec.TraitDefinitions = map[string]*v1beta1.TraitDefinition{"internal": {}} - _, err := p.ParseWorkloadFromRevisionAndClient(ctx, comp, appRev) + _, err := p.ParseComponentFromRevisionAndClient(ctx, comp, appRev) require.NoError(t, err) _comp1 := comp.DeepCopy() _comp1.Type = "bad" - _, err = p.ParseWorkloadFromRevisionAndClient(ctx, *_comp1, appRev) + _, err = p.ParseComponentFromRevisionAndClient(ctx, *_comp1, appRev) require.Error(t, err) _comp2 := comp.DeepCopy() _comp2.Traits[0].Type = "bad" - _, err = p.ParseWorkloadFromRevisionAndClient(ctx, *_comp2, appRev) + _, err = p.ParseComponentFromRevisionAndClient(ctx, *_comp2, appRev) require.Error(t, err) _comp3 := comp.DeepCopy() _comp3.Traits[0].Properties = &runtime.RawExtension{Raw: []byte(`bad`)} - _, err = p.ParseWorkloadFromRevisionAndClient(ctx, *_comp3, appRev) + _, err = p.ParseComponentFromRevisionAndClient(ctx, *_comp3, appRev) require.Error(t, err) } diff --git a/pkg/appfile/validate.go b/pkg/appfile/validate.go index 006425ef5..ca8ed35b7 100644 --- a/pkg/appfile/validate.go +++ b/pkg/appfile/validate.go @@ -30,7 +30,7 @@ import ( // ValidateCUESchematicAppfile validates CUE schematic workloads in an Appfile func (p *Parser) ValidateCUESchematicAppfile(a *Appfile) error { - for _, wl := range a.Workloads { + for _, wl := range a.ParsedComponents { // because helm & kube schematic has no CUE template // it only validates CUE schematic workload if wl.CapabilityCategory != types.CUECategory || wl.Type == v1alpha1.RefObjectsComponentType { @@ -53,7 +53,7 @@ func (p *Parser) ValidateCUESchematicAppfile(a *Appfile) error { return nil } -func newValidationProcessContext(wl *Workload, ctxData velaprocess.ContextData) (process.Context, error) { +func newValidationProcessContext(c *Component, ctxData velaprocess.ContextData) (process.Context, error) { baseHooks := []process.BaseHook{ // add more hook funcs here to validate CUE base } @@ -65,7 +65,7 @@ func newValidationProcessContext(wl *Workload, ctxData velaprocess.ContextData) ctxData.BaseHooks = baseHooks ctxData.AuxiliaryHooks = auxiliaryHooks pCtx := velaprocess.NewContext(ctxData) - if err := wl.EvalContext(pCtx); err != nil { + if err := c.EvalContext(pCtx); err != nil { return nil, errors.Wrapf(err, "evaluate base template app=%s in namespace=%s", ctxData.AppName, ctxData.Namespace) } return pCtx, nil diff --git a/pkg/appfile/validate_test.go b/pkg/appfile/validate_test.go index eb753d631..5642369b3 100644 --- a/pkg/appfile/validate_test.go +++ b/pkg/appfile/validate_test.go @@ -34,7 +34,7 @@ var _ = Describe("Test validate CUE schematic Appfile", func() { DescribeTable("Test validate outputs name unique", func(tc SubTestCase) { Expect("").Should(BeEmpty()) - wl := &Workload{ + wl := &Component{ Name: "myweb", Type: "worker", CapabilityCategory: types.CUECategory, diff --git a/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go b/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go index 2a803ceb6..0f5709b6d 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/application_controller.go @@ -258,7 +258,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu } var phase = common.ApplicationRunning - if !hasHealthCheckPolicy(appFile.PolicyWorkloads) { + if !hasHealthCheckPolicy(appFile.ParsedPolicies) { app.Status.Services = handler.services if !isHealthy(handler.services) { phase = common.ApplicationUnhealthy @@ -498,7 +498,7 @@ func (r *Reconciler) doWorkflowFinish(logCtx monitorContext.Context, app *v1beta logCtx.Info("Application manifests has applied by workflow successfully") } -func hasHealthCheckPolicy(policies []*appfile.Workload) bool { +func hasHealthCheckPolicy(policies []*appfile.Component) bool { for _, p := range policies { if p.FullTemplate != nil && p.FullTemplate.PolicyDefinition != nil && p.FullTemplate.PolicyDefinition.Spec.ManageHealthCheck { diff --git a/pkg/controller/core.oam.dev/v1beta1/application/apply.go b/pkg/controller/core.oam.dev/v1beta1/application/apply.go index 90d676fe2..0caa0e4a7 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/apply.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/apply.go @@ -227,13 +227,13 @@ func (h *AppHandler) ProduceArtifacts(ctx context.Context, comps []*types.Compon } // collectTraitHealthStatus collect trait health status -func (h *AppHandler) collectTraitHealthStatus(wl *appfile.Workload, tr *appfile.Trait, appRev *v1beta1.ApplicationRevision, overrideNamespace string) (common.ApplicationTraitStatus, []*unstructured.Unstructured, error) { +func (h *AppHandler) collectTraitHealthStatus(comp *appfile.Component, tr *appfile.Trait, appRev *v1beta1.ApplicationRevision, overrideNamespace string) (common.ApplicationTraitStatus, []*unstructured.Unstructured, error) { defer func(clusterName string) { - wl.Ctx.SetCtx(pkgmulticluster.WithCluster(wl.Ctx.GetCtx(), clusterName)) - }(multicluster.ClusterNameInContext(wl.Ctx.GetCtx())) + comp.Ctx.SetCtx(pkgmulticluster.WithCluster(comp.Ctx.GetCtx(), clusterName)) + }(multicluster.ClusterNameInContext(comp.Ctx.GetCtx())) var ( - pCtx = wl.Ctx + pCtx = comp.Ctx appName = appRev.Spec.Application.Name traitStatus = common.ApplicationTraitStatus{ Type: tr.Name, @@ -249,55 +249,55 @@ func (h *AppHandler) collectTraitHealthStatus(wl *appfile.Workload, tr *appfile. _accessor := util.NewApplicationResourceNamespaceAccessor(h.app.Namespace, traitOverrideNamespace) templateContext, err := tr.GetTemplateContext(pCtx, h.r.Client, _accessor) if err != nil { - return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, get template context error", appName, wl.Name, tr.Name) + return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, get template context error", appName, comp.Name, tr.Name) } if ok, err := tr.EvalHealth(templateContext); !ok || err != nil { traitStatus.Healthy = false } traitStatus.Message, err = tr.EvalStatus(templateContext) if err != nil { - return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, evaluate status message error", appName, wl.Name, tr.Name) + return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, evaluate status message error", appName, comp.Name, tr.Name) } return traitStatus, extractOutputs(templateContext), nil } // collectWorkloadHealthStatus collect workload health status -func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, status *common.ApplicationComponentStatus, accessor util.NamespaceAccessor) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { +func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, status *common.ApplicationComponentStatus, accessor util.NamespaceAccessor) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) { var output *unstructured.Unstructured var outputs []*unstructured.Unstructured var ( appName = appRev.Spec.Application.Name isHealth = true ) - if wl.CapabilityCategory == types.TerraformCategory { + if comp.CapabilityCategory == types.TerraformCategory { var configuration terraforv1beta2.Configuration - if err := h.r.Client.Get(ctx, client.ObjectKey{Name: wl.Name, Namespace: accessor.Namespace()}, &configuration); err != nil { + if err := h.r.Client.Get(ctx, client.ObjectKey{Name: comp.Name, Namespace: accessor.Namespace()}, &configuration); err != nil { if kerrors.IsNotFound(err) { var legacyConfiguration terraforv1beta1.Configuration - if err := h.r.Client.Get(ctx, client.ObjectKey{Name: wl.Name, Namespace: accessor.Namespace()}, &legacyConfiguration); err != nil { - return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, wl.Name) + if err := h.r.Client.Get(ctx, client.ObjectKey{Name: comp.Name, Namespace: accessor.Namespace()}, &legacyConfiguration); err != nil { + return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, comp.Name) } isHealth = setStatus(status, legacyConfiguration.Status.ObservedGeneration, legacyConfiguration.Generation, legacyConfiguration.GetLabels(), appRev.Name, legacyConfiguration.Status.Apply.State, legacyConfiguration.Status.Apply.Message) } else { - return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, wl.Name) + return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, comp.Name) } } else { isHealth = setStatus(status, configuration.Status.ObservedGeneration, configuration.Generation, configuration.GetLabels(), appRev.Name, configuration.Status.Apply.State, configuration.Status.Apply.Message) } } else { - templateContext, err := wl.GetTemplateContext(wl.Ctx, h.r.Client, accessor) + templateContext, err := comp.GetTemplateContext(comp.Ctx, h.r.Client, accessor) if err != nil { - return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, get template context error", appName, wl.Name) + return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, get template context error", appName, comp.Name) } - if ok, err := wl.EvalHealth(templateContext); !ok || err != nil { + if ok, err := comp.EvalHealth(templateContext); !ok || err != nil { isHealth = false } status.Healthy = isHealth - status.Message, err = wl.EvalStatus(templateContext) + status.Message, err = comp.EvalStatus(templateContext) if err != nil { - return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, evaluate workload status message error", appName, wl.Name) + return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, evaluate workload status message error", appName, comp.Name) } output, outputs = extractOutputAndOutputs(templateContext) } @@ -306,14 +306,14 @@ func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, wl *appfil // nolint // collectHealthStatus will collect health status of component, including component itself and traits. -func (h *AppHandler) collectHealthStatus(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, overrideNamespace string, skipWorkload bool, traitFilters ...TraitFilter) (*common.ApplicationComponentStatus, *unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { +func (h *AppHandler) collectHealthStatus(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, overrideNamespace string, skipWorkload bool, traitFilters ...TraitFilter) (*common.ApplicationComponentStatus, *unstructured.Unstructured, []*unstructured.Unstructured, bool, error) { output := new(unstructured.Unstructured) outputs := make([]*unstructured.Unstructured, 0) accessor := util.NewApplicationResourceNamespaceAccessor(h.app.Namespace, overrideNamespace) var ( status = common.ApplicationComponentStatus{ - Name: wl.Name, - WorkloadDefinition: wl.FullTemplate.Reference.Definition, + Name: comp.Name, + WorkloadDefinition: comp.FullTemplate.Reference.Definition, Healthy: true, Namespace: accessor.Namespace(), Cluster: multicluster.ClusterNameInContext(ctx), @@ -324,7 +324,7 @@ func (h *AppHandler) collectHealthStatus(ctx context.Context, wl *appfile.Worklo status = h.getServiceStatus(status) if !skipWorkload { - isHealth, output, outputs, err = h.collectWorkloadHealthStatus(ctx, wl, appRev, &status, accessor) + isHealth, output, outputs, err = h.collectWorkloadHealthStatus(ctx, comp, appRev, &status, accessor) if err != nil { return nil, nil, nil, false, err } @@ -332,7 +332,7 @@ func (h *AppHandler) collectHealthStatus(ctx context.Context, wl *appfile.Worklo var traitStatusList []common.ApplicationTraitStatus collectNext: - for _, tr := range wl.Traits { + for _, tr := range comp.Traits { for _, filter := range traitFilters { // If filtered out by one of the filters if filter(*tr) { @@ -340,7 +340,7 @@ collectNext: } } - traitStatus, _outputs, err := h.collectTraitHealthStatus(wl, tr, appRev, overrideNamespace) + traitStatus, _outputs, err := h.collectTraitHealthStatus(comp, tr, appRev, overrideNamespace) if err != nil { return nil, nil, nil, false, err } diff --git a/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go b/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go index 2e91c69be..b286169b3 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/dispatcher.go @@ -108,8 +108,8 @@ func ByTraitType(readyTraits, checkTraits []*unstructured.Unstructured) TraitFil // manifestDispatcher is a manifest dispatcher type manifestDispatcher struct { - run func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error) - healthCheck func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision) (bool, error) + run func(ctx context.Context, c *appfile.Component, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error) + healthCheck func(ctx context.Context, c *appfile.Component, appRev *v1beta1.ApplicationRevision) (bool, error) } func (h *AppHandler) generateDispatcher(appRev *v1beta1.ApplicationRevision, readyWorkload *unstructured.Unstructured, readyTraits []*unstructured.Unstructured, overrideNamespace string) ([]*manifestDispatcher, error) { @@ -124,25 +124,25 @@ func (h *AppHandler) generateDispatcher(appRev *v1beta1.ApplicationRevision, rea } dispatcher := new(manifestDispatcher) - dispatcher.healthCheck = func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision) (bool, error) { - skipWorkload, manifests := assembleManifestFn(wl.SkipApplyWorkload) + dispatcher.healthCheck = func(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision) (bool, error) { + skipWorkload, manifests := assembleManifestFn(comp.SkipApplyWorkload) if !h.resourceKeeper.ContainsResources(manifests) { return false, nil } - _, _, _, isHealth, err := h.collectHealthStatus(ctx, wl, appRev, options.OverrideNamespace, skipWorkload, + _, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, appRev, options.OverrideNamespace, skipWorkload, ByTraitType(readyTraits, options.Traits)) if err != nil { return false, err } return isHealth, nil } - dispatcher.run = func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error) { - skipWorkload, dispatchManifests := assembleManifestFn(wl.SkipApplyWorkload) - if isHealth, err := dispatcher.healthCheck(ctx, wl, appRev); !isHealth || err != nil { + dispatcher.run = func(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error) { + skipWorkload, dispatchManifests := assembleManifestFn(comp.SkipApplyWorkload) + if isHealth, err := dispatcher.healthCheck(ctx, comp, appRev); !isHealth || err != nil { if err := h.Dispatch(ctx, clusterName, common.WorkflowResourceCreator, dispatchManifests...); err != nil { return false, errors.WithMessage(err, "Dispatch") } - status, _, _, isHealth, err := h.collectHealthStatus(ctx, wl, appRev, options.OverrideNamespace, skipWorkload, + status, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, appRev, options.OverrideNamespace, skipWorkload, ByTraitType(readyTraits, options.Traits)) if err != nil { return false, errors.WithMessage(err, "CollectHealthStatus") diff --git a/pkg/controller/core.oam.dev/v1beta1/application/generator.go b/pkg/controller/core.oam.dev/v1beta1/application/generator.go index b57360796..3951c61fd 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/generator.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/generator.go @@ -108,8 +108,8 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context, oamProvider.Install(handlerProviders, app, af, h.r.Client, h.applyComponentFunc( appParser, appRev, af), h.renderComponentFunc(appParser, appRev, af)) pCtx := velaprocess.NewContext(generateContextDataFromApp(app, appRev.Name)) - renderer := func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Workload, error) { - return appParser.ParseWorkloadFromRevisionAndClient(ctx, comp, appRev) + renderer := func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error) { + return appParser.ParseComponentFromRevisionAndClient(ctx, comp, appRev) } multiclusterProvider.Install(handlerProviders, h.r.Client, app, af, h.applyComponentFunc(appParser, appRev, af), @@ -439,8 +439,8 @@ func (h *AppHandler) prepareWorkloadAndManifests(ctx context.Context, comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision, patcher *value.Value, - af *appfile.Appfile) (*appfile.Workload, *types.ComponentManifest, error) { - wl, err := appParser.ParseWorkloadFromRevisionAndClient(ctx, comp, appRev) + af *appfile.Appfile) (*appfile.Component, *types.ComponentManifest, error) { + wl, err := appParser.ParseComponentFromRevisionAndClient(ctx, comp, appRev) if err != nil { return nil, nil, errors.WithMessage(err, "ParseWorkload") } @@ -490,10 +490,10 @@ func renderComponentsAndTraits(client client.Client, manifest *types.ComponentMa return readyWorkload, readyTraits, nil } -func checkSkipApplyWorkload(wl *appfile.Workload) { - for _, trait := range wl.Traits { +func checkSkipApplyWorkload(comp *appfile.Component) { + for _, trait := range comp.Traits { if trait.FullTemplate.TraitDefinition.Spec.ManageWorkload { - wl.SkipApplyWorkload = true + comp.SkipApplyWorkload = true break } } diff --git a/pkg/controller/core.oam.dev/v1beta1/application/revision.go b/pkg/controller/core.oam.dev/v1beta1/application/revision.go index fba5ee483..5e01a0437 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/revision.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/revision.go @@ -213,7 +213,7 @@ func (h *AppHandler) gatherRevisionSpec(af *appfile.Appfile) (*v1beta1.Applicati }, }, } - for _, w := range af.Workloads { + for _, w := range af.ParsedComponents { if w == nil { continue } @@ -238,7 +238,7 @@ func (h *AppHandler) gatherRevisionSpec(af *appfile.Appfile) (*v1beta1.Applicati } } } - for _, p := range af.PolicyWorkloads { + for _, p := range af.ParsedPolicies { if p == nil || p.FullTemplate == nil { continue } diff --git a/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go b/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go index 9ceecbea4..a9bec583d 100644 --- a/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go +++ b/pkg/controller/core.oam.dev/v1beta1/application/revision_test.go @@ -177,7 +177,7 @@ var _ = Describe("test generate revision ", func() { Expect(handler.FinalizeAndApplyAppRevision(ctx)).Should(Succeed()) prevHash := generatedAppfile.AppRevisionHash handler.app.Status.LatestRevision = &common.Revision{Name: generatedAppfile.AppRevisionName, Revision: 1, RevisionHash: generatedAppfile.AppRevisionHash} - generatedAppfile.Workloads[0].FullTemplate.ComponentDefinition = nil + generatedAppfile.ParsedComponents[0].FullTemplate.ComponentDefinition = nil generatedAppfile.RelatedComponentDefinitions = map[string]*v1beta1.ComponentDefinition{} Expect(handler.PrepareCurrentAppRevision(ctx, generatedAppfile)).Should(Succeed()) nonChangeHash := generatedAppfile.AppRevisionHash diff --git a/pkg/oam/labels.go b/pkg/oam/labels.go index 27e221516..318902d58 100644 --- a/pkg/oam/labels.go +++ b/pkg/oam/labels.go @@ -23,8 +23,6 @@ const ( LabelAppName = "app.oam.dev/name" // LabelAppRevision records the name of Application, it's equal to name of AppConfig created by Application LabelAppRevision = "app.oam.dev/appRevision" - // LabelAppDeployment records the name of AppDeployment. - LabelAppDeployment = "app.oam.dev/appDeployment" // LabelAppComponent records the name of Component LabelAppComponent = "app.oam.dev/component" // LabelReplicaKey records the replica key of Component @@ -62,11 +60,6 @@ const ( // LabelControllerRevisionComponent indicate which component the revision belong to LabelControllerRevisionComponent = "controller.oam.dev/component" - // LabelComponentRevisionHash records the hash value of a component - LabelComponentRevisionHash = "app.oam.dev/component-revision-hash" - - // LabelAddonsName records the name of initializer stored in configMap - LabelAddonsName = "addons.oam.dev/type" // LabelAddonName indicates the name of the corresponding Addon LabelAddonName = "addons.oam.dev/name" @@ -142,13 +135,6 @@ const ( // its controller should not try to reconcile it AnnotationAppRevision = "app.oam.dev/app-revision" - // AnnotationAppRevisionOnly the Application update should only generate revision, - // not any appContexts or components. - AnnotationAppRevisionOnly = "app.oam.dev/revision-only" - - // AnnotationWorkflowContext is used to pass in the workflow context marshalled in json format. - AnnotationWorkflowContext = "app.oam.dev/workflow-context" - // AnnotationKubeVelaVersion is used to record current KubeVela version AnnotationKubeVelaVersion = "oam.dev/kubevela-version" @@ -158,15 +144,9 @@ const ( // AnnotationFilterLabelKeys is used to filter labels passed to workload and trait, split by comma AnnotationFilterLabelKeys = "filter.oam.dev/label-keys" - // AnnotationSkipGC is used to tell application to skip gc workload/trait - AnnotationSkipGC = "app.oam.dev/skipGC" - // AnnotationDefinitionRevisionName is used to specify the name of DefinitionRevision in component/trait definition AnnotationDefinitionRevisionName = "definitionrevision.oam.dev/name" - // AnnotationAddonsName records the name of initializer stored in configMap - AnnotationAddonsName = "addons.oam.dev/name" - // AnnotationLastAppliedConfiguration is kubectl annotations for 3-way merge AnnotationLastAppliedConfiguration = "kubectl.kubernetes.io/last-applied-configuration" @@ -189,12 +169,6 @@ const ( // AnnotationAppAlias specifies the alias for application in db. AnnotationAppAlias = "app.oam.dev/appAlias" - // AnnotationWorkloadGVK indicates the managed workload's GVK by trait - AnnotationWorkloadGVK = "trait.oam.dev/workload-gvk" - - // AnnotationWorkloadName indicates the managed workload's name by trait - AnnotationWorkloadName = "trait.oam.dev/workload-name" - // AnnotationControllerRequirement indicates the controller version that can process the application/definition. AnnotationControllerRequirement = "app.oam.dev/controller-version-require" diff --git a/pkg/workflow/providers/oam/apply.go b/pkg/workflow/providers/oam/apply.go index 9c0214676..69e47cf1f 100644 --- a/pkg/workflow/providers/oam/apply.go +++ b/pkg/workflow/providers/oam/apply.go @@ -53,7 +53,7 @@ type ComponentRender func(ctx context.Context, comp common.ApplicationComponent, type ComponentHealthCheck func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) // WorkloadRenderer renderer to render application component into workload -type WorkloadRenderer func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Workload, error) +type WorkloadRenderer func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error) type provider struct { render ComponentRender diff --git a/pkg/workflow/providers/terraform/terraform_test.go b/pkg/workflow/providers/terraform/terraform_test.go index 83d02b96f..246771723 100644 --- a/pkg/workflow/providers/terraform/terraform_test.go +++ b/pkg/workflow/providers/terraform/terraform_test.go @@ -33,14 +33,14 @@ import ( "github.com/oam-dev/kubevela/pkg/appfile" ) -func fakeWorkloadRenderer(_ context.Context, comp apicommon.ApplicationComponent) (*appfile.Workload, error) { +func fakeWorkloadRenderer(_ context.Context, comp apicommon.ApplicationComponent) (*appfile.Component, error) { if strings.HasPrefix(comp.Name, "error") { return nil, errors.New(comp.Name) } if strings.HasPrefix(comp.Name, "terraform") { - return &appfile.Workload{CapabilityCategory: types.TerraformCategory}, nil + return &appfile.Component{CapabilityCategory: types.TerraformCategory}, nil } - return &appfile.Workload{CapabilityCategory: types.CUECategory}, nil + return &appfile.Component{CapabilityCategory: types.CUECategory}, nil } func TestLoadTerraformComponents(t *testing.T) { diff --git a/references/appfile/addon.go b/references/appfile/addon.go index 3a0991012..ec2dbf077 100644 --- a/references/appfile/addon.go +++ b/references/appfile/addon.go @@ -71,7 +71,7 @@ func ApplyTerraform(app *v1beta1.Application, k8sClient client.Client, ioStream return nil, err } - for i, wl := range appFile.Workloads { + for i, wl := range appFile.ParsedComponents { switch wl.CapabilityCategory { case types.TerraformCategory: name := wl.Name @@ -191,8 +191,8 @@ func generateSecretFromTerraformOutput(k8sClient client.Client, outputList []str } // getTerraformJSONFiles gets Terraform JSON files or modules from workload -func getTerraformJSONFiles(wl *appfile.Workload, ctxData process.ContextData) ([]byte, error) { - pCtx, err := appfile.PrepareProcessContext(wl, ctxData) +func getTerraformJSONFiles(comp *appfile.Component, ctxData process.ContextData) ([]byte, error) { + pCtx, err := appfile.PrepareProcessContext(comp, ctxData) if err != nil { return nil, err } diff --git a/references/cli/components.go b/references/cli/components.go index 18933684c..abf2da8cc 100644 --- a/references/cli/components.go +++ b/references/cli/components.go @@ -190,7 +190,7 @@ func PrintComponentListFromRegistry(registry Registry, ioStreams cmdutil.IOStrea // InstallCompByNameFromRegistry will install given componentName comp to cluster from registry func InstallCompByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStreams, compName string, registry Registry) error { - capObj, data, err := registry.GetCap(compName) + _, data, err := registry.GetCap(compName) if err != nil { return err } @@ -200,7 +200,7 @@ func InstallCompByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStreams return err } - err = common.InstallComponentDefinition(k8sClient, data, ioStream, &capObj) + err = common.InstallComponentDefinition(k8sClient, data, ioStream) if err != nil { return err } diff --git a/references/cli/traits.go b/references/cli/traits.go index 249d2cf04..c7583a52d 100644 --- a/references/cli/traits.go +++ b/references/cli/traits.go @@ -189,7 +189,7 @@ func PrintTraitListFromRegistry(registry Registry, ioStreams cmdutil.IOStreams, // InstallTraitByNameFromRegistry will install given traitName trait to cluster func InstallTraitByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStreams, traitName string, registry Registry) error { - capObj, data, err := registry.GetCap(traitName) + _, data, err := registry.GetCap(traitName) if err != nil { return err } @@ -199,7 +199,7 @@ func InstallTraitByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStream return err } - err = common.InstallTraitDefinition(k8sClient, data, ioStream, &capObj) + err = common.InstallTraitDefinition(k8sClient, data, ioStream) if err != nil { return err } diff --git a/references/common/registry.go b/references/common/registry.go index 8d7f9a30e..9ac2fdb44 100644 --- a/references/common/registry.go +++ b/references/common/registry.go @@ -23,19 +23,17 @@ import ( "github.com/pkg/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" - "github.com/oam-dev/kubevela/pkg/oam/util" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" ) // InstallComponentDefinition will add a component into K8s cluster and install its controller -func InstallComponentDefinition(client client.Client, componentData []byte, ioStreams cmdutil.IOStreams, tp *types.Capability) error { +func InstallComponentDefinition(client client.Client, componentData []byte, ioStreams cmdutil.IOStreams) error { var cd v1beta1.ComponentDefinition var err error if componentData == nil { @@ -46,12 +44,6 @@ func InstallComponentDefinition(client client.Client, componentData []byte, ioSt } cd.Namespace = types.DefaultKubeVelaNS ioStreams.Info("Installing component: " + cd.Name) - if cd.Spec.Workload.Type == "" { - tp.CrdInfo = &types.CRDInfo{ - APIVersion: cd.Spec.Workload.Definition.APIVersion, - Kind: cd.Spec.Workload.Definition.Kind, - } - } if err = client.Create(context.Background(), &cd); err != nil && !apierrors.IsAlreadyExists(err) { return err } @@ -59,7 +51,7 @@ func InstallComponentDefinition(client client.Client, componentData []byte, ioSt } // InstallTraitDefinition will add a trait into K8s cluster and install it's controller -func InstallTraitDefinition(client client.Client, traitdata []byte, ioStreams cmdutil.IOStreams, cap *types.Capability) error { +func InstallTraitDefinition(client client.Client, traitdata []byte, ioStreams cmdutil.IOStreams) error { var td v1beta1.TraitDefinition var err error if err = yaml.Unmarshal(traitdata, &td); err != nil { @@ -67,17 +59,6 @@ func InstallTraitDefinition(client client.Client, traitdata []byte, ioStreams cm } td.Namespace = types.DefaultKubeVelaNS ioStreams.Info("Installing trait " + td.Name) - gvk, err := util.GetGVKFromDefinition(client.RESTMapper(), td.Spec.Reference) - if err != nil { - return err - } - cap.CrdInfo = &types.CRDInfo{ - APIVersion: v1.GroupVersion{ - Group: gvk.Group, - Version: gvk.Version, - }.String(), - Kind: gvk.Kind, - } if err = client.Create(context.Background(), &td); err != nil && !apierrors.IsAlreadyExists(err) { return err } diff --git a/references/docgen/cluster.go b/references/docgen/cluster.go index a64a05136..5006e2cc9 100644 --- a/references/docgen/cluster.go +++ b/references/docgen/cluster.go @@ -24,7 +24,6 @@ import ( "github.com/pkg/errors" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" @@ -171,7 +170,7 @@ func GetComponentsFromClusterWithValidateOption(ctx context.Context, namespace s continue } if validateFlag && defRef.Name != types.AutoDetectWorkloadDefinition { - if err = validateCapabilities(tmp, newClient.RESTMapper(), cd.Name, defRef); err != nil { + if err = validateCapabilities(newClient.RESTMapper(), cd.Name, defRef); err != nil { return nil, nil, err } } @@ -214,7 +213,7 @@ func GetTraitsFromClusterWithValidateOption(ctx context.Context, namespace strin } tmp.Namespace = namespace if validateFlag { - if err = validateCapabilities(tmp, newClient.RESTMapper(), td.Name, td.Spec.Reference); err != nil { + if err = validateCapabilities(newClient.RESTMapper(), td.Name, td.Spec.Reference); err != nil { return nil, nil, err } } @@ -285,22 +284,16 @@ func GetPolicies(ctx context.Context, namespace string, c common.Args) ([]types. } // validateCapabilities validates whether GVK are successfully retrieved. -func validateCapabilities(tmp *types.Capability, mapper meta.RESTMapper, definitionName string, reference commontypes.DefinitionReference) error { - var err error - gvk, err := util.GetGVKFromDefinition(mapper, reference) +func validateCapabilities(mapper meta.RESTMapper, definitionName string, reference commontypes.DefinitionReference) error { + _, err := util.GetGVKFromDefinition(mapper, reference) if err != nil { errMsg := err.Error() var substr = "no matches for " if strings.Contains(errMsg, substr) { - err = fmt.Errorf("expected provider: %s", strings.Split(errMsg, substr)[1]) + return fmt.Errorf("expected provider: %s", strings.Split(errMsg, substr)[1]) } return fmt.Errorf("installing capability '%s'... %w", definitionName, err) } - tmp.CrdInfo = &types.CRDInfo{ - APIVersion: metav1.GroupVersion{Group: gvk.Group, Version: gvk.Version}.String(), - Kind: gvk.Kind, - } - return nil } diff --git a/references/docgen/cluster_test.go b/references/docgen/cluster_test.go index bc7f1ef5f..7ef950bf5 100644 --- a/references/docgen/cluster_test.go +++ b/references/docgen/cluster_test.go @@ -77,10 +77,6 @@ var _ = Describe("DefinitionFiles", func() { Name: "env", }, }, - CrdInfo: &types.CRDInfo{ - APIVersion: "apps/v1", - Kind: "Deployment", - }, Labels: map[string]string{"usecase": "forplugintest"}, } @@ -110,11 +106,7 @@ var _ = Describe("DefinitionFiles", func() { }, }, CrdName: "deployments.apps", - CrdInfo: &types.CRDInfo{ - APIVersion: "apps/v1", - Kind: "Deployment", - }, - Labels: map[string]string{"usecase": "forplugintest"}, + Labels: map[string]string{"usecase": "forplugintest"}, } req, _ := labels.NewRequirement("usecase", selection.Equals, []string{"forplugintest"})