secret.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package opts
  2. import (
  3. "encoding/csv"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strconv"
  8. "strings"
  9. "github.com/docker/docker/api/types"
  10. )
  11. // SecretOpt is a Value type for parsing secrets
  12. type SecretOpt struct {
  13. values []*types.SecretRequestOption
  14. }
  15. // Set a new secret value
  16. func (o *SecretOpt) Set(value string) error {
  17. csvReader := csv.NewReader(strings.NewReader(value))
  18. fields, err := csvReader.Read()
  19. if err != nil {
  20. return err
  21. }
  22. options := &types.SecretRequestOption{
  23. Source: "",
  24. Target: "",
  25. UID: "0",
  26. GID: "0",
  27. Mode: 0444,
  28. }
  29. // support a simple syntax of --secret foo
  30. if len(fields) == 1 {
  31. options.Source = fields[0]
  32. options.Target = fields[0]
  33. o.values = append(o.values, options)
  34. return nil
  35. }
  36. for _, field := range fields {
  37. parts := strings.SplitN(field, "=", 2)
  38. key := strings.ToLower(parts[0])
  39. if len(parts) != 2 {
  40. return fmt.Errorf("invalid field '%s' must be a key=value pair", field)
  41. }
  42. value := parts[1]
  43. switch key {
  44. case "source", "src":
  45. options.Source = value
  46. case "target":
  47. tDir, _ := filepath.Split(value)
  48. if tDir != "" {
  49. return fmt.Errorf("target must not be a path")
  50. }
  51. options.Target = value
  52. case "uid":
  53. options.UID = value
  54. case "gid":
  55. options.GID = value
  56. case "mode":
  57. m, err := strconv.ParseUint(value, 0, 32)
  58. if err != nil {
  59. return fmt.Errorf("invalid mode specified: %v", err)
  60. }
  61. options.Mode = os.FileMode(m)
  62. default:
  63. if len(fields) == 1 && value == "" {
  64. } else {
  65. return fmt.Errorf("invalid field in secret request: %s", key)
  66. }
  67. }
  68. }
  69. if options.Source == "" {
  70. return fmt.Errorf("source is required")
  71. }
  72. o.values = append(o.values, options)
  73. return nil
  74. }
  75. // Type returns the type of this option
  76. func (o *SecretOpt) Type() string {
  77. return "secret"
  78. }
  79. // String returns a string repr of this option
  80. func (o *SecretOpt) String() string {
  81. secrets := []string{}
  82. for _, secret := range o.values {
  83. repr := fmt.Sprintf("%s -> %s", secret.Source, secret.Target)
  84. secrets = append(secrets, repr)
  85. }
  86. return strings.Join(secrets, ", ")
  87. }
  88. // Value returns the secret requests
  89. func (o *SecretOpt) Value() []*types.SecretRequestOption {
  90. return o.values
  91. }