97 lines
3.7 KiB
Go
97 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func archiveOf(t *testing.T, h tar.Header, body string) string {
|
|
t.Helper()
|
|
var buf bytes.Buffer
|
|
w := tar.NewWriter(&buf)
|
|
h.Size = int64(len(body))
|
|
if h.Typeflag == tar.TypeSymlink {
|
|
h.Size = 0
|
|
}
|
|
if err := w.WriteHeader(&h); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if h.Typeflag != tar.TypeSymlink {
|
|
if _, err := w.Write([]byte(body)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
w.Close()
|
|
return buf.String()
|
|
}
|
|
|
|
// Issue 348: route-proxy asked 10.10.0.1 alone while the machine listed both mesh resolvers; its copy
|
|
// of the file could not be read by anything on the mesh.
|
|
func TestAContainersResolverFileIsReadThroughTheArchiveAndComparedWithTheMachines(t *testing.T) {
|
|
inside := "# Generated by Docker Engine.\nnameserver 10.10.0.1\nsearch node-c.internal\noptions timeout:1 attempts:2\n"
|
|
f := (&fake{}).on("docker cp route-proxy:/etc/resolv.conf -",
|
|
Ran{Stdout: archiveOf(t, tar.Header{Name: "resolv.conf", Typeflag: tar.TypeReg, Mode: 0o644}, inside)})
|
|
c := client(f, 1000)
|
|
c.ReadFile = func(p string) ([]byte, error) {
|
|
if p != HostResolvConf {
|
|
t.Fatalf("read %s", p)
|
|
}
|
|
return []byte("nameserver 10.10.0.1\nnameserver 10.10.0.2\noptions timeout:1 attempts:2 edns0\n"), nil
|
|
}
|
|
got, err := c.ResolvConfOf(context.Background(), "route-proxy")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rc := got["resolv_conf"].(ResolvConf)
|
|
if strings.Join(rc.Nameservers, ",") != "10.10.0.1" || strings.Join(rc.Search, ",") != "node-c.internal" ||
|
|
strings.Join(rc.Options, ",") != "timeout:1,attempts:2" || rc.Raw != inside {
|
|
t.Fatalf("parsed: %+v", rc)
|
|
}
|
|
if got["same_as_machine"] != false || got["note"] == nil {
|
|
t.Fatalf("a copy listing fewer resolvers than the machine is not said: %v", got)
|
|
}
|
|
if f.ran("docker exec") {
|
|
t.Fatal("read by exec, not through the archive")
|
|
}
|
|
}
|
|
|
|
func TestAResolverFileThatCannotBeReadIsSaidPlainly(t *testing.T) {
|
|
c := client((&fake{}).on("docker cp", Ran{Status: 1, Stderr: "Error response from daemon: No such container: nope\n"}), 1000)
|
|
if _, err := c.ResolvConfOf(context.Background(), "nope"); err == nil || !strings.Contains(err.Error(), "could not be read") {
|
|
t.Fatalf("a missing container: %v", err)
|
|
}
|
|
link := archiveOf(t, tar.Header{Name: "resolv.conf", Typeflag: tar.TypeSymlink, Linkname: "/run/systemd/resolve/stub-resolv.conf"}, "")
|
|
c = client((&fake{}).on("docker cp", Ran{Stdout: link}), 1000)
|
|
if _, err := c.ResolvConfOf(context.Background(), "x"); err == nil || !strings.Contains(err.Error(), "link to") {
|
|
t.Fatalf("a link inside: %v", err)
|
|
}
|
|
c = client((&fake{}).on("docker cp", Ran{Stdout: "not a tar"}), 1000)
|
|
if _, err := c.ResolvConfOf(context.Background(), "x"); err == nil {
|
|
t.Fatal("garbage was read as a file")
|
|
}
|
|
ok := archiveOf(t, tar.Header{Name: "resolv.conf", Typeflag: tar.TypeReg, Mode: 0o644}, "nameserver 10.10.0.1\n")
|
|
c = client((&fake{}).on("docker cp", Ran{Stdout: ok}), 1000)
|
|
c.ReadFile = func(string) ([]byte, error) { return nil, errors.New("permission denied") }
|
|
got, err := c.ResolvConfOf(context.Background(), "x")
|
|
if err != nil || !strings.Contains(got["machine"].(string), "could not be read") || got["same_as_machine"] != nil {
|
|
t.Fatalf("an unreadable machine file: %v, %v", got, err)
|
|
}
|
|
}
|
|
|
|
// The container is named as docker knows it, never as something docker would read as an option.
|
|
func TestAResolverFileIsAskedOnlyOfAContainerRef(t *testing.T) {
|
|
f := &fake{}
|
|
for _, ref := range []string{"--privileged", "a b", "", "x;rm"} {
|
|
if _, err := client(f, 1000).ResolvConfOf(context.Background(), ref); err == nil {
|
|
t.Errorf("%q was asked of the runtime", ref)
|
|
}
|
|
}
|
|
if len(f.calls) != 0 {
|
|
t.Fatalf("the runtime was asked: %+v", f.calls)
|
|
}
|
|
}
|