Skip to content

Commit

Permalink
Merge pull request #107 from peopledoc/get-all-flat
Browse files Browse the repository at this point in the history
Add a flat output to the get-all command
  • Loading branch information
Mickaël Guérin authored Aug 1, 2019
2 parents cf767b7 + c2462e2 commit 4875b00
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ CHANGELOG

- Add implicit and explicit caching (#102 / #103)
- Add `config_file=` in lib mode
- Add a `--flat` option to the `get-all` command (the new output uses full paths as dictionnary key)

0.9.0 (2019-07-11)
------------------
Expand Down
7 changes: 7 additions & 0 deletions tests/integration/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ def test_integration_cli(cli_runner, clean_vault):
"""
)

assert call(cli_runner, ["get-all", "--flat", ""]).output == (
"""---
a: b
c/d: e
"""
)

call(cli_runner, ["delete", "a"])

assert call(cli_runner, ["list"]).output == "c/\n"
Expand Down
9 changes: 9 additions & 0 deletions tests/unit/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ def test_get_all(cli_runner, vault_with_token):
assert result.exit_code == 0


def test_get_all_flat(cli_runner, vault_with_token):

vault_with_token.db = {"a/baz": {"value": "bar"}, "a/foo": {"value": "yay"}}
result = cli_runner.invoke(cli.cli, ["get-all", "--flat", "a"])

assert yaml.safe_load(result.output) == {"a/baz": "bar", "a/foo": "yay"}
assert result.exit_code == 0


def test_set(cli_runner, vault_with_token):

result = cli_runner.invoke(cli.cli, ["set", "a", "b"])
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/test_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,18 @@ def test_vault_client_base_get_all_secrets(vault):
assert result == {"a": {"c": "secret-ac"}}


def test_vault_client_base_get_all_secrets_flat(vault):
vault.db = {"a/c": {"value": "secret-ac"}, "b": {"value": "secret-b"}}

result = vault.get_all_secrets("a", "", flat=True)

assert result == {"a/c": "secret-ac", "b": "secret-b"}

result = vault.get_all_secrets("a", flat=True)

assert result == {"a/c": "secret-ac"}


@pytest.mark.parametrize(
"input, expected", [("a", {"a/c": "secret-ac"}), ("b", {"b": "secret-b"})]
)
Expand Down
9 changes: 7 additions & 2 deletions vault_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,23 @@ def list_(client_obj: client.VaultClientBase, path: str):


@cli.command(name="get-all")
@click.option(
"--flat",
is_flag=True,
help=("Returns the full path as keys instead of merging paths into a tree"),
)
@click.argument("path", required=False, nargs=-1)
@click.pass_obj
@handle_errors()
def get_all(client_obj: client.VaultClientBase, path: Sequence[str]):
def get_all(client_obj: client.VaultClientBase, path: Sequence[str], flat: bool):
"""
Return multiple secrets. Return a single yaml with all the secrets located
at the given paths. Folders are recursively explored. Without a path,
explores all the vault.
"""
paths = list(path) or [""]

result = client_obj.get_all_secrets(*paths)
result = client_obj.get_all_secrets(*paths, flat=flat)

click.echo(
yaml.safe_dump(result, default_flow_style=False, explicit_start=True), nl=False
Expand Down
15 changes: 11 additions & 4 deletions vault_cli/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ def _browse_recursive_secrets(
yield sub_path

@caching
def get_all_secrets(self, *paths: str, render: bool = True) -> types.JSONDict:
def get_all_secrets(
self, *paths: str, render: bool = True, flat: bool = False
) -> types.JSONDict:
"""
Takes several paths, return the nested dict of all secrets below
those paths
Expand All @@ -220,7 +222,10 @@ def get_all_secrets(self, *paths: str, render: bool = True) -> types.JSONDict:
*paths : str
Paths to read recursively
render : bool, optional
Wether templated secrets should be rendered, by default True
Whether templated secrets should be rendered, by default True
flat : bool, optional
Whether to return flat structure with full path as keys or nested
structure that looks like a tree
Returns
-------
Expand All @@ -232,8 +237,10 @@ def get_all_secrets(self, *paths: str, render: bool = True) -> types.JSONDict:

for path in paths:
path_dict = self.get_secrets(path, render=render)

result.update(utils.path_to_nested(path_dict))
if flat:
result.update(path_dict)
else:
result.update(utils.path_to_nested(path_dict))

return result

Expand Down

0 comments on commit 4875b00

Please sign in to comment.