parse.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package service
  2. import (
  3. "context"
  4. "fmt"
  5. "path/filepath"
  6. "strings"
  7. "github.com/docker/docker/api/types"
  8. "github.com/docker/docker/api/types/filters"
  9. swarmtypes "github.com/docker/docker/api/types/swarm"
  10. "github.com/docker/docker/client"
  11. )
  12. // parseSecretString parses the requested secret and returns the secret name
  13. // and target. Expects format SECRET_NAME:TARGET
  14. func parseSecretString(secretString string) (string, string, error) {
  15. tokens := strings.Split(secretString, ":")
  16. secretName := strings.TrimSpace(tokens[0])
  17. targetName := secretName
  18. if secretName == "" {
  19. return "", "", fmt.Errorf("invalid secret name provided")
  20. }
  21. if len(tokens) > 1 {
  22. targetName = strings.TrimSpace(tokens[1])
  23. if targetName == "" {
  24. return "", "", fmt.Errorf("invalid presentation name provided")
  25. }
  26. }
  27. // ensure target is a filename only; no paths allowed
  28. tDir, _ := filepath.Split(targetName)
  29. if tDir != "" {
  30. return "", "", fmt.Errorf("target must not have a path")
  31. }
  32. return secretName, targetName, nil
  33. }
  34. // parseSecrets retrieves the secrets from the requested names and converts
  35. // them to secret references to use with the spec
  36. func parseSecrets(client client.APIClient, requestedSecrets []string) ([]*swarmtypes.SecretReference, error) {
  37. secretRefs := make(map[string]*swarmtypes.SecretReference)
  38. ctx := context.Background()
  39. for _, secret := range requestedSecrets {
  40. n, t, err := parseSecretString(secret)
  41. if err != nil {
  42. return nil, err
  43. }
  44. secretRef := &swarmtypes.SecretReference{
  45. SecretName: n,
  46. Mode: swarmtypes.SecretReferenceFile,
  47. Target: t,
  48. }
  49. if _, exists := secretRefs[t]; exists {
  50. return nil, fmt.Errorf("duplicate secret target for %s not allowed", n)
  51. }
  52. secretRefs[t] = secretRef
  53. }
  54. args := filters.NewArgs()
  55. for _, s := range secretRefs {
  56. args.Add("names", s.SecretName)
  57. }
  58. secrets, err := client.SecretList(ctx, types.SecretListOptions{
  59. Filter: args,
  60. })
  61. if err != nil {
  62. return nil, err
  63. }
  64. foundSecrets := make(map[string]string)
  65. for _, secret := range secrets {
  66. foundSecrets[secret.Spec.Annotations.Name] = secret.ID
  67. }
  68. addedSecrets := []*swarmtypes.SecretReference{}
  69. for _, ref := range secretRefs {
  70. id, ok := foundSecrets[ref.SecretName]
  71. if !ok {
  72. return nil, fmt.Errorf("secret not found: %s", ref.SecretName)
  73. }
  74. // set the id for the ref to properly assign in swarm
  75. // since swarm needs the ID instead of the name
  76. ref.SecretID = id
  77. addedSecrets = append(addedSecrets, ref)
  78. }
  79. return addedSecrets, nil
  80. }