Skip to content

Commit

Permalink
Add arg to not execute docker build instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Duchesne committed May 3, 2019
1 parent a64bade commit 88b6955
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 11 deletions.
3 changes: 3 additions & 0 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type TGFApplication struct {
LoggingLevel string
MountPoint string
NoAWS bool
NoDockerBuild bool
NoHome bool
NoTemp bool
PruneImages bool
Expand All @@ -99,6 +100,7 @@ func (app *TGFApplication) parse() *TGFApplication {
app.Switch("get-image-name", "Just return the resulting image name (alias --gi)").BoolVar(&app.GetImageName)
app.Switch("interactive", "On by default, use --no-interactive or --no-it to disable launching Docker in interactive mode or set "+envInteractive+" to 0 or false").Envar(envInteractive).BoolVar(&app.DockerInteractive)
app.Switch("local-image", "If set, TGF will not pull the image when refreshing (alias --li)").BoolVar(&app.UseLocalImage)
app.Switch("no-docker-build", "Disable docker build instructions configured in the config files (alias --nb)").BoolVar(&app.NoDockerBuild)
app.Switch("no-home", "Disable the mapping of the home directory (alias --nh) or set "+envNoHome).Envar(envNoHome).BoolVar(&app.NoHome)
app.Switch("no-temp", "Disable the mapping of the temp directory (alias --nt) or set "+envNoTemp).Envar(envNoTemp).BoolVar(&app.NoTemp)
app.Switch("no-aws", "Disable use of AWS to get configuration (alias --na) or set "+envNoAWS).Envar(envNoAWS).BoolVar(&app.NoAWS)
Expand Down Expand Up @@ -126,6 +128,7 @@ func (app *TGFApplication) parse() *TGFApplication {
app.Switch("it", "alias for interactive").Hidden().BoolVar(&app.DockerInteractive)
app.Switch("li", "alias for local-image").Hidden().BoolVar(&app.UseLocalImage)
app.Switch("na", "alias for no-aws").Hidden().BoolVar(&app.NoAWS)
app.Switch("nb", "alias for no-docker-build").Hidden().BoolVar(&app.NoDockerBuild)
app.Switch("nh", "alias for no-home").Hidden().BoolVar(&app.NoHome)
app.Switch("nt", "alias for no-temp").Hidden().BoolVar(&app.NoTemp)
app.Switch("ri", "alias for refresh-image)").Hidden().BoolVar(&app.Refresh)
Expand Down
30 changes: 19 additions & 11 deletions docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func callDocker(config *TGFConfig, args ...string) int {
command = append(command, "--terragrunt-source-update")
}

imageName := getImage(config)
imageName := getImage(config, app.NoDockerBuild, app.Refresh, app.UseLocalImage)

if app.GetImageName {
Println(imageName)
Expand Down Expand Up @@ -206,12 +206,16 @@ func runCommands(commands []string) error {

// Returns the image name to use
// If docker-image-build option has been set, an image is dynamically built and the resulting image digest is returned
func getImage(config *TGFConfig) (name string) {
func getImage(config *TGFConfig, noDockerBuild bool, refresh bool, useLocalImage bool) (name string) {
name = config.GetImageName()
if !strings.Contains(name, ":") {
name += ":latest"
}

if noDockerBuild {
return
}

lastHash := ""
for i, ib := range config.imageBuildConfigs {
var temp, folder, dockerFile string
Expand Down Expand Up @@ -258,10 +262,10 @@ func getImage(config *TGFConfig) (name string) {
if image, tag := Split2(name, ":"); len(tag) > maxDockerTagLength {
name = image + ":" + tag[0:maxDockerTagLength]
}
if app.Refresh || getImageHash(name) != ib.hash() {
if refresh || getImageHash(name) != ib.hash() {
label := fmt.Sprintf("hash=%s", ib.hash())
args := []string{"build", ".", "-f", dockerfilePattern, "--quiet", "--force-rm", "--label", label}
if i == 0 && app.Refresh && !app.UseLocalImage {
if i == 0 && refresh && !useLocalImage {
args = append(args, "--pull")
}
if dockerFile != "" {
Expand All @@ -279,13 +283,21 @@ func getImage(config *TGFConfig) (name string) {
buildCmd.Stderr = os.Stderr
buildCmd.Dir = folder
must(buildCmd.Output())
prune(config)
pruneDangling(config)
}
}

return
}

var pruneDangling = func(config *TGFConfig) {
cli, ctx := getDockerClient()
danglingFilters := filters.NewArgs()
danglingFilters.Add("dangling", "true")
must(cli.ImagesPrune(ctx, danglingFilters))
must(cli.ContainersPrune(ctx, filters.Args{}))
}

func prune(config *TGFConfig, images ...string) {
cli, ctx := getDockerClient()
if len(images) > 0 {
Expand Down Expand Up @@ -318,11 +330,7 @@ func prune(config *TGFConfig, images ...string) {
}
}
}

danglingFilters := filters.NewArgs()
danglingFilters.Add("dangling", "true")
must(cli.ImagesPrune(ctx, danglingFilters))
must(cli.ContainersPrune(ctx, filters.Args{}))
pruneDangling(config)
}

func deleteImage(id string) {
Expand All @@ -343,7 +351,7 @@ func deleteImage(id string) {

// GetActualImageVersion returns the real image version stored in the environment variable TGF_IMAGE_VERSION
func GetActualImageVersion(config *TGFConfig) string {
return getActualImageVersionInternal(getImage(config))
return getActualImageVersionInternal(getImage(config, app.NoDockerBuild, app.Refresh, app.UseLocalImage))
}

func getDockerClient() (*client.Client, context.Context) {
Expand Down
96 changes: 96 additions & 0 deletions docker_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"os/exec"
"strconv"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetImage(t *testing.T) {
t.Parallel()

pruneDangling = func(*TGFConfig) {}

testImageName := "test-image" + strconv.Itoa(randInt())
testTag := "test" + strconv.Itoa(randInt())

// build test image
c1 := exec.Command("echo", "-e", "FROM scratch\nLABEL name="+testTag)
c2 := exec.Command("docker", "build", "-", "-t", testImageName+":"+testTag)
c2.Stdin, _ = c1.StdoutPipe()
c2.Start()
c1.Run()
c2.Wait()

tests := []struct {
name string
config *TGFConfig
noDockerBuild bool
refresh bool
useLocalImage bool
result string
}{
{
name: "Without build configs and tag",
config: &TGFConfig{Image: testImageName},
noDockerBuild: false,
refresh: false,
useLocalImage: false,
result: testImageName + ":latest",
},
{
name: "Without build configs but with a tag",
config: &TGFConfig{
Image: testImageName,
ImageTag: &testTag,
},
noDockerBuild: false,
refresh: false,
useLocalImage: false,
result: testImageName + ":" + testTag,
},
{
name: "With build config",
config: &TGFConfig{
ImageTag: &testTag,
Image: testImageName,
imageBuildConfigs: []TGFConfigBuild{
TGFConfigBuild{
Instructions: "LABEL another=test",
Tag: "buildtag",
},
},
},
noDockerBuild: false,
refresh: false,
useLocalImage: true,
result: testImageName + ":" + testTag + "-" + "buildtag",
},
{
name: "With build config and no build flag",
config: &TGFConfig{
ImageTag: &testTag,
Image: testImageName,
imageBuildConfigs: []TGFConfigBuild{
TGFConfigBuild{
Instructions: "LABEL another=test",
Tag: "buildtag",
},
},
},
noDockerBuild: true,
refresh: false,
useLocalImage: true,
result: testImageName + ":" + testTag,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
app = NewTGFApplication()
assert.Equal(t, tt.result, getImage(tt.config, tt.noDockerBuild, tt.refresh, tt.useLocalImage), "The result image tag is not correct")
})
}
}

0 comments on commit 88b6955

Please sign in to comment.