mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Refactor: capabilities and workload in appfile parsing (#6250)
This commit is contained in:
@@ -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"`
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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"})
|
||||
|
||||
Reference in New Issue
Block a user