2016-10-19 12:22:02 -04:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"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"
|
2016-11-03 14:09:13 -04:00
|
|
|
"golang.org/x/net/context"
|
2016-10-19 12:22:02 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// parseSecrets retrieves the secrets from the requested names and converts
|
|
|
|
// them to secret references to use with the spec
|
Update order of '--secret-rm' and '--secret-add'
When using both `--secret-rm` and `--secret-add` on `docker service update`,
`--secret-rm` was always performed last. This made it impossible to update
a secret that was already in use on a service (for example, to change
it's permissions, or mount-location inside the container).
This patch changes the order in which `rm` and `add` are performed,
allowing updating a secret in a single `docker service update`.
Before this change, the `rm` was always performed "last", so the secret
was always removed:
$ echo "foo" | docker secret create foo -f -
foo
$ docker service create --name myservice --secret foo nginx:alpine
62xjcr9sr0c2hvepdzqrn3ssn
$ docker service update --secret-rm foo --secret-add source=foo,target=foo2 myservice
myservice
$ docker service inspect --format '{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}' myservice | jq .
null
After this change, the `rm` is performed _first_, allowing users to
update a secret without updating the service _twice_;
$ echo "foo" | docker secret create foo -f -
1bllmvw3a1yaq3eixqw3f7bjl
$ docker service create --name myservice --secret foo nginx:alpine
lr6s3uoggli1x0hab78glpcxo
$ docker service update --secret-rm foo --secret-add source=foo,target=foo2 myservice
myservice
$ docker service inspect --format '{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}' myservice | jq .
[
{
"File": {
"Name": "foo2",
"UID": "0",
"GID": "0",
"Mode": 292
},
"SecretID": "tn9qiblgnuuut11eufquw5dev",
"SecretName": "foo"
}
]
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2016-12-30 12:15:53 -05:00
|
|
|
func parseSecrets(client client.SecretAPIClient, requestedSecrets []*types.SecretRequestOption) ([]*swarmtypes.SecretReference, error) {
|
2016-10-27 20:57:38 -04:00
|
|
|
secretRefs := make(map[string]*swarmtypes.SecretReference)
|
2016-10-19 12:22:02 -04:00
|
|
|
ctx := context.Background()
|
|
|
|
|
|
|
|
for _, secret := range requestedSecrets {
|
2016-11-15 10:04:36 -05:00
|
|
|
if _, exists := secretRefs[secret.Target]; exists {
|
|
|
|
return nil, fmt.Errorf("duplicate secret target for %s not allowed", secret.Source)
|
|
|
|
}
|
2016-10-19 12:22:02 -04:00
|
|
|
secretRef := &swarmtypes.SecretReference{
|
2016-11-15 10:04:36 -05:00
|
|
|
File: &swarmtypes.SecretReferenceFileTarget{
|
2016-11-03 11:08:22 -04:00
|
|
|
Name: secret.Target,
|
|
|
|
UID: secret.UID,
|
|
|
|
GID: secret.GID,
|
|
|
|
Mode: secret.Mode,
|
2016-11-01 18:11:43 -04:00
|
|
|
},
|
2016-11-15 10:04:36 -05:00
|
|
|
SecretName: secret.Source,
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
2016-11-03 11:08:22 -04:00
|
|
|
secretRefs[secret.Target] = secretRef
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
args := filters.NewArgs()
|
2016-10-27 20:57:38 -04:00
|
|
|
for _, s := range secretRefs {
|
|
|
|
args.Add("names", s.SecretName)
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
secrets, err := client.SecretList(ctx, types.SecretListOptions{
|
2016-11-03 14:09:13 -04:00
|
|
|
Filters: args,
|
2016-10-19 12:22:02 -04:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-10-27 03:41:32 -04:00
|
|
|
foundSecrets := make(map[string]string)
|
2016-10-19 12:22:02 -04:00
|
|
|
for _, secret := range secrets {
|
2016-10-27 03:41:32 -04:00
|
|
|
foundSecrets[secret.Spec.Annotations.Name] = secret.ID
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
addedSecrets := []*swarmtypes.SecretReference{}
|
|
|
|
|
2016-10-27 20:57:38 -04:00
|
|
|
for _, ref := range secretRefs {
|
|
|
|
id, ok := foundSecrets[ref.SecretName]
|
2016-10-27 20:18:12 -04:00
|
|
|
if !ok {
|
2016-10-27 20:57:38 -04:00
|
|
|
return nil, fmt.Errorf("secret not found: %s", ref.SecretName)
|
2016-10-27 20:18:12 -04:00
|
|
|
}
|
|
|
|
|
2016-10-19 12:22:02 -04:00
|
|
|
// set the id for the ref to properly assign in swarm
|
|
|
|
// since swarm needs the ID instead of the name
|
2016-10-27 20:57:38 -04:00
|
|
|
ref.SecretID = id
|
|
|
|
addedSecrets = append(addedSecrets, ref)
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return addedSecrets, nil
|
|
|
|
}
|