github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/opts/parse.go (about)

     1  package opts
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/api/types/container"
    10  )
    11  
    12  // ReadKVStrings reads a file of line terminated key=value pairs, and overrides any keys
    13  // present in the file with additional pairs specified in the override parameter
    14  func ReadKVStrings(files []string, override []string) ([]string, error) {
    15  	return readKVStrings(files, override, nil)
    16  }
    17  
    18  // ReadKVEnvStrings reads a file of line terminated key=value pairs, and overrides any keys
    19  // present in the file with additional pairs specified in the override parameter.
    20  // If a key has no value, it will get the value from the environment.
    21  func ReadKVEnvStrings(files []string, override []string) ([]string, error) {
    22  	return readKVStrings(files, override, os.LookupEnv)
    23  }
    24  
    25  func readKVStrings(files []string, override []string, emptyFn func(string) (string, bool)) ([]string, error) {
    26  	var variables []string
    27  	for _, ef := range files {
    28  		parsedVars, err := parseKeyValueFile(ef, emptyFn)
    29  		if err != nil {
    30  			return nil, err
    31  		}
    32  		variables = append(variables, parsedVars...)
    33  	}
    34  	// parse the '-e' and '--env' after, to allow override
    35  	variables = append(variables, override...)
    36  
    37  	return variables, nil
    38  }
    39  
    40  // ConvertKVStringsToMap converts ["key=value"] to {"key":"value"}
    41  func ConvertKVStringsToMap(values []string) map[string]string {
    42  	result := make(map[string]string, len(values))
    43  	for _, value := range values {
    44  		k, v, _ := strings.Cut(value, "=")
    45  		result[k] = v
    46  	}
    47  
    48  	return result
    49  }
    50  
    51  // ConvertKVStringsToMapWithNil converts ["key=value"] to {"key":"value"}
    52  // but set unset keys to nil - meaning the ones with no "=" in them.
    53  // We use this in cases where we need to distinguish between
    54  //
    55  //	FOO=  and FOO
    56  //
    57  // where the latter case just means FOO was mentioned but not given a value
    58  func ConvertKVStringsToMapWithNil(values []string) map[string]*string {
    59  	result := make(map[string]*string, len(values))
    60  	for _, value := range values {
    61  		k, v, ok := strings.Cut(value, "=")
    62  		if !ok {
    63  			result[k] = nil
    64  		} else {
    65  			result[k] = &v
    66  		}
    67  	}
    68  
    69  	return result
    70  }
    71  
    72  // ParseRestartPolicy returns the parsed policy or an error indicating what is incorrect
    73  func ParseRestartPolicy(policy string) (container.RestartPolicy, error) {
    74  	if policy == "" {
    75  		// for backward-compatibility, we don't set the default ("no")
    76  		// policy here, because older versions of the engine may not
    77  		// support it.
    78  		return container.RestartPolicy{}, nil
    79  	}
    80  
    81  	p := container.RestartPolicy{}
    82  	k, v, ok := strings.Cut(policy, ":")
    83  	if ok && k == "" {
    84  		return container.RestartPolicy{}, fmt.Errorf("invalid restart policy format: no policy provided before colon")
    85  	}
    86  	if v != "" {
    87  		count, err := strconv.Atoi(v)
    88  		if err != nil {
    89  			return container.RestartPolicy{}, fmt.Errorf("invalid restart policy format: maximum retry count must be an integer")
    90  		}
    91  		p.MaximumRetryCount = count
    92  	}
    93  
    94  	p.Name = container.RestartPolicyMode(k)
    95  	return p, nil
    96  }