github.com/afbjorklund/moby@v20.10.5+incompatible/integration/plugin/common/plugin_test.go (about) 1 package common // import "github.com/docker/docker/integration/plugin/common" 2 3 import ( 4 "context" 5 "encoding/base64" 6 "encoding/json" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "net" 11 "net/http" 12 "os" 13 "path" 14 "path/filepath" 15 "strings" 16 "testing" 17 18 "github.com/docker/docker/api/types" 19 "github.com/docker/docker/testutil/daemon" 20 "github.com/docker/docker/testutil/fixtures/plugin" 21 "github.com/docker/docker/testutil/registry" 22 "github.com/docker/docker/testutil/request" 23 "gotest.tools/v3/assert" 24 is "gotest.tools/v3/assert/cmp" 25 "gotest.tools/v3/skip" 26 ) 27 28 func TestPluginInvalidJSON(t *testing.T) { 29 defer setupTest(t)() 30 31 endpoints := []string{"/plugins/foobar/set"} 32 33 for _, ep := range endpoints { 34 t.Run(ep, func(t *testing.T) { 35 t.Parallel() 36 37 res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON) 38 assert.NilError(t, err) 39 assert.Equal(t, res.StatusCode, http.StatusBadRequest) 40 41 buf, err := request.ReadBody(body) 42 assert.NilError(t, err) 43 assert.Check(t, is.Contains(string(buf), "invalid character 'i' looking for beginning of object key string")) 44 45 res, body, err = request.Post(ep, request.JSON) 46 assert.NilError(t, err) 47 assert.Equal(t, res.StatusCode, http.StatusBadRequest) 48 49 buf, err = request.ReadBody(body) 50 assert.NilError(t, err) 51 assert.Check(t, is.Contains(string(buf), "got EOF while reading request body")) 52 }) 53 } 54 } 55 56 func TestPluginInstall(t *testing.T) { 57 skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") 58 skip.If(t, testEnv.OSType == "windows") 59 skip.If(t, testEnv.IsRootless, "rootless mode has different view of localhost") 60 61 ctx := context.Background() 62 client := testEnv.APIClient() 63 64 t.Run("no auth", func(t *testing.T) { 65 defer setupTest(t)() 66 67 reg := registry.NewV2(t) 68 defer reg.Close() 69 70 name := "test-" + strings.ToLower(t.Name()) 71 repo := path.Join(registry.DefaultURL, name+":latest") 72 assert.NilError(t, plugin.CreateInRegistry(ctx, repo, nil)) 73 74 rdr, err := client.PluginInstall(ctx, repo, types.PluginInstallOptions{Disabled: true, RemoteRef: repo}) 75 assert.NilError(t, err) 76 defer rdr.Close() 77 78 _, err = io.Copy(ioutil.Discard, rdr) 79 assert.NilError(t, err) 80 81 _, _, err = client.PluginInspectWithRaw(ctx, repo) 82 assert.NilError(t, err) 83 }) 84 85 t.Run("with htpasswd", func(t *testing.T) { 86 defer setupTest(t)() 87 88 reg := registry.NewV2(t, registry.Htpasswd) 89 defer reg.Close() 90 91 name := "test-" + strings.ToLower(t.Name()) 92 repo := path.Join(registry.DefaultURL, name+":latest") 93 auth := &types.AuthConfig{ServerAddress: registry.DefaultURL, Username: "testuser", Password: "testpassword"} 94 assert.NilError(t, plugin.CreateInRegistry(ctx, repo, auth)) 95 96 authEncoded, err := json.Marshal(auth) 97 assert.NilError(t, err) 98 99 rdr, err := client.PluginInstall(ctx, repo, types.PluginInstallOptions{ 100 RegistryAuth: base64.URLEncoding.EncodeToString(authEncoded), 101 Disabled: true, 102 RemoteRef: repo, 103 }) 104 assert.NilError(t, err) 105 defer rdr.Close() 106 107 _, err = io.Copy(ioutil.Discard, rdr) 108 assert.NilError(t, err) 109 110 _, _, err = client.PluginInspectWithRaw(ctx, repo) 111 assert.NilError(t, err) 112 }) 113 t.Run("with insecure", func(t *testing.T) { 114 skip.If(t, !testEnv.IsLocalDaemon()) 115 116 addrs, err := net.InterfaceAddrs() 117 assert.NilError(t, err) 118 119 var bindTo string 120 for _, addr := range addrs { 121 ip, ok := addr.(*net.IPNet) 122 if !ok { 123 continue 124 } 125 if ip.IP.IsLoopback() || ip.IP.To4() == nil { 126 continue 127 } 128 bindTo = ip.IP.String() 129 } 130 131 if bindTo == "" { 132 t.Skip("No suitable interface to bind registry to") 133 } 134 135 regURL := bindTo + ":5000" 136 137 d := daemon.New(t) 138 defer d.Stop(t) 139 140 d.Start(t, "--insecure-registry="+regURL) 141 defer d.Stop(t) 142 143 reg := registry.NewV2(t, registry.URL(regURL)) 144 defer reg.Close() 145 146 name := "test-" + strings.ToLower(t.Name()) 147 repo := path.Join(regURL, name+":latest") 148 assert.NilError(t, plugin.CreateInRegistry(ctx, repo, nil, plugin.WithInsecureRegistry(regURL))) 149 150 client := d.NewClientT(t) 151 rdr, err := client.PluginInstall(ctx, repo, types.PluginInstallOptions{Disabled: true, RemoteRef: repo}) 152 assert.NilError(t, err) 153 defer rdr.Close() 154 155 _, err = io.Copy(ioutil.Discard, rdr) 156 assert.NilError(t, err) 157 158 _, _, err = client.PluginInspectWithRaw(ctx, repo) 159 assert.NilError(t, err) 160 }) 161 // TODO: test insecure registry with https 162 } 163 164 func TestPluginsWithRuntimes(t *testing.T) { 165 skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") 166 skip.If(t, testEnv.IsRootless, "Test not supported on rootless due to buggy daemon setup in rootless mode due to daemon restart") 167 skip.If(t, testEnv.OSType == "windows") 168 169 dir, err := ioutil.TempDir("", t.Name()) 170 assert.NilError(t, err) 171 defer os.RemoveAll(dir) 172 173 d := daemon.New(t) 174 defer d.Cleanup(t) 175 176 d.Start(t) 177 defer d.Stop(t) 178 179 ctx := context.Background() 180 client := d.NewClientT(t) 181 182 assert.NilError(t, plugin.Create(ctx, client, "test:latest")) 183 defer client.PluginRemove(ctx, "test:latest", types.PluginRemoveOptions{Force: true}) 184 185 assert.NilError(t, client.PluginEnable(ctx, "test:latest", types.PluginEnableOptions{Timeout: 30})) 186 187 p := filepath.Join(dir, "myrt") 188 script := fmt.Sprintf(`#!/bin/sh 189 file="%s/success" 190 if [ "$1" = "someArg" ]; then 191 shift 192 file="${file}_someArg" 193 fi 194 195 touch $file 196 exec runc $@ 197 `, dir) 198 199 assert.NilError(t, ioutil.WriteFile(p, []byte(script), 0777)) 200 201 type config struct { 202 Runtimes map[string]types.Runtime `json:"runtimes"` 203 } 204 205 cfg, err := json.Marshal(config{ 206 Runtimes: map[string]types.Runtime{ 207 "myrt": {Path: p}, 208 "myrtArgs": {Path: p, Args: []string{"someArg"}}, 209 }, 210 }) 211 configPath := filepath.Join(dir, "config.json") 212 ioutil.WriteFile(configPath, cfg, 0644) 213 214 t.Run("No Args", func(t *testing.T) { 215 d.Restart(t, "--default-runtime=myrt", "--config-file="+configPath) 216 _, err = os.Stat(filepath.Join(dir, "success")) 217 assert.NilError(t, err) 218 }) 219 220 t.Run("With Args", func(t *testing.T) { 221 d.Restart(t, "--default-runtime=myrtArgs", "--config-file="+configPath) 222 _, err = os.Stat(filepath.Join(dir, "success_someArg")) 223 assert.NilError(t, err) 224 }) 225 }