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/Makefile b/Makefile index 2630ad9..e571e8f 100644 --- a/Makefile +++ b/Makefile @@ -10,16 +10,18 @@ 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/... + @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..c063b70 100755 --- a/bin/build +++ b/bin/build @@ -21,7 +21,13 @@ 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" >> "${profile_dir}.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 "${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..1257938 --- /dev/null +++ b/cmd/exports/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + + "github.com/buildpack/libbuildpack/logger" + "github.com/heroku/cnb-shim" +) + +func main() { + 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 { + log.Info(err.Error()) + os.Exit(1) + } + + data, err := ioutil.ReadFile(exportsPath) + if err != nil { + log.Info(err.Error()) + os.Exit(2) + } + + 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..8362769 --- /dev/null +++ b/exports.go @@ -0,0 +1,42 @@ +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" { + 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] + } + return true, strings.TrimSpace(export[1]), val + } 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..cfb1baa --- /dev/null +++ b/exports_test.go @@ -0,0 +1,103 @@ +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) + } +} + +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) + } +} \ 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) {