From 24e71d1464b9d081056d61f43fde09fba2d8505f Mon Sep 17 00:00:00 2001 From: Victor Colombo Date: Tue, 25 Jul 2023 22:50:37 -0300 Subject: [PATCH] feat: Add `environment` support for `kurtosis import` (#982) ## Description: This PR notably does not include support for `env_file` ## Is this change user facing? YES ## References (if applicable): Closes #981 --- .circleci/config.yml | 7 ++- cli/cli/commands/import/import.go | 60 ++++++++++++------- cli/cli/go.mod | 1 + cli/cli/go.sum | 5 ++ .../resources/docker_import_cli_test/.env | 5 ++ .../docker_import_cli_test/docker-compose.yml | 23 +++++-- 6 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 internal_testsuites/resources/docker_import_cli_test/.env diff --git a/.circleci/config.yml b/.circleci/config.yml index 4405ea3ce3..454ee64214 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -195,7 +195,10 @@ parameters: rendertemplate-cli-test-template-relative-path: type: string default: "internal_testsuites/resources/render_template_cli_test/template.txt" - dockerimport-cli-test-relative-path: + dockerimport-cli-dotenv-relative-path: + type: string + default: "internal_testsuites/resources/docker_import_cli_test/.env" + dockerimport-cli-dockerfile-relative-path: type: string default: "internal_testsuites/resources/docker_import_cli_test/docker-compose.yml" rendertemplate-cli-test-data-json-relative-path: @@ -754,7 +757,7 @@ jobs: - run: "${KURTOSIS_BINPATH} run --enclave test-datastore github.com/kurtosis-tech/datastore-army-package '{\"num_datastores\": 2}'" # Execute docker compose import - - run: "${KURTOSIS_BINPATH} import --enclave test-import << pipeline.parameters.dockerimport-cli-test-relative-path >>" + - run: "${KURTOSIS_BINPATH} import --enclave test-import --env << pipeline.parameters.dockerimport-cli-dotenv-relative-path >> << pipeline.parameters.dockerimport-cli-dockerfile-relative-path >>" - run: "${KURTOSIS_BINPATH} enclave stop test-enclave" diff --git a/cli/cli/commands/import/import.go b/cli/cli/commands/import/import.go index 6e2354aea9..da02f6354a 100644 --- a/cli/cli/commands/import/import.go +++ b/cli/cli/commands/import/import.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/compose-spec/compose-go/loader" "github.com/compose-spec/compose-go/types" + "github.com/joho/godotenv" "github.com/kurtosis-tech/kurtosis/api/golang/core/kurtosis_core_rpc_api_bindings" enclave_consts "github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/enclave" "github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context" @@ -17,16 +18,16 @@ import ( "github.com/kurtosis-tech/kurtosis/cli/cli/helpers/output_printers" "github.com/kurtosis-tech/stacktrace" "github.com/sirupsen/logrus" - "io" - "os" "strings" ) const ( enclaveNameFlagKey = "enclave" pathArgKey = "file-path" + dotEnvPathFlagKey = "env" isPathArgOptional = false defaultPathArg = "" + defaultDotEnvPathFlag = ".env" emptyPrivateIpPlaceholder = "" nonSupportedField = "" defaultMainFunction = "" @@ -43,7 +44,7 @@ var ImportCmd = &lowlevel.LowlevelKurtosisCommand{ Flags: []*flags.FlagConfig{ { Key: enclaveNameFlagKey, - Shorthand: "e", + Shorthand: "n", Default: autogenerateEnclaveNameKeyword, Usage: fmt.Sprintf( "The enclave name to give the new enclave, which must match regex '%v' "+ @@ -52,6 +53,13 @@ var ImportCmd = &lowlevel.LowlevelKurtosisCommand{ ), Type: flags.FlagType_String, }, + { + Key: dotEnvPathFlagKey, + Shorthand: "e", + Default: defaultDotEnvPathFlag, + Usage: "The .env file path to be loaded into docker compose", + Type: flags.FlagType_String, + }, }, Args: []*args.ArgConfig{ file_system_path_arg.NewFilepathOrDirpathArg( @@ -71,19 +79,20 @@ func run(ctx context.Context, flags *flags.ParsedFlags, args *args.ParsedArgs) e if err != nil { return stacktrace.Propagate(err, "Path arg '%v' is missing", pathArgKey) } - file, err := os.Open(path) + + dotEnvPath, err := flags.GetString(dotEnvPathFlagKey) if err != nil { - return stacktrace.Propagate(err, "File on '%v' was not found", path) + return stacktrace.Propagate(err, "Dot env path arg '%v' is missing", dotEnvPath) } - defer file.Close() - // Read the content of the file into a []byte slice - content, err := io.ReadAll(file) + dotEnvMap, err := godotenv.Read(dotEnvPath) if err != nil { - return stacktrace.Propagate(err, "Error reading file: %s\n", err) + logrus.Debugf("No dotenv file was found: %v", err) + dotEnvMap = map[string]string{} } + logrus.Infof("Enviroment loaded: %v", dotEnvMap) - script, err := convertComposeFileToStarlark(content) + script, err := convertComposeFileToStarlark(path, dotEnvMap) if err != nil { return stacktrace.Propagate(err, "Failed to convert compose to starlark") } @@ -101,16 +110,10 @@ func run(ctx context.Context, flags *flags.ParsedFlags, args *args.ParsedArgs) e return nil } -func convertComposeFileToStarlark(content []byte) (string, error) { - // Load the Compose configuration from the []byte slice - config, err := loader.ParseYAML(content) - if err != nil { - return "", stacktrace.Propagate(err, "Error parsing YAML: %s\n", err) - } - - // Convert the generic map to a structured compose.Config +func convertComposeFileToStarlark(path string, dotEnvMap map[string]string) (string, error) { project, err := loader.Load(types.ConfigDetails{ //nolint:exhaustruct - ConfigFiles: []types.ConfigFile{{Config: config}}, + ConfigFiles: []types.ConfigFile{{Filename: path}}, + Environment: dotEnvMap, }) if err != nil { return "", stacktrace.Propagate(err, "Error parsing docker compose") @@ -134,7 +137,22 @@ func convertComposeProjectToStarlark(compose *types.Project) (string, error) { } portPiecesStr = append(portPiecesStr, portStr) } - starlarkConfig, err := add.GetServiceConfigStarlark(serviceConfig.Image, strings.Join(portPiecesStr, ","), serviceConfig.Command, serviceConfig.Entrypoint, nonSupportedField, nonSupportedField, emptyPrivateIpPlaceholder) + envvarsPiecesStr := []string{} + for envKey, envValue := range serviceConfig.Environment { + envValueStr := "" + if envValue != nil { + envValueStr = *envValue + } + envvarsPiecesStr = append(envvarsPiecesStr, fmt.Sprintf("%s=%s", envKey, envValueStr)) + } + starlarkConfig, err := add.GetServiceConfigStarlark( + serviceConfig.Image, + strings.Join(portPiecesStr, ","), + serviceConfig.Command, + serviceConfig.Entrypoint, + strings.Join(envvarsPiecesStr, ","), + nonSupportedField, + emptyPrivateIpPlaceholder) if err != nil { return "", stacktrace.Propagate(err, "Error getting service config starlark for '%v'", serviceConfig) } @@ -158,7 +176,7 @@ func runStarlark(ctx context.Context, enclaveName string, starlarkScript string) if err != nil { return stacktrace.Propagate(err, "An error occurred creating an enclave '%v'", enclaveName) } - defer output_printers.PrintEnclaveName(enclaveName) + defer output_printers.PrintEnclaveName(enclaveCtx.GetEnclaveName()) starlarkRunResult, err := enclaveCtx.RunStarlarkScriptBlocking(ctx, defaultMainFunction, starlarkScript, noStarlarkParams, false, 1, []kurtosis_core_rpc_api_bindings.KurtosisFeatureFlag{}) if err != nil { diff --git a/cli/cli/go.mod b/cli/cli/go.mod index 174ddabba9..1110c9f43c 100644 --- a/cli/cli/go.mod +++ b/cli/cli/go.mod @@ -93,6 +93,7 @@ require ( github.com/imdario/mergo v0.3.16 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.7 // indirect diff --git a/cli/cli/go.sum b/cli/cli/go.sum index f95a235fb3..b5ee32b23c 100644 --- a/cli/cli/go.sum +++ b/cli/cli/go.sum @@ -261,6 +261,7 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -310,6 +311,8 @@ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod github.com/jarcoal/httpmock v1.0.4/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -644,6 +647,7 @@ go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.starlark.net v0.0.0-20210223155950-e043a3d3c984/go.mod h1:t3mmBBPzAVvK0L0n1drDmrQsJ8FoIx4INCqVMTr/Zo0= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -841,6 +845,7 @@ google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+ google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/internal_testsuites/resources/docker_import_cli_test/.env b/internal_testsuites/resources/docker_import_cli_test/.env new file mode 100644 index 0000000000..961e9abe0d --- /dev/null +++ b/internal_testsuites/resources/docker_import_cli_test/.env @@ -0,0 +1,5 @@ +POSTGRES_USER=yourUser +POSTGRES_PW=changeit +POSTGRES_DB=postgres +PGADMIN_MAIL=your@email.com +PGADMIN_PW=changeit \ No newline at end of file diff --git a/internal_testsuites/resources/docker_import_cli_test/docker-compose.yml b/internal_testsuites/resources/docker_import_cli_test/docker-compose.yml index 9af8c6caa4..b32f82e5f7 100644 --- a/internal_testsuites/resources/docker_import_cli_test/docker-compose.yml +++ b/internal_testsuites/resources/docker_import_cli_test/docker-compose.yml @@ -1,6 +1,21 @@ services: - nginx-a: - image: nginx:latest - container_name: nginx + postgres: + container_name: postgres + image: postgres:latest + environment: + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PW} + - POSTGRES_DB=${POSTGRES_DB} #optional (specify default database instead of $POSTGRES_DB) ports: - - 123:80 \ No newline at end of file + - "5432:5432" + restart: always + + pgadmin: + container_name: pgadmin + image: dpage/pgadmin4:latest + environment: + - PGADMIN_DEFAULT_EMAIL=${PGADMIN_MAIL} + - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PW} + ports: + - "5050:80" + restart: always \ No newline at end of file