2018-11-05 14:50:33 +01:00
|
|
|
package common // import "github.com/docker/docker/integration/plugin/common"
|
|
|
|
|
|
|
|
import (
|
2020-02-10 16:31:04 -08:00
|
|
|
"context"
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/json"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"net"
|
2018-11-05 14:50:33 +01:00
|
|
|
"net/http"
|
2020-02-10 16:31:04 -08:00
|
|
|
"path"
|
|
|
|
"strings"
|
2018-11-05 14:50:33 +01:00
|
|
|
"testing"
|
|
|
|
|
2020-02-10 16:31:04 -08:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/testutil/daemon"
|
|
|
|
"github.com/docker/docker/testutil/fixtures/plugin"
|
|
|
|
"github.com/docker/docker/testutil/registry"
|
2019-08-29 15:52:40 -05:00
|
|
|
"github.com/docker/docker/testutil/request"
|
2020-02-07 14:39:24 +01:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
is "gotest.tools/v3/assert/cmp"
|
2020-02-10 16:31:04 -08:00
|
|
|
"gotest.tools/v3/skip"
|
2018-11-05 14:50:33 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestPluginInvalidJSON(t *testing.T) {
|
|
|
|
defer setupTest(t)()
|
|
|
|
|
|
|
|
endpoints := []string{"/plugins/foobar/set"}
|
|
|
|
|
|
|
|
for _, ep := range endpoints {
|
|
|
|
t.Run(ep, func(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Equal(t, res.StatusCode, http.StatusBadRequest)
|
|
|
|
|
|
|
|
buf, err := request.ReadBody(body)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Check(t, is.Contains(string(buf), "invalid character 'i' looking for beginning of object key string"))
|
|
|
|
|
|
|
|
res, body, err = request.Post(ep, request.JSON)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Equal(t, res.StatusCode, http.StatusBadRequest)
|
|
|
|
|
|
|
|
buf, err = request.ReadBody(body)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Check(t, is.Contains(string(buf), "got EOF while reading request body"))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2020-02-10 16:31:04 -08:00
|
|
|
|
|
|
|
func TestPluginInstall(t *testing.T) {
|
|
|
|
skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon")
|
|
|
|
skip.If(t, testEnv.OSType == "windows")
|
|
|
|
skip.If(t, testEnv.IsRootless, "rootless mode has different view of localhost")
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
client := testEnv.APIClient()
|
|
|
|
|
|
|
|
t.Run("no auth", func(t *testing.T) {
|
|
|
|
defer setupTest(t)()
|
|
|
|
|
|
|
|
reg := registry.NewV2(t)
|
|
|
|
defer reg.Close()
|
|
|
|
|
|
|
|
name := "test-" + strings.ToLower(t.Name())
|
|
|
|
repo := path.Join(registry.DefaultURL, name+":latest")
|
|
|
|
assert.NilError(t, plugin.CreateInRegistry(ctx, repo, nil))
|
|
|
|
|
|
|
|
rdr, err := client.PluginInstall(ctx, repo, types.PluginInstallOptions{Disabled: true, RemoteRef: repo})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
defer rdr.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(ioutil.Discard, rdr)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
|
|
|
_, _, err = client.PluginInspectWithRaw(ctx, repo)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("with htpasswd", func(t *testing.T) {
|
|
|
|
defer setupTest(t)()
|
|
|
|
|
|
|
|
reg := registry.NewV2(t, registry.Htpasswd)
|
|
|
|
defer reg.Close()
|
|
|
|
|
|
|
|
name := "test-" + strings.ToLower(t.Name())
|
|
|
|
repo := path.Join(registry.DefaultURL, name+":latest")
|
|
|
|
auth := &types.AuthConfig{ServerAddress: registry.DefaultURL, Username: "testuser", Password: "testpassword"}
|
|
|
|
assert.NilError(t, plugin.CreateInRegistry(ctx, repo, auth))
|
|
|
|
|
|
|
|
authEncoded, err := json.Marshal(auth)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
|
|
|
rdr, err := client.PluginInstall(ctx, repo, types.PluginInstallOptions{
|
|
|
|
RegistryAuth: base64.URLEncoding.EncodeToString(authEncoded),
|
|
|
|
Disabled: true,
|
|
|
|
RemoteRef: repo,
|
|
|
|
})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
defer rdr.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(ioutil.Discard, rdr)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
|
|
|
_, _, err = client.PluginInspectWithRaw(ctx, repo)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
})
|
|
|
|
t.Run("with insecure", func(t *testing.T) {
|
|
|
|
skip.If(t, !testEnv.IsLocalDaemon())
|
|
|
|
|
|
|
|
addrs, err := net.InterfaceAddrs()
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
|
|
|
var bindTo string
|
|
|
|
for _, addr := range addrs {
|
|
|
|
ip, ok := addr.(*net.IPNet)
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if ip.IP.IsLoopback() || ip.IP.To4() == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
bindTo = ip.IP.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
if bindTo == "" {
|
|
|
|
t.Skip("No suitable interface to bind registry to")
|
|
|
|
}
|
|
|
|
|
|
|
|
regURL := bindTo + ":5000"
|
|
|
|
|
|
|
|
d := daemon.New(t)
|
|
|
|
defer d.Stop(t)
|
|
|
|
|
|
|
|
d.Start(t, "--insecure-registry="+regURL)
|
|
|
|
defer d.Stop(t)
|
|
|
|
|
|
|
|
reg := registry.NewV2(t, registry.URL(regURL))
|
|
|
|
defer reg.Close()
|
|
|
|
|
|
|
|
name := "test-" + strings.ToLower(t.Name())
|
|
|
|
repo := path.Join(regURL, name+":latest")
|
|
|
|
assert.NilError(t, plugin.CreateInRegistry(ctx, repo, nil, plugin.WithInsecureRegistry(regURL)))
|
|
|
|
|
|
|
|
client := d.NewClientT(t)
|
|
|
|
rdr, err := client.PluginInstall(ctx, repo, types.PluginInstallOptions{Disabled: true, RemoteRef: repo})
|
|
|
|
assert.NilError(t, err)
|
|
|
|
defer rdr.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(ioutil.Discard, rdr)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
|
|
|
|
_, _, err = client.PluginInspectWithRaw(ctx, repo)
|
|
|
|
assert.NilError(t, err)
|
|
|
|
})
|
|
|
|
// TODO: test insecure registry with https
|
|
|
|
}
|