diff --git a/internal/commands/pull.go b/internal/commands/pull.go index e8751247c..f4eed1e0c 100644 --- a/internal/commands/pull.go +++ b/internal/commands/pull.go @@ -41,6 +41,10 @@ The policy location defaults to the policy directory in the local folder. The location can be overridden with the '--policy' flag, e.g.: $ conftest pull --policy + +When using absolute paths, you can enable the '--absolute-paths' flag to preserve them: + + $ conftest pull --absolute-paths --policy /absolute/path/to/policies ` // NewPullCommand creates a new pull command to allow users @@ -57,6 +61,9 @@ func NewPullCommand(ctx context.Context) *cobra.Command { if err := viper.BindPFlag("tls", cmd.Flags().Lookup("tls")); err != nil { return fmt.Errorf("bind flag: %w", err) } + if err := viper.BindPFlag("absolute-paths", cmd.Flags().Lookup("absolute-paths")); err != nil { + return fmt.Errorf("bind flag: %w", err) + } return nil }, @@ -66,7 +73,13 @@ func NewPullCommand(ctx context.Context) *cobra.Command { return fmt.Errorf("missing required arguments") } - policyDir := filepath.Join(".", viper.GetString("policy")) + policyPath := viper.GetString("policy") + var policyDir string + if viper.GetBool("absolute-paths") && filepath.IsAbs(policyPath) { + policyDir = policyPath + } else { + policyDir = filepath.Join(".", policyPath) + } if err := downloader.Download(ctx, policyDir, args); err != nil { return fmt.Errorf("download policies: %w", err) @@ -78,6 +91,7 @@ func NewPullCommand(ctx context.Context) *cobra.Command { cmd.Flags().StringP("policy", "p", "policy", "Path to download the policies to") cmd.Flags().BoolP("tls", "s", true, "Use TLS to access the registry") + cmd.Flags().Bool("absolute-paths", false, "Preserve absolute paths in policy flag") return &cmd } diff --git a/tests/pull-absolute-paths/test.bats b/tests/pull-absolute-paths/test.bats new file mode 100644 index 000000000..5f726b50a --- /dev/null +++ b/tests/pull-absolute-paths/test.bats @@ -0,0 +1,39 @@ +#!/usr/bin/env bats + +setup() { + # Create temporary directories for testing + export TEMP_DIR=$(mktemp -d) + export REL_TEMP_DIR="examples/tmp-conftest-test-$$" + export ABS_POLICY_DIR="${TEMP_DIR}/conftest-policies" + mkdir -p "${ABS_POLICY_DIR}" + mkdir -p "${REL_TEMP_DIR}" +} + +teardown() { + # Clean up temporary directories + rm -rf "${TEMP_DIR}" + rm -rf "${REL_TEMP_DIR}" +} + +@test "Pull command works with relative paths (default behavior)" { + run $CONFTEST pull --policy $REL_TEMP_DIR https://raw.githubusercontent.com/open-policy-agent/conftest/master/examples/compose/policy/deny.rego + [ "$status" -eq 0 ] + [ -d "$REL_TEMP_DIR" ] + [ -f "$REL_TEMP_DIR/deny.rego" ] +} + +@test "Pull command uses absolute paths as relative when --absolute-paths is not set" { + run $CONFTEST pull --policy "${ABS_POLICY_DIR}" https://raw.githubusercontent.com/open-policy-agent/conftest/master/examples/compose/policy/deny.rego + [ "$status" -eq 0 ] + # The policy should be downloaded to ./ABS_POLICY_DIR instead of the absolute path + [ ! -d "${ABS_POLICY_DIR}/deny.rego" ] + [ -f "./${ABS_POLICY_DIR}/deny.rego" ] +} + +@test "Pull command works with absolute path when --absolute-paths is set" { + run $CONFTEST pull --absolute-paths --policy "${ABS_POLICY_DIR}" https://raw.githubusercontent.com/open-policy-agent/conftest/master/examples/compose/policy/deny.rego + [ "$status" -eq 0 ] + # The policy should be downloaded to the absolute path + [ ! -f "./${ABS_POLICY_DIR#/}/deny.rego" ] + [ -f "${ABS_POLICY_DIR}/deny.rego" ] +} \ No newline at end of file