Skip to content

Commit

Permalink
Add settings get/set/remove/show commands (#179)
Browse files Browse the repository at this point in the history
Contributes to #65

Signed-off-by: Sylvain Hellegouarch <sh@defuze.org>
  • Loading branch information
Lawouach committed Jun 19, 2020
1 parent f345e9e commit e057452
Show file tree
Hide file tree
Showing 5 changed files with 413 additions and 3 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,13 @@

[Unreleased]: https://github.com/chaostoolkit/chaostoolkit/compare/1.4.2...HEAD

### Added

- Commands to get/set/remove an entry from the settings as well as show
the settings file entirely [#65][65]

[65]: https://github.com/chaostoolkit/chaostoolkit-lib/issues/65

## [1.4.2][] - 2020-04-29

[1.4.2]: https://github.com/chaostoolkit/chaostoolkit/compare/1.4.1...1.4.2
Expand Down
134 changes: 132 additions & 2 deletions chaostoolkit/cli.py
Expand Up @@ -2,6 +2,7 @@
import io
import json
import os
import re
from typing import List
import uuid

Expand All @@ -15,8 +16,9 @@
from chaoslib.loader import load_experiment
from chaoslib.notification import notify, DiscoverFlowEvent, InitFlowEvent, \
RunFlowEvent, ValidateFlowEvent
from chaoslib.settings import load_settings, CHAOSTOOLKIT_CONFIG_PATH
from chaoslib.types import Activity, Discovery, Experiment, Journal
from chaoslib.settings import load_settings, locate_settings_entry, \
save_settings, CHAOSTOOLKIT_CONFIG_PATH
from chaoslib.types import Activity, Discovery, Experiment, Journal, Settings
import click
from click_plugins import with_plugins
try:
Expand Down Expand Up @@ -179,6 +181,134 @@ def validate(ctx: click.Context, source: str,
return experiment


@cli.group()
def settings():
"""
Read, write or remove from your settings file.
"""
pass


cli.add_command(settings)


@settings.command('show')
@click.option('--format', 'fmt', default="yaml", show_default=False,
help="Output format.",
type=click.Choice(['json', 'yaml']))
@click.pass_context
def show_settings(ctx: click.Context, fmt: str = "json"):
"""
Show the entire content of the settings file.
Be aware this will not obfuscate secret data.
"""
if not os.path.isfile(ctx.obj["settings_path"]):
click.abort(
"No settings file found at {}".format(ctx.obj["settings_path"]))

settings = load_settings(ctx.obj["settings_path"]) or {}
if fmt == "json":
click.echo(json.dumps(settings, indent=2))
elif fmt == "yaml":
click.echo(yaml.dump(settings, indent=2))


settings.add_command(show_settings)


@settings.command('set')
@click.argument('key', nargs=1)
@click.argument('value', nargs=1)
@click.pass_context
def set_settings_value(ctx: click.Context, key: str, value: str = None):
"""
Set a settings value.
The value must be a valid JSON string so that it can be interpreted
with the appropriate type.
The key must be dotted path to its location in the settings file.
"""
if not os.path.isfile(ctx.obj["settings_path"]):
ctx.exit(1)

settings = load_settings(ctx.obj["settings_path"]) or {}
item = locate_settings_entry(settings, key)
if not item:
ctx.exit(1)
parent, entry, key_tail, index = item

value = json.loads(value)
if key_tail is not None:
parent[key_tail] = value
elif index is not None:
parent[index] = value
save_settings(settings, ctx.obj["settings_path"])


settings.add_command(set_settings_value)


@settings.command('remove')
@click.argument('key', nargs=1)
@click.pass_context
def remove_settings_value(ctx: click.Context, key: str):
"""
Remove a settings key and its children.
The key must be dotted path to its location in the settings file.
"""
if not os.path.isfile(ctx.obj["settings_path"]):
ctx.exit(1)

settings = load_settings(ctx.obj["settings_path"]) or {}
item = locate_settings_entry(settings, key)
if not item:
ctx.exit(1)
parent, entry, key_tail, index = item

if key_tail is not None:
parent.pop(key_tail, None)
elif index is not None:
parent.remove(parent[index])
save_settings(settings, ctx.obj["settings_path"])


settings.add_command(remove_settings_value)


@settings.command('get')
@click.option('--format', 'fmt', default="yaml", show_default=False,
help="Output format.",
type=click.Choice(['string', 'json', 'yaml']))
@click.argument('key', nargs=1)
@click.pass_context
def get_settings_value(ctx: click.Context, key: str, fmt: str = "json"):
"""
Show a settings value.
The key must be dotted path to its location in the settings file.
"""
if not os.path.isfile(ctx.obj["settings_path"]):
ctx.exit(1)

settings = load_settings(ctx.obj["settings_path"]) or {}
item = locate_settings_entry(settings, key)
if not item:
ctx.exit(1)
parent, entry, key_tail, index = item

if fmt == "json":
click.echo(json.dumps(entry, indent=2))
elif fmt == "string":
click.echo(str(entry))
elif fmt == "yaml":
click.echo(yaml.dump(entry, indent=2))


settings.add_command(get_settings_value)


@cli.command()
@click.argument('target',
type=click.Choice(['core', 'settings', 'extensions']),
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
@@ -1,7 +1,7 @@
click>=7.0
click-plugins>=1.0.4
logzero>=1.5.0
chaostoolkit-lib~=1.9
chaostoolkit-lib~=1.10
requests>=2.21
python-json-logger>=0.1.11
PyYAML>=5.1.2
Expand Down
13 changes: 13 additions & 0 deletions tests/fixtures/complete-settings.yaml
@@ -0,0 +1,13 @@
auths:
chaos.example.com:8443:
type: bearer
value: a1234
controls:
my-control:
provider:
arguments:
recipients:
- name: john
message: hello world
- name: jane
message: hello as well

0 comments on commit e057452

Please sign in to comment.