github.com/AliyunContainerService/cli@v0.0.0-20181009023821-814ced4b30d0/cli/command/utils.go (about)

     1  package command
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  	"runtime"
    10  	"strings"
    11  
    12  	"github.com/docker/docker/api/types/filters"
    13  	"github.com/docker/docker/pkg/system"
    14  	"github.com/spf13/pflag"
    15  )
    16  
    17  // CopyToFile writes the content of the reader to the specified file
    18  func CopyToFile(outfile string, r io.Reader) error {
    19  	// We use sequential file access here to avoid depleting the standby list
    20  	// on Windows. On Linux, this is a call directly to ioutil.TempFile
    21  	tmpFile, err := system.TempFileSequential(filepath.Dir(outfile), ".docker_temp_")
    22  	if err != nil {
    23  		return err
    24  	}
    25  
    26  	tmpPath := tmpFile.Name()
    27  
    28  	_, err = io.Copy(tmpFile, r)
    29  	tmpFile.Close()
    30  
    31  	if err != nil {
    32  		os.Remove(tmpPath)
    33  		return err
    34  	}
    35  
    36  	if err = os.Rename(tmpPath, outfile); err != nil {
    37  		os.Remove(tmpPath)
    38  		return err
    39  	}
    40  
    41  	return nil
    42  }
    43  
    44  // capitalizeFirst capitalizes the first character of string
    45  func capitalizeFirst(s string) string {
    46  	switch l := len(s); l {
    47  	case 0:
    48  		return s
    49  	case 1:
    50  		return strings.ToLower(s)
    51  	default:
    52  		return strings.ToUpper(string(s[0])) + strings.ToLower(s[1:])
    53  	}
    54  }
    55  
    56  // PrettyPrint outputs arbitrary data for human formatted output by uppercasing the first letter.
    57  func PrettyPrint(i interface{}) string {
    58  	switch t := i.(type) {
    59  	case nil:
    60  		return "None"
    61  	case string:
    62  		return capitalizeFirst(t)
    63  	default:
    64  		return capitalizeFirst(fmt.Sprintf("%s", t))
    65  	}
    66  }
    67  
    68  // PromptForConfirmation requests and checks confirmation from user.
    69  // This will display the provided message followed by ' [y/N] '. If
    70  // the user input 'y' or 'Y' it returns true other false.  If no
    71  // message is provided "Are you sure you want to proceed? [y/N] "
    72  // will be used instead.
    73  func PromptForConfirmation(ins io.Reader, outs io.Writer, message string) bool {
    74  	if message == "" {
    75  		message = "Are you sure you want to proceed?"
    76  	}
    77  	message += " [y/N] "
    78  
    79  	fmt.Fprintf(outs, message)
    80  
    81  	// On Windows, force the use of the regular OS stdin stream.
    82  	if runtime.GOOS == "windows" {
    83  		ins = NewInStream(os.Stdin)
    84  	}
    85  
    86  	reader := bufio.NewReader(ins)
    87  	answer, _, _ := reader.ReadLine()
    88  	return strings.ToLower(string(answer)) == "y"
    89  }
    90  
    91  // PruneFilters returns consolidated prune filters obtained from config.json and cli
    92  func PruneFilters(dockerCli Cli, pruneFilters filters.Args) filters.Args {
    93  	if dockerCli.ConfigFile() == nil {
    94  		return pruneFilters
    95  	}
    96  	for _, f := range dockerCli.ConfigFile().PruneFilters {
    97  		parts := strings.SplitN(f, "=", 2)
    98  		if len(parts) != 2 {
    99  			continue
   100  		}
   101  		if parts[0] == "label" {
   102  			// CLI label filter supersede config.json.
   103  			// If CLI label filter conflict with config.json,
   104  			// skip adding label! filter in config.json.
   105  			if pruneFilters.Contains("label!") && pruneFilters.ExactMatch("label!", parts[1]) {
   106  				continue
   107  			}
   108  		} else if parts[0] == "label!" {
   109  			// CLI label! filter supersede config.json.
   110  			// If CLI label! filter conflict with config.json,
   111  			// skip adding label filter in config.json.
   112  			if pruneFilters.Contains("label") && pruneFilters.ExactMatch("label", parts[1]) {
   113  				continue
   114  			}
   115  		}
   116  		pruneFilters.Add(parts[0], parts[1])
   117  	}
   118  
   119  	return pruneFilters
   120  }
   121  
   122  // AddPlatformFlag adds `platform` to a set of flags for API version 1.32 and later.
   123  func AddPlatformFlag(flags *pflag.FlagSet, target *string) {
   124  	flags.StringVar(target, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
   125  	flags.SetAnnotation("platform", "version", []string{"1.32"})
   126  	flags.SetAnnotation("platform", "experimental", nil)
   127  }