mirror of
https://github.com/mappu/miqt.git
synced 2025-05-07 04:20:22 +00:00
106 lines
2.1 KiB
Go
106 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
)
|
|
|
|
var (
|
|
needsSudo bool
|
|
)
|
|
|
|
// dockerImage describes an image available in the docker daemon.
|
|
type dockerImage struct {
|
|
ID string
|
|
Repository string
|
|
Tag string
|
|
}
|
|
|
|
// dockerCommand creates an *exec.Cmd for running docker. It respects the global
|
|
// `needsSudo` state.
|
|
func dockerCommand(args ...string) *exec.Cmd {
|
|
docker := os.Getenv("DOCKER")
|
|
if docker == "" {
|
|
docker = "docker"
|
|
}
|
|
|
|
if needsSudo {
|
|
useArgs := make([]string, 0, len(args)+1)
|
|
useArgs = append(useArgs, docker)
|
|
useArgs = append(useArgs, args...)
|
|
return exec.Command(`sudo`, useArgs...)
|
|
}
|
|
|
|
return exec.Command(docker, args...)
|
|
}
|
|
|
|
// dockerListImages lists all the current docker images.
|
|
func dockerListImages() ([]dockerImage, error) {
|
|
|
|
cmd := dockerCommand(`image`, `ls`, `--format`, `{{json . }}`)
|
|
cmd.Stderr = os.Stderr // passthrough
|
|
|
|
buff, err := cmd.Output()
|
|
if err != nil {
|
|
if !needsSudo {
|
|
// Retry with sudo
|
|
log.Println("Retrying with sudo...")
|
|
needsSudo = true
|
|
return dockerListImages()
|
|
}
|
|
|
|
return nil, err
|
|
}
|
|
|
|
var ret []dockerImage
|
|
|
|
dec := json.NewDecoder(bytes.NewReader(buff))
|
|
for {
|
|
var entry dockerImage
|
|
err = dec.Decode(&entry)
|
|
if err != nil {
|
|
if errors.Is(err, io.EOF) {
|
|
return ret, nil
|
|
}
|
|
return nil, err // real error
|
|
}
|
|
|
|
ret = append(ret, entry)
|
|
}
|
|
}
|
|
|
|
// dockerFindImage searches all the current docker images to find one named as
|
|
// the supplied `repository:tag`.
|
|
func dockerFindImage(repository, tag string) (*dockerImage, error) {
|
|
|
|
images, err := dockerListImages()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, im := range images {
|
|
if im.Repository == repository && im.Tag == tag {
|
|
// found it
|
|
return &im, nil
|
|
}
|
|
}
|
|
|
|
// No match
|
|
return nil, os.ErrNotExist
|
|
}
|
|
|
|
// dockerBuild builds the supplied dockerfile and tags it as repository:tag
|
|
// as well as repository:latest.
|
|
func dockerBuild(dockerfile []byte, repository, tag string) error {
|
|
cmd := dockerCommand(`build`, `-t`, repository+`:`+tag, `-t`, repository+`:latest`, `-`)
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Stdin = bytes.NewReader(dockerfile)
|
|
|
|
return cmd.Run()
|
|
}
|