Skip to content

Commit e669725

Browse files
committed
clean up
1 parent d751996 commit e669725

File tree

6 files changed

+270
-233
lines changed

6 files changed

+270
-233
lines changed

cli/docker.go

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func dockerCmd() *cobra.Command {
224224
log.Debug(ctx, "using custom docker bridge CIDR", slog.F("cidr", cidr))
225225
}
226226

227-
dargs, err := dockerdArgs(flags.ethlink, cidr, flags.extraCertsPath, false)
227+
dargs, err := dockerdArgs(flags.ethlink, cidr, false)
228228
if err != nil {
229229
return xerrors.Errorf("dockerd args: %w", err)
230230
}
@@ -257,7 +257,7 @@ func dockerCmd() *cobra.Command {
257257
// directory is going to be on top of an overlayfs filesystem
258258
// we have to use the vfs storage driver.
259259
if xunix.IsNoSpaceErr(err) {
260-
args, err = dockerdArgs(flags.ethlink, cidr, flags.extraCertsPath, true)
260+
args, err = dockerdArgs(flags.ethlink, cidr, true)
261261
if err != nil {
262262
blog.Info("Failed to create Container-based Virtual Machine: " + err.Error())
263263
//nolint
@@ -304,7 +304,7 @@ func dockerCmd() *cobra.Command {
304304
if xunix.IsNoSpaceErr(err) {
305305
blog.Info("Insufficient space to start inner container. Restarting dockerd using the vfs driver. Your performance will be degraded. Clean up your home volume and then restart the workspace to improve performance.")
306306
log.Debug(ctx, "encountered 'no space left on device' error while starting workspace", slog.Error(err))
307-
args, err := dockerdArgs(flags.ethlink, cidr, flags.extraCertsPath, true)
307+
args, err := dockerdArgs(flags.ethlink, cidr, true)
308308
if err != nil {
309309
return xerrors.Errorf("dockerd args for restart: %w", err)
310310
}
@@ -718,7 +718,7 @@ func runDockerCVM(ctx context.Context, log slog.Logger, client dockerutil.Docker
718718
}
719719

720720
//nolint:revive
721-
func dockerdArgs(link, cidr string, caCertsPath string, isNoSpace bool) ([]string, error) {
721+
func dockerdArgs(link, cidr string, isNoSpace bool) ([]string, error) {
722722
// We need to adjust the MTU for the host otherwise packets will fail delivery.
723723
// 1500 is the standard, but certain deployments (like GKE) use custom MTU values.
724724
// See: https://www.atlantis-press.com/journals/ijndc/125936177/view#sec-s3.1
@@ -743,25 +743,6 @@ func dockerdArgs(link, cidr string, caCertsPath string, isNoSpace bool) ([]strin
743743
fmt.Sprintf("--bip=%s/%d", dockerBip, prefixLen),
744744
}
745745

746-
if caCertsPath != "" {
747-
f, err := os.Stat(caCertsPath)
748-
if err != nil {
749-
return nil, xerrors.Errorf("open %v: %w", caCertsPath, err)
750-
}
751-
if f.IsDir() {
752-
entries, err := os.ReadDir(caCertsPath)
753-
if err != nil {
754-
return nil, xerrors.Errorf("read dir %v: %w", caCertsPath, err)
755-
}
756-
for _, entry := range entries {
757-
p := filepath.Join(caCertsPath, entry.Name())
758-
args = append(args, fmt.Sprintf("--tlscacert=%s", p))
759-
}
760-
} else {
761-
args = append(args, fmt.Sprintf("--tlscacert=%s", caCertsPath))
762-
}
763-
}
764-
765746
if isNoSpace {
766747
args = append(args,
767748
fmt.Sprintf("--data-root=%s", noSpaceDataDir),

integration/docker_test.go

Lines changed: 32 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,8 @@
44
package integration_test
55

66
import (
7-
"context"
8-
"crypto/tls"
9-
"encoding/json"
107
"fmt"
118
"net"
12-
"net/http"
13-
"net/http/httptest"
149
"os"
1510
"path/filepath"
1611
"strconv"
@@ -21,8 +16,6 @@ import (
2116
dockertest "github.com/ory/dockertest/v3"
2217
"github.com/stretchr/testify/require"
2318

24-
"github.com/coder/coder/v2/codersdk"
25-
"github.com/coder/coder/v2/codersdk/agentsdk"
2619
"github.com/coder/envbox/cli"
2720
"github.com/coder/envbox/integration/integrationtest"
2821
)
@@ -285,87 +278,77 @@ func TestDocker(t *testing.T) {
285278
t.Parallel()
286279

287280
var (
288-
dir = integrationtest.TmpDir(t)
289-
binds = integrationtest.DefaultBinds(t, dir)
290-
ctx, cancel = context.WithTimeout(context.Background(), time.Minute*5)
281+
dir = integrationtest.TmpDir(t)
282+
binds = integrationtest.DefaultBinds(t, dir)
291283
)
292-
t.Cleanup(cancel)
293284

294285
pool, err := dockertest.NewPool("")
295286
require.NoError(t, err)
296287

288+
// Create some listeners for the Docker and Coder
289+
// services we'll be running with self signed certs.
297290
bridgeIP := integrationtest.DockerBridgeIP(t)
298-
l, err := net.Listen("tcp", fmt.Sprintf("%s:0", bridgeIP))
299-
require.NoError(t, err)
300-
defer l.Close()
301-
302-
host, port, err := net.SplitHostPort(l.Addr().String())
291+
coderListener, err := net.Listen("tcp", fmt.Sprintf("%s:0", bridgeIP))
303292
require.NoError(t, err)
293+
defer coderListener.Close()
294+
coderAddr := tcpAddr(t, coderListener)
304295

305296
registryListener, err := net.Listen("tcp", fmt.Sprintf("%s:0", bridgeIP))
306297
require.NoError(t, err)
307298
err = registryListener.Close()
308299
require.NoError(t, err)
300+
registryAddr := tcpAddr(t, registryListener)
309301

310-
registryHost, registryPort, err := net.SplitHostPort(registryListener.Addr().String())
311-
require.NoError(t, err)
302+
coderCert := integrationtest.GenerateTLSCertificate(t, "host.docker.internal", coderAddr.IP.String())
303+
dockerCert := integrationtest.GenerateTLSCertificate(t, "host.docker.internal", registryAddr.IP.String())
312304

313-
t.Logf("registryHost: %s", registryHost)
314-
coderCert := integrationtest.GenerateTLSCertificate(t, "host.docker.internal", host)
315-
dockerCert := integrationtest.GenerateTLSCertificate(t, "host.docker.internal", registryHost)
305+
// Startup our fake Coder "control-plane".
306+
recorder := integrationtest.FakeBuildLogRecorder(t, coderListener, coderCert)
316307

317-
fakeServer, buildLogCh := fakeCoder(t)
318-
s := httptest.NewUnstartedServer(fakeServer)
319-
s.Listener = l
320-
s.TLS = &tls.Config{
321-
Certificates: []tls.Certificate{coderCert},
322-
}
323-
s.StartTLS()
308+
certDir := integrationtest.MkdirAll(t, dir, "certs")
324309

325-
certDir := filepath.Join(dir, "certs")
326-
err = os.MkdirAll(certDir, 0777)
327-
require.NoError(t, err)
310+
// Write the Coder cert disk.
328311
coderCertPath := filepath.Join(certDir, "coder_cert.pem")
329312
coderKeyPath := filepath.Join(certDir, "coder_key.pem")
330313
integrationtest.WriteCertificate(t, coderCert, coderCertPath, coderKeyPath)
331-
certMount := integrationtest.BindMount(certDir, "/tmp/certs", false)
314+
coderCertMount := integrationtest.BindMount(certDir, "/tmp/certs", false)
332315

316+
// Write the Registry cert to disk.
333317
regCertPath := filepath.Join(certDir, "registry_cert.crt")
334318
regKeyPath := filepath.Join(certDir, "registry_key.pem")
335319
integrationtest.WriteCertificate(t, dockerCert, regCertPath, regKeyPath)
336320

321+
// Start up the docker registry and push an image
322+
// to it that we can reference.
337323
image := integrationtest.RunLocalDockerRegistry(t, pool, integrationtest.RegistryConfig{
338324
HostCertPath: regCertPath,
339325
HostKeyPath: regKeyPath,
340326
Image: integrationtest.UbuntuImage,
341-
TLSPort: registryPort,
327+
TLSPort: strconv.Itoa(registryAddr.Port),
342328
})
343329

344-
innerImageHost := strings.Split(image, "/")[0]
345-
t.Logf("innerhost: %s", innerImageHost)
346-
regCAPath := filepath.Join("/etc/docker/certs.d", innerImageHost, "ca.crt")
347-
t.Log("regcapath: ", regCAPath)
348-
330+
// Mount the cert into the expected location
331+
// for the Envbox Docker daemon.
332+
regCAPath := filepath.Join("/etc/docker/certs.d", image.Registry(), "ca.crt")
349333
registryCAMount := integrationtest.BindMount(regCertPath, regCAPath, false)
350334

351335
envs := []string{
352336
integrationtest.EnvVar(cli.EnvAgentToken, "faketoken"),
353-
integrationtest.EnvVar(cli.EnvAgentURL, fmt.Sprintf("https://%s:%s", "host.docker.internal", port)),
337+
integrationtest.EnvVar(cli.EnvAgentURL, fmt.Sprintf("https://%s:%d", "host.docker.internal", coderAddr.Port)),
354338
integrationtest.EnvVar(cli.EnvExtraCertsPath, "/tmp/certs"),
355339
}
356340

357-
buildLogDone := waitForBuildLog(t, ctx, buildLogCh)
358-
359-
t.Logf("image: %s", image)
360341
// Run the envbox container.
361342
_ = integrationtest.RunEnvbox(t, pool, &integrationtest.CreateDockerCVMConfig{
362-
Image: image,
343+
Image: image.String(),
363344
Username: "coder",
364345
Envs: envs,
365-
OuterMounts: append(binds, certMount, registryCAMount),
346+
OuterMounts: append(binds, coderCertMount, registryCAMount),
366347
})
367348

368-
<-buildLogDone
349+
// This indicates we've made it all the way to end
350+
// of the logs we attempt to push.
351+
require.True(t, recorder.ContainsLog("Bootstrapping workspace..."))
369352
})
370353
}
371354

@@ -392,70 +375,10 @@ func requireSliceContains(t *testing.T, ss []string, els ...string) {
392375
}
393376
}
394377

395-
func bindMount(src, dest string, ro bool) string {
396-
if ro {
397-
return fmt.Sprintf("%s:%s:%s", src, dest, "ro")
398-
}
399-
return fmt.Sprintf("%s:%s", src, dest)
400-
}
401-
402-
func fakeCoder(t testing.TB) (http.Handler, <-chan string) {
378+
func tcpAddr(t testing.TB, l net.Listener) *net.TCPAddr {
403379
t.Helper()
404380

405-
logCh := make(chan string)
406-
t.Cleanup(func() { close(logCh) })
407-
408-
mux := http.NewServeMux()
409-
mux.Handle("/api/v2/buildinfo", http.HandlerFunc(
410-
func(w http.ResponseWriter, r *http.Request) {
411-
w.Header().Set("Content-Type", "application/json; charset=utf-8")
412-
w.WriteHeader(http.StatusOK)
413-
414-
enc := json.NewEncoder(w)
415-
enc.SetEscapeHTML(true)
416-
417-
// We can't really do much about these errors, it's probably due to a
418-
// dropped connection.
419-
_ = enc.Encode(&codersdk.BuildInfoResponse{
420-
Version: "v1.0.0",
421-
})
422-
}))
423-
424-
mux.Handle("/api/v2/workspaceagents/me/logs", http.HandlerFunc(
425-
func(w http.ResponseWriter, r *http.Request) {
426-
var logs agentsdk.PatchLogs
427-
err := json.NewDecoder(r.Body).Decode(&logs)
428-
require.NoError(t, err)
429-
w.WriteHeader(http.StatusOK)
430-
for _, log := range logs.Logs {
431-
logCh <- log.Output
432-
}
433-
}))
434-
435-
mux.Handle("/", http.HandlerFunc(
436-
func(w http.ResponseWriter, r *http.Request) {
437-
t.Fatalf("unexpected route %v", r.URL.Path)
438-
}))
439-
440-
return mux, logCh
441-
}
442-
443-
// todo this sucks refactor it.
444-
func waitForBuildLog(t testing.TB, ctx context.Context, buildLogCh <-chan string) <-chan struct{} {
445-
t.Helper()
446-
done := make(chan struct{})
447-
go func() {
448-
defer close(done)
449-
for {
450-
select {
451-
case <-ctx.Done():
452-
t.Fatalf("timed out waiting for final build log")
453-
case log := <-buildLogCh:
454-
if log == "Bootstrapping workspace..." {
455-
return
456-
}
457-
}
458-
}
459-
}()
460-
return done
381+
tcpAddr, ok := l.Addr().(*net.TCPAddr)
382+
require.True(t, ok)
383+
return tcpAddr
461384
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package integrationtest
2+
3+
import (
4+
"bytes"
5+
"crypto/ecdsa"
6+
"crypto/elliptic"
7+
"crypto/rand"
8+
"crypto/tls"
9+
"crypto/x509"
10+
"crypto/x509/pkix"
11+
"encoding/pem"
12+
"math/big"
13+
"net"
14+
"os"
15+
"testing"
16+
"time"
17+
18+
"github.com/stretchr/testify/require"
19+
)
20+
21+
func GenerateTLSCertificate(t testing.TB, commonName string, ipAddr string) tls.Certificate {
22+
t.Helper()
23+
24+
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
25+
require.NoError(t, err)
26+
template := x509.Certificate{
27+
SerialNumber: big.NewInt(1),
28+
Subject: pkix.Name{
29+
Organization: []string{"Acme Co"},
30+
CommonName: commonName,
31+
},
32+
DNSNames: []string{commonName},
33+
NotBefore: time.Now(),
34+
NotAfter: time.Now().Add(time.Hour * 24 * 180),
35+
36+
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
37+
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
38+
BasicConstraintsValid: true,
39+
IPAddresses: []net.IP{net.ParseIP(ipAddr)},
40+
IsCA: true,
41+
}
42+
43+
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
44+
require.NoError(t, err)
45+
var certFile bytes.Buffer
46+
require.NoError(t, err)
47+
_, err = certFile.Write(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}))
48+
require.NoError(t, err)
49+
privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
50+
require.NoError(t, err)
51+
var keyFile bytes.Buffer
52+
err = pem.Encode(&keyFile, &pem.Block{Type: "PRIVATE KEY", Bytes: privateKeyBytes})
53+
require.NoError(t, err)
54+
cert, err := tls.X509KeyPair(certFile.Bytes(), keyFile.Bytes())
55+
require.NoError(t, err)
56+
return cert
57+
}
58+
59+
func writePEM(t testing.TB, path string, typ string, contents []byte) {
60+
t.Helper()
61+
62+
f, err := os.Create(path)
63+
require.NoError(t, err)
64+
defer f.Close()
65+
66+
err = pem.Encode(f, &pem.Block{
67+
Type: typ,
68+
Bytes: contents,
69+
})
70+
require.NoError(t, err)
71+
}
72+
73+
func WriteCertificate(t testing.TB, c tls.Certificate, certPath, keyPath string) {
74+
require.Len(t, c.Certificate, 1, "expecting 1 certificate")
75+
key, err := x509.MarshalPKCS8PrivateKey(c.PrivateKey)
76+
require.NoError(t, err)
77+
78+
cert := c.Certificate[0]
79+
80+
writePEM(t, keyPath, "PRIVATE KEY", key)
81+
writePEM(t, certPath, "CERTIFICATE", cert)
82+
}

0 commit comments

Comments
 (0)