Skip to content

Commit 94679c5

Browse files
committed
canary
1 parent c9bffc4 commit 94679c5

8 files changed

Lines changed: 525 additions & 3 deletions

File tree

cmd/canary.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package cmd
2+
3+
import (
4+
"github.com/drycc/controller-sdk-go/api"
5+
"github.com/drycc/controller-sdk-go/appsettings"
6+
"strings"
7+
)
8+
9+
// CanaryList tells the informations about app's autoscale status
10+
func (d *DryccCmd) CanaryInfo(appID string) error {
11+
s, appID, err := load(d.ConfigFile, appID)
12+
13+
if err != nil {
14+
return err
15+
}
16+
17+
appSettings, err := appsettings.List(s.Client, appID)
18+
if d.checkAPICompatibility(s.Client, err) != nil {
19+
return err
20+
}
21+
22+
d.Printf("=== %s Canary\n\n", appID)
23+
24+
for _, procType := range appSettings.Canaries {
25+
d.Println(procType)
26+
}
27+
28+
return nil
29+
}
30+
31+
// CanaryCreate sets canary options for the app proc type.
32+
func (d *DryccCmd) CanaryCreate(appID string, processType []string) error {
33+
s, appID, err := load(d.ConfigFile, appID)
34+
35+
if err != nil {
36+
return err
37+
}
38+
39+
d.Printf("Applying canary settings for process type %s on %s... ", strings.Join(processType, ","), appID)
40+
41+
quit := progress(d.WOut)
42+
_, err = appsettings.Set(s.Client, appID, api.AppSettings{Canaries: processType})
43+
44+
quit <- true
45+
<-quit
46+
47+
if err != nil {
48+
return err
49+
}
50+
51+
d.Println("done")
52+
return nil
53+
}
54+
55+
// CanaryRemove remove canary for the app proc type.
56+
func (d *DryccCmd) CanaryRemove(appID string, processType []string) error {
57+
s, appID, err := load(d.ConfigFile, appID)
58+
59+
if err != nil {
60+
return err
61+
}
62+
63+
d.Printf("Removing canary for process type %s on %s... ", strings.Join(processType, ","), appID)
64+
65+
quit := progress(d.WOut)
66+
67+
err = appsettings.CanaryRemove(s.Client, appID, api.AppSettings{Canaries: processType})
68+
69+
quit <- true
70+
<-quit
71+
72+
if err != nil {
73+
return err
74+
}
75+
76+
d.Println("done")
77+
return nil
78+
}
79+
80+
// CanaryRelease release canary for the app.
81+
func (d *DryccCmd) CanaryRelease(appID string) error {
82+
s, appID, err := load(d.ConfigFile, appID)
83+
84+
if err != nil {
85+
return err
86+
}
87+
88+
d.Printf("Release canary for %s... ", appID)
89+
90+
quit := progress(d.WOut)
91+
92+
err = appsettings.CanaryRelease(s.Client, appID)
93+
94+
quit <- true
95+
<-quit
96+
97+
if err != nil {
98+
return err
99+
}
100+
101+
d.Println("done")
102+
return nil
103+
}
104+
105+
// CanaryRollback rollback canary for the app.
106+
func (d *DryccCmd) CanaryRollback(appID string) error {
107+
s, appID, err := load(d.ConfigFile, appID)
108+
109+
if err != nil {
110+
return err
111+
}
112+
113+
d.Printf("Rollback canary for %s... ", appID)
114+
115+
quit := progress(d.WOut)
116+
117+
err = appsettings.CanaryRollback(s.Client, appID)
118+
119+
quit <- true
120+
<-quit
121+
122+
if err != nil {
123+
return err
124+
}
125+
126+
d.Println("done")
127+
return nil
128+
}

cmd/canary_test.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"net/http"
7+
"testing"
8+
9+
"github.com/drycc/controller-sdk-go/api"
10+
"github.com/drycc/workflow-cli/pkg/testutil"
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestCanaryInfo(t *testing.T) {
15+
t.Parallel()
16+
cf, server, err := testutil.NewTestServerAndClient()
17+
if err != nil {
18+
t.Fatal(err)
19+
}
20+
defer server.Close()
21+
var b bytes.Buffer
22+
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
23+
24+
server.Mux.HandleFunc("/v2/apps/rivendell/settings/", func(w http.ResponseWriter, r *http.Request) {
25+
testutil.SetHeaders(w)
26+
fmt.Fprintf(w, `{
27+
"owner": "elrond",
28+
"app": "rivendell",
29+
"canaries": ["cmd"],
30+
"created": "2014-01-01T00:00:00UTC",
31+
"updated": "2014-01-01T00:00:00UTC",
32+
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
33+
}`)
34+
})
35+
36+
err = cmdr.CanaryInfo("rivendell")
37+
assert.NoError(t, err)
38+
assert.Equal(t, b.String(), "=== rivendell Canary\n\ncmd\n", "output")
39+
40+
server.Mux.HandleFunc("/v2/apps/mordor/settings/", func(w http.ResponseWriter, r *http.Request) {
41+
testutil.SetHeaders(w)
42+
fmt.Fprintf(w, `{
43+
"owner": "sauron",
44+
"app": "mordor",
45+
"created": "2014-01-01T00:00:00UTC",
46+
"updated": "2014-01-01T00:00:00UTC",
47+
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
48+
}`)
49+
})
50+
b.Reset()
51+
52+
err = cmdr.CanaryInfo("mordor")
53+
assert.NoError(t, err)
54+
assert.Equal(t, b.String(), "=== mordor Canary\n\n", "output")
55+
}
56+
57+
func TestCanaryCreate(t *testing.T) {
58+
t.Parallel()
59+
cf, server, err := testutil.NewTestServerAndClient()
60+
if err != nil {
61+
t.Fatal(err)
62+
}
63+
defer server.Close()
64+
var b bytes.Buffer
65+
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
66+
67+
server.Mux.HandleFunc("/v2/apps/lothlorien/settings/", func(w http.ResponseWriter, r *http.Request) {
68+
testutil.SetHeaders(w)
69+
data := []string{"cmd"}
70+
testutil.AssertBody(t, api.AppSettings{Canaries: data}, r)
71+
fmt.Fprintf(w, `{}`)
72+
})
73+
74+
err = cmdr.CanaryCreate("lothlorien", []string{"cmd"})
75+
assert.NoError(t, err)
76+
assert.Equal(t, testutil.StripProgress(b.String()), "Applying canary settings for process type cmd on lothlorien... done\n", "output")
77+
}
78+
79+
func TestCanaryRemove(t *testing.T) {
80+
t.Parallel()
81+
cf, server, err := testutil.NewTestServerAndClient()
82+
if err != nil {
83+
t.Fatal(err)
84+
}
85+
defer server.Close()
86+
var b bytes.Buffer
87+
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
88+
89+
server.Mux.HandleFunc("/v2/apps/bree/settings/", func(w http.ResponseWriter, r *http.Request) {
90+
testutil.SetHeaders(w)
91+
data := []string{"cmd"}
92+
testutil.AssertBody(t, api.AppSettings{Canaries: data}, r)
93+
w.WriteHeader(http.StatusNoContent)
94+
})
95+
96+
err = cmdr.CanaryRemove("bree", []string{"cmd"})
97+
assert.NoError(t, err)
98+
assert.Equal(t, testutil.StripProgress(b.String()), "Removing canary for process type cmd on bree... done\n", "output")
99+
}
100+
101+
func TestCanaryRelease(t *testing.T) {
102+
t.Parallel()
103+
cf, server, err := testutil.NewTestServerAndClient()
104+
if err != nil {
105+
t.Fatal(err)
106+
}
107+
defer server.Close()
108+
var b bytes.Buffer
109+
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
110+
111+
server.Mux.HandleFunc("/v2/apps/bree/canary/release/", func(w http.ResponseWriter, r *http.Request) {
112+
testutil.SetHeaders(w)
113+
w.WriteHeader(http.StatusNoContent)
114+
})
115+
116+
err = cmdr.CanaryRelease("bree")
117+
assert.NoError(t, err)
118+
assert.Equal(t, testutil.StripProgress(b.String()), "Release canary for bree... done\n", "output")
119+
}
120+
121+
func TestCanaryRollback(t *testing.T) {
122+
t.Parallel()
123+
cf, server, err := testutil.NewTestServerAndClient()
124+
if err != nil {
125+
t.Fatal(err)
126+
}
127+
defer server.Close()
128+
var b bytes.Buffer
129+
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
130+
131+
server.Mux.HandleFunc("/v2/apps/bree/canary/rollback/", func(w http.ResponseWriter, r *http.Request) {
132+
testutil.SetHeaders(w)
133+
w.WriteHeader(http.StatusNoContent)
134+
})
135+
136+
err = cmdr.CanaryRollback("bree")
137+
assert.NoError(t, err)
138+
assert.Equal(t, testutil.StripProgress(b.String()), "Rollback canary for bree... done\n", "output")
139+
}

cmd/cmd.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ type Commander interface {
2626
Whoami(bool) error
2727
BuildsList(string, int) error
2828
BuildsCreate(string, string, string, string) error
29+
CanaryInfo(string) error
30+
CanaryCreate(string, []string) error
31+
CanaryRemove(string, []string) error
32+
CanaryRelease(string) error
33+
CanaryRollback(string) error
2934
CertsList(int, time.Time) error
3035
CertAdd(string, string, string) error
3136
CertRemove(string) error

drycc.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Subcommands, use 'drycc help [subcommand]' to learn more:
5050
apps manage applications used to provide services
5151
autoscale manage autoscale for applications
5252
builds manage builds created using 'git push'
53+
canary manage canary deploy for applications
5354
certs manage SSL endpoints for an app
5455
config manage environment variables that define app config
5556
domains manage and assign domain names to your applications
@@ -118,6 +119,8 @@ Use 'git push drycc main' to deploy to an application.
118119
err = parser.Autoscale(argv, &cmdr)
119120
case "builds":
120121
err = parser.Builds(argv, &cmdr)
122+
case "canary":
123+
err = parser.Canary(argv, &cmdr)
121124
case "certs":
122125
err = parser.Certs(argv, &cmdr)
123126
case "config":

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ require (
2828
gopkg.in/yaml.v2 v2.4.0 // indirect
2929
)
3030

31-
replace github.com/drycc/controller-sdk-go => github.com/jianxiaoguo/controller-sdk-go v0.0.0-20230524075627-dcfa3f6f1df1
31+
replace github.com/drycc/controller-sdk-go => github.com/jianxiaoguo/controller-sdk-go v0.0.0-20230526072711-4ced8c7513c4

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
1717
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
1818
github.com/goware/urlx v0.3.2 h1:gdoo4kBHlkqZNaf6XlQ12LGtQOmpKJrR04Rc3RnpJEo=
1919
github.com/goware/urlx v0.3.2/go.mod h1:h8uwbJy68o+tQXCGZNa9D73WN8n0r9OBae5bUnLcgjw=
20-
github.com/jianxiaoguo/controller-sdk-go v0.0.0-20230524075627-dcfa3f6f1df1 h1:uColqj3QFfLHTmhdNNsakhIl1JoB1kzrAa/6E3i1MeQ=
21-
github.com/jianxiaoguo/controller-sdk-go v0.0.0-20230524075627-dcfa3f6f1df1/go.mod h1:q6gbIO0f+xUM8mejPgbbUT8pdAYTIb5vugUsoTcbLw0=
20+
github.com/jianxiaoguo/controller-sdk-go v0.0.0-20230526072711-4ced8c7513c4 h1:2ZwNxhJ6h/XOwH5wHQuvKclLW6phJjzxFvRNka8M05A=
21+
github.com/jianxiaoguo/controller-sdk-go v0.0.0-20230526072711-4ced8c7513c4/go.mod h1:q6gbIO0f+xUM8mejPgbbUT8pdAYTIb5vugUsoTcbLw0=
2222
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
2323
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
2424
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=

0 commit comments

Comments
 (0)