Skip to content

Commit 1e10268

Browse files
committed
feat(controller-sdk-go): add pod exec
1 parent de65d8c commit 1e10268

5 files changed

Lines changed: 92 additions & 2 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ _testmain.go
2626
vendor
2727
coverage.txt
2828
.idea/*
29+
.vscode/

go.mod

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
module github.com/drycc/controller-sdk-go
22

3-
go 1.17
3+
go 1.19
44

5-
require github.com/goware/urlx v0.3.1
5+
require (
6+
github.com/gorilla/websocket v1.5.0
7+
github.com/goware/urlx v0.3.1
8+
)
69

710
require (
811
github.com/PuerkitoBio/purell v1.1.1 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
22
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
33
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
44
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
5+
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
6+
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
57
github.com/goware/urlx v0.3.1 h1:BbvKl8oiXtJAzOzMqAQ0GfIhf96fKeNEZfm9ocNSUBI=
68
github.com/goware/urlx v0.3.1/go.mod h1:h8uwbJy68o+tQXCGZNa9D73WN8n0r9OBae5bUnLcgjw=
79
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=

ps/ps.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ package ps
44
import (
55
"encoding/json"
66
"fmt"
7+
"net/http"
8+
"net/url"
79
"sort"
810

911
drycc "github.com/drycc/controller-sdk-go"
1012
"github.com/drycc/controller-sdk-go/api"
13+
"github.com/gorilla/websocket"
1114
)
1215

1316
// List lists an app's processes.
@@ -26,6 +29,36 @@ func List(c *drycc.Client, appID string, results int) (api.PodsList, int, error)
2629
return procs, count, reqErr
2730
}
2831

32+
// Exec a command in a container.
33+
func Exec(c *drycc.Client, app, pod string, tty, stdin bool, command []string) (*websocket.Conn, error) {
34+
scheme := "ws"
35+
if c.ControllerURL.Scheme == "https" {
36+
scheme = "wss"
37+
}
38+
path := fmt.Sprintf("v2/apps/%s/pods/%s/exec/", app, pod)
39+
endpoint := url.URL{Scheme: scheme, Host: c.ControllerURL.Host, Path: path}
40+
conn, _, err := websocket.DefaultDialer.Dial(
41+
endpoint.String(),
42+
http.Header{
43+
"User-Agent": {c.UserAgent},
44+
"Authorization": {"token " + c.Token},
45+
"X-Drycc-Builder-Auth": {c.HooksToken},
46+
},
47+
)
48+
if err != nil {
49+
return nil, err
50+
}
51+
data, err := json.Marshal(&command)
52+
if err != nil {
53+
return nil, err
54+
}
55+
conn.WriteMessage(
56+
websocket.TextMessage,
57+
[]byte(fmt.Sprintf(`{"tty": %t, "stdin": %t, "command": %s}`, tty, stdin, data)),
58+
)
59+
return conn, nil
60+
}
61+
2962
// Scale increases or decreases an app's processes. The processes are specified in the target argument,
3063
// a key-value map, where the key is the process name and the value is the number of replicas
3164
func Scale(c *drycc.Client, appID string, targets map[string]int) error {

ps/ps_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ps
33
import (
44
"fmt"
55
"io/ioutil"
6+
"log"
67
"net/http"
78
"net/http/httptest"
89
"reflect"
@@ -11,6 +12,7 @@ import (
1112
drycc "github.com/drycc/controller-sdk-go"
1213
"github.com/drycc/controller-sdk-go/api"
1314
"github.com/drycc/controller-sdk-go/pkg/time"
15+
"github.com/gorilla/websocket"
1416
)
1517

1618
const processesFixture string = `
@@ -64,6 +66,8 @@ const restartWebTwoFixture string = `[
6466

6567
const scaleExpected string = `{"web":2}`
6668

69+
var upgrader = websocket.Upgrader{} // use default options
70+
6771
type fakeHTTPServer struct{}
6872

6973
func (fakeHTTPServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
@@ -74,6 +78,29 @@ func (fakeHTTPServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
7478
return
7579
}
7680

81+
if req.URL.Path == "/v2/apps/example-go/pods/example-go-web-111/exec/" {
82+
c, err := upgrader.Upgrade(res, req, nil)
83+
if err != nil {
84+
log.Print("upgrade:", err)
85+
return
86+
}
87+
defer c.Close()
88+
for {
89+
messageType, message, err := c.ReadMessage()
90+
if err != nil {
91+
log.Println("read:", err)
92+
break
93+
}
94+
95+
log.Printf("recv: %s", message)
96+
err = c.WriteMessage(messageType, []byte("# "+"\n"))
97+
if err != nil {
98+
log.Println("write:", err)
99+
break
100+
}
101+
}
102+
}
103+
77104
if req.URL.Path == "/v2/apps/example-go/pods/restart/" && req.Method == "POST" {
78105
res.Write([]byte(restartAllFixture))
79106
return
@@ -155,6 +182,30 @@ func TestProcessesList(t *testing.T) {
155182
}
156183
}
157184

185+
func TestExec(t *testing.T) {
186+
handler := fakeHTTPServer{}
187+
server := httptest.NewServer(&handler)
188+
defer server.Close()
189+
190+
drycc, err := drycc.New(false, server.URL, "abc")
191+
if err != nil {
192+
t.Fatal(err)
193+
}
194+
conn, err := Exec(drycc, "example-go", "example-go-web-111", true, true, []string{"/bin/sh"})
195+
if err != nil {
196+
t.Fatal(err)
197+
}
198+
expected := []byte("# " + "\n")
199+
_, actual, err := conn.ReadMessage()
200+
if err != nil {
201+
t.Fatal(err)
202+
}
203+
204+
if !reflect.DeepEqual(actual, expected) {
205+
t.Errorf("Expected: %v, Got %v", expected, actual)
206+
}
207+
}
208+
158209
type testExpected struct {
159210
Name string
160211
Type string

0 commit comments

Comments
 (0)