Files
docker-cli/components/engine/cli/command/service/parse.go
Evan Hazlett dde21cf7dc review changes
- fix lint issues
- use errors pkg for wrapping errors
- cleanup on error when setting up secrets mount
- fix erroneous import
- remove unneeded switch for secret reference mode
- return single mount for secrets instead of slice

Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
Upstream-commit: 857e60c2f943a09e3ec0ac0f236821b797935900
Component: engine
2016-11-09 14:27:43 -05:00

101 lines
2.5 KiB
Go

package service
import (
"context"
"fmt"
"path/filepath"
"strings"
"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"
)
// parseSecretString parses the requested secret and returns the secret name
// and target. Expects format SECRET_NAME:TARGET
func parseSecretString(secretString string) (string, string, error) {
tokens := strings.Split(secretString, ":")
secretName := strings.TrimSpace(tokens[0])
targetName := ""
if secretName == "" {
return "", "", fmt.Errorf("invalid secret name provided")
}
if len(tokens) > 1 {
targetName = strings.TrimSpace(tokens[1])
if targetName == "" {
return "", "", fmt.Errorf("invalid presentation name provided")
}
} else {
targetName = secretName
}
// ensure target is a filename only; no paths allowed
tDir, _ := filepath.Split(targetName)
if tDir != "" {
return "", "", fmt.Errorf("target must not have a path")
}
return secretName, targetName, nil
}
// parseSecrets retrieves the secrets from the requested names and converts
// them to secret references to use with the spec
func parseSecrets(client client.APIClient, requestedSecrets []string) ([]*swarmtypes.SecretReference, error) {
lookupSecretNames := []string{}
needSecrets := make(map[string]*swarmtypes.SecretReference)
ctx := context.Background()
for _, secret := range requestedSecrets {
n, t, err := parseSecretString(secret)
if err != nil {
return nil, err
}
secretRef := &swarmtypes.SecretReference{
SecretName: n,
Mode: swarmtypes.SecretReferenceFile,
Target: t,
}
lookupSecretNames = append(lookupSecretNames, n)
needSecrets[n] = secretRef
}
args := filters.NewArgs()
for _, s := range lookupSecretNames {
args.Add("names", s)
}
secrets, err := client.SecretList(ctx, types.SecretListOptions{
Filter: args,
})
if err != nil {
return nil, err
}
foundSecrets := make(map[string]*swarmtypes.Secret)
for _, secret := range secrets {
foundSecrets[secret.Spec.Annotations.Name] = &secret
}
addedSecrets := []*swarmtypes.SecretReference{}
for secretName, secretRef := range needSecrets {
s, ok := foundSecrets[secretName]
if !ok {
return nil, fmt.Errorf("secret not found: %s", secretName)
}
// set the id for the ref to properly assign in swarm
// since swarm needs the ID instead of the name
secretRef.SecretID = s.ID
addedSecrets = append(addedSecrets, secretRef)
}
return addedSecrets, nil
}