mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
![Yong Tang](/assets/img/avatar_default.png)
The canonical import comment was added some time ago, though several newly added files do not have the comment. This fix adds the missing canonical import comment to files in integration tests Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
367 lines
10 KiB
Go
367 lines
10 KiB
Go
package secret // import "github.com/docker/docker/integration/secret"
|
|
|
|
import (
|
|
"bytes"
|
|
"sort"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/filters"
|
|
swarmtypes "github.com/docker/docker/api/types/swarm"
|
|
"github.com/docker/docker/client"
|
|
"github.com/docker/docker/integration/internal/swarm"
|
|
"github.com/docker/docker/internal/testutil"
|
|
"github.com/docker/docker/pkg/stdcopy"
|
|
"github.com/gotestyourself/gotestyourself/skip"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
func TestSecretInspect(t *testing.T) {
|
|
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
|
|
|
defer setupTest(t)()
|
|
d := swarm.NewSwarm(t, testEnv)
|
|
defer d.Stop(t)
|
|
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
|
require.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
testName := "test_secret"
|
|
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
|
|
|
secret, _, err := client.SecretInspectWithRaw(context.Background(), secretID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, secret.Spec.Name, testName)
|
|
|
|
secret, _, err = client.SecretInspectWithRaw(context.Background(), testName)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, secretID, secretID)
|
|
}
|
|
|
|
func TestSecretList(t *testing.T) {
|
|
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
|
|
|
defer setupTest(t)()
|
|
d := swarm.NewSwarm(t, testEnv)
|
|
defer d.Stop(t)
|
|
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
|
require.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
testName0 := "test0"
|
|
testName1 := "test1"
|
|
testNames := []string{testName0, testName1}
|
|
sort.Strings(testNames)
|
|
|
|
// create secret test0
|
|
createSecret(ctx, t, client, testName0, []byte("TESTINGDATA0"), map[string]string{"type": "test"})
|
|
|
|
// create secret test1
|
|
secret1ID := createSecret(ctx, t, client, testName1, []byte("TESTINGDATA1"), map[string]string{"type": "production"})
|
|
|
|
names := func(entries []swarmtypes.Secret) []string {
|
|
values := []string{}
|
|
for _, entry := range entries {
|
|
values = append(values, entry.Spec.Name)
|
|
}
|
|
sort.Strings(values)
|
|
return values
|
|
}
|
|
|
|
// test by `secret ls`
|
|
entries, err := client.SecretList(ctx, types.SecretListOptions{})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, names(entries), testNames)
|
|
|
|
testCases := []struct {
|
|
filters filters.Args
|
|
expected []string
|
|
}{
|
|
// test filter by name `secret ls --filter name=xxx`
|
|
{
|
|
filters: filters.NewArgs(filters.Arg("name", testName0)),
|
|
expected: []string{testName0},
|
|
},
|
|
// test filter by id `secret ls --filter id=xxx`
|
|
{
|
|
filters: filters.NewArgs(filters.Arg("id", secret1ID)),
|
|
expected: []string{testName1},
|
|
},
|
|
// test filter by label `secret ls --filter label=xxx`
|
|
{
|
|
filters: filters.NewArgs(filters.Arg("label", "type")),
|
|
expected: testNames,
|
|
},
|
|
{
|
|
filters: filters.NewArgs(filters.Arg("label", "type=test")),
|
|
expected: []string{testName0},
|
|
},
|
|
{
|
|
filters: filters.NewArgs(filters.Arg("label", "type=production")),
|
|
expected: []string{testName1},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
entries, err = client.SecretList(ctx, types.SecretListOptions{
|
|
Filters: tc.filters,
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, names(entries), tc.expected)
|
|
|
|
}
|
|
}
|
|
|
|
func createSecret(ctx context.Context, t *testing.T, client client.APIClient, name string, data []byte, labels map[string]string) string {
|
|
secret, err := client.SecretCreate(ctx, swarmtypes.SecretSpec{
|
|
Annotations: swarmtypes.Annotations{
|
|
Name: name,
|
|
Labels: labels,
|
|
},
|
|
Data: data,
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, secret.ID, "")
|
|
return secret.ID
|
|
}
|
|
|
|
func TestSecretsCreateAndDelete(t *testing.T) {
|
|
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
|
|
|
defer setupTest(t)()
|
|
d := swarm.NewSwarm(t, testEnv)
|
|
defer d.Stop(t)
|
|
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
|
require.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
testName := "test_secret"
|
|
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
|
|
|
// create an already existin secret, daemon should return a status code of 409
|
|
_, err = client.SecretCreate(ctx, swarmtypes.SecretSpec{
|
|
Annotations: swarmtypes.Annotations{
|
|
Name: testName,
|
|
},
|
|
Data: []byte("TESTINGDATA"),
|
|
})
|
|
testutil.ErrorContains(t, err, "already exists")
|
|
|
|
// Ported from original TestSecretsDelete
|
|
err = client.SecretRemove(ctx, secretID)
|
|
require.NoError(t, err)
|
|
|
|
_, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
|
testutil.ErrorContains(t, err, "No such secret")
|
|
|
|
err = client.SecretRemove(ctx, "non-existin")
|
|
testutil.ErrorContains(t, err, "No such secret: non-existin")
|
|
|
|
// Ported from original TestSecretsCreteaWithLabels
|
|
testName = "test_secret_with_labels"
|
|
secretID = createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), map[string]string{
|
|
"key1": "value1",
|
|
"key2": "value2",
|
|
})
|
|
|
|
insp, _, err := client.SecretInspectWithRaw(ctx, secretID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, insp.Spec.Name, testName)
|
|
assert.Equal(t, len(insp.Spec.Labels), 2)
|
|
assert.Equal(t, insp.Spec.Labels["key1"], "value1")
|
|
assert.Equal(t, insp.Spec.Labels["key2"], "value2")
|
|
}
|
|
|
|
func TestSecretsUpdate(t *testing.T) {
|
|
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
|
|
|
defer setupTest(t)()
|
|
d := swarm.NewSwarm(t, testEnv)
|
|
defer d.Stop(t)
|
|
client, err := client.NewClientWithOpts(client.WithHost((d.Sock())))
|
|
require.NoError(t, err)
|
|
|
|
ctx := context.Background()
|
|
|
|
testName := "test_secret"
|
|
secretID := createSecret(ctx, t, client, testName, []byte("TESTINGDATA"), nil)
|
|
require.NoError(t, err)
|
|
|
|
insp, _, err := client.SecretInspectWithRaw(ctx, secretID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, insp.ID, secretID)
|
|
|
|
// test UpdateSecret with full ID
|
|
insp.Spec.Labels = map[string]string{"test": "test1"}
|
|
err = client.SecretUpdate(ctx, secretID, insp.Version, insp.Spec)
|
|
require.NoError(t, err)
|
|
|
|
insp, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, insp.Spec.Labels["test"], "test1")
|
|
|
|
// test UpdateSecret with full name
|
|
insp.Spec.Labels = map[string]string{"test": "test2"}
|
|
err = client.SecretUpdate(ctx, testName, insp.Version, insp.Spec)
|
|
require.NoError(t, err)
|
|
|
|
insp, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, insp.Spec.Labels["test"], "test2")
|
|
|
|
// test UpdateSecret with prefix ID
|
|
insp.Spec.Labels = map[string]string{"test": "test3"}
|
|
err = client.SecretUpdate(ctx, secretID[:1], insp.Version, insp.Spec)
|
|
require.NoError(t, err)
|
|
|
|
insp, _, err = client.SecretInspectWithRaw(ctx, secretID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, insp.Spec.Labels["test"], "test3")
|
|
|
|
// test UpdateSecret in updating Data which is not supported in daemon
|
|
// this test will produce an error in func UpdateSecret
|
|
insp.Spec.Data = []byte("TESTINGDATA2")
|
|
err = client.SecretUpdate(ctx, secretID, insp.Version, insp.Spec)
|
|
testutil.ErrorContains(t, err, "only updates to Labels are allowed")
|
|
}
|
|
|
|
func TestTemplatedSecret(t *testing.T) {
|
|
d := swarm.NewSwarm(t, testEnv)
|
|
defer d.Stop(t)
|
|
|
|
ctx := context.Background()
|
|
client := swarm.GetClient(t, d)
|
|
|
|
referencedSecretSpec := swarmtypes.SecretSpec{
|
|
Annotations: swarmtypes.Annotations{
|
|
Name: "referencedsecret",
|
|
},
|
|
Data: []byte("this is a secret"),
|
|
}
|
|
referencedSecret, err := client.SecretCreate(ctx, referencedSecretSpec)
|
|
assert.NoError(t, err)
|
|
|
|
referencedConfigSpec := swarmtypes.ConfigSpec{
|
|
Annotations: swarmtypes.Annotations{
|
|
Name: "referencedconfig",
|
|
},
|
|
Data: []byte("this is a config"),
|
|
}
|
|
referencedConfig, err := client.ConfigCreate(ctx, referencedConfigSpec)
|
|
assert.NoError(t, err)
|
|
|
|
secretSpec := swarmtypes.SecretSpec{
|
|
Annotations: swarmtypes.Annotations{
|
|
Name: "templated_secret",
|
|
},
|
|
Templating: &swarmtypes.Driver{
|
|
Name: "golang",
|
|
},
|
|
Data: []byte("SERVICE_NAME={{.Service.Name}}\n" +
|
|
"{{secret \"referencedsecrettarget\"}}\n" +
|
|
"{{config \"referencedconfigtarget\"}}\n"),
|
|
}
|
|
|
|
templatedSecret, err := client.SecretCreate(ctx, secretSpec)
|
|
assert.NoError(t, err)
|
|
|
|
serviceID := swarm.CreateService(t, d,
|
|
swarm.ServiceWithSecret(
|
|
&swarmtypes.SecretReference{
|
|
File: &swarmtypes.SecretReferenceFileTarget{
|
|
Name: "templated_secret",
|
|
UID: "0",
|
|
GID: "0",
|
|
Mode: 0600,
|
|
},
|
|
SecretID: templatedSecret.ID,
|
|
SecretName: "templated_secret",
|
|
},
|
|
),
|
|
swarm.ServiceWithConfig(
|
|
&swarmtypes.ConfigReference{
|
|
File: &swarmtypes.ConfigReferenceFileTarget{
|
|
Name: "referencedconfigtarget",
|
|
UID: "0",
|
|
GID: "0",
|
|
Mode: 0600,
|
|
},
|
|
ConfigID: referencedConfig.ID,
|
|
ConfigName: "referencedconfig",
|
|
},
|
|
),
|
|
swarm.ServiceWithSecret(
|
|
&swarmtypes.SecretReference{
|
|
File: &swarmtypes.SecretReferenceFileTarget{
|
|
Name: "referencedsecrettarget",
|
|
UID: "0",
|
|
GID: "0",
|
|
Mode: 0600,
|
|
},
|
|
SecretID: referencedSecret.ID,
|
|
SecretName: "referencedsecret",
|
|
},
|
|
),
|
|
swarm.ServiceWithName("svc"),
|
|
)
|
|
|
|
var tasks []swarmtypes.Task
|
|
waitAndAssert(t, 60*time.Second, func(t *testing.T) bool {
|
|
tasks = swarm.GetRunningTasks(t, d, serviceID)
|
|
return len(tasks) > 0
|
|
})
|
|
|
|
task := tasks[0]
|
|
waitAndAssert(t, 60*time.Second, func(t *testing.T) bool {
|
|
if task.NodeID == "" || (task.Status.ContainerStatus == nil || task.Status.ContainerStatus.ContainerID == "") {
|
|
task, _, _ = client.TaskInspectWithRaw(context.Background(), task.ID)
|
|
}
|
|
return task.NodeID != "" && task.Status.ContainerStatus != nil && task.Status.ContainerStatus.ContainerID != ""
|
|
})
|
|
|
|
attach := swarm.ExecTask(t, d, task, types.ExecConfig{
|
|
Cmd: []string{"/bin/cat", "/run/secrets/templated_secret"},
|
|
AttachStdout: true,
|
|
AttachStderr: true,
|
|
})
|
|
|
|
expect := "SERVICE_NAME=svc\n" +
|
|
"this is a secret\n" +
|
|
"this is a config\n"
|
|
assertAttachedStream(t, attach, expect)
|
|
|
|
attach = swarm.ExecTask(t, d, task, types.ExecConfig{
|
|
Cmd: []string{"mount"},
|
|
AttachStdout: true,
|
|
AttachStderr: true,
|
|
})
|
|
assertAttachedStream(t, attach, "tmpfs on /run/secrets/templated_secret type tmpfs")
|
|
}
|
|
|
|
func assertAttachedStream(t *testing.T, attach types.HijackedResponse, expect string) {
|
|
buf := bytes.NewBuffer(nil)
|
|
_, err := stdcopy.StdCopy(buf, buf, attach.Reader)
|
|
require.NoError(t, err)
|
|
assert.Contains(t, buf.String(), expect)
|
|
}
|
|
|
|
func waitAndAssert(t *testing.T, timeout time.Duration, f func(*testing.T) bool) {
|
|
t.Helper()
|
|
after := time.After(timeout)
|
|
for {
|
|
select {
|
|
case <-after:
|
|
t.Fatalf("timed out waiting for condition")
|
|
default:
|
|
}
|
|
if f(t) {
|
|
return
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
}
|