Skip to content

Commit

Permalink
Fix breaking change with new Docker version (symbolic links no longer…
Browse files Browse the repository at this point in the history
… supported on mapping)

Add --no-temp option to allow disabling mapping of temporary folder.
Refactoring of the options management
Print environment variables on --debug
  • Loading branch information
jocgir committed Jan 10, 2018
1 parent 275bba0 commit 4b259f5
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 78 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.pkg
dist
vendor
tasks.json
51 changes: 24 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ or install it through command line:
On `OSX`:

```bash
curl -sL https://github.com/coveo/tgf/releases/download/v1.15.3/tgf_1.15.3_macOS_64-bits.zip | bsdtar -xf- -C /usr/local/bin && chmod +x /usr/local/bin/tgf
curl -sL https://github.com/coveo/tgf/releases/download/v1.15.4/tgf_1.15.4_macOS_64-bits.zip | bsdtar -xf- -C /usr/local/bin && chmod +x /usr/local/bin/tgf
```

On `Linux`:

```bash
curl -sL https://github.com/coveo/tgf/releases/download/v1.15.3/tgf_1.15.3_linux_64-bits.zip | gzip -d > /usr/local/bin/tgf && chmod +x /usr/local/bin/tgf
curl -sL https://github.com/coveo/tgf/releases/download/v1.15.4/tgf_1.15.4_linux_64-bits.zip | gzip -d > /usr/local/bin/tgf && chmod +x /usr/local/bin/tgf
```

On `Windows` with Powershell:

```powershell
Invoke-WebRequest https://github.com/coveo/tgf/releases/download/v1.15.3/tgf_1.15.3_windows_64-bits.zip -OutFile tgf.zip
Invoke-WebRequest https://github.com/coveo/tgf/releases/download/v1.15.4/tgf_1.15.4_windows_64-bits.zip -OutFile tgf.zip
```

## Configuration
Expand Down Expand Up @@ -105,61 +105,58 @@ Note: *The key names are not case sensitive*
> tgf
usage: tgf [<flags>]
DESCRIPTION:
TGF (terragrunt frontend) is a Docker frontend for terragrunt/terraform. It automatically maps your current
folder, your HOME folder, your TEMP folder as well of most environment variables to the docker process. You
can add -D to your command to get the exact docker command that is generated.
DESCRIPTION: TGF (terragrunt frontend) is a Docker frontend for terragrunt/terraform. It automatically maps your current folder, your HOME folder, your TEMP folder as well of most
environment variables to the docker process. You can add -D to your command to get the exact docker command that is generated.
It then looks in your current folder and all its parents to find a file named '.tgf.config' to retrieve the
default configuration. If not all configurable values are satisfied and you have an AWS configuration, it
will then try to retrieve the missing elements from the AWS Parameter Store under the key '/default/tgf'.
It then looks in your current folder and all its parents to find a file named '.tgf.config' to retrieve the default configuration. If not all configurable values are satisfied and you have an AWS configuration,
it will then try to retrieve the missing elements from the AWS Parameter Store under the key '/default/tgf'.
Configurable values are: docker-image, docker-image-version, docker-image-tag, docker-refresh, docker-options, recommended-image-version, required-image-version, logging-level, entry-point, tgf-recommended-version.
Configurable values are: docker-image, docker-image-version, docker-image-tag, docker-image-build, docker-refresh, docker-options, recommended-image-version, required-image-version, logging-level,
entry-point, tgf-recommended-version.
You can get the full documentation at https://github.com/coveo/tgf/blob/master/README.md and check for new
version at https://github.com/coveo/tgf/releases/latest.
You can get the full documentation at https://github.com/coveo/tgf/blob/master/README.md and check for new version at https://github.com/coveo/tgf/releases/latest.
Any docker image could be used, but TGF specialized images could be found at: https://hub.docker.com/r/coveo/tgf/tags.
Terragrunt documentation could be found at https://github.com/coveo/terragrunt/blob/master/README.md (Coveo fork) or https://github.com/gruntwork-io/terragrunt/blob/master/README.md (Gruntwork.io original)
Terragrunt documentation could be found at https://github.com/coveo/terragrunt/blob/master/README.md (Coveo fork) or https://github.com/gruntwork-io/terragrunt/blob/master/README.md
(Gruntwork.io original)
Terraform documentation could be found at https://www.terraform.io/docs/index.html.
IMPORTANT: Most of the tgf command line arguments are in uppercase to avoid potential conflict with the
underlying command. If any of the tgf arguments conflicts with an argument of the desired entry point, you
must place that argument after -- to ensure that they are not interpreted by tgf and are passed to the entry point.
Any non conflicting argument will be passed to the entry point wherever it is located on the invocation arguments.
IMPORTANT: Most of the tgf command line arguments are in uppercase to avoid potential conflict with the underlying command. If any of the tgf arguments conflicts with an argument of the desired entry point, you
must place that argument after -- to ensure that they are not interpreted by tgf and are passed to the entry point. Any non conflicting argument will be passed to the entry point wherever it is located on the
invocation arguments.
tgf ls -- -D # Avoid -D to be interpretated by tgf as --debug-docker
VERSION: 1.15.3
VERSION: 1.15.4
AUTHOR: Coveo
Flags:
-H, --tgf-help Show context-sensitive help (also try --help-man).
-D, --debug-docker Print the docker command issued
-F, --flush-cache Invoke terragrunt with --terragrunt-update-source to flush the cache
--refresh-image Force a refresh of the docker image (alias --ri)
--docker-arg=<opt> ... Supply extra argument to Docker (alias --da)
--get-image-name Just return the resulting image name (alias --gi)
--no-home Disable the mapping of the home directory (alias --nh)
--no-temp Disable the mapping of the temp directory (alias --nt)
-E, --entrypoint=terragrunt Override the entry point for docker
--image=coveo/tgf Use the specified image instead of the default one
--image-version=version Use a different version of docker image instead of the default one (alias --iv)
-T, --tag=latest Use a different tag of docker image instead of the default one
-P, --profile="" Set the AWS profile configuration to use
-D, --debug-docker Print the docker command issued
--refresh-image Force a refresh of the docker image (alias --ri)
-L, --logging-level=<level> Set the logging level (critical=0, error=1, warning=2, notice=3, info=4, debug=5, full=6)
-F, --flush-cache Invoke terragrunt with --terragrunt-update-source to flush the cache
--no-home Disable the mapping of the home directory (alias --nh)
--get-image-name Just return the resulting image name (alias --gi)
--docker-arg=<opt> ... Supply extra argument to Docker (alias --da)
--all-versions Get versions of TGF & all others underlying utilities (alias --av)
--current-version Get current version infomation (alias --cv)
```

Example:

```bash
> tgf --current-version
tgf v1.15.3
tgf v1.15.4
```

Returns the current version of the tgf tool
Expand Down
30 changes: 19 additions & 11 deletions docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,17 @@ func callDocker(args ...string) int {
homeWithoutVolume := strings.TrimPrefix(home, filepath.VolumeName(home))

cwd := filepath.ToSlash(Must(os.Getwd()).(string))
cwd = Must(filepath.EvalSymlinks(cwd)).(string)
currentDrive := fmt.Sprintf("%s/", filepath.VolumeName(cwd))
rootFolder := strings.Split(strings.TrimPrefix(cwd, currentDrive), "/")[0]

temp := filepath.ToSlash(filepath.Join(os.TempDir(), "tgf-cache"))
tempDrive := fmt.Sprintf("%s/", filepath.VolumeName(temp))
tempFolder := strings.TrimPrefix(temp, tempDrive)

dockerArgs := []string{
"run", "-it",
"-v", fmt.Sprintf("%s%s:/%[2]s", convertDrive(currentDrive), rootFolder),
"-v", fmt.Sprintf("%s%s:/var/tgf", convertDrive(tempDrive), tempFolder),
"-w", strings.TrimPrefix(cwd, filepath.VolumeName(cwd)),
"--rm",
}
if mapHome {
if !noHome {
dockerArgs = append(dockerArgs, []string{
"-v", fmt.Sprintf("%v:%v", convertDrive(home), homeWithoutVolume),
"-e", fmt.Sprintf("HOME=%v", homeWithoutVolume),
Expand All @@ -77,7 +73,14 @@ func callDocker(args ...string) int {
dockerArgs = append(dockerArgs, config.DockerOptions...)
}

os.Setenv("TERRAGRUNT_CACHE", "/var/tgf")
if !noTemp {
temp := filepath.ToSlash(filepath.Join(Must(filepath.EvalSymlinks(os.TempDir())).(string), "tgf-cache"))
tempDrive := fmt.Sprintf("%s/", filepath.VolumeName(temp))
tempFolder := strings.TrimPrefix(temp, tempDrive)
dockerArgs = append(dockerArgs, "-v", fmt.Sprintf("%s%s:/var/tgf", convertDrive(tempDrive), tempFolder))
os.Setenv("TERRAGRUNT_CACHE", "/var/tgf")
}

os.Setenv("TGF_COMMAND", config.EntryPoint)
os.Setenv("TGF_VERSION", version)
os.Setenv("TGF_IMAGE", config.Image)
Expand All @@ -97,7 +100,7 @@ func callDocker(args ...string) int {
for _, do := range dockerOptions {
dockerArgs = append(dockerArgs, strings.Split(do, " ")...)
}
dockerArgs = append(dockerArgs, getEnviron(mapHome)...)
dockerArgs = append(dockerArgs, getEnviron(!noHome)...)
dockerArgs = append(dockerArgs, imageName)
dockerArgs = append(dockerArgs, command...)
dockerCmd := exec.Command("docker", dockerArgs...)
Expand All @@ -106,7 +109,12 @@ func callDocker(args ...string) int {
dockerCmd.Stderr = &stderr

if debug {
printfDebug(os.Stderr, "%s\n\n", strings.Join(dockerCmd.Args, " "))
for _, s := range os.Environ() {
if strings.HasPrefix(s, "TGF_") || strings.HasPrefix(s, "TERRAGRUNT_") || strings.HasPrefix(s, "AWS_") {
printfDebug(os.Stderr, "export %s\n", s)
}
}
printfDebug(os.Stderr, "\n%s\n\n", strings.Join(dockerCmd.Args, " "))
}

if err := dockerCmd.Run(); err != nil {
Expand Down Expand Up @@ -172,7 +180,7 @@ func refreshImage(image string) {
fmt.Fprintln(os.Stderr)
}

func getEnviron(mapHome bool) (result []string) {
func getEnviron(noHome bool) (result []string) {
for _, env := range os.Environ() {
split := strings.Split(env, "=")
varName := strings.TrimSpace(split[0])
Expand All @@ -193,7 +201,7 @@ func getEnviron(mapHome bool) (result []string) {
"PROMPT", "SHELL", "SH", "ZSH", "HOME",
"LANG", "LC_CTYPE", "DISPLAY", "TERM":
case "LOGNAME", "USER":
if !mapHome {
if noHome {
continue
}
fallthrough
Expand Down
69 changes: 29 additions & 40 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ var (
debug bool
flushCache bool
getImageName bool
mapHome bool
noHome bool
noTemp bool
refresh bool
)

Expand Down Expand Up @@ -97,50 +98,38 @@ func main() {
app.HelpFlag.Bool()
kingpin.CommandLine = app.Application

app.Switch("debug-docker", "Print the docker command issued", 'D').BoolVar(&debug)
app.Switch("flush-cache", "Invoke terragrunt with --terragrunt-update-source to flush the cache", 'F').BoolVar(&flushCache)
app.Switch("refresh-image", "Force a refresh of the docker image (alias --ri)").BoolVar(&refresh)
app.Argument("docker-arg", "Supply extra argument to Docker (alias --da)").PlaceHolder("<opt>").StringsVar(&dockerOptions)
app.Switch("get-image-name", "Just return the resulting image name (alias --gi)").BoolVar(&getImageName)
app.Switch("no-home", "Disable the mapping of the home directory (alias --nh)").BoolVar(&noHome)
app.Switch("no-temp", "Disable the mapping of the temp directory (alias --nt)").BoolVar(&noTemp)

var (
defaultEntryPoint = app.Argument("entrypoint", "Override the entry point for docker", 'E').PlaceHolder("terragrunt").String()
image = app.Argument("image", "Use the specified image instead of the default one").PlaceHolder("coveo/tgf").String()
imageVersion = app.Argument("image-version", "Use a different version of docker image instead of the default one (alias --iv)").PlaceHolder("version").Default("-").String()
imageTag = app.Argument("tag", "Use a different tag of docker image instead of the default one", 'T').PlaceHolder("latest").Default("-").String()
awsProfile = app.Argument("profile", "Set the AWS profile configuration to use", 'P').Default("").String()
debug1 = app.Switch("debug-docker", "Print the docker command issued", 'D').Bool()
refresh1 = app.Switch("refresh-image", "Force a refresh of the docker image (alias --ri)").Bool()
loggingLevel = app.Argument("logging-level", "Set the logging level (critical=0, error=1, warning=2, notice=3, info=4, debug=5, full=6)", 'L').PlaceHolder("<level>").String()
flushCache1 = app.Switch("flush-cache", "Invoke terragrunt with --terragrunt-update-source to flush the cache", 'F').Bool()
noHome1 = app.Switch("no-home", "Disable the mapping of the home directory (alias --nh)").Bool()
getImageName1 = app.Switch("get-image-name", "Just return the resulting image name (alias --gi)").Bool()
dockerOptions1 = app.Argument("docker-arg", "Supply extra argument to Docker (alias --da)").PlaceHolder("<opt>").Strings()
getAllVersions1 = app.Switch("all-versions", "Get versions of TGF & all others underlying utilities (alias --av)").Bool()
getCurrentVersion1 = app.Switch("current-version", "Get current version infomation (alias --cv)").Bool()

// Shorten version of the tags
refresh2 = app.Switch("ri", "alias for refresh-image)").Hidden().Bool()
getImageName2 = app.Switch("gi", "alias for get-image-name").Hidden().Bool()
noHome2 = app.Switch("nh", "alias for no-home-mapping").Hidden().Bool()
getCurrentVersion2 = app.Switch("cv", "alias for current-version").Hidden().Bool()
getAllVersions2 = app.Switch("av", "alias for all-versions").Hidden().Bool()
dockerOptions2 = app.Argument("da", "alias for docker-arg").Hidden().Strings()
imageVersion2 = app.Argument("iv", "alias for image-version").Default("-").Hidden().String()
defaultEntryPoint = app.Argument("entrypoint", "Override the entry point for docker", 'E').PlaceHolder("terragrunt").String()
image = app.Argument("image", "Use the specified image instead of the default one").PlaceHolder("coveo/tgf").String()
imageVersion = app.Argument("image-version", "Use a different version of docker image instead of the default one (alias --iv)").PlaceHolder("version").Default("-").String()
imageTag = app.Argument("tag", "Use a different tag of docker image instead of the default one", 'T').PlaceHolder("latest").Default("-").String()
awsProfile = app.Argument("profile", "Set the AWS profile configuration to use", 'P').Default("").String()
loggingLevel = app.Argument("logging-level", "Set the logging level (critical=0, error=1, warning=2, notice=3, info=4, debug=5, full=6)", 'L').PlaceHolder("<level>").String()
getAllVersions = app.Switch("all-versions", "Get versions of TGF & all others underlying utilities (alias --av)").Bool()
getCurrentVersion = app.Switch("current-version", "Get current version infomation (alias --cv)").Bool()
)

app.Switch("ri", "alias for refresh-image)").Hidden().BoolVar(&refresh)
app.Switch("gi", "alias for get-image-name").Hidden().BoolVar(&getImageName)
app.Switch("nh", "alias for no-home").Hidden().BoolVar(&noHome)
app.Switch("nt", "alias for no-temp").Hidden().BoolVar(&noTemp)
app.Switch("cv", "alias for current-version").Hidden().BoolVar(getCurrentVersion)
app.Switch("av", "alias for all-versions").Hidden().BoolVar(getAllVersions)
app.Argument("da", "alias for docker-arg").Hidden().StringsVar(&dockerOptions)
app.Argument("iv", "alias for image-version").Default("-").Hidden().StringVar(imageVersion)

// Split up the managed parameters from the unmanaged ones
managed, unmanaged := app.SplitManaged()
Must(app.Parse(managed))

// We combine the tags that have multiple definitions
debug = *debug1
flushCache = *flushCache1
getImageName = *getImageName1 || *getImageName2
mapHome = !(*noHome1 || *noHome2)
refresh = *refresh1 || *refresh2
dockerOptions = append(*dockerOptions1, *dockerOptions2...)
getCurrentVersion := *getCurrentVersion1 || *getCurrentVersion2
getAllVersions := *getAllVersions1 || *getAllVersions2
dockerOptions = append(*dockerOptions1, *dockerOptions2...)
if *imageVersion2 != "-" {
imageVersion = imageVersion2
}

// If AWS profile is supplied, we freeze the current session
if *awsProfile != "" {
Must(aws_helper.InitAwsSession(*awsProfile))
Expand Down Expand Up @@ -180,12 +169,12 @@ func main() {
os.Exit(1)
}

if getCurrentVersion {
if *getCurrentVersion {
fmt.Printf("tgf v%s\n", version)
os.Exit(0)
}

if getAllVersions {
if *getAllVersions {
if config.EntryPoint != "terragrunt" {
fmt.Fprintln(os.Stderr, errorString("--all-version works only with terragrunt as the entrypoint"))
os.Exit(1)
Expand Down

0 comments on commit 4b259f5

Please sign in to comment.