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 }