From bccd5b9ff3b103addfff1f45f6ce61cef6b7716b Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Mon, 20 May 2019 10:06:20 -0700 Subject: [PATCH 1/3] Fix drone build --- .drone.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 714d83419..5a7f58b2a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -272,7 +272,6 @@ steps: event: - tag -steps: - name: manifest-cert-checker image: plugins/manifest:1.0.2 settings: From 8b41f0c1d894534ec8ccae1c6db74d27b010d46b Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Mon, 20 May 2019 10:07:36 -0700 Subject: [PATCH 2/3] Pretty up the ps output --- cli/cmd/ps/ps_services.go | 58 +++++++++++++- cli/pkg/tables/apps.go | 75 +++++++++++++++++-- cli/pkg/tables/service.go | 6 +- modules/build/controllers/build/controller.go | 39 ++++++---- pkg/apis/rio.cattle.io/v1/service_types.go | 5 +- 5 files changed, 158 insertions(+), 25 deletions(-) diff --git a/cli/cmd/ps/ps_services.go b/cli/cmd/ps/ps_services.go index d09ac1e91..75d2a617b 100644 --- a/cli/cmd/ps/ps_services.go +++ b/cli/cmd/ps/ps_services.go @@ -5,6 +5,9 @@ import ( "github.com/rancher/rio/cli/pkg/tables" "github.com/rancher/rio/cli/pkg/types" riov1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" + "github.com/rancher/rio/pkg/services" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) type ServiceData struct { @@ -16,10 +19,61 @@ type ServiceData struct { } func (p *Ps) apps(ctx *clicontext.CLIContext) error { - objs, err := ctx.List(types.AppType) + var appDataList []runtime.Object + appDatas := map[string]tables.AppData{} + + appObjs, err := ctx.List(types.AppType) + if err != nil { + return err + } + + for _, v := range appObjs { + app := v.(*riov1.App) + appDatas[app.Namespace+"/"+app.Name] = tables.AppData{ + App: app, + Revisions: map[string]*riov1.Service{}, + } + } + + svcObjs, err := ctx.List(types.ServiceType) if err != nil { return err } + + for _, v := range svcObjs { + svc := v.(*riov1.Service) + appName, version := services.AppAndVersion(svc) + key := svc.Namespace + "/" + appName + app, ok := appDatas[key] + if !ok { + app = tables.AppData{ + App: riov1.NewApp(svc.Namespace, appName, riov1.App{ + ObjectMeta: v1.ObjectMeta{ + CreationTimestamp: svc.CreationTimestamp, + }, + Spec: riov1.AppSpec{ + Revisions: []riov1.Revision{ + { + Scale: svc.Spec.Scale, + Version: version, + }, + }, + }, + }), + Revisions: map[string]*riov1.Service{}, + } + appDatas[key] = app + } + app.Revisions[version] = svc + } + + for _, v := range appDatas { + copy := v + copy.Namespace = v.App.Namespace + copy.Name = v.App.Name + appDataList = append(appDataList, ©) + } + writer := tables.NewApp(ctx) - return writer.Write(objs) + return writer.Write(appDataList) } diff --git a/cli/pkg/tables/apps.go b/cli/pkg/tables/apps.go index a3a1a2867..2dc4da9af 100644 --- a/cli/pkg/tables/apps.go +++ b/cli/pkg/tables/apps.go @@ -5,22 +5,51 @@ import ( "sort" "strings" + "k8s.io/apimachinery/pkg/runtime" + "github.com/rancher/rio/cli/pkg/table" riov1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +type AppData struct { + metav1.TypeMeta + metav1.ObjectMeta + + App *riov1.App + Revisions map[string]*riov1.Service +} + +func (a *AppData) DeepCopyObject() runtime.Object { + ad := &AppData{ + TypeMeta: a.TypeMeta, + ObjectMeta: *a.ObjectMeta.DeepCopy(), + App: a.App.DeepCopy(), + Revisions: map[string]*riov1.Service{}, + } + + for k, v := range a.Revisions { + ad.Revisions[k] = v.DeepCopy() + } + + return ad +} + func NewApp(cfg Config) TableWriter { writer := table.NewWriter([][]string{ - {"NAME", "{{stackScopedName .Obj.Namespace .Obj.Name ``}}"}, - {"ENDPOINT", "{{.Obj.Status.Endpoints | array}}"}, - {"REVISIONS", "{{revisions .Obj.Spec.Revisions}}"}, - {"SCALE", "{{appScale .Obj.Spec.Revisions}}"}, - {"WEIGHT", "{{weightVersioned .Obj}}"}, + {"NAME", "{{stackScopedName .Obj.App.Namespace .Obj.App.Name ``}}"}, + {"CREATED", "{{.Obj.App.CreationTimestamp | ago}}"}, + {"ENDPOINT", "{{.Obj.App.Status.Endpoints | array}}"}, + {"REVISIONS", "{{revisions .Obj.App.Spec.Revisions}}"}, + {"SCALE", "{{appScale .Obj.App.Spec.Revisions}}"}, + {"WEIGHT", "{{weightVersioned .Obj.App}}"}, + {"DETAIL", "{{detail .Obj}}"}, }, cfg) writer.AddFormatFunc("revisions", formatRevisions) writer.AddFormatFunc("appScale", formatAppScale) writer.AddFormatFunc("weightVersioned", formatWeightGraph) + writer.AddFormatFunc("detail", formatAppDetail) writer.AddFormatFunc("stackScopedName", table.FormatStackScopedName(cfg.GetSetNamespace())) return &tableWriter{ @@ -82,3 +111,39 @@ func formatWeightGraph(obj interface{}) (string, error) { } return strings.Join(result, ","), nil } + +func formatAppDetail(obj interface{}) (string, error) { + appData := obj.(*AppData) + buffer := strings.Builder{} + + versions := revisionsByVersion(appData.App.Spec.Revisions) + for _, name := range revisions(appData.App.Spec.Revisions) { + rev := versions[name] + if !rev.DeploymentReady { + if buffer.Len() > 0 { + buffer.WriteString("; ") + } + buffer.WriteString(name) + buffer.WriteString(" NotReady") + } + + svc, ok := appData.Revisions[name] + if ok && svc.Spec.Image == "" { + if riov1.ServiceConditionImageReady.IsFalse(svc) { + if buffer.Len() > 0 { + buffer.WriteString("; ") + } + buffer.WriteString(name) + buffer.WriteString(" build failed: ") + buffer.WriteString(riov1.ServiceConditionImageReady.GetMessage(svc)) + } else if !riov1.ServiceConditionImageReady.IsTrue(svc) { + if buffer.Len() > 0 { + buffer.WriteString("; ") + } + buffer.WriteString(name) + buffer.WriteString(" waiting on build") + } + } + } + return buffer.String(), nil +} diff --git a/cli/pkg/tables/service.go b/cli/pkg/tables/service.go index 3e67c3333..59bb50f28 100644 --- a/cli/pkg/tables/service.go +++ b/cli/pkg/tables/service.go @@ -45,10 +45,14 @@ func FormatScale(data, data2, data3 interface{}) (string, error) { scaleStr := strconv.Itoa(scale) scaleStatus, ok := data2.(*v1.ScaleStatus) - if !ok || scaleStatus == nil { + if !ok { return scaleStr, nil } + if scaleStatus == nil { + scaleStatus = &v1.ScaleStatus{} + } + if scaleStatus.Available == 0 && scaleStatus.Unavailable == 0 && scaleStatus.Ready == scale { return scaleStr, nil } diff --git a/modules/build/controllers/build/controller.go b/modules/build/controllers/build/controller.go index f90127000..7edf750f3 100644 --- a/modules/build/controllers/build/controller.go +++ b/modules/build/controllers/build/controller.go @@ -2,9 +2,11 @@ package build import ( "context" + "errors" "github.com/knative/build/pkg/apis/build/v1alpha1" "github.com/rancher/rio/modules/build/controllers/service" + v1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" "github.com/rancher/rio/pkg/constants" projectv1controller "github.com/rancher/rio/pkg/generated/controllers/admin.rio.cattle.io/v1" riov1controller "github.com/rancher/rio/pkg/generated/controllers/rio.cattle.io/v1" @@ -46,27 +48,38 @@ func (h handler) updateService(key string, build *v1alpha1.Build) (*v1alpha1.Bui } con := build.Status.GetCondition(v1alpha1.BuildSucceeded) - if con != nil && con.IsTrue() { - namespace := build.Labels["service-namespace"] - name := build.Labels["service-name"] - svc, err := h.services.Cache().Get(namespace, name) - if err != nil { - return build, nil - } + if con == nil { + return build, nil + } - if svc.Spec.Image != "" { - return build, nil - } + namespace := build.Labels["service-namespace"] + name := build.Labels["service-name"] + svc, err := h.services.Cache().Get(namespace, name) + if err != nil { + return build, nil + } + if svc.Spec.Image != "" { + return build, nil + } + + if con.IsTrue() { imageName := service.ImageName(h.registry, h.systemNamespace, build.Spec.Source.Git.Revision, domain, svc) if svc.Spec.Image != imageName { - deepcopy := svc.DeepCopy() - deepcopy.Spec.Image = service.ImageName(h.registry, h.systemNamespace, build.Spec.Source.Git.Revision, domain, deepcopy) - if _, err := h.services.Update(deepcopy); err != nil { + deepCopy := svc.DeepCopy() + v1.ServiceConditionImageReady.SetError(deepCopy, "", nil) + deepCopy.Spec.Image = service.ImageName(h.registry, h.systemNamespace, build.Spec.Source.Git.Revision, domain, deepCopy) + if _, err := h.services.Update(deepCopy); err != nil { return build, err } } + } else if con.IsFalse() { + deepCopy := svc.DeepCopy() + v1.ServiceConditionImageReady.SetError(deepCopy, con.Reason, errors.New(con.Message)) + _, err := h.services.Update(deepCopy) + return build, err } + return build, nil } diff --git a/pkg/apis/rio.cattle.io/v1/service_types.go b/pkg/apis/rio.cattle.io/v1/service_types.go index c2f27d952..923248f89 100644 --- a/pkg/apis/rio.cattle.io/v1/service_types.go +++ b/pkg/apis/rio.cattle.io/v1/service_types.go @@ -14,10 +14,7 @@ import ( ) var ( - ServiceConditionCurrentRevision = condition.Cond("CurrentRevision") - ServiceConditionImageReady = condition.Cond("ImageReady") - ServiceConditionDeploymentStable = condition.Cond("DeploymentStable") - ServiceConditionPromoted = condition.Cond("Promoted") + ServiceConditionImageReady = condition.Cond("ImageReady") ) // +genclient From d1eb5dced45ac0ac849bd6fd3a5e4e22fd701889 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Mon, 20 May 2019 10:07:48 -0700 Subject: [PATCH 3/3] Remove TUI_HACK --- cli/cmd/tui/refreshers.go | 34 +++++++++++++++++----------------- cli/pkg/table/flags.go | 5 +++-- cli/pkg/table/writer.go | 8 ++++---- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/cli/cmd/tui/refreshers.go b/cli/cmd/tui/refreshers.go index 05afdcde3..9137c58cf 100644 --- a/cli/cmd/tui/refreshers.go +++ b/cli/cmd/tui/refreshers.go @@ -3,9 +3,9 @@ package tui import ( "bytes" "os" - "os/exec" "strings" + "github.com/docker/docker/pkg/reexec" "github.com/pkg/errors" ) @@ -19,9 +19,9 @@ var ( if showSystem { args = append([]string{"--system"}, args...) } - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { @@ -35,9 +35,9 @@ var ( if showSystem { args = append([]string{"--system"}, args...) } - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { @@ -51,9 +51,9 @@ var ( if showSystem { args = append([]string{"--system"}, args...) } - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { @@ -67,9 +67,9 @@ var ( if showSystem { args = append([]string{"--system"}, args...) } - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { @@ -83,9 +83,9 @@ var ( if showSystem { args = append([]string{"--system"}, args...) } - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { @@ -102,9 +102,9 @@ var ( if showSystem { args = append([]string{"--system"}, args...) } - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { @@ -121,9 +121,9 @@ var ( if showSystem { args = append([]string{"--system"}, args...) } - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { @@ -134,9 +134,9 @@ var ( BuildRefresher = func(b *bytes.Buffer) error { args := []string{"build"} - cmd := exec.Command("rio", args...) + cmd := reexec.Command(append([]string{"rio"}, args...)...) errBuffer := &strings.Builder{} - cmd.Env = append(os.Environ(), "TUI_HACK=true") + cmd.Env = append(os.Environ(), "FORMAT=raw") cmd.Stdout = b cmd.Stderr = errBuffer if err := cmd.Run(); err != nil { diff --git a/cli/pkg/table/flags.go b/cli/pkg/table/flags.go index 315aa3e33..140a97dde 100644 --- a/cli/pkg/table/flags.go +++ b/cli/pkg/table/flags.go @@ -8,8 +8,9 @@ var stackLsFlags = []cli.Flag{ Usage: "Only display IDs", }, cli.StringFlag{ - Name: "format", - Usage: "'json' or 'yaml' or Custom format: '{{.ID}} {{.Stack.ServiceName}}'", + Name: "format", + EnvVar: "FORMAT", + Usage: "'json' or 'yaml' or Custom format: '{{.ID}} {{.Stack.ServiceName}}'", }, } diff --git a/cli/pkg/table/writer.go b/cli/pkg/table/writer.go index 71f5d44c3..a96c8dfbc 100644 --- a/cli/pkg/table/writer.go +++ b/cli/pkg/table/writer.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "io" - "os" "strings" "text/tabwriter" "text/template" @@ -16,9 +15,9 @@ import ( "github.com/Masterminds/sprig" "github.com/davecgh/go-spew/spew" - units "github.com/docker/go-units" + "github.com/docker/go-units" "github.com/rancher/mapper/convert" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -85,7 +84,7 @@ func NewWriter(values [][]string, config WriterConfig) Writer { funcMap: funcMap, } - if os.Getenv("TUI_HACK") == "true" { + if config.Format() == "raw" { t.Writer = config.Writer() } else { t.Writer = tabwriter.NewWriter(config.Writer(), 10, 1, 3, ' ', 0) @@ -108,6 +107,7 @@ func NewWriter(values [][]string, config WriterConfig) Writer { } else if customFormat == "yaml" { t.HeaderFormat = "" t.ValueFormat = "yaml" + } else if customFormat == "raw" { } else if customFormat != "" { t.ValueFormat = customFormat + "\n" t.HeaderFormat = ""