github.com/ph/moby@v1.13.1/opts/secret.go (about)

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