From cc1e25da74387a59a38acf80446d378ca2a21f3a Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Wed, 8 May 2019 17:45:02 +0000 Subject: [PATCH 1/8] paired with @elbandito on multibuildpack support --- Makefile | 2 ++ bin/build | 6 ++++++ cmd/exports/main.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 cmd/exports/main.go diff --git a/Makefile b/Makefile index 2630ad9..d54dced 100644 --- a/Makefile +++ b/Makefile @@ -14,12 +14,14 @@ VERSION := "v0.0.4" build: @GOOS=linux go build -o "bin/release" ./cmd/release/... + @GOOS=linux go build -o "bin/exports" ./cmd/exports/... test: go test ./... -v clean: -rm -f cnb-shim-$(VERSION).tgz + -rm -f bin/exports -rm -f bin/release package: clean build diff --git a/bin/build b/bin/build index 3821115..6ea8972 100755 --- a/bin/build +++ b/bin/build @@ -23,5 +23,11 @@ mkdir -p "${profile_dir}/profile.d" cp .profile.d/* "${profile_dir}/profile.d/" echo "launch = true" > ${layers_dir}/profile.toml +if [ -f "{$target_dir}/exports" ]; then + echo "build = true" >> ${layers_dir}/profile.toml + mkdir -p "${profile_dir}/profile.d/env.build/" + "${bp_dir}/bin/exports" "${target_dir}/exports" "${platform_dir}" +fi + # run bin/release, read Procfile, and generate launch.toml "${bp_dir}/bin/release" "${target_dir}" "${layers_dir}" "${platform_dir}" diff --git a/cmd/exports/main.go b/cmd/exports/main.go new file mode 100644 index 0000000..5a4baf2 --- /dev/null +++ b/cmd/exports/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + + "github.com/buildpack/libbuildpack/logger" +) + +func main() { + if len(os.Args) != 2 { + fmt.Println("Usage:", os.Args[0], "EXPORTS_PATH", "PLATFORM_DIR") + return + } + + log, err := logger.DefaultLogger(os.Args[3]) + if err != nil { + log.Info(err.Error()) + os.Exit(1) + } + + exportsPath := os.Args[1] + + data, err := ioutil.ReadFile(exportsPath) + if err != nil { + log.Info(err.Error()) + os.Exit(2) + } + + contents := string(data) + lines := strings.SplitN(contents, "\n", 2) + + for _, line := range lines { + components := strings.Split(line, "=") + ioutil.WriteFile(components[0], []byte(components[1]), 0644) + } +} From 6a082862467cdde3dc6c3651bf0c64a4a842034b Mon Sep 17 00:00:00 2001 From: Travis Date: Wed, 8 May 2019 15:34:34 -0600 Subject: [PATCH 2/8] WIP --- Makefile | 2 +- bin/build | 14 ++++++++++++-- cmd/exports/main.go | 23 ++++++++++++++++++----- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index d54dced..e571e8f 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ SHELL=/bin/bash -o pipefail GO111MODULE := on -VERSION := "v0.0.4" +VERSION := "v0.0.5" build: @GOOS=linux go build -o "bin/release" ./cmd/release/... diff --git a/bin/build b/bin/build index 6ea8972..cd1e1b6 100755 --- a/bin/build +++ b/bin/build @@ -23,10 +23,20 @@ mkdir -p "${profile_dir}/profile.d" cp .profile.d/* "${profile_dir}/profile.d/" echo "launch = true" > ${layers_dir}/profile.toml -if [ -f "{$target_dir}/exports" ]; then +if [ -f "${target_dir}/export" ]; then echo "build = true" >> ${layers_dir}/profile.toml mkdir -p "${profile_dir}/profile.d/env.build/" - "${bp_dir}/bin/exports" "${target_dir}/exports" "${platform_dir}" + "${bp_dir}/bin/exports" "${target_dir}/export" "${platform_dir}" + ls -al "${profile_dir}/profile.d/env.build/" + cat "${profile_dir}/profile.d/env.build/PATH" +# else +# echo "bp_dir:" +# find ${bp_dir} -name export +# echo "target_dir:" +# find ${target_dir} -name export +# echo "pwd:" +# find $(pwd) -name export +# exit 1 fi # run bin/release, read Procfile, and generate launch.toml diff --git a/cmd/exports/main.go b/cmd/exports/main.go index 5a4baf2..93b830c 100644 --- a/cmd/exports/main.go +++ b/cmd/exports/main.go @@ -4,25 +4,27 @@ import ( "fmt" "io/ioutil" "os" + "path/filepath" "strings" "github.com/buildpack/libbuildpack/logger" ) func main() { - if len(os.Args) != 2 { + if len(os.Args) != 3 { fmt.Println("Usage:", os.Args[0], "EXPORTS_PATH", "PLATFORM_DIR") return } - log, err := logger.DefaultLogger(os.Args[3]) + exportsPath := os.Args[1] + platformDir := os.Args[2] + + log, err := logger.DefaultLogger(platformDir) if err != nil { log.Info(err.Error()) os.Exit(1) } - exportsPath := os.Args[1] - data, err := ioutil.ReadFile(exportsPath) if err != nil { log.Info(err.Error()) @@ -33,7 +35,18 @@ func main() { lines := strings.SplitN(contents, "\n", 2) for _, line := range lines { + fmt.Println(line) components := strings.Split(line, "=") - ioutil.WriteFile(components[0], []byte(components[1]), 0644) + export := strings.Split(components[0], " ") + if strings.TrimSpace(export[0]) == "export" { + fmt.Println("Export 1:") + fmt.Println(export[1]) + file := filepath.Join(platformDir, strings.TrimSpace(export[1])) + err := ioutil.WriteFile(file, []byte(components[1]), 0644) + if err != nil { + log.Info(err.Error()) + os.Exit(3) + } + } } } From 5ab805cab2bd5237f7a6b6a5637f2a24b5316a0f Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Wed, 8 May 2019 17:55:05 -0500 Subject: [PATCH 3/8] moved exports stuff into top level and added tests --- .gitignore | 1 + bin/build | 12 +--------- cmd/exports/main.go | 28 ++++++---------------- cmd/release/main.go | 2 +- exports.go | 36 ++++++++++++++++++++++++++++ exports_test.go | 57 +++++++++++++++++++++++++++++++++++++++++++++ go.sum | 2 ++ releaser.go | 2 +- releaser_test.go | 9 +++---- 9 files changed, 111 insertions(+), 38 deletions(-) create mode 100644 exports.go create mode 100644 exports_test.go diff --git a/.gitignore b/.gitignore index 9aeef84..b815701 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ target *.iml .DS_Store bin/release +bin/exports cnb-shim-*.tgz \ No newline at end of file diff --git a/bin/build b/bin/build index cd1e1b6..8d90fa0 100755 --- a/bin/build +++ b/bin/build @@ -26,17 +26,7 @@ echo "launch = true" > ${layers_dir}/profile.toml if [ -f "${target_dir}/export" ]; then echo "build = true" >> ${layers_dir}/profile.toml mkdir -p "${profile_dir}/profile.d/env.build/" - "${bp_dir}/bin/exports" "${target_dir}/export" "${platform_dir}" - ls -al "${profile_dir}/profile.d/env.build/" - cat "${profile_dir}/profile.d/env.build/PATH" -# else -# echo "bp_dir:" -# find ${bp_dir} -name export -# echo "target_dir:" -# find ${target_dir} -name export -# echo "pwd:" -# find $(pwd) -name export -# exit 1 + "${bp_dir}/bin/exports" "${target_dir}/export" "${platform_dir}" "${profile_dir}/profile.d/env.build/" fi # run bin/release, read Procfile, and generate launch.toml diff --git a/cmd/exports/main.go b/cmd/exports/main.go index 93b830c..1257938 100644 --- a/cmd/exports/main.go +++ b/cmd/exports/main.go @@ -4,20 +4,20 @@ import ( "fmt" "io/ioutil" "os" - "path/filepath" - "strings" "github.com/buildpack/libbuildpack/logger" + "github.com/heroku/cnb-shim" ) func main() { - if len(os.Args) != 3 { - fmt.Println("Usage:", os.Args[0], "EXPORTS_PATH", "PLATFORM_DIR") + if len(os.Args) != 4 { + fmt.Println("Usage:", os.Args[0], "EXPORTS_PATH", "PLATFORM_DIR", "ENV_DIR") return } exportsPath := os.Args[1] platformDir := os.Args[2] + envDir := os.Args[3] log, err := logger.DefaultLogger(platformDir) if err != nil { @@ -31,22 +31,8 @@ func main() { os.Exit(2) } - contents := string(data) - lines := strings.SplitN(contents, "\n", 2) - - for _, line := range lines { - fmt.Println(line) - components := strings.Split(line, "=") - export := strings.Split(components[0], " ") - if strings.TrimSpace(export[0]) == "export" { - fmt.Println("Export 1:") - fmt.Println(export[1]) - file := filepath.Join(platformDir, strings.TrimSpace(export[1])) - err := ioutil.WriteFile(file, []byte(components[1]), 0644) - if err != nil { - log.Info(err.Error()) - os.Exit(3) - } - } + if err := cnbshim.DumpExportsFile(string(data), envDir); err != nil { + log.Info(err.Error()) + os.Exit(3) } } diff --git a/cmd/release/main.go b/cmd/release/main.go index 9693afe..2b86016 100644 --- a/cmd/release/main.go +++ b/cmd/release/main.go @@ -30,7 +30,7 @@ func main() { os.Exit(2) } - err = releaser.WriteLaunchMetadata(appDir, layersDir, targetDir, log) + err = cnbshim.WriteLaunchMetadata(appDir, layersDir, targetDir, log) if err != nil { log.Info(err.Error()) os.Exit(3) diff --git a/exports.go b/exports.go new file mode 100644 index 0000000..26ddc6d --- /dev/null +++ b/exports.go @@ -0,0 +1,36 @@ +package cnbshim + +import ( + "io/ioutil" + "path/filepath" + "strings" +) + +func DumpExportsFile(exportsData, envDir string) error { + lines := strings.SplitN(exportsData, "\n", 2) + + for _, line := range lines { + if found, key, value := ParseExportsFileLine(line); found { + err := WriteEnvFile(envDir, key, value) + if err != nil { + return err + } + } + } + return nil +} + +func ParseExportsFileLine(line string) (bool, string, string) { + components := strings.Split(line, "=") + export := strings.Split(components[0], " ") + if strings.TrimSpace(export[0]) == "export" { + return true, strings.TrimSpace(export[1]), components[1] + } else { + return false, "", "" + } + +} + +func WriteEnvFile(envDir, filename, value string) error { + return ioutil.WriteFile(filepath.Join(envDir, filename), []byte(value), 0644) +} \ No newline at end of file diff --git a/exports_test.go b/exports_test.go new file mode 100644 index 0000000..8c40000 --- /dev/null +++ b/exports_test.go @@ -0,0 +1,57 @@ +package cnbshim_test + +import ( + "io/ioutil" + "path/filepath" + "strings" + "testing" + + "github.com/heroku/cnb-shim" +) + +func TestWriteEnvFile(t *testing.T) { + envDir, err := ioutil.TempDir("", "env") + if err != nil { + t.Error(err.Error()) + } + + expectedFilename := "FOO" + expected := "bar" + err = cnbshim.WriteEnvFile(envDir, expectedFilename, expected) + if err != nil { + t.Error(err.Error()) + } + + expectedFile := filepath.Join(envDir, expectedFilename) + actual, err := ioutil.ReadFile(expectedFile) + if err != nil { + t.Error(err.Error()) + } + + if string(actual) != expected { + t.Errorf("Expected %s; got %s", expected, actual) + } +} + +func TestDumpExportsFile(t *testing.T) { + envDir, err := ioutil.TempDir("", "env") + + exports := ` +export FOO=bar +` + err = cnbshim.DumpExportsFile(exports, envDir) + if err != nil { + t.Error(err.Error()) + } + + expectedFile := filepath.Join(envDir, "FOO") + expected := "bar" + actual, err := ioutil.ReadFile(expectedFile) + if err != nil { + t.Error(err.Error()) + } + + if strings.TrimSpace(string(actual)) != expected { + t.Errorf("Expected %s; got %s", expected, actual) + } +} \ No newline at end of file diff --git a/go.sum b/go.sum index 1ffc7a1..8adbd99 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/buildpack/libbuildpack v1.11.0/go.mod h1:tKGgGnBYfOL23Ma4JWM8ucBcGX6I github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/heroku/cnb-shim v0.0.4 h1:BCPe2mIoqnN1k7L71sBMz0FfxvelG8TDqms1+qieuuE= +github.com/heroku/cnb-shim v0.0.4/go.mod h1:Mdp7qcTZ2xLuNaKFnxVeqbIZRp4yCtwEeBskvgYuQ0g= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/releaser.go b/releaser.go index dd69bf9..7e2fa7d 100644 --- a/releaser.go +++ b/releaser.go @@ -1,4 +1,4 @@ -package releaser +package cnbshim import ( "io/ioutil" diff --git a/releaser_test.go b/releaser_test.go index 977023a..658ace8 100644 --- a/releaser_test.go +++ b/releaser_test.go @@ -1,15 +1,16 @@ -package releaser_test +package cnbshim_test + import ( - "github.com/BurntSushi/toml" - "github.com/buildpack/libbuildpack/layers" "io/ioutil" "os" "path/filepath" "testing" "github.com/buildpack/libbuildpack/logger" - "github.com/heroku/cnb-shim" + "github.com/BurntSushi/toml" + "github.com/buildpack/libbuildpack/layers" + releaser "github.com/heroku/cnb-shim" ) func TestReadProcfileWithWebAndWorker(t *testing.T) { From 6d63184afb7be255e5ecd510e62542f81a604ffe Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Wed, 8 May 2019 20:17:12 -0500 Subject: [PATCH 4/8] Remove profile.d dir prefix from exporting envs --- bin/build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/build b/bin/build index 8d90fa0..50674ec 100755 --- a/bin/build +++ b/bin/build @@ -24,9 +24,9 @@ cp .profile.d/* "${profile_dir}/profile.d/" echo "launch = true" > ${layers_dir}/profile.toml if [ -f "${target_dir}/export" ]; then - echo "build = true" >> ${layers_dir}/profile.toml - mkdir -p "${profile_dir}/profile.d/env.build/" - "${bp_dir}/bin/exports" "${target_dir}/export" "${platform_dir}" "${profile_dir}/profile.d/env.build/" + echo "build = true" >> ${layers_dir}/profile.toml + mkdir -p "${profile_dir}/env.build/" + "${bp_dir}/bin/exports" "${target_dir}/export" "${platform_dir}" "${profile_dir}/env.build/" fi # run bin/release, read Procfile, and generate launch.toml From 97e95ecf8eff483b5b1d624581e5f2315a9261d1 Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Wed, 8 May 2019 20:19:55 -0500 Subject: [PATCH 5/8] Clean up bash and vars in bin/build --- bin/build | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/build b/bin/build index 50674ec..c063b70 100755 --- a/bin/build +++ b/bin/build @@ -21,10 +21,10 @@ echo "cache = true" > ${layers_dir}/shim.toml profile_dir="${layers_dir}/profile" mkdir -p "${profile_dir}/profile.d" cp .profile.d/* "${profile_dir}/profile.d/" -echo "launch = true" > ${layers_dir}/profile.toml +echo "launch = true" > "${profile_dir}.toml" -if [ -f "${target_dir}/export" ]; then - echo "build = true" >> ${layers_dir}/profile.toml +if [[ -f "${target_dir}/export" ]]; then + echo "build = true" >> "${profile_dir}.toml" mkdir -p "${profile_dir}/env.build/" "${bp_dir}/bin/exports" "${target_dir}/export" "${platform_dir}" "${profile_dir}/env.build/" fi From 67411ae65916b4569b55ff3775be6a4c37ba5c3f Mon Sep 17 00:00:00 2001 From: Travis Date: Wed, 8 May 2019 23:11:07 -0600 Subject: [PATCH 6/8] remove surrounding quotes from env var --- exports.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exports.go b/exports.go index 26ddc6d..ea32407 100644 --- a/exports.go +++ b/exports.go @@ -11,7 +11,7 @@ func DumpExportsFile(exportsData, envDir string) error { for _, line := range lines { if found, key, value := ParseExportsFileLine(line); found { - err := WriteEnvFile(envDir, key, value) + err := WriteEnvFile(envDir, key, value[1 : len(value)-1]) if err != nil { return err } From 8202cfffc3bd79256c94297fe9f3618bd004353b Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Thu, 9 May 2019 07:24:17 -0500 Subject: [PATCH 7/8] Only trim quotes from exported env var if there are quotes --- exports.go | 8 ++++++-- exports_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/exports.go b/exports.go index ea32407..9e5cf80 100644 --- a/exports.go +++ b/exports.go @@ -11,7 +11,7 @@ func DumpExportsFile(exportsData, envDir string) error { for _, line := range lines { if found, key, value := ParseExportsFileLine(line); found { - err := WriteEnvFile(envDir, key, value[1 : len(value)-1]) + err := WriteEnvFile(envDir, key, value) if err != nil { return err } @@ -24,7 +24,11 @@ func ParseExportsFileLine(line string) (bool, string, string) { components := strings.Split(line, "=") export := strings.Split(components[0], " ") if strings.TrimSpace(export[0]) == "export" { - return true, strings.TrimSpace(export[1]), components[1] + val := strings.TrimSpace(components[1]) + if string(val[0]) == "\"" && string(val[len(val)-1]) == "\"" { + val = val[1: len(val)-1] + } + return true, strings.TrimSpace(export[1]), val } else { return false, "", "" } diff --git a/exports_test.go b/exports_test.go index 8c40000..cfb1baa 100644 --- a/exports_test.go +++ b/exports_test.go @@ -51,6 +51,52 @@ export FOO=bar t.Error(err.Error()) } + if strings.TrimSpace(string(actual)) != expected { + t.Errorf("Expected %s; got %s", expected, actual) + } +} + +func TestDumpExportsFileWithQuotes(t *testing.T) { + envDir, err := ioutil.TempDir("", "env") + + exports := ` +export FOO="bar" +` + err = cnbshim.DumpExportsFile(exports, envDir) + if err != nil { + t.Error(err.Error()) + } + + expectedFile := filepath.Join(envDir, "FOO") + expected := "bar" + actual, err := ioutil.ReadFile(expectedFile) + if err != nil { + t.Error(err.Error()) + } + + if strings.TrimSpace(string(actual)) != expected { + t.Errorf("Expected %s; got %s", expected, actual) + } +} + +func TestDumpExportsFileWithEscapedQuotes(t *testing.T) { + envDir, err := ioutil.TempDir("", "env") + + exports := ` +export FOO="b\"a\"r" +` + err = cnbshim.DumpExportsFile(exports, envDir) + if err != nil { + t.Error(err.Error()) + } + + expectedFile := filepath.Join(envDir, "FOO") + expected := "b\\\"a\\\"r" + actual, err := ioutil.ReadFile(expectedFile) + if err != nil { + t.Error(err.Error()) + } + if strings.TrimSpace(string(actual)) != expected { t.Errorf("Expected %s; got %s", expected, actual) } From 50f401d4a8d2c2888ab7f880627f1240c8c50bfd Mon Sep 17 00:00:00 2001 From: Joe Kutner Date: Thu, 9 May 2019 07:25:15 -0500 Subject: [PATCH 8/8] Added comments --- exports.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exports.go b/exports.go index 9e5cf80..8362769 100644 --- a/exports.go +++ b/exports.go @@ -25,6 +25,8 @@ func ParseExportsFileLine(line string) (bool, string, string) { export := strings.Split(components[0], " ") if strings.TrimSpace(export[0]) == "export" { val := strings.TrimSpace(components[1]) + + // Ideally we'd eval, but we don't want to eval things like $PATH embedded in the val if string(val[0]) == "\"" && string(val[len(val)-1]) == "\"" { val = val[1: len(val)-1] }