github.com/git-ogawa/go-dbyml@v1.2.1/dbyml/cli.go (about) 1 // Dbyml is a CLI tool to build a docker image with the arguments loaded from configs in yaml. 2 // 3 // Usage 4 // 5 // The following command will generate a configuration file. 6 // dbyml --init 7 // 8 // The configuration file where the about image build is written. 9 // 10 // dbyml 11 // 12 // The options on image build can be written in the config. 13 // See https://github.com/git-ogawa/dbyml how to edit contents in config file. 14 package dbyml 15 16 import ( 17 "fmt" 18 "os" 19 "time" 20 21 "github.com/akamensky/argparse" 22 ) 23 24 // CLIoptions defines cli options. 25 type CLIoptions struct { 26 // Path to config file. 27 Config string 28 29 // Whether to generate config file. 30 Init bool 31 } 32 33 // GetArgs gets cli options from user inputs. 34 func GetArgs() (CLIoptions, bool) { 35 desc := "Dbyml is a CLI tool to build a docker image with the arguments loaded from configs in yaml.\n\n" 36 desc += "Passing the config file where the arguments are listed to build the image from your dockerfile,\n" 37 desc += "push it to the docker registry.\n\n" 38 desc += "To make sample config file, run the following command.\n" 39 desc += "\n" 40 desc += "$ dbyml --init\n" 41 42 parser := argparse.NewParser("dbyml", desc) 43 parser.HelpFunc = func(c *argparse.Command, msg interface{}) string { 44 var help string 45 help += fmt.Sprintln(c.GetDescription()) 46 help += "Optional arguments:\n" 47 for _, arg := range c.GetArgs() { 48 if arg.GetOpts() != nil { 49 sopt := arg.GetSname() 50 var prefix string 51 var suffix string 52 if sopt != "" { 53 prefix = "-" 54 suffix = "," 55 } else { 56 prefix = "" 57 suffix = "" 58 } 59 sname := fmt.Sprintf("%v%s%v", prefix, sopt, suffix) 60 lname := fmt.Sprintf("--%-15s", arg.GetLname()) 61 helpMsg := arg.GetOpts().Help 62 help += fmt.Sprintf(" %3s %s %s\n", sname, lname, helpMsg) 63 } else { 64 help += fmt.Sprintf("Sname: %s, Lname: %s\n", arg.GetSname(), arg.GetLname()) 65 } 66 } 67 return help 68 } 69 70 Config := parser.String("c", "config", &argparse.Options{Help: "Path to config file."}) 71 Init := parser.Flag("", "init", &argparse.Options{Help: "Generate config."}) 72 Version := parser.Flag("v", "version", &argparse.Options{Help: "Show version."}) 73 74 err := parser.Parse(os.Args) 75 if err != nil { 76 fmt.Print(parser.Usage(err)) 77 } 78 79 if *Version { 80 ShowVersion() 81 return CLIoptions{}, false 82 } 83 84 return CLIoptions{*Config, *Init}, true 85 } 86 87 // Parse checks the input options, run actions according to the options. 88 func (options *CLIoptions) Parse() { 89 if options.Init { 90 config := NewConfiguration() 91 MakeTemplate(config) 92 return 93 } 94 if options.Config != "" { 95 if exist := ConfigExists(options.Config); exist { 96 ExecBuild(options.Config) 97 } else { 98 fmt.Printf("%v not found. Check the file exists.\n", options.Config) 99 } 100 } else { 101 if exist := ConfigExists("dbyml.yml"); exist { 102 ExecBuild("dbyml.yml") 103 } else { 104 msg := "Config file not found in the current directory.\nRun the following commands to generate config file." 105 fmt.Println(msg) 106 fmt.Println() 107 fmt.Println("$ dbyml --init") 108 } 109 } 110 } 111 112 // ExecBuild run the build sequence. 113 func ExecBuild(path string) { 114 config := LoadConfig(path) 115 config.ImageInfo.Registry = config.RegistryInfo 116 config.ImageInfo.BuildInfo = config.BuildInfo 117 if config.BuildInfo.Verbose { 118 config.ShowConfig() 119 } 120 121 if config.BuildkitInfo.Enabled { 122 err := buildkit(path, config) 123 if err != nil { 124 fmt.Printf("Error has occurred: %v\n", err) 125 fmt.Println("\x1b[31mBuild Failed\x1b[0m") 126 os.Exit(1) 127 } 128 } else { 129 err := dockerBuild(path, config) 130 if err != nil { 131 fmt.Printf("Error has occurred: %v\n", err) 132 fmt.Println("\x1b[31mBuild Failed\x1b[0m") 133 os.Exit(1) 134 } 135 } 136 } 137 138 func buildkit(path string, config *Configuration) error { 139 fmt.Println() 140 PrintCenter("Build start", 30, "-") 141 fmt.Println() 142 143 cmd := config.BuildkitInfo.ParseOptions(config.ImageInfo) 144 builder := NewBuilder() 145 builder.AddCmd(cmd...) 146 147 if !builder.Image.Exists() { 148 fmt.Printf("Image %s not found and will be pulled from docker hub.\n", buildkitImageName) 149 err := builder.Image.Pull() 150 if err != nil { 151 return err 152 } 153 } 154 155 if !builder.Exists() { 156 err := builder.Setup(&config.RegistryInfo) 157 if err != nil { 158 return err 159 } 160 } else { 161 err := builder.SetContainerID() 162 if err != nil { 163 return err 164 } 165 } 166 167 builder.Start() 168 time.Sleep(time.Second * 3) 169 builder.CopyFiles(config.ImageInfo.Context, "/tmp") 170 err := builder.Build(config.BuildInfo.Verbose) 171 if err != nil { 172 return err 173 } 174 175 if config.BuildkitInfo.Remove { 176 builder.Remove() 177 } else { 178 builder.Stop() 179 } 180 return nil 181 } 182 183 func dockerBuild(path string, config *Configuration) error { 184 fmt.Println() 185 PrintCenter("Build start", 30, "-") 186 fmt.Println() 187 err := config.ImageInfo.Build() 188 PrintCenter("Build finish", 30, "-") 189 fmt.Println() 190 if err != nil { 191 return err 192 } 193 194 fmt.Printf("Image %v successfully built.\n", config.ImageInfo.ImageName) 195 196 if config.RegistryInfo.Enabled { 197 fmt.Println() 198 PrintCenter("Push start", 30, "-") 199 fmt.Println() 200 err = config.ImageInfo.Push() 201 fmt.Println() 202 PrintCenter("Push finish", 30, "-") 203 204 fmt.Println() 205 if err != nil { 206 return err 207 } 208 209 fmt.Printf("Image %v successfully pushed.\n", config.ImageInfo.FullName) 210 } 211 return nil 212 }