Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 11cd031

Browse files
authored
Add basic env create|edit integration tests (#160)
1 parent a171882 commit 11cd031

File tree

9 files changed

+125
-34
lines changed

9 files changed

+125
-34
lines changed

.github/workflows/integration.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ jobs:
2222
- uses: actions/setup-go@v2
2323
with:
2424
go-version: '^1.14'
25-
- name: go test
26-
run: go test -v ./ci/integration/...
25+
- name: integration tests
26+
run: ./ci/steps/integration.sh

ci/integration/Dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM ubuntu:20.04
2+
3+
RUN apt-get update && apt-get install -y jq curl

ci/integration/devurls_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ func TestDevURLCLI(t *testing.T) {
1212
run(t, "coder-cli-devurl-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
1313
c.Run(ctx, "which coder").Assert(t,
1414
tcli.Success(),
15-
tcli.StdoutMatches("/usr/sbin/coder"),
1615
tcli.StderrEmpty(),
1716
)
1817

ci/integration/envs_test.go

+97-25
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,46 @@ package integration
22

33
import (
44
"context"
5+
"fmt"
6+
"math"
7+
"net/url"
58
"regexp"
69
"testing"
10+
"time"
711

812
"cdr.dev/coder-cli/ci/tcli"
13+
"cdr.dev/coder-cli/coder-sdk"
14+
"cdr.dev/slog"
15+
"cdr.dev/slog/sloggers/slogtest"
16+
"cdr.dev/slog/sloggers/slogtest/assert"
17+
"github.com/google/go-cmp/cmp"
918
)
1019

11-
// From Coder organization images
12-
// const ubuntuImgID = "5f443b16-30652892427b955601330fa5"
20+
func cleanupClient(t *testing.T, ctx context.Context) *coder.Client {
21+
creds := login(ctx, t)
22+
23+
u, err := url.Parse(creds.url)
24+
assert.Success(t, "parse base url", err)
25+
26+
return &coder.Client{BaseURL: u, Token: creds.token}
27+
}
28+
29+
func cleanupEnv(t *testing.T, client *coder.Client, envID string) func() {
30+
return func() {
31+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
32+
defer cancel()
33+
34+
slogtest.Info(t, "cleanuping up environment", slog.F("env_id", envID))
35+
_ = client.DeleteEnvironment(ctx, envID)
36+
}
37+
}
1338

1439
func TestEnvsCLI(t *testing.T) {
1540
t.Parallel()
1641

1742
run(t, "coder-cli-env-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
1843
headlessLogin(ctx, t, c)
19-
20-
// Ensure binary is present.
21-
c.Run(ctx, "which coder").Assert(t,
22-
tcli.Success(),
23-
tcli.StdoutMatches("/usr/sbin/coder"),
24-
tcli.StderrEmpty(),
25-
)
44+
client := cleanupClient(t, ctx)
2645

2746
// Minimum args not received.
2847
c.Run(ctx, "coder envs create").Assert(t,
@@ -49,21 +68,74 @@ func TestEnvsCLI(t *testing.T) {
4968
tcli.Error(),
5069
)
5170

52-
// TODO(Faris) : uncomment this when we can safely purge the environments
53-
// the integrations tests would create in the sidecar
54-
// Successfully create environment.
55-
// c.Run(ctx, "coder envs create --image "+ubuntuImgID+" test-ubuntu").Assert(t,
56-
// tcli.Success(),
57-
// // why does flog.Success write to stderr?
58-
// tcli.StderrMatches(regexp.QuoteMeta("Successfully created environment \"test-ubuntu\"")),
59-
// )
60-
61-
// TODO(Faris) : uncomment this when we can safely purge the environments
62-
// the integrations tests would create in the sidecar
63-
// Successfully provision environment with fractional resource amounts
64-
// c.Run(ctx, fmt.Sprintf(`coder envs create -i %s -c 1.2 -m 1.4 non-whole-resource-amounts`, ubuntuImgID)).Assert(t,
65-
// tcli.Success(),
66-
// tcli.StderrMatches(regexp.QuoteMeta("Successfully created environment \"non-whole-resource-amounts\"")),
67-
// )
71+
name := randString(10)
72+
cpu := 2.3
73+
c.Run(ctx, fmt.Sprintf("coder envs create %s --image ubuntu --cpu %f", name, cpu)).Assert(t,
74+
tcli.Success(),
75+
)
76+
77+
c.Run(ctx, "coder envs ls").Assert(t,
78+
tcli.Success(),
79+
tcli.StdoutMatches(regexp.QuoteMeta(name)),
80+
)
81+
82+
var env coder.Environment
83+
c.Run(ctx, fmt.Sprintf(`coder envs ls -o json | jq '.[] | select(.name == "%s")'`, name)).Assert(t,
84+
tcli.Success(),
85+
tcli.StdoutJSONUnmarshal(&env),
86+
)
87+
88+
// attempt to cleanup the environment even if tests fail
89+
t.Cleanup(cleanupEnv(t, client, env.ID))
90+
91+
assert.Equal(t, "environment cpu was correctly set", cpu, float64(env.CPUCores), floatComparer)
92+
93+
c.Run(ctx, fmt.Sprintf("coder envs watch-build %s", name)).Assert(t,
94+
tcli.Success(),
95+
)
96+
97+
c.Run(ctx, fmt.Sprintf("coder envs rm %s --force", name)).Assert(t,
98+
tcli.Success(),
99+
)
100+
})
101+
102+
run(t, "coder-cli-env-edit-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
103+
headlessLogin(ctx, t, c)
104+
client := cleanupClient(t, ctx)
105+
106+
name := randString(10)
107+
c.Run(ctx, fmt.Sprintf("coder envs create %s --image ubuntu --follow", name)).Assert(t,
108+
tcli.Success(),
109+
)
110+
111+
var env coder.Environment
112+
c.Run(ctx, fmt.Sprintf(`coder envs ls -o json | jq '.[] | select(.name == "%s")'`, name)).Assert(t,
113+
tcli.Success(),
114+
tcli.StdoutJSONUnmarshal(&env),
115+
)
116+
117+
// attempt to cleanup the environment even if tests fail
118+
t.Cleanup(cleanupEnv(t, client, env.ID))
119+
120+
cpu := 2.1
121+
c.Run(ctx, fmt.Sprintf(`coder envs edit %s --cpu %f --follow`, name, cpu)).Assert(t,
122+
tcli.Success(),
123+
)
124+
125+
c.Run(ctx, fmt.Sprintf(`coder envs ls -o json | jq '.[] | select(.name == "%s")'`, name)).Assert(t,
126+
tcli.Success(),
127+
tcli.StdoutJSONUnmarshal(&env),
128+
)
129+
assert.Equal(t, "cpu cores were updated", cpu, float64(env.CPUCores), floatComparer)
130+
131+
c.Run(ctx, fmt.Sprintf("coder envs rm %s --force", name)).Assert(t,
132+
tcli.Success(),
133+
)
68134
})
69135
}
136+
137+
var floatComparer = cmp.Comparer(func(x, y float64) bool {
138+
delta := math.Abs(x - y)
139+
mean := math.Abs(x+y) / 2.0
140+
return delta/mean < 0.001
141+
})

ci/integration/integration_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func run(t *testing.T, container string, execute func(t *testing.T, ctx context.
1818
defer cancel()
1919

2020
c, err := tcli.NewContainerRunner(ctx, &tcli.ContainerConfig{
21-
Image: "codercom/enterprise-dev",
21+
Image: "coder-cli-integration:latest",
2222
Name: container,
2323
BindMounts: map[string]string{
2424
binpath: "/bin/coder",
@@ -36,7 +36,6 @@ func TestCoderCLI(t *testing.T) {
3636
run(t, "test-coder-cli", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
3737
c.Run(ctx, "which coder").Assert(t,
3838
tcli.Success(),
39-
tcli.StdoutMatches("/usr/sbin/coder"),
4039
tcli.StderrEmpty(),
4140
)
4241

@@ -87,7 +86,7 @@ func TestCoderCLI(t *testing.T) {
8786
var seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
8887

8988
func randString(length int) string {
90-
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
89+
const charset = "abcdefghijklmnopqrstuvwxyz"
9190
b := make([]byte, length)
9291
for i := range b {
9392
b[i] = charset[seededRand.Intn(len(charset))]

ci/integration/setup_test.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,17 @@ func build(path string) error {
5151
// write session tokens to the given container runner
5252
func headlessLogin(ctx context.Context, t *testing.T, runner *tcli.ContainerRunner) {
5353
creds := login(ctx, t)
54-
cmd := exec.CommandContext(ctx, "sh", "-c", "mkdir -p ~/.config/coder && cat > ~/.config/coder/session")
54+
cmd := exec.CommandContext(ctx, "sh", "-c", "mkdir -p $HOME/.config/coder && cat > $HOME/.config/coder/session")
5555

5656
// !IMPORTANT: be careful that this does not appear in logs
5757
cmd.Stdin = strings.NewReader(creds.token)
5858
runner.RunCmd(cmd).Assert(t,
5959
tcli.Success(),
6060
)
61-
runner.Run(ctx, fmt.Sprintf("echo -ne %s > ~/.config/coder/url", creds.url)).Assert(t,
61+
62+
cmd = exec.CommandContext(ctx, "sh", "-c", "cat > $HOME/.config/coder/url")
63+
cmd.Stdin = strings.NewReader(creds.url)
64+
runner.RunCmd(cmd).Assert(t,
6265
tcli.Success(),
6366
)
6467
}

ci/integration/users_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ func TestUsers(t *testing.T) {
1414
run(t, "users-cli-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
1515
c.Run(ctx, "which coder").Assert(t,
1616
tcli.Success(),
17-
tcli.StdoutMatches("/usr/sbin/coder"),
1817
tcli.StderrEmpty(),
1918
)
2019

ci/steps/integration.sh

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
3+
set -eo pipefail
4+
5+
log() {
6+
echo "--- $@"
7+
}
8+
9+
cd "$(git rev-parse --show-toplevel)"
10+
11+
log "building integration test image"
12+
docker build -f ./ci/integration/Dockerfile -t coder-cli-integration:latest .
13+
14+
log "starting integration tests"
15+
go test ./ci/integration -count=1

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
cdr.dev/wsep v0.0.0-20200728013649-82316a09813f
88
github.com/briandowns/spinner v1.11.1
99
github.com/fatih/color v1.9.0
10+
github.com/google/go-cmp v0.4.0
1011
github.com/gorilla/websocket v1.4.2
1112
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
1213
github.com/klauspost/compress v1.10.8 // indirect

0 commit comments

Comments
 (0)