Skip to content

Commit

Permalink
feat: add squashing support
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomasz Gągor authored and Tomasz Gągor committed Dec 17, 2024
1 parent d4cfce9 commit ed73884
Show file tree
Hide file tree
Showing 15 changed files with 306 additions and 26 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ __pycache__
.venv
*.pyc
*.Dockerfile
*.tar
.poetry-version
*.bak
*.old
Expand Down
1 change: 1 addition & 0 deletions cmd/td/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func init() {
cmd.Flags().BoolVarP(&flags.Build, "build", "b", false, "Build Docker images after templating")
cmd.Flags().BoolVarP(&flags.Push, "push", "p", false, "Push Docker images after building")
cmd.Flags().BoolVarP(&flags.Delete, "delete", "d", false, "Delete templated Dockerfiles after successful building")
cmd.Flags().BoolVarP(&flags.Squash, "squash", "s", false, "Squash images to reduce size (experimental)")
// cmd.Flags().BoolVarP(&flags.DryRun, "dry-run", "d", false, "Print actions but don't execute them")
cmd.Flags().IntVar(&flags.Threads, "parallel", runtime.NumCPU(), "Specify the number of threads to use, defaults to number of CPUs")
cmd.Flags().StringVarP(&flags.Tag, "tag", "t", "", "Tag to use as the image version")
Expand Down
1 change: 0 additions & 1 deletion example/complex.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ labels:
Let try templates here.
Image test-case-2d on Alpine Linux {{ .alpine }}
org.opencontainers.image.test-case-2.name: alpine:{{ .alpine }}
images:
base:
Expand Down
62 changes: 57 additions & 5 deletions pkg/cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"bytes"
"context"
"os"
"os/exec"
Expand All @@ -15,6 +16,7 @@ type Cmd struct {
verbose bool
preText string
postText string
output string
}

func New(c string) Cmd {
Expand Down Expand Up @@ -50,31 +52,81 @@ func (c Cmd) PostInfo(msg string) Cmd {
return c
}

func (c Cmd) Run(ctx context.Context) error {
func (c Cmd) Run(ctx context.Context) (string, error) {
if c.preText != "" {
log.Info().Msg(c.preText)
}

cmd := exec.CommandContext(ctx, c.cmd, c.args...)

// pipe the commands output to the applications
var b bytes.Buffer
if c.verbose {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
} else {
cmd.Stdout = &b
cmd.Stderr = &b
}

log.Debug().Str("cmd", c.cmd).Interface("args", c.args).Msg("Running")
if err := cmd.Run(); err != nil {
log.Error().Err(err).Msg("Could not run command")
return err
err := cmd.Run()

// Check for context cancellation or timeout
if ctx.Err() != nil {
// If the context was canceled, suppress output and return context error
if ctx.Err() == context.Canceled {
log.Warn().Str("cmd", c.cmd).Msg("Command was cancelled")
} else if ctx.Err() == context.DeadlineExceeded {
log.Warn().Str("cmd", c.cmd).Msg("Command timed out")
}
return "", ctx.Err()
}

// Handle other errors
if err != nil {
log.Error().Err(err).Str("cmd", c.cmd).Interface("args", c.args).Msg("Could not run command")
// c.setOutput(&b)
c.output = b.String()
log.Error().Msg(c.output)
return c.output, err
}
c.output = b.String()

if c.postText != "" {
log.Info().Msg(c.postText)
}
return nil
return c.output, nil
}

func (c Cmd) String() string {
return c.cmd + " " + strings.Join(c.args, " ")
}

func (c Cmd) Output() (string, error) {
cmd := exec.Command(c.cmd, c.args...)

// pipe the commands output to the applications
var b bytes.Buffer
if c.verbose {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
} else {
cmd.Stdout = &b
cmd.Stderr = &b
}

log.Debug().Str("cmd", c.cmd).Interface("args", c.args).Msg("Running")
err := cmd.Run()

// Handle other errors
if err != nil {
log.Error().Err(err).Str("cmd", c.cmd).Interface("args", c.args).Msg("Could not run command")
c.output = b.String()
log.Error().Msg(c.output)
return c.output, err
}
c.output = b.String()

return c.output, nil
}
9 changes: 5 additions & 4 deletions pkg/config/flags.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package config

type Flags struct {
Build bool
BuildFile string
Delete bool
DryRun bool
Build bool
PrintVersion bool
Push bool
Delete bool
Threads int
Squash bool
Tag string
Threads int
Verbose bool
PrintVersion bool
}
31 changes: 31 additions & 0 deletions pkg/parser/byte-count.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package parser

import "fmt"

func ByteCountSI(b uint64) string {
const unit = 1000
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB",
float64(b)/float64(div), "kMGTPE"[exp])
}

func ByteCountIEC(b uint64) string {
const unit = 1024
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %ciB",
float64(b)/float64(div), "KMGTPE"[exp])
}
44 changes: 44 additions & 0 deletions pkg/parser/docker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package parser

import (
"encoding/json"
"os"

"github.com/rs/zerolog/log"
"github.com/tgagor/template-dockerfiles/pkg/cmd"
"github.com/tgagor/template-dockerfiles/pkg/util"
)

type DockerInspect []struct {
Config struct {
Env []string `json:"Env"`
Cmd []string `json:"Cmd"`
Volumes map[string]struct{} `json:"Volumes"`
WorkingDir string `json:"WorkingDir"`
Entrypoint []string `json:"Entrypoint"`
Labels map[string]string `json:"Labels"`
} `json:"Config"`
Size uint64
}

func inspectImg(image string) (DockerInspect, error) {
out, err := cmd.New("docker").Arg("inspect").Arg("--format").Arg("json").Arg(image).Output()
util.FailOnError(err)

// Create a variable to hold the unmarshaled data
var inspect DockerInspect

// Unmarshal the JSON data into the DockerInspect structure

if err := json.Unmarshal([]byte(out), &inspect); err != nil {
log.Error().Err(err).Msg("Error parsing JSON.")
os.Exit(1)
}

return inspect, nil
}

// func imgSize(image string) string {
// out, err := cmd.New("docker").Arg("inspect").Arg("--format").Arg("json").Arg(image).Output()
// util.FailOnError(err)
// }
Loading

0 comments on commit ed73884

Please sign in to comment.