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  }