From 077a42c1c2b90243adb741cfab9382f081717a9a Mon Sep 17 00:00:00 2001 From: yalefresne Date: Thu, 27 Mar 2025 10:47:41 +0100 Subject: [PATCH] Feat: Add docker action to build parent image --- commands/docker.go | 115 +++++++++++++++++++++++++++++++++++++++++++++ commands/root.go | 28 +++++++++-- 2 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 commands/docker.go diff --git a/commands/docker.go b/commands/docker.go new file mode 100644 index 0000000..4e11342 --- /dev/null +++ b/commands/docker.go @@ -0,0 +1,115 @@ +package cmd + +import ( + "bufio" + "errors" + "fmt" + "log" + "os" + "os/exec" + "strings" + + "github.com/MyLittleParis/dvopsctl/utils" +) + +const dockerfile = "Dockerfile" +const defaultRegistry = "ghcr.io/mylittleparis" +const defaultGithub = "https://github.com/MyLittleParis" +const defaultRepositoryName = "devops-docker-php" + +var defaultRegistryRepo = fmt.Sprintf("%s/%s", defaultRegistry, defaultRepositoryName) +var defaultRepository = fmt.Sprintf("%s/%s", defaultGithub, defaultRepositoryName) +var defaultPath = []string {"./", ".docker/"} + +func BuildParentImage(path string) (int, error) { + errCode := 0 + var err error + + dockerImage, tag := searchInDockerfile(path) + + if dockerImage == "" { + log.Printf("No docker image found.") + return 1, errors.New("No Docker image found.") + } + + err = os.Chdir("../" + defaultRepositoryName) + + if err != nil { + err = os.Chdir("../") + utils.GitClone(defaultRepository) + err = os.Chdir(defaultRepositoryName) + } else { + utils.GitPull() + } + utils.GitCheckout(dockerImage) + Build(fmt.Sprintf("%s/%s:%s",defaultRegistryRepo, dockerImage, tag)) + + return errCode, err +} + +func searchInDockerfile(path string) (dockerImage, tag string) { + paths := defaultPath + if path != "" { + paths = []string{path} + } + + for _, path := range paths { + fmt.Println("Search in " + path + dockerfile) + if content, err := os.Open(path + dockerfile); err == nil { + scanner := bufio.NewScanner(content) + for scanner.Scan() { + dockerImage, tag = extractImageName(scanner.Text()) + if dockerImage != "" { + fmt.Printf("Image found %s\n", dockerImage) + return dockerImage, tag + } + } + } + } + + return dockerImage, tag +} + +/* + Extract image name if is a ghcr.io/mylittleparis image + From: + FROM ghcr.io/mylittleparis/devops-docker-php/php7.4-fpm-alpine:latest AS prod + To: + php7.4-fpm-alpine:latest +*/ +func extractImageName(line string) (dockerImage, tag string) { + if dockerImage, found := strings.CutPrefix(line, "FROM " + defaultRegistry + "/" + defaultRepositoryName + "/"); found { + if found {fmt.Printf("Parent Image found %s\n", dockerImage)} + if removeAs, _, found := strings.Cut(dockerImage, " AS "); found { + if found {fmt.Printf("Image found %s\n", removeAs)} + dockerImage, tag, _ = strings.Cut(removeAs, ":") + return dockerImage, tag + } + } + return dockerImage, tag +} + +func Build(tag string) { + dockerBuild := exec.Command("docker", "build", "-t", tag, ".") + fmt.Printf("Docker build %s", tag) + pipe, _ := dockerBuild.StdoutPipe() + + err := dockerBuild.Start() + + if err != nil { + log.Fatal(err) + } + + reader := bufio.NewReader(pipe) + line, err := reader.ReadString('\n') + for err == nil { + fmt.Println(line) + line, err = reader.ReadString('\n') + } + + err = dockerBuild.Wait() + + if err != nil { + log.Printf("Command finished with error: %v", err) + } +} diff --git a/commands/root.go b/commands/root.go index 3f5e51d..e45b9f9 100644 --- a/commands/root.go +++ b/commands/root.go @@ -23,9 +23,22 @@ func Run(args []string) (int, error) { fmt.Println("") } + dockerCmd := flag.NewFlagSet("docker", flag.ExitOnError) + // subcommands + dockerBuild := dockerCmd.Bool("build", false, "Build parent docker image in local") + // args + dockerPath := dockerCmd.String("path", "", "Path to docker file") + + dockerCmd.Usage = func() { + fmt.Println("docker [options]") + dockerCmd.PrintDefaults() + fmt.Println("") + } + // Commands list to use it in usage function commands := []*flag.FlagSet{ - serverCmd, + dockerCmd, + serverCmd, } var usage func() @@ -49,10 +62,15 @@ func Run(args []string) (int, error) { if *serverOpen { errCode, rootError = ServerOpen() } - default: - fmt.Println("Unknown command: " + args[1]) - usage() - return -1, errors.New(unknownCmd) + case "docker": + dockerCmd.Parse(args[2:]) + if *dockerBuild { + BuildParentImage(*dockerPath) + } + default: + fmt.Println("Unknown command: " + args[1]) + usage() + return -1, errors.New(unknownCmd) } return errCode, rootError