1// Copyright 2018 go-dockerclient authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package docker
6
7import (
8	"context"
9	"encoding/json"
10	"fmt"
11	"net/http"
12
13	"reflect"
14
15	"testing"
16)
17
18var (
19	expectPluginDetail = PluginDetail{
20		ID:     "5724e2c8652da337ab2eedd19fc6fc0ec908e4bd907c7421bf6a8dfc70c4c078",
21		Name:   "tiborvass/sample-volume-plugin",
22		Tag:    "latest",
23		Active: true,
24		Settings: PluginSettings{
25			Env:     []string{"DEBUG=0"},
26			Args:    nil,
27			Devices: nil,
28		},
29		Config: PluginConfig{
30			Description:   "A sample volume plugin for Docker",
31			Documentation: "https://docs.docker.com/engine/extend/plugins/",
32			Interface: PluginInterface{
33				Types:  []string{"docker.volumedriver/1.0"},
34				Socket: "plugins.sock",
35			},
36			Entrypoint: []string{
37				"/usr/bin/sample-volume-plugin",
38				"/data",
39			},
40			WorkDir:         "",
41			User:            PluginUser{},
42			Network:         PluginNetwork{Type: ""},
43			Linux:           PluginLinux{Capabilities: nil, AllowAllDevices: false, Devices: nil},
44			Mounts:          nil,
45			PropagatedMount: "/data",
46			Env: []PluginEnv{
47				{
48					Name:        "DEBUG",
49					Description: "If set, prints debug messages",
50					Settable:    nil,
51					Value:       "0",
52				},
53			},
54			Args: PluginArgs{
55				Name:        "args",
56				Description: "command line arguments",
57				Settable:    nil,
58				Value:       []string{},
59			},
60		},
61	}
62)
63
64const (
65	jsonPluginDetail = `{
66    "Id": "5724e2c8652da337ab2eedd19fc6fc0ec908e4bd907c7421bf6a8dfc70c4c078",
67    "Name": "tiborvass/sample-volume-plugin",
68    "Tag": "latest",
69    "Enabled": true,
70    "Settings": {
71      "Env": [
72        "DEBUG=0"
73      ],
74      "Args": null,
75      "Devices": null
76    },
77    "Config": {
78      "Description": "A sample volume plugin for Docker",
79      "Documentation": "https://docs.docker.com/engine/extend/plugins/",
80      "Interface": {
81        "Types": [
82          "docker.volumedriver/1.0"
83        ],
84        "Socket": "plugins.sock"
85      },
86      "Entrypoint": [
87        "/usr/bin/sample-volume-plugin",
88        "/data"
89      ],
90      "WorkDir": "",
91      "User": {},
92      "Network": {
93        "Type": ""
94      },
95      "Linux": {
96        "Capabilities": null,
97        "AllowAllDevices": false,
98        "Devices": null
99      },
100      "Mounts": null,
101      "PropagatedMount": "/data",
102      "Env": [
103        {
104          "Name": "DEBUG",
105          "Description": "If set, prints debug messages",
106          "Settable": null,
107          "Value": "0"
108        }
109      ],
110      "Args": {
111        "Name": "args",
112        "Description": "command line arguments",
113        "Settable": null,
114        "Value": []
115      }
116    }
117  }`
118)
119
120func TestListPlugins(t *testing.T) {
121	t.Parallel()
122	jsonPlugins := fmt.Sprintf("[%s]", jsonPluginDetail)
123	var expected []PluginDetail
124	err := json.Unmarshal([]byte(jsonPlugins), &expected)
125	if err != nil {
126		t.Fatal(err)
127	}
128	client := newTestClient(&FakeRoundTripper{message: jsonPlugins, status: http.StatusOK})
129	pluginDetails, err := client.ListPlugins(context.Background())
130	if err != nil {
131		t.Fatal(err)
132	}
133	if !reflect.DeepEqual(pluginDetails, expected) {
134		t.Errorf("ListPlugins: Expected %#v. Got %#v.", expected, pluginDetails)
135	}
136}
137
138func TestListFilteredPlugins(t *testing.T) {
139	t.Parallel()
140	jsonPlugins := fmt.Sprintf("[%s]", jsonPluginDetail)
141	var expected []PluginDetail
142	err := json.Unmarshal([]byte(jsonPlugins), &expected)
143	if err != nil {
144		t.Fatal(err)
145	}
146	client := newTestClient(&FakeRoundTripper{message: jsonPlugins, status: http.StatusOK})
147
148	pluginDetails, err := client.ListFilteredPlugins(
149		ListFilteredPluginsOptions{
150			Filters: map[string][]string{
151				"capability": {"volumedriver"},
152				"enabled":    {"true"},
153			},
154			Context: context.Background()})
155	if err != nil {
156		t.Fatal(err)
157	}
158	if !reflect.DeepEqual(pluginDetails, expected) {
159		t.Errorf("ListPlugins: Expected %#v. Got %#v.", expected, pluginDetails)
160	}
161}
162
163func TestListFilteredPluginsFailure(t *testing.T) {
164	t.Parallel()
165	var tests = []struct {
166		status  int
167		message string
168	}{
169		{400, "bad parameter"},
170		{500, "internal server error"},
171	}
172	for _, tt := range tests {
173		client := newTestClient(&FakeRoundTripper{message: tt.message, status: tt.status})
174		expected := Error{Status: tt.status, Message: tt.message}
175		pluginDetails, err := client.ListFilteredPlugins(ListFilteredPluginsOptions{})
176		if !reflect.DeepEqual(expected, *err.(*Error)) {
177			t.Errorf("Wrong error in ListFilteredPlugins. Want %#v. Got %#v.", expected, err)
178		}
179		if len(pluginDetails) > 0 {
180			t.Errorf("ListFilteredPlugins failure. Expected empty list. Got %#v.", pluginDetails)
181		}
182	}
183}
184
185func TestGetPluginPrivileges(t *testing.T) {
186	t.Parallel()
187	name := "test_plugin"
188	jsonPluginPrivileges := `[ { "Name": "network", "Description": "", "Value": [ "host" ] }]`
189	fakeRT := &FakeRoundTripper{message: jsonPluginPrivileges, status: http.StatusNoContent}
190	client := newTestClient(fakeRT)
191	expected := []PluginPrivilege{
192		{
193			Name:        "network",
194			Description: "",
195			Value:       []string{"host"},
196		}}
197	pluginPrivileges, err := client.GetPluginPrivileges(name, context.Background())
198	if err != nil {
199		t.Fatal(err)
200	}
201	if !reflect.DeepEqual(pluginPrivileges, expected) {
202		t.Errorf("PluginPrivileges: Expected %#v. Got %#v.", expected, pluginPrivileges)
203	}
204}
205
206func TestInstallPlugins(t *testing.T) {
207	opts := InstallPluginOptions{
208		Remote: "", Name: "test",
209		Plugins: []PluginPrivilege{
210			{
211				Name:        "network",
212				Description: "",
213				Value:       []string{"host"},
214			},
215		},
216		Context: context.Background(),
217		Auth:    AuthConfiguration{},
218	}
219
220	client := newTestClient(&FakeRoundTripper{message: "", status: http.StatusOK})
221	err := client.InstallPlugins(opts)
222	if err != nil {
223		t.Fatal(err)
224	}
225}
226
227func TestInspectPlugin(t *testing.T) {
228	name := "test_plugin"
229	fakeRT := &FakeRoundTripper{message: jsonPluginDetail, status: http.StatusNoContent}
230	client := newTestClient(fakeRT)
231	pluginPrivileges, err := client.InspectPlugins(name, context.Background())
232	if err != nil {
233		t.Fatal(err)
234	}
235	if !reflect.DeepEqual(pluginPrivileges, &expectPluginDetail) {
236		t.Errorf("InspectPlugins: Expected %#v. Got %#v.", &expectPluginDetail, pluginPrivileges)
237	}
238}
239
240func TestRemovePlugin(t *testing.T) {
241	opts := RemovePluginOptions{
242		Name:    "test_plugin",
243		Force:   false,
244		Context: context.Background(),
245	}
246	fakeRT := &FakeRoundTripper{message: jsonPluginDetail, status: http.StatusNoContent}
247	client := newTestClient(fakeRT)
248	pluginPrivileges, err := client.RemovePlugin(opts)
249	if err != nil {
250		t.Fatal(err)
251	}
252	if !reflect.DeepEqual(pluginPrivileges, &expectPluginDetail) {
253		t.Errorf("RemovePlugin: Expected %#v. Got %#v.", &expectPluginDetail, pluginPrivileges)
254	}
255}
256
257func TestEnablePlugin(t *testing.T) {
258	opts := EnablePluginOptions{
259		Name:    "test",
260		Timeout: 5,
261		Context: context.Background(),
262	}
263	client := newTestClient(&FakeRoundTripper{message: "", status: http.StatusOK})
264	err := client.EnablePlugin(opts)
265	if err != nil {
266		t.Fatal(err)
267	}
268}
269
270func TestDisablePlugin(t *testing.T) {
271	opts := DisablePluginOptions{
272		Name:    "test",
273		Context: context.Background(),
274	}
275	client := newTestClient(&FakeRoundTripper{message: "", status: http.StatusOK})
276	err := client.DisablePlugin(opts)
277	if err != nil {
278		t.Fatal(err)
279	}
280}
281
282func TestCreatePlugin(t *testing.T) {
283	opts := CreatePluginOptions{
284		Name:    "test",
285		Path:    "",
286		Context: context.Background(),
287	}
288	client := newTestClient(&FakeRoundTripper{message: "", status: http.StatusOK})
289	_, err := client.CreatePlugin(opts)
290	if err != nil {
291		t.Fatal(err)
292	}
293}
294
295func TestPushPlugin(t *testing.T) {
296	opts := PushPluginOptions{
297		Name:    "test",
298		Context: context.Background(),
299	}
300	client := newTestClient(&FakeRoundTripper{message: "", status: http.StatusOK})
301	err := client.PushPlugin(opts)
302	if err != nil {
303		t.Fatal(err)
304	}
305}
306
307func TestConfigurePlugin(t *testing.T) {
308	opts := ConfigurePluginOptions{
309		Name:    "test",
310		Envs:    []string{},
311		Context: context.Background(),
312	}
313	client := newTestClient(&FakeRoundTripper{message: "", status: http.StatusOK})
314	err := client.ConfigurePlugin(opts)
315	if err != nil {
316		t.Fatal(err)
317	}
318}
319