status app

This commit is contained in:
lj176172
2021-02-02 21:23:01 +08:00
committed by 天元
parent 2efeec8a8e
commit dd6810314e
6 changed files with 166 additions and 68 deletions
+38
View File
@@ -77,6 +77,7 @@ type Trait struct {
Params map[string]interface{}
Template string
Health string
Status string
}
// EvalContext eval trait template and set result to context
@@ -84,6 +85,11 @@ func (trait *Trait) EvalContext(ctx process.Context) error {
return definition.NewTDTemplater(trait.Name, trait.Template, "").Params(trait.Params).Complete(ctx)
}
// 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)
}
// 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()
@@ -188,6 +194,7 @@ func (p *Parser) parseTrait(name string, properties map[string]interface{}) (*Tr
Params: properties,
Template: templ.TemplateStr,
Health: templ.Health,
Status: templ.CustomStatus,
}, nil
}
@@ -244,6 +251,37 @@ 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) {
base, assists := pCtx.Output()
+6 -1
View File
@@ -19,6 +19,7 @@ import (
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/appfile/api"
cmdutil "github.com/oam-dev/kubevela/pkg/commands/util"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/plugins"
"github.com/oam-dev/kubevela/pkg/serverlib"
"github.com/oam-dev/kubevela/pkg/utils/env"
@@ -103,8 +104,12 @@ func NewInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
if deployStatus != compStatusDeployed {
return nil
}
dm, err := discoverymapper.New(c.Config)
if err != nil {
return err
}
return printComponentStatus(context.Background(), o.client, o.IOStreams, o.workloadName, o.appName, o.Env)
return printAppStatus(context.Background(), newClient, dm, ioStreams, o.appName, o.Env, cmd)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeStart,
+37 -60
View File
@@ -19,7 +19,7 @@ import (
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/appfile/api"
cmdutil "github.com/oam-dev/kubevela/pkg/commands/util"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
oam2 "github.com/oam-dev/kubevela/pkg/serverlib"
)
@@ -103,7 +103,11 @@ func NewAppStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
if err != nil {
return err
}
return printAppStatus(ctx, newClient, ioStreams, appName, env, cmd)
dm, err := discoverymapper.New(c.Config)
if err != nil {
return err
}
return printAppStatus(ctx, newClient, dm, ioStreams, appName, env, cmd)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeApp,
@@ -114,17 +118,12 @@ func NewAppStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
return cmd
}
func printAppStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, appName string, env *types.EnvMeta, cmd *cobra.Command) error {
func printAppStatus(ctx context.Context, c client.Client, dm discoverymapper.DiscoveryMapper, ioStreams cmdutil.IOStreams, appName string, env *types.EnvMeta, cmd *cobra.Command) error {
app, err := appfile.LoadApplication(env.Name, appName)
if err != nil {
return err
}
namespace := env.Name
targetServices, err := oam2.GetServicesWhenDescribingApplication(cmd, app)
if err != nil {
return err
}
namespace := env.Namespace
cmd.Printf("About:\n\n")
table := newUITable()
@@ -136,16 +135,36 @@ func printAppStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOSt
cmd.Printf("Services:\n\n")
for _, svcName := range targetServices {
if err := printComponentStatus(ctx, c, ioStreams, svcName, appName, env); err != nil {
return err
}
remoteApp, err := loadRemoteApplication(c, namespace, appName)
if err != nil {
return err
}
return nil
parser := appfile.NewApplicationParser(c, dm)
appFile, err := parser.GenerateAppFile(appName, remoteApp)
if err != nil {
return err
}
return appfile.PrintApplicationComponents(appFile, c, namespace, componentPrinter(ctx, c, ioStreams, env))
}
func printComponentStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, compName, appName string, env *types.EnvMeta) error {
func loadRemoteApplication(c client.Client, ns string, name string) (*v1alpha2.Application, error) {
app := new(v1alpha2.Application)
err := c.Get(context.Background(), client.ObjectKey{
Namespace: ns,
Name: name,
}, app)
return app, err
}
func componentPrinter(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, env *types.EnvMeta) func(compName string, appName string, traitsStatus map[string]string) error {
return func(compName string, appName string, traitsStatus map[string]string) error {
return printComponentStatus(ctx, c, ioStreams, compName, appName, env, traitsStatus)
}
}
func printComponentStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, compName string, appName string, env *types.EnvMeta, traitsStatus map[string]string) error {
app, appConfig, err := getAppConfig(ctx, c, compName, appName, env)
if err != nil {
return err
@@ -173,14 +192,9 @@ func printComponentStatus(ctx context.Context, c client.Client, ioStreams cmduti
// workload Must found
ioStreams.Infof(" Traits:\n")
workloadStatus, _ := getWorkloadStatusFromAppConfig(appConfig, compName)
for _, tr := range workloadStatus.Traits {
traitType, traitInfo, err := traitCheckLoop(ctx, c, tr.Reference, compName, appConfig, app, 60*time.Second)
if err != nil {
ioStreams.Infof(" - %s%s: %s, err: %v", emojiFail, white.Sprint(traitType), traitInfo, err)
continue
}
ioStreams.Infof(" - %s%s: %s", emojiSucceed, white.Sprint(traitType), traitInfo)
for traitType, traitInfo := range traitsStatus {
ioStreams.Infof(" - %s: %s", white.Sprint(traitType), traitInfo)
}
ioStreams.Info("")
ioStreams.Infof(" Last Deployment:\n")
@@ -189,43 +203,6 @@ func printComponentStatus(ctx context.Context, c client.Client, ioStreams cmduti
return nil
}
func traitCheckLoop(ctx context.Context, c client.Client, reference runtimev1alpha1.TypedReference, compName string, appConfig *v1alpha2.ApplicationConfiguration, app *api.Application, timeout time.Duration) (string, string, error) {
tr, err := oam2.GetUnstructured(ctx, c, appConfig.Namespace, reference)
if err != nil {
return "", "", err
}
traitType, ok := tr.GetLabels()[oam.TraitTypeLabel]
if !ok {
message, err := oam2.GetStatusFromObject(tr)
return traitType, message, err
}
checker := oam2.GetChecker(traitType, c)
// Health Check Loop For Trait
var message string
sHealthCheck := newTrackingSpinner(fmt.Sprintf("Checking %s status ...", traitType))
sHealthCheck.Start()
defer sHealthCheck.Stop()
CheckLoop:
for {
time.Sleep(trackingInterval)
var check oam2.CheckStatus
check, message, err = checker.Check(ctx, reference, compName, appConfig, app)
if err != nil {
message = red.Sprintf("%s check failed!", traitType)
return traitType, message, err
}
if check == oam2.StatusDone {
break CheckLoop
}
if time.Since(tr.GetCreationTimestamp().Time) >= timeout {
return traitType, fmt.Sprintf("Checking timeout: %s", message), nil
}
}
return traitType, message, nil
}
func healthCheckLoop(ctx context.Context, c client.Client, compName, appName string, env *types.EnvMeta) (HealthStatus, string, error) {
// Health Check Loop For Workload
var healthInfo string
+54
View File
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
"cuelang.org/go/cue"
"cuelang.org/go/cue/build"
@@ -25,6 +26,8 @@ const (
OutputFieldName = "output"
// OutputsFieldName is the name of the struct contains the map[string]CR data
OutputsFieldName = "outputs"
// OutputObjectPath is the path of output object in template
OutputObjectPath = "path"
// PatchFieldName is the name of the struct contains the patch of CR data
PatchFieldName = "patch"
)
@@ -45,6 +48,7 @@ type Template interface {
Complete(ctx process.Context) error
Output(ctx process.Context, client client.Client, name string) Template
HealthCheck() error
Status(ctx process.Context, cli client.Client, ns string, handleTempl string) (string, error)
}
type def struct {
@@ -174,6 +178,11 @@ func (wd *workloadDef) HealthCheck() error {
return nil
}
// Status get workload status
func (wd *workloadDef) Status(ctx process.Context, cli client.Client, ns string, handleTempl string) (string, error) {
return "", nil
}
type traitDef struct {
def
}
@@ -232,6 +241,7 @@ func (td *traitDef) Complete(ctx process.Context) error {
if err != nil {
return errors.WithMessagef(err, "traitDef %s new Assist", td.name)
}
other.SetTag(OutputObjectPath, OutputFieldName)
ctx.PutAssistants(process.Assistant{Ins: other, Type: td.name})
}
@@ -247,6 +257,7 @@ func (td *traitDef) Complete(ctx process.Context) error {
if err != nil {
return errors.WithMessagef(err, "traitDef %s new Assists(%s)", td.name, fieldInfo.Name)
}
other.SetTag(OutputObjectPath, strings.Join([]string{OutputsFieldName, fieldInfo.Name}, "."))
ctx.PutAssistants(process.Assistant{Ins: other, Type: td.name})
}
}
@@ -266,6 +277,49 @@ func (td *traitDef) Complete(ctx process.Context) error {
return nil
}
// Status get trait status by handleTempl
func (td *traitDef) Status(ctx process.Context, cli client.Client, ns string, handleTempl string) (string, error) {
_, assists := ctx.Output()
var root = map[string]interface{}{}
for _, assist := range assists {
if assist.Type != td.name {
continue
}
traitRef, err := assist.Ins.Unstructured()
if err != nil {
return "", err
}
if err := cli.Get(context.Background(), client.ObjectKey{
Namespace: ns,
Name: traitRef.GetName(),
}, traitRef); err != nil {
return "", err
}
paths := strings.Split(assist.Ins.GetTag(OutputObjectPath), ".")
x := traitRef.Object
for i := len(paths) - 1; i >= 0; i-- {
x = map[string]interface{}{paths[i]: x}
}
for k, v := range x {
root[k] = v
}
}
bt, _ := json.Marshal(root)
var buff = "context: " + string(bt)
buff += "\n" + handleTempl
var r cue.Runtime
inst, err := r.Compile("-", buff)
if err != nil {
return "", err
}
return inst.Lookup("output").String()
}
// Output fetch the trait cr and set result to context
func (td *traitDef) Output(ctx process.Context, client client.Client, name string) Template {
_, assists := ctx.Output()
+16 -1
View File
@@ -16,11 +16,14 @@ type Instance interface {
IsBase() bool
Unify(other Instance) error
Compile() ([]byte, error)
SetTag(k, v string)
GetTag(k string) string
}
type instance struct {
v string
base bool
tags map[string]string
}
// String return instance's cue format string
@@ -33,6 +36,16 @@ func (inst *instance) IsBase() bool {
return inst.base
}
// SetTag add or update tag for model
func (inst *instance) SetTag(k, v string) {
inst.tags[k] = v
}
// GetTag get the tag of model by key
func (inst *instance) GetTag(k string) string {
return inst.tags[k]
}
func (inst *instance) Compile() ([]byte, error) {
var r cue.Runtime
cueInst, err := r.Compile("-", inst.v)
@@ -82,6 +95,7 @@ func NewBase(v cue.Value) (Instance, error) {
return &instance{
v: vs,
base: true,
tags: map[string]string{},
}, nil
}
@@ -92,7 +106,8 @@ func NewOther(v cue.Value) (Instance, error) {
return nil, err
}
return &instance{
v: vs,
v: vs,
tags: map[string]string{},
}, nil
}
+15 -6
View File
@@ -18,6 +18,7 @@ import (
type Template struct {
TemplateStr string
Health string
CustomStatus string
CapabilityCategory types.CapabilityCategory
}
@@ -46,7 +47,7 @@ func LoadTemplate(cli client.Reader, key string, kd types.CapType) (*Template, e
if wd.Annotations["type"] == string(types.TerraformCategory) {
capabilityCategory = types.TerraformCategory
}
tmpl, err := getTemplAndHealth(wd.Spec.Extension.Raw)
tmpl, err := getTempl(wd.Spec.Extension.Raw)
if err != nil {
return nil, errors.WithMessagef(err, "LoadTemplate [%s] ", key)
}
@@ -65,7 +66,7 @@ func LoadTemplate(cli client.Reader, key string, kd types.CapType) (*Template, e
if td.Annotations["type"] == string(types.TerraformCategory) {
capabilityCategory = types.TerraformCategory
}
tmpl, err := getTemplAndHealth(td.Spec.Extension.Raw)
tmpl, err := getTempl(td.Spec.Extension.Raw)
if err != nil {
return nil, errors.WithMessagef(err, "LoadTemplate [%s] ", key)
}
@@ -81,15 +82,23 @@ func LoadTemplate(cli client.Reader, key string, kd types.CapType) (*Template, e
return nil, fmt.Errorf("kind(%s) of %s not supported", kd, key)
}
func getTemplAndHealth(raw []byte) (*Template, error) {
func getTempl(raw []byte) (*Template, error) {
_tmp := map[string]interface{}{}
if err := json.Unmarshal(raw, &_tmp); err != nil {
return nil, err
}
var health string
var (
health string
status string
)
if _, ok := _tmp["healthPolicy"]; ok {
health = fmt.Sprint(_tmp["healthPolicy"])
}
return &Template{TemplateStr: fmt.Sprint(_tmp["template"]),
Health: health}, nil
if _, ok := _tmp["customStatus"]; ok {
status = fmt.Sprint(_tmp["customStatus"])
}
return &Template{
TemplateStr: fmt.Sprint(_tmp["template"]),
Health: health,
CustomStatus: status}, nil
}