diff --git a/README.md b/README.md index d09c26c..cfa23e9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ACodeNinja's Collection of cloud native buildpacks. All buildpacks are released under the [MIT license](./LICENSE). -- [Playwright](./playwright) - Adds requirements for running [playwright](https://playwright.dev/python/) -- [Python Security](./python-security) - Adds requirements for using Python Security packages. -- [Install](./install) - Install packages from the Ubuntu apt repositories. +- [`acodeninja/install`](./install) - Install packages from the Ubuntu apt repositories. +- [`acodeninja/playwright`](./playwright) - Adds requirements for running [playwright](https://playwright.dev/python/) +- [`acodeninja/python-security`](./python-security) - Adds requirements for using Python Security packages. +- [`acodeninja/psql`](./psql) - Adds several PostgreSQL client tools. diff --git a/common/apt/apt.go b/common/apt/apt.go index aeaf8ab..7473fb7 100644 --- a/common/apt/apt.go +++ b/common/apt/apt.go @@ -50,7 +50,7 @@ func InstallAptPackages(layer libcnb.Layer, packageList []string, logger bard.Lo if err != nil { return err } - logger.Body(" Created", directory) + logger.Body(" Created ", directory) } err = common.CopyFile("/etc/apt/sources.list", fmt.Sprintf("%s/sources.list", aptSourcesDirectory)) diff --git a/install/buildpack.toml b/install/buildpack.toml index 44f1736..294901f 100644 --- a/install/buildpack.toml +++ b/install/buildpack.toml @@ -3,7 +3,7 @@ api = "0.8" [buildpack] id = "acodeninja/install" name = "ACodeNinja Buildpack for installing system packages" - version = "1.0.0" + version = "1.0.1" homepage = "https://github.com/acodeninja/buildpacks/tree/main/install" [[buildpack.licenses]] diff --git a/playwright/buildpack.toml b/playwright/buildpack.toml index 8081bde..a83cc3b 100644 --- a/playwright/buildpack.toml +++ b/playwright/buildpack.toml @@ -3,7 +3,7 @@ api = "0.8" [buildpack] id = "acodeninja/playwright" name = "ACodeNinja Buildpack for Playwright" - version = "3.0.1" + version = "3.0.2" homepage = "https://github.com/acodeninja/buildpacks/tree/main/playwright" [[buildpack.licenses]] diff --git a/psql/README.md b/psql/README.md index aaeef5d..2c03561 100644 --- a/psql/README.md +++ b/psql/README.md @@ -1,3 +1,15 @@ # ACodeNinja Buildpack for PostgreSQL client +**Buildpack id**: `acodeninja/psql` + This buildpack installs the PostgreSQL client and associated tools. + +- `pg_amcheck` +- `pgbench` +- `pg_config` +- `pg_dump` +- `pg_dumpall` +- `pg_isready` +- `pg_receivewal` +- `pg_restore` +- `psql` diff --git a/psql/buildpack.toml b/psql/buildpack.toml index 553c445..1f9fcd9 100644 --- a/psql/buildpack.toml +++ b/psql/buildpack.toml @@ -3,7 +3,7 @@ api = "0.8" [buildpack] id = "acodeninja/psql" name = "ACodeNinja Buildpack for PostgreSQL client" - version = "1.0.0" + version = "1.1.0" homepage = "https://github.com/acodeninja/buildpacks/tree/main/psql" [[buildpack.licenses]] diff --git a/psql/fixtures/bash/test.sh b/psql/fixtures/bash/test.sh index db226fb..2b03d6b 100644 --- a/psql/fixtures/bash/test.sh +++ b/psql/fixtures/bash/test.sh @@ -1,26 +1,40 @@ #!/usr/bin/env bash -PSQL_WHICH_TEST_OUTCOME="" -PSQL_WHICH="$(which psql)" -if [[ "$PSQL_WHICH" == "/layers/acodeninja_psql/psql/psql-bin/psql" ]] -then - PSQL_WHICH_TEST_OUTCOME="passed 🟢" -else - PSQL_WHICH_TEST_OUTCOME="psql is located at $PSQL_WHICH 🔴" -fi -echo "psql command location: $PSQL_WHICH_TEST_OUTCOME" +TESTS_FAILED="" +CURRENT_TEST_GROUP_NAME="" -PSQL_VERSION_TEST_OUTCOME="" -PSQL_VERSION="$(psql --version)" -if [[ "$PSQL_VERSION" =~ "(PostgreSQL) 14" ]] -then - PSQL_VERSION_TEST_OUTCOME="passed 🟢" -else - PSQL_VERSION_TEST_OUTCOME="psql version is $PSQL_VERSION 🔴" -fi -echo "psql command version: $PSQL_VERSION_TEST_OUTCOME" +function test_group() { + TEST_GROUP_NAME=$1 + CURRENT_TEST_GROUP_NAME="$TEST_GROUP_NAME" +} + +function run_test() { + TEST_NAME=$1 + TEST_COMMAND=$2 + TEST_EXPECTED_OUTPUT=$3 + + TEST_OUTCOME="" + TEST_OUTPUT=`$TEST_COMMAND 2>&1` + if [[ "$TEST_OUTPUT" =~ "$TEST_EXPECTED_OUTPUT" ]] + then + TEST_OUTCOME="passed 🟢" + else + TEST_OUTCOME="failed 🔴 - $TEST_OUTPUT" + TESTS_FAILED="yes" + fi + echo "[$CURRENT_TEST_GROUP_NAME][$TEST_NAME]: $TEST_OUTCOME" +} + +COMMANDS_TO_TEST="pg_amcheck pgbench pg_config pg_dump pg_dumpall pg_isready pg_receivewal pg_restore psql" + +for COMMAND_TO_TEST in $COMMANDS_TO_TEST; do + test_group "$COMMAND_TO_TEST" + run_test "location" "which $COMMAND_TO_TEST" "/layers/acodeninja_psql/psql/psql-bin/$COMMAND_TO_TEST" + run_test "$COMMAND_TO_TEST version" "$COMMAND_TO_TEST --version" "14" + run_test "$COMMAND_TO_TEST server" "$COMMAND_TO_TEST --version" "PostgreSQL" +done -if [[ "$PSQL_VERSION_TEST_OUTCOME" == "passed 🟢" && "$PSQL_VERSION_TEST_OUTCOME" == "passed 🟢" ]] +if [[ -z "$TESTS_FAILED" ]] then exit 0 else diff --git a/psql/psql.go b/psql/psql.go index f66f604..98056f6 100644 --- a/psql/psql.go +++ b/psql/psql.go @@ -12,13 +12,14 @@ import ( "text/template" ) -//go:embed psql.sh +//go:embed wrapper.sh var embeddedFiles embed.FS -type PSQLScriptData struct { +type WrapperScriptInput struct { LibLocations []string PerlLibLocation string PostgresClientPath string + PostgresCommand string } type PostgresClientLayer struct { @@ -77,59 +78,28 @@ func (psql PostgresClientLayer) Contribute(layer libcnb.Layer) (libcnb.Layer, er return libcnb.Layer{}, fmt.Errorf("unable to install postgresql-client\n%w", err) } - psql.Logger.Header("Installing bash wrapper") - - psqlScript, err := embeddedFiles.ReadFile("psql.sh") - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to read embeded psql script\n%w", err) - } - - psqlFileTemplate, err := template.New("psql").Parse(string(psqlScript)) - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to parse psql script template\n%w", err) - } - - psqlFileLocation := fmt.Sprintf("%s/psql-bin", layer.Path) - - err = os.MkdirAll(psqlFileLocation, os.ModePerm) - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to create psql script location\n%w", err) - } - - psqlFile, err := os.Create(fmt.Sprintf("%s/psql", psqlFileLocation)) - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to create psql wrapper file\n%w", err) - } - - err = psqlFileTemplate.Execute(psqlFile, PSQLScriptData{ - LibLocations: []string{ - fmt.Sprintf("%s/usr/lib/x86_64-linux-gnu/sasl2", layer.Path), - fmt.Sprintf("%s/usr/lib/x86_64-linux-gnu", layer.Path), - fmt.Sprintf("%s/lib/x86_64-linux-gnu", layer.Path), - }, - PerlLibLocation: fmt.Sprintf("%s/usr/share/perl5", layer.Path), - PostgresClientPath: fmt.Sprintf("%s/usr/lib/postgresql/14/bin", layer.Path), - }) - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to create psql wrapper file\n%w", err) + psql.Logger.Header("Installing command wrappers") + commandsToWrap := []string{ + "pg_amcheck", + "pgbench", + "pg_config", + "pg_dump", + "pg_dumpall", + "pg_isready", + "pg_receivewal", + "pg_restore", + "psql", } - err = psqlFile.Sync() - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to sync psql script\n%w", err) + for _, command := range commandsToWrap { + err = WriteWrapperToBin(layer, psql.Logger, command) + if err != nil { + return libcnb.Layer{}, err + } } - err = psqlFile.Close() - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to close psql script\n%w", err) - } - - err = os.Chmod(fmt.Sprintf("%s/psql", psqlFileLocation), 0775) - if err != nil { - return libcnb.Layer{}, fmt.Errorf("unable to chmod psql script\n%w", err) - } - - layer.SharedEnvironment.Prepend("PATH", ":", psqlFileLocation) + psql.Logger.Header("Writing environment") + layer.SharedEnvironment.Prepend("PATH", ":", fmt.Sprintf("%s/psql-bin", layer.Path)) layer.LayerTypes.Build = true layer.LayerTypes.Launch = true @@ -143,6 +113,63 @@ func (psql PostgresClientLayer) Name() string { return "psql" } +func WriteWrapperToBin(layer libcnb.Layer, logger bard.Logger, pgBinary string) error { + logger.Bodyf("Writing wrapper script for %s", pgBinary) + + script, err := embeddedFiles.ReadFile("wrapper.sh") + if err != nil { + return fmt.Errorf("unable to read embeded %s script\n%w", pgBinary, err) + } + + wrapperFileTemplate, err := template.New("wrapper").Parse(string(script)) + if err != nil { + return fmt.Errorf("unable to parse %s script template\n%w", pgBinary, err) + } + + wrapperFileLocation := fmt.Sprintf("%s/psql-bin", layer.Path) + + err = os.MkdirAll(wrapperFileLocation, os.ModePerm) + if err != nil { + return fmt.Errorf("unable to create %s script location\n%w", pgBinary, err) + } + + wrapperFile, err := os.Create(fmt.Sprintf("%s/%s", wrapperFileLocation, pgBinary)) + if err != nil { + return fmt.Errorf("unable to create %s wrapper file\n%w", pgBinary, err) + } + + err = wrapperFileTemplate.Execute(wrapperFile, WrapperScriptInput{ + LibLocations: []string{ + fmt.Sprintf("%s/usr/lib/x86_64-linux-gnu/sasl2", layer.Path), + fmt.Sprintf("%s/usr/lib/x86_64-linux-gnu", layer.Path), + fmt.Sprintf("%s/lib/x86_64-linux-gnu", layer.Path), + }, + PerlLibLocation: fmt.Sprintf("%s/usr/share/perl5", layer.Path), + PostgresClientPath: fmt.Sprintf("%s/usr/lib/postgresql/14/bin", layer.Path), + PostgresCommand: pgBinary, + }) + if err != nil { + return fmt.Errorf("unable to create %s wrapper file\n%w", pgBinary, err) + } + + err = wrapperFile.Sync() + if err != nil { + return fmt.Errorf("unable to sync %s script\n%w", pgBinary, err) + } + + err = wrapperFile.Close() + if err != nil { + return fmt.Errorf("unable to close %s script\n%w", pgBinary, err) + } + + err = os.Chmod(fmt.Sprintf("%s/%s", wrapperFileLocation, pgBinary), 0775) + if err != nil { + return fmt.Errorf("unable to chmod %s script\n%w", pgBinary, err) + } + + return nil +} + func ResolvePostgresClientVersion(logger bard.Logger) string { psqlVersion := "14" ubuntuVersion := ResolveUbuntuVersion(logger) diff --git a/psql/psql.sh b/psql/wrapper.sh similarity index 91% rename from psql/psql.sh rename to psql/wrapper.sh index f194efb..a0942b4 100644 --- a/psql/psql.sh +++ b/psql/wrapper.sh @@ -5,4 +5,4 @@ PATH="{{.PostgresClientPath}}:$PATH" LD_LIBRARY_PATH="{{range $val := .LibLocations}}{{$val}}:{{end}}$LD_LIBRARY_PATH" LIBRARY_PATH="{{range $val := .LibLocations}}{{$val}}:{{end}}$LD_LIBRARY_PATH" -psql $@ +{{.PostgresCommand}} $@ diff --git a/python-security/buildpack.toml b/python-security/buildpack.toml index 831b19f..61e008a 100644 --- a/python-security/buildpack.toml +++ b/python-security/buildpack.toml @@ -3,7 +3,7 @@ api = "0.8" [buildpack] id = "acodeninja/python-security" name = "ACodeNinja Buildpack for Python Security" - version = "2.0.2" + version = "2.0.3" homepage = "https://github.com/acodeninja/buildpacks/tree/main/python-security" [[buildpack.licenses]]