mirror of
https://github.com/foomo/squadron.git
synced 2025-10-16 12:35:42 +00:00
feat: use docker buildx by default and add args
This commit is contained in:
parent
87966bea58
commit
29d784eb19
76
build.go
76
build.go
@ -16,19 +16,28 @@ const (
|
||||
)
|
||||
|
||||
type Build struct {
|
||||
Image string `yaml:"image,omitempty"`
|
||||
Tag string `yaml:"tag,omitempty"`
|
||||
Context string `yaml:"context,omitempty"`
|
||||
Dockerfile string `yaml:"dockerfile,omitempty"`
|
||||
Args []string `yaml:"args,omitempty"`
|
||||
Secrets []string `yaml:"secrets,omitempty"`
|
||||
Labels []string `yaml:"labels,omitempty"`
|
||||
CacheFrom []string `yaml:"cache_from,omitempty"`
|
||||
Network string `yaml:"network,omitempty"`
|
||||
Target string `yaml:"target,omitempty"`
|
||||
ShmSize string `yaml:"shm_size,omitempty"`
|
||||
ExtraHosts []string `yaml:"extra_hosts,omitempty"`
|
||||
Isolation string `yaml:"isolation,omitempty"`
|
||||
Args []string `yaml:"args,omitempty"`
|
||||
Builder string `yaml:"builder,omitempty"`
|
||||
CacheFrom []string `yaml:"cache_from,omitempty"`
|
||||
Context string `yaml:"context,omitempty"`
|
||||
Dockerfile string `yaml:"dockerfile,omitempty"`
|
||||
ExtraHosts []string `yaml:"extra_hosts,omitempty"`
|
||||
Image string `yaml:"image,omitempty"`
|
||||
IIDFile string `yaml:"iidfile,omitempty"`
|
||||
Labels []string `yaml:"labels,omitempty"`
|
||||
Load bool `yaml:"load,omitempty"`
|
||||
MetadataFile string `yaml:"metadata_file,omitempty"`
|
||||
Network string `yaml:"network,omitempty"`
|
||||
NoCache bool `yaml:"no_cache,omitempty"`
|
||||
Output string `yaml:"output,omitempty"`
|
||||
Platform string `yaml:"platform,omitempty"`
|
||||
Platforms []string `yaml:"platforms,omitempty"`
|
||||
Secrets []string `yaml:"secrets,omitempty"`
|
||||
ShmSize string `yaml:"shm_size,omitempty"`
|
||||
SSH string `yaml:"ssh,omitempty"`
|
||||
Tag string `yaml:"tag,omitempty"`
|
||||
Target string `yaml:"target,omitempty"`
|
||||
ULimit string `yaml:"ulimit,omitempty"`
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -36,26 +45,41 @@ type Build struct {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// Build ...
|
||||
func (b *Build) Build(ctx context.Context) (string, error) {
|
||||
func (b *Build) Build(ctx context.Context, args []string) (string, error) {
|
||||
logrus.Debugf("running docker build for %q", b.Context)
|
||||
return util.NewDockerCommand().Build(b.Context).
|
||||
Arg("-t", fmt.Sprintf("%s:%s", b.Image, b.Tag)).
|
||||
Arg("--file", b.Dockerfile).
|
||||
ListArg("--build-arg", b.Args).
|
||||
ListArg("--secrets", b.Secrets).
|
||||
ListArg("--label", b.Labels).
|
||||
ListArg("--cache-from", b.CacheFrom).
|
||||
Arg("--network", b.Network).
|
||||
Arg("--target", b.Target).
|
||||
Arg("--shm-size", b.ShmSize).
|
||||
ListArg("--add-host", b.ExtraHosts).
|
||||
Arg("--isolation", b.Isolation).Run(ctx)
|
||||
ListArg("--build-arg", b.Args).
|
||||
Arg("--builder", b.Builder).
|
||||
ListArg("--cache-from", b.CacheFrom).
|
||||
Arg("--file", b.Dockerfile).
|
||||
Arg("--iidfile", b.IIDFile).
|
||||
ListArg("--label", b.Labels).
|
||||
BoolArg("--load", b.Load).
|
||||
Arg("--metadata-file", b.MetadataFile).
|
||||
Arg("--network", b.Network).
|
||||
BoolArg("--no-cache", b.NoCache).
|
||||
Arg("--output", b.Output).
|
||||
Arg("--platform", b.Platform).
|
||||
ListArg("--platform", b.Platforms).
|
||||
// Arg("--progress", xxx).
|
||||
// Arg("--push", xxx).
|
||||
// Arg("--pull", xxx).
|
||||
// Arg("--quiet", xxx).
|
||||
ListArg("--secret", b.Secrets).
|
||||
Arg("--shm-size", b.ShmSize).
|
||||
Arg("--ssh", b.SSH).
|
||||
Arg("--tag", fmt.Sprintf("%s:%s", b.Image, b.Tag)).
|
||||
Arg("--target", b.Target).
|
||||
Arg("--ulimit", b.ULimit).
|
||||
Args(args...).
|
||||
Run(ctx)
|
||||
}
|
||||
|
||||
// Push ...
|
||||
func (b *Build) Push(ctx context.Context) (string, error) {
|
||||
func (b *Build) Push(ctx context.Context, args []string) (string, error) {
|
||||
logrus.Debugf("running docker push for %s:%s", b.Image, b.Tag)
|
||||
return util.NewDockerCommand().Push(ctx, b.Image, b.Tag)
|
||||
return util.NewDockerCommand().Push(b.Image, b.Tag).Args(args...).Run(ctx)
|
||||
}
|
||||
|
||||
// UnmarshalYAML ...
|
||||
|
||||
@ -2,6 +2,7 @@ package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -14,6 +15,8 @@ import (
|
||||
func init() {
|
||||
buildCmd.Flags().BoolVarP(&flagPush, "push", "p", false, "pushes built squadron units to the registry")
|
||||
buildCmd.Flags().IntVar(&flagParallel, "parallel", 1, "run command in parallel")
|
||||
buildCmd.Flags().StringVar(&flagBuildArgs, "build-args", "", "additional docker buildx build args")
|
||||
buildCmd.Flags().StringVar(&flagPushArgs, "push-args", "", "additional docker push args")
|
||||
}
|
||||
|
||||
var buildCmd = &cobra.Command{
|
||||
@ -65,7 +68,7 @@ func build(ctx context.Context, args []string, cwd string, files []string, push
|
||||
return err
|
||||
}
|
||||
defer sem.Release(1)
|
||||
if out, err := unit.Build(wgCtx, sq.Name(), name); err != nil {
|
||||
if out, err := unit.Build(wgCtx, sq.Name(), name, strings.Split(flagBuildArgs, " ")); err != nil {
|
||||
return errors.Wrap(err, out)
|
||||
}
|
||||
return nil
|
||||
@ -88,7 +91,7 @@ func build(ctx context.Context, args []string, cwd string, files []string, push
|
||||
return err
|
||||
}
|
||||
defer sem.Release(1)
|
||||
if out, err := unit.Push(wgCtx, sq.Name(), name); err != nil {
|
||||
if out, err := unit.Push(wgCtx, sq.Name(), name, strings.Split(flagPushArgs, " ")); err != nil {
|
||||
return errors.Wrap(err, out)
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -2,6 +2,7 @@ package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
@ -15,6 +16,8 @@ func init() {
|
||||
pushCmd.Flags().StringVarP(&flagNamespace, "namespace", "n", "default", "specifies the namespace")
|
||||
pushCmd.Flags().BoolVarP(&flagBuild, "build", "b", false, "builds or rebuilds units")
|
||||
pushCmd.Flags().IntVar(&flagParallel, "parallel", 1, "run command in parallel")
|
||||
pushCmd.Flags().StringVar(&flagBuildArgs, "build-args", "", "additional docker buildx build args")
|
||||
pushCmd.Flags().StringVar(&flagPushArgs, "push-args", "", "additional docker push args")
|
||||
}
|
||||
|
||||
var pushCmd = &cobra.Command{
|
||||
@ -65,7 +68,7 @@ func push(ctx context.Context, args []string, cwd, namespace string, build bool,
|
||||
return err
|
||||
}
|
||||
defer sem.Release(1)
|
||||
if out, err := unit.Build(wgCtx, sq.Name(), name); err != nil {
|
||||
if out, err := unit.Build(wgCtx, sq.Name(), name, strings.Split(flagBuildArgs, " ")); err != nil {
|
||||
return errors.Wrap(err, out)
|
||||
}
|
||||
return nil
|
||||
@ -89,7 +92,7 @@ func push(ctx context.Context, args []string, cwd, namespace string, build bool,
|
||||
return err
|
||||
}
|
||||
defer sem.Release(1)
|
||||
if out, err := unit.Push(wgCtx, sq.Name(), name); err != nil {
|
||||
if out, err := unit.Push(wgCtx, sq.Name(), name, strings.Split(flagPushArgs, " ")); err != nil {
|
||||
return errors.Wrap(err, out)
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -45,6 +45,8 @@ var (
|
||||
flagBuild bool
|
||||
flagPush bool
|
||||
flagParallel int
|
||||
flagBuildArgs string
|
||||
flagPushArgs string
|
||||
flagDiff bool
|
||||
flagFiles []string
|
||||
)
|
||||
|
||||
@ -21,6 +21,8 @@ func init() {
|
||||
upCmd.Flags().BoolVarP(&flagPush, "push", "p", false, "pushes units to the registry")
|
||||
upCmd.Flags().BoolVar(&flagDiff, "diff", false, "preview upgrade as a coloured diff")
|
||||
upCmd.Flags().IntVar(&flagParallel, "parallel", 1, "run command in parallel")
|
||||
upCmd.Flags().StringVar(&flagBuildArgs, "build-args", "", "additional docker buildx build args")
|
||||
upCmd.Flags().StringVar(&flagPushArgs, "push-args", "", "additional docker push args")
|
||||
}
|
||||
|
||||
var upCmd = &cobra.Command{
|
||||
@ -73,7 +75,7 @@ func up(ctx context.Context, args []string, cwd, namespace string, build, push,
|
||||
return err
|
||||
}
|
||||
defer sem.Release(1)
|
||||
if out, err := unit.Build(wgCtx, sq.Name(), name); err != nil {
|
||||
if out, err := unit.Build(wgCtx, sq.Name(), name, strings.Split(flagBuildArgs, " ")); err != nil {
|
||||
return errors.Wrap(err, out)
|
||||
}
|
||||
return nil
|
||||
@ -96,7 +98,7 @@ func up(ctx context.Context, args []string, cwd, namespace string, build, push,
|
||||
return err
|
||||
}
|
||||
defer sem.Release(1)
|
||||
if out, err := unit.Push(wgCtx, sq.Name(), name); err != nil {
|
||||
if out, err := unit.Push(wgCtx, sq.Name(), name, strings.Split(flagPushArgs, " ")); err != nil {
|
||||
return errors.Wrap(err, out)
|
||||
}
|
||||
return nil
|
||||
|
||||
38
configuration.go
Normal file
38
configuration.go
Normal file
@ -0,0 +1,38 @@
|
||||
package squadron
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Configuration struct {
|
||||
Name string `yaml:"name,omitempty"`
|
||||
Version string `yaml:"version,omitempty"`
|
||||
Prefix string `yaml:"prefix,omitempty"`
|
||||
Unite bool `yaml:"unite,omitempty"`
|
||||
Global map[string]interface{} `yaml:"global,omitempty"`
|
||||
Units map[string]*Unit `yaml:"squadron,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalYAML ...
|
||||
func (c *Configuration) UnmarshalYAML(value *yaml.Node) error {
|
||||
if value.Tag == TagMap {
|
||||
type wrapper Configuration
|
||||
err := value.Decode((*wrapper)(c))
|
||||
if err == nil {
|
||||
// if the decode is successful, remove units that are nil
|
||||
c.removeNilUnits()
|
||||
}
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("unsupported node tag type for %T: %q", c, value.Tag)
|
||||
}
|
||||
|
||||
func (c *Configuration) removeNilUnits() {
|
||||
for uName, u := range c.Units {
|
||||
if u == nil {
|
||||
delete(c.Units, uName)
|
||||
}
|
||||
}
|
||||
}
|
||||
45
squadron.go
45
squadron.go
@ -33,15 +33,6 @@ const (
|
||||
errHelmReleaseNotFound = "Error: release: not found"
|
||||
)
|
||||
|
||||
type Configuration struct {
|
||||
Name string `yaml:"name,omitempty"`
|
||||
Version string `yaml:"version,omitempty"`
|
||||
Prefix string `yaml:"prefix,omitempty"`
|
||||
Unite bool `yaml:"unite,omitempty"`
|
||||
Global map[string]interface{} `yaml:"global,omitempty"`
|
||||
Units map[string]*Unit `yaml:"squadron,omitempty"`
|
||||
}
|
||||
|
||||
type Squadron struct {
|
||||
name string
|
||||
basePath string
|
||||
@ -73,28 +64,6 @@ func (sq *Squadron) GetConfigYAML() string {
|
||||
return sq.config
|
||||
}
|
||||
|
||||
// UnmarshalYAML ...
|
||||
func (c *Configuration) UnmarshalYAML(value *yaml.Node) error {
|
||||
if value.Tag == TagMap {
|
||||
type wrapper Configuration
|
||||
err := value.Decode((*wrapper)(c))
|
||||
if err == nil {
|
||||
// if the decode is successful, remove units that are nil
|
||||
c.removeNilUnits()
|
||||
}
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("unsupported node tag type for %T: %q", c, value.Tag)
|
||||
}
|
||||
|
||||
func (c *Configuration) removeNilUnits() {
|
||||
for uName, u := range c.Units {
|
||||
if u == nil {
|
||||
delete(c.Units, uName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sq *Squadron) MergeConfigFiles() error {
|
||||
logrus.Info("merging config files")
|
||||
logrus.WithField("files", sq.files).Debug("using files")
|
||||
@ -142,36 +111,40 @@ func (sq *Squadron) RenderConfig(ctx context.Context) error {
|
||||
// execute again with loaded template vars
|
||||
tv = TemplateVars{}
|
||||
if value, ok := vars["global"]; ok {
|
||||
replace(value)
|
||||
toSnakeCaseKeys(value)
|
||||
tv.add("Global", value)
|
||||
}
|
||||
if value, ok := vars["squadron"]; ok {
|
||||
replace(value)
|
||||
toSnakeCaseKeys(value)
|
||||
tv.add("Squadron", value)
|
||||
}
|
||||
logrus.Debug("executing file template")
|
||||
// execute without errors to get existing values
|
||||
out, err := executeFileTemplate(ctx, sq.config, tv, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to execute initial file template")
|
||||
}
|
||||
|
||||
logrus.Debug("unmarshalling vars")
|
||||
if err := yaml.Unmarshal(out, &vars); err != nil {
|
||||
return err
|
||||
}
|
||||
// execute again with loaded template vars
|
||||
tv = TemplateVars{}
|
||||
if value, ok := vars["global"]; ok {
|
||||
replace(value)
|
||||
toSnakeCaseKeys(value)
|
||||
tv.add("Global", value)
|
||||
}
|
||||
if value, ok := vars["squadron"]; ok {
|
||||
replace(value)
|
||||
toSnakeCaseKeys(value)
|
||||
tv.add("Squadron", value)
|
||||
}
|
||||
|
||||
logrus.Debug("executing file template")
|
||||
out, err = executeFileTemplate(ctx, sq.config, tv, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to execute second file template")
|
||||
}
|
||||
logrus.Debug("unmarshalling vars")
|
||||
if err := yaml.Unmarshal(out, &sq.c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -101,14 +101,14 @@ func base64(v string) string {
|
||||
return b64.StdEncoding.EncodeToString([]byte(v))
|
||||
}
|
||||
|
||||
func replace(in interface{}) {
|
||||
func toSnakeCaseKeys(in interface{}) {
|
||||
if value, ok := in.(map[string]interface{}); ok {
|
||||
for k, v := range value {
|
||||
if strings.Contains(k, "-") {
|
||||
value[strings.ReplaceAll(k, "-", "_")] = v
|
||||
delete(value, k)
|
||||
}
|
||||
replace(v)
|
||||
toSnakeCaseKeys(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ func indent(spaces int, v string) string {
|
||||
}
|
||||
|
||||
func quote(v string) string {
|
||||
return "\"" + v + "\""
|
||||
return "'" + v + "'"
|
||||
}
|
||||
|
||||
func render(name, text string, data interface{}, errorOnMissing bool) (string, error) {
|
||||
|
||||
8
unit.go
8
unit.go
@ -17,13 +17,13 @@ type Unit struct {
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// Build ...
|
||||
func (u *Unit) Build(ctx context.Context, squadron, unit string) (string, error) {
|
||||
func (u *Unit) Build(ctx context.Context, squadron, unit string, args []string) (string, error) {
|
||||
var i int
|
||||
for _, build := range u.Builds {
|
||||
i++
|
||||
pterm.Info.Printfln("[%d/%d] Building %s/%s", i, len(u.Builds), squadron, unit)
|
||||
pterm.FgGray.Printfln("└ %s:%s", build.Image, build.Tag)
|
||||
if out, err := build.Build(ctx); err != nil {
|
||||
if out, err := build.Build(ctx, args); err != nil {
|
||||
pterm.Error.Printfln("[%d/%d] Failed to build squadron unit %s/%s", i, len(u.Builds), squadron, unit)
|
||||
pterm.FgGray.Printfln("└ %s:%s", build.Image, build.Tag)
|
||||
return out, err
|
||||
@ -33,13 +33,13 @@ func (u *Unit) Build(ctx context.Context, squadron, unit string) (string, error)
|
||||
}
|
||||
|
||||
// Push ...
|
||||
func (u *Unit) Push(ctx context.Context, squadron, unit string) (string, error) {
|
||||
func (u *Unit) Push(ctx context.Context, squadron, unit string, args []string) (string, error) {
|
||||
var i int
|
||||
for _, build := range u.Builds {
|
||||
i++
|
||||
pterm.Info.Printfln("[%d/%d] Pushing %s/%s", i, len(u.Builds), squadron, unit)
|
||||
pterm.FgGray.Printfln("└ %s:%s", build.Image, build.Tag)
|
||||
if out, err := build.Push(ctx); err != nil {
|
||||
if out, err := build.Push(ctx, args); err != nil {
|
||||
pterm.Error.Printfln("[%d/%d] Failed to push %s/%s", i, len(u.Builds), squadron, unit)
|
||||
pterm.FgGray.Printfln("└ %s:%s", build.Image, build.Tag)
|
||||
return out, err
|
||||
|
||||
@ -61,6 +61,14 @@ func (c *Cmd) Arg(name, v string) *Cmd {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Cmd) BoolArg(name string, v bool) *Cmd {
|
||||
if name == "" || !v {
|
||||
return c
|
||||
}
|
||||
c.command = append(c.command, name)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Cmd) ListArg(name string, vs []string) *Cmd {
|
||||
if name == "" {
|
||||
return c
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type DockerCmd struct {
|
||||
@ -16,14 +14,9 @@ func NewDockerCommand() *DockerCmd {
|
||||
}
|
||||
|
||||
func (c *DockerCmd) Build(workDir string) *Cmd {
|
||||
args := []string{"build"}
|
||||
if platform := os.Getenv("SQUADRON_DOCKER_BUILDX"); platform != "" {
|
||||
args = []string{"buildx", "build", "--platform", platform}
|
||||
}
|
||||
args = append(args, ".")
|
||||
return c.Cwd(workDir).Args(args...)
|
||||
return c.Cwd(workDir).Args("buildx", "build", ".")
|
||||
}
|
||||
|
||||
func (c *DockerCmd) Push(ctx context.Context, image, tag string) (string, error) {
|
||||
return c.Args("push", fmt.Sprintf("%s:%s", image, tag)).Run(ctx)
|
||||
func (c *DockerCmd) Push(image, tag string) *Cmd {
|
||||
return c.Args("push", fmt.Sprintf("%s:%s", image, tag))
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user