Skip to content

Commit

Permalink
implement vela status in application CRD controller and refactor the …
Browse files Browse the repository at this point in the history
…health check code
  • Loading branch information
wonderflow committed Feb 3, 2021
1 parent dd68103 commit 8ff8128
Show file tree
Hide file tree
Showing 21 changed files with 726 additions and 477 deletions.
20 changes: 20 additions & 0 deletions apis/core.oam.dev/v1alpha2/application_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ const (
ApplicationRendering ApplicationPhase = "rendering"
// ApplicationRunning means the app finished rendering and applied result to the cluster
ApplicationRunning ApplicationPhase = "running"
// ApplicationHealthChecking means the app finished rendering and applied result to the cluster, but still unhealthy
ApplicationHealthChecking ApplicationPhase = "healthChecking"
)

// AppStatus defines the observed state of Application
Expand All @@ -49,6 +51,24 @@ type AppStatus struct {

// Components record the related Components created by Application Controller
Components []runtimev1alpha1.TypedReference `json:"components,omitempty"`

// Services record the status of the application services
Services []ApplicationComponentStatus `json:"services,omitempty"`
}

// ApplicationComponentStatus record the health status of App component
type ApplicationComponentStatus struct {
Name string `json:"name"`
Healthy bool `json:"healthy"`
Message string `json:"message,omitempty"`
Traits []ApplicationTraitStatus `json:"traits,omitempty"`
}

// ApplicationTraitStatus records the trait health status
type ApplicationTraitStatus struct {
Type string `json:"type"`
Healthy bool `json:"healthy"`
Message string `json:"message,omitempty"`
}

// ApplicationTrait defines the trait of application
Expand Down
42 changes: 42 additions & 0 deletions apis/core.oam.dev/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions charts/vela-core/crds/core.oam.dev_applications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,37 @@ spec:
- type
type: object
type: array
services:
description: Services record the status of the application services
items:
description: ApplicationComponentStatus record the health status of App component
properties:
healthy:
type: boolean
message:
type: string
name:
type: string
traits:
items:
description: ApplicationTraitStatus records the trait health status
properties:
healthy:
type: boolean
message:
type: string
type:
type: string
required:
- healthy
- type
type: object
type: array
required:
- healthy
- name
type: object
type: array
status:
description: ApplicationPhase is a label for the condition of a application at the current time
type: string
Expand Down
31 changes: 31 additions & 0 deletions legacy/charts/vela-core-legacy/crds/core.oam.dev_applications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,37 @@ spec:
- type
type: object
type: array
services:
description: Services record the status of the application services
items:
description: ApplicationComponentStatus record the health status of App component
properties:
healthy:
type: boolean
message:
type: string
name:
type: string
traits:
items:
description: ApplicationTraitStatus records the trait health status
properties:
healthy:
type: boolean
message:
type: string
type:
type: string
required:
- healthy
- type
type: object
type: array
required:
- healthy
- name
type: object
type: array
status:
description: ApplicationPhase is a label for the condition of a application at the current time
type: string
Expand Down
2 changes: 1 addition & 1 deletion pkg/appfile/addon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var _ = It("Test ApplyTerraform", func() {
ioStream := util.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
dm, _ := discoverymapper.New(cfg)
_, err := ApplyTerraform(app, k8sClient, ioStream, addonNamespace, dm)
Expect(err.Error()).Should(Equal("exit status 1"))
Expect(err).ShouldNot(BeNil())
})

var _ = Describe("Test generateSecretFromTerraformOutput", func() {
Expand Down
7 changes: 6 additions & 1 deletion pkg/appfile/api/appfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ const (
DefaultUnknowFormatAppfilePath = "./Appfile"
)

const (
// DefaultHealthScopeKey is the key in application for default health scope
DefaultHealthScopeKey = "healthscopes.core.oam.dev"
)

// AppFile defines the spec of KubeVela Appfile
type AppFile struct {
Name string `json:"name"`
Expand Down Expand Up @@ -179,7 +184,7 @@ func addDefaultHealthScopeToApplication(app *v1alpha2.Application) *v1alpha2.Hea
health.Spec.WorkloadReferences = make([]v1alpha1.TypedReference, 0)
for i := range app.Spec.Components {
// FIXME(wonderflow): the hardcode health scope should be fixed.
app.Spec.Components[i].Scopes = map[string]string{"healthscopes.core.oam.dev": health.Name}
app.Spec.Components[i].Scopes = map[string]string{DefaultHealthScopeKey: health.Name}
}
return health
}
Expand Down
100 changes: 43 additions & 57 deletions pkg/appfile/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const (
// AppfileBuiltinConfig defines the built-in config variable
AppfileBuiltinConfig = "config"

// OAMApplicationLabel is application's metadata label
// OAMApplicationLabel is application's metadata label tagged on AC and Component
OAMApplicationLabel = "application.oam.dev"
)

Expand All @@ -32,10 +32,12 @@ type Workload struct {
Type string
CapabilityCategory types.CapabilityCategory
Params map[string]interface{}
Template string
Health string
Traits []*Trait
Scopes []Scope

Template string
HealthCheckPolicy string
CustomStatusFormat string
}

// GetUserConfigName get user config from AppFile, it will contain config file in it.
Expand All @@ -56,12 +58,17 @@ func (wl *Workload) GetUserConfigName() string {

// EvalContext eval workload template and set result to context
func (wl *Workload) EvalContext(ctx process.Context) error {
return definition.NewWDTemplater(wl.Name, wl.Template, "").Params(wl.Params).Complete(ctx)
return definition.NewWorkloadAbstractEngine(wl.Name).Params(wl.Params).Complete(ctx, wl.Template)
}

// EvalStatus eval workload status
func (wl *Workload) EvalStatus(ctx process.Context, cli client.Client, ns string) (string, error) {
return definition.NewTraitAbstractEngine(wl.Name).Status(ctx, cli, ns, wl.CustomStatusFormat)
}

// EvalHealth eval workload health check
func (wl *Workload) EvalHealth(ctx process.Context, client client.Client, name string) error {
return definition.NewWDTemplater(wl.Name, "", wl.Health).Output(ctx, client, name).HealthCheck()
func (wl *Workload) EvalHealth(ctx process.Context, client client.Client, namespace string) (bool, error) {
return definition.NewWorkloadAbstractEngine(wl.Name).HealthCheck(ctx, client, namespace, wl.HealthCheckPolicy)
}

// Scope defines the scope of workload
Expand All @@ -72,27 +79,29 @@ type Scope struct {

// Trait is ComponentTrait
type Trait struct {
// The Name is name of TraitDefinition, actually it's a type of the trait instance
Name string
CapabilityCategory types.CapabilityCategory
Params map[string]interface{}

Template string
Health string
Status string
HealthCheckPolicy string
CustomStatusFormat string
}

// EvalContext eval trait template and set result to context
func (trait *Trait) EvalContext(ctx process.Context) error {
return definition.NewTDTemplater(trait.Name, trait.Template, "").Params(trait.Params).Complete(ctx)
return definition.NewTraitAbstractEngine(trait.Name).Params(trait.Params).Complete(ctx, trait.Template)
}

// EvalStatus eval trait status
func (trait *Trait) EvalStatus(ctx process.Context, cli client.Client, ns string) (string, error) {
return definition.NewTDTemplater(trait.Name, "", "").Status(ctx, cli, ns, trait.Status)
return definition.NewTraitAbstractEngine(trait.Name).Status(ctx, cli, ns, trait.CustomStatusFormat)
}

// EvalHealth eval trait health check
func (trait *Trait) EvalHealth(ctx process.Context, client client.Client, name string) error {
return definition.NewTDTemplater(trait.Name, "", trait.Health).Output(ctx, client, name).HealthCheck()
func (trait *Trait) EvalHealth(ctx process.Context, client client.Client, namespace string) (bool, error) {
return definition.NewTraitAbstractEngine(trait.Name).HealthCheck(ctx, client, namespace, trait.HealthCheckPolicy)
}

// Appfile describes application
Expand Down Expand Up @@ -148,7 +157,8 @@ func (p *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload, e
}
workload.CapabilityCategory = templ.CapabilityCategory
workload.Template = templ.TemplateStr
workload.Health = templ.Health
workload.HealthCheckPolicy = templ.Health
workload.CustomStatusFormat = templ.CustomStatus
settings, err := util.RawExtension2Map(&comp.Settings)
if err != nil {
return nil, errors.WithMessagef(err, "fail to parse settings for %s", comp.Name)
Expand Down Expand Up @@ -193,8 +203,8 @@ func (p *Parser) parseTrait(name string, properties map[string]interface{}) (*Tr
CapabilityCategory: templ.CapabilityCategory,
Params: properties,
Template: templ.TemplateStr,
Health: templ.Health,
Status: templ.CustomStatus,
HealthCheckPolicy: templ.Health,
CustomStatusFormat: templ.CustomStatus,
}, nil
}

Expand Down Expand Up @@ -223,7 +233,7 @@ func (p *Parser) GenerateApplicationConfiguration(app *Appfile, ns string) (*v1a
return nil, nil, err
}
}
comp, acComp, err := evalWorkloadWithContext(pCtx, wl)
comp, acComp, err := evalWorkloadWithContext(pCtx, wl, app.Name, wl.Name)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -251,52 +261,20 @@ func (p *Parser) GenerateApplicationConfiguration(app *Appfile, ns string) (*v1a
return appconfig, components, nil
}

// PrintApplicationComponents print appComponent status for application
func PrintApplicationComponents(app *Appfile, cli client.Client, ns string,
printer func(compName string, appName string, traitsStatus map[string]string) error) error {

for _, wl := range app.Workloads {
traitsStatus := map[string]string{}
pCtx, err := PrepareProcessContext(cli, wl, app.Name, ns)
if err != nil {
return err
}
for _, tr := range wl.Traits {
if err := tr.EvalContext(pCtx); err != nil {
return err
}
}

for _, tr := range wl.Traits {
status, err := tr.EvalStatus(pCtx, cli, ns)
if err != nil {
return errors.WithMessagef(err, "[%s.%s] eval error", wl.Name, tr.Name)
}

traitsStatus[tr.Name] = status
}
if err := printer(wl.Name, app.Name, traitsStatus); err != nil {
return err
}
}
return nil
}

// evalWorkloadWithContext evaluate the workload's template to generate component and ACComponent
func evalWorkloadWithContext(pCtx process.Context, wl *Workload) (*v1alpha2.Component, *v1alpha2.ApplicationConfigurationComponent, error) {
func evalWorkloadWithContext(pCtx process.Context, wl *Workload, appName, compName string) (*v1alpha2.Component, *v1alpha2.ApplicationConfigurationComponent, error) {
base, assists := pCtx.Output()
componentWorkload, err := base.Unstructured()
if err != nil {
return nil, nil, err
}
workloadType := wl.Type
labels := componentWorkload.GetLabels()
if labels == nil {
labels = map[string]string{oam.WorkloadTypeLabel: workloadType}
} else {
labels[oam.WorkloadTypeLabel] = workloadType

labels := map[string]string{
oam.WorkloadTypeLabel: wl.Type,
oam.LabelAppName: appName,
oam.LabelAppComponent: compName,
}
componentWorkload.SetLabels(labels)
util.AddLabels(componentWorkload, labels)

component := &v1alpha2.Component{}
component.Spec.Workload.Object = componentWorkload
Expand All @@ -308,7 +286,15 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload) (*v1alpha2.Comp
if err != nil {
return nil, nil, err
}
tr.SetLabels(map[string]string{oam.TraitTypeLabel: assist.Type})
labels := map[string]string{
oam.TraitTypeLabel: assist.Type,
oam.LabelAppName: appName,
oam.LabelAppComponent: compName,
}
if assist.Name != "" {
labels[oam.TraitResource] = assist.Name
}
util.AddLabels(tr, labels)
acComponent.Traits = append(acComponent.Traits, v1alpha2.ComponentTrait{
Trait: runtime.RawExtension{
Object: tr,
Expand All @@ -320,7 +306,7 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload) (*v1alpha2.Comp

// PrepareProcessContext prepares a DSL process Context
func PrepareProcessContext(k8sClient client.Client, wl *Workload, applicationName string, namespace string) (process.Context, error) {
pCtx := process.NewContext(wl.Name)
pCtx := process.NewContext(wl.Name, applicationName)
userConfig := wl.GetUserConfigName()
if userConfig != "" {
cg := config.Configmap{Client: k8sClient}
Expand Down

0 comments on commit 8ff8128

Please sign in to comment.