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  }