@@ -3,9 +3,11 @@ package cmd
33import (
44 "fmt"
55 "io/ioutil"
6+ "os"
67 "strings"
8+ "time"
79
8- "github.com/deis/pkg/prettyprint "
10+ "github.com/olekukonko/tablewriter "
911
1012 "github.com/deis/workflow/client/controller/client"
1113 "github.com/deis/workflow/client/controller/models/certs"
@@ -34,45 +36,67 @@ func CertsList(results int) error {
3436 return nil
3537 }
3638
37- certMap := make (map [string ]string )
38- nameMax := 0
39- expiresMax := 0
39+ table := tablewriter .NewWriter (os .Stdout )
40+ table .SetAlignment (tablewriter .ALIGN_LEFT )
41+ table .SetBorder (false )
42+ table .SetAutoFormatHeaders (false )
43+ table .SetHeaderLine (true )
44+ table .SetHeader ([]string {"Name" , "Common Name" , "SubjectAltName" , "Expires" , "Fingerprint" , "Domains" , "Updated" , "Created" })
4045 for _ , cert := range certList {
41- certMap [cert .Name ] = cert .Expires
42-
43- if len (cert .Name ) > nameMax {
44- nameMax = len (cert .Name )
45- }
46- if len (cert .Expires ) > nameMax {
47- expiresMax = len (cert .Expires )
46+ domains := strings .Join (cert .Domains [:], "," )
47+ san := strings .Join (cert .SubjectAltName [:], "," )
48+
49+ // Make dates more readable
50+ now := time .Now ()
51+ expires := cert .Expires .Time .Format ("2 Jan 2006" )
52+ created := cert .Created .Time .Format ("2 Jan 2006" )
53+ updated := cert .Updated .Time .Format ("2 Jan 2006" )
54+
55+ if cert .Expires .Time .Before (now ) {
56+ expires += " (expired)"
57+ } else {
58+ // Ghetto solution
59+ expires += " (in"
60+ year := cert .Expires .Time .Year () - now .Year ()
61+ month := cert .Expires .Time .Month () - now .Month ()
62+ day := cert .Expires .Time .Day () - now .Day ()
63+
64+ if year > 0 {
65+ expires += fmt .Sprintf (" %d year" , year )
66+ if year > 1 {
67+ expires += "s"
68+ }
69+ } else if month > 0 {
70+ expires += fmt .Sprintf (" %d month" , month )
71+ if month > 1 {
72+ expires += "s"
73+ }
74+ } else if day != 0 {
75+ // special handling on negative days
76+ if day < 0 {
77+ day *= - 1
78+ }
79+
80+ expires += fmt .Sprintf (" %d day" , day )
81+ if day > 1 {
82+ expires += "s"
83+ }
84+ }
85+ expires += ")"
4886 }
49- }
5087
51- nameHeader := "Common Name"
52- expiresHeader := "Expires"
53- tabSpaces := 5
54- bufferSpaces := tabSpaces
88+ // show a shorter version of the fingerprint
89+ fingerprint := cert .Fingerprint [:5 ] + "[...]" + cert .Fingerprint [len (cert .Fingerprint )- 5 :]
5590
56- if nameMax < len (nameHeader ) {
57- tabSpaces += len (nameHeader ) - nameMax
58- nameMax = len (nameHeader )
59- } else {
60- bufferSpaces += nameMax - len (nameHeader )
91+ table .Append ([]string {cert .Name , cert .CommonName , san , expires , fingerprint , domains , updated , created })
6192 }
93+ table .Render ()
6294
63- if expiresMax < len (expiresHeader ) {
64- expiresMax = len (expiresHeader )
65- }
66-
67- fmt .Printf ("%s%s%s\n " , nameHeader , strings .Repeat (" " , bufferSpaces ), expiresHeader )
68- fmt .Printf ("%s%s%s\n " , strings .Repeat ("-" , nameMax ), strings .Repeat (" " , 5 ),
69- strings .Repeat ("-" , expiresMax ))
70- fmt .Print (prettyprint .PrettyTabs (certMap , tabSpaces ))
7195 return nil
7296}
7397
7498// CertAdd adds a cert to the controller.
75- func CertAdd (cert , key , commonName , sans string ) error {
99+ func CertAdd (cert string , key string , name string ) error {
76100 c , err := client .New ()
77101
78102 if err != nil {
@@ -81,7 +105,7 @@ func CertAdd(cert, key, commonName, sans string) error {
81105
82106 fmt .Print ("Adding SSL endpoint... " )
83107 quit := progress ()
84- err = processCertsAdd (c , cert , key , commonName , sans )
108+ err = doCertAdd (c , cert , key , name )
85109 quit <- true
86110 <- quit
87111
@@ -93,48 +117,117 @@ func CertAdd(cert, key, commonName, sans string) error {
93117 return nil
94118}
95119
96- func processCertsAdd (c * client.Client , cert , key , commonName , sans string ) error {
97- if sans != "" {
98- for _ , san := range strings .Split (sans , "," ) {
99- if err := doCertAdd (c , cert , key , san ); err != nil {
100- return err
101- }
102- }
103- return nil
120+ func doCertAdd (c * client.Client , cert string , key string , name string ) error {
121+ certFile , err := ioutil .ReadFile (cert )
122+ if err != nil {
123+ return err
124+ }
125+
126+ keyFile , err := ioutil .ReadFile (key )
127+ if err != nil {
128+ return err
104129 }
105130
106- return doCertAdd (c , cert , key , commonName )
131+ _ , err = certs .New (c , string (certFile ), string (keyFile ), name )
132+ return err
107133}
108134
109- func doCertAdd (c * client.Client , cert string , key string , commonName string ) error {
110- certFile , err := ioutil .ReadFile (cert )
135+ // CertRemove deletes a cert from the controller.
136+ func CertRemove (name string ) error {
137+ c , err := client .New ()
138+ if err != nil {
139+ return err
140+ }
111141
142+ fmt .Printf ("Removing %s... " , name )
143+ quit := progress ()
144+
145+ certs .Delete (c , name )
146+
147+ quit <- true
148+ <- quit
149+
150+ if err == nil {
151+ fmt .Println ("done" )
152+ }
153+
154+ return err
155+ }
156+
157+ // CertInfo gets info about certficiate
158+ func CertInfo (name string ) error {
159+ c , err := client .New ()
112160 if err != nil {
113161 return err
114162 }
115163
116- keyFile , err := ioutil .ReadFile (key )
164+ cert , err := certs .Get (c , name )
165+ if err != nil {
166+ return err
167+ }
168+
169+ domains := strings .Join (cert .Domains [:], "," )
170+ if domains == "" {
171+ domains = "No connected domains"
172+ }
173+
174+ san := strings .Join (cert .SubjectAltName [:], "," )
175+ if san == "" {
176+ san = "N/A"
177+ }
178+
179+ fmt .Printf ("=== %s Certificate\n " , cert .Name )
180+ fmt .Println ("Common Name(s): " , cert .CommonName )
181+ fmt .Println ("Expires At: " , cert .Expires )
182+ fmt .Println ("Starts At: " , cert .Starts )
183+ fmt .Println ("Fingerprint: " , cert .Fingerprint )
184+ fmt .Println ("Subject Alt Name: " , san )
185+ fmt .Println ("Issuer: " , cert .Issuer )
186+ fmt .Println ("Subject: " , cert .Subject )
187+ fmt .Println ()
188+ fmt .Println ("Connected Domains: " , domains )
189+ fmt .Println ("Owner: " , cert .Owner )
190+ fmt .Println ("Created: " , cert .Created )
191+ fmt .Println ("Updated: " , cert .Updated )
192+
193+ return nil
194+ }
195+
196+ // CertAttach attaches a certificate to a domain
197+ func CertAttach (name string , domain string ) error {
198+ c , err := client .New ()
117199
118200 if err != nil {
119201 return err
120202 }
121203
122- _ , err = certs .New (c , string (certFile ), string (keyFile ), commonName )
204+ fmt .Printf ("Attaching certificate %s to domain %s... " , name , domain )
205+ quit := progress ()
206+
207+ certs .Attach (c , name , domain )
208+
209+ quit <- true
210+ <- quit
211+
212+ if err == nil {
213+ fmt .Println ("done" )
214+ }
215+
123216 return err
124217}
125218
126- // CertRemove deletes a cert from the controller.
127- func CertRemove ( commonName string ) error {
219+ // CertDetach detaches a certificate from a domain
220+ func CertDetach ( name string , domain string ) error {
128221 c , err := client .New ()
129222
130223 if err != nil {
131224 return err
132225 }
133226
134- fmt .Printf ("Removing %s ... " , commonName )
227+ fmt .Printf ("Detaching certificate %s from domain %s ... " , name , domain )
135228 quit := progress ()
136229
137- certs .Delete (c , commonName )
230+ certs .Detach (c , name , domain )
138231
139232 quit <- true
140233 <- quit
0 commit comments