@@ -2,15 +2,31 @@ package commands
22
33import (
44 "fmt"
5+ "io"
6+ "os"
7+ "sort"
8+ "strings"
9+ "text/tabwriter"
10+ "time"
511
612 "github.com/deislabs/duffle/pkg/action"
713 "github.com/deislabs/duffle/pkg/credentials"
814 "github.com/docker/app/internal"
15+ "github.com/docker/app/internal/store"
916 "github.com/docker/cli/cli"
1017 "github.com/docker/cli/cli/command"
18+ units "github.com/docker/go-units"
1119 "github.com/spf13/cobra"
1220)
1321
22+ var (
23+ knownStatusActions = []string {
24+ internal .ActionStatusName ,
25+ // TODO: Extract this constant to the cnab-go library
26+ "io.cnab.status" ,
27+ }
28+ )
29+
1430func statusCmd (dockerCli command.Cli ) * cobra.Command {
1531 var opts credentialOptions
1632
@@ -42,6 +58,14 @@ func runStatus(dockerCli command.Cli, installationName string, opts credentialOp
4258 if err != nil {
4359 return err
4460 }
61+ displayInstallationStatus (os .Stdout , installation )
62+
63+ // Check if the bundle knows the docker app status action, if not just exit without error.
64+ statusAction := resolveStatusAction (installation )
65+ if statusAction == "" {
66+ return nil
67+ }
68+
4569 bind , err := requiredClaimBindMount (installation .Claim , opts .targetContext , dockerCli )
4670 if err != nil {
4771 return err
@@ -62,12 +86,86 @@ func runStatus(dockerCli command.Cli, installationName string, opts credentialOp
6286 if err := credentials .Validate (creds , installation .Bundle .Credentials ); err != nil {
6387 return err
6488 }
89+ printHeader (os .Stdout , "STATUS" )
6590 status := & action.RunCustom {
66- Action : internal . ActionStatusName ,
91+ Action : statusAction ,
6792 Driver : driverImpl ,
6893 }
6994 if err := status .Run (& installation .Claim , creds , dockerCli .Out ()); err != nil {
7095 return fmt .Errorf ("status failed: %s\n %s" , err , errBuf )
7196 }
7297 return nil
7398}
99+
100+ func displayInstallationStatus (w io.Writer , installation * store.Installation ) {
101+ printHeader (w , "INSTALLATION" )
102+ tab := tabwriter .NewWriter (w , 0 , 0 , 1 , ' ' , 0 )
103+ printValue (tab , "Name" , installation .Name )
104+ printValue (tab , "Created" , units .HumanDuration (time .Since (installation .Created )))
105+ printValue (tab , "Modified" , units .HumanDuration (time .Since (installation .Modified )))
106+ printValue (tab , "Revision" , installation .Revision )
107+ printValue (tab , "Last Action" , installation .Result .Action )
108+ printValue (tab , "Result" , strings .ToUpper (installation .Result .Status ))
109+ if o , ok := installation .Parameters [internal .ParameterOrchestratorName ]; ok {
110+ orchestrator := fmt .Sprintf ("%v" , o )
111+ if orchestrator == "" {
112+ orchestrator = string (command .OrchestratorSwarm )
113+ }
114+ printValue (tab , "Orchestrator" , orchestrator )
115+ if kubeNamespace , ok := installation .Parameters [internal .ParameterKubernetesNamespaceName ]; ok && orchestrator == string (command .OrchestratorKubernetes ) {
116+ printValue (tab , "Kubernetes namespace" , fmt .Sprintf ("%v" , kubeNamespace ))
117+ }
118+ }
119+
120+ tab .Flush ()
121+ fmt .Fprintln (w )
122+
123+ printHeader (w , "APPLICATION" )
124+ tab = tabwriter .NewWriter (w , 0 , 0 , 1 , ' ' , 0 )
125+ printValue (tab , "Name" , installation .Bundle .Name )
126+ printValue (tab , "Version" , installation .Bundle .Version )
127+ printValue (tab , "Reference" , installation .Reference )
128+ tab .Flush ()
129+ fmt .Fprintln (w )
130+
131+ if len (installation .Parameters ) > 0 {
132+ printHeader (w , "PARAMETERS" )
133+ tab = tabwriter .NewWriter (w , 0 , 0 , 1 , ' ' , 0 )
134+ params := sortParameters (installation )
135+ for _ , param := range params {
136+ if ! strings .HasPrefix (param , internal .Namespace ) {
137+ // TODO: Trim long []byte parameters, maybe add type too (string, int...)
138+ printValue (tab , param , fmt .Sprintf ("%v" , installation .Parameters [param ]))
139+ }
140+ }
141+ tab .Flush ()
142+ fmt .Fprintln (w )
143+ }
144+ }
145+
146+ func sortParameters (installation * store.Installation ) []string {
147+ var params []string
148+ for name := range installation .Parameters {
149+ params = append (params , name )
150+ }
151+ sort .Strings (params )
152+ return params
153+ }
154+
155+ func printHeader (w io.Writer , header string ) {
156+ fmt .Fprintln (w , header )
157+ fmt .Fprintln (w , strings .Repeat ("-" , len (header )))
158+ }
159+
160+ func printValue (w io.Writer , key , value string ) {
161+ fmt .Fprintf (w , "%s:\t %s\n " , key , value )
162+ }
163+
164+ func resolveStatusAction (installation * store.Installation ) string {
165+ for _ , name := range knownStatusActions {
166+ if _ , ok := installation .Bundle .Actions [name ]; ok {
167+ return name
168+ }
169+ }
170+ return ""
171+ }
0 commit comments