github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/cli/opts/secret.go (about)

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