Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul CLI documentation and aesthetics #2703

Merged
merged 28 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
19d8169
Update requirements.txt
ThomasLaPiana Feb 25, 2023
d973264
feat: add rich_click and play around with formatting
ThomasLaPiana Feb 25, 2023
9878d90
feat: add more formatting, update docstrings
ThomasLaPiana Feb 25, 2023
466b6da
docs: more docstring updates
ThomasLaPiana Feb 25, 2023
47ac9ee
docs: more broad changes
ThomasLaPiana Feb 25, 2023
b9e9dab
docs: update `annotate` group documentation
ThomasLaPiana Feb 25, 2023
dfaedaf
docs: db commands
ThomasLaPiana Feb 25, 2023
75dd0a4
feat: clean up the CRUD command documentation as well as outputs and …
ThomasLaPiana Feb 28, 2023
1e59a03
docs: slight deploy verbiage tweak
ThomasLaPiana Feb 28, 2023
1143b3e
docs: update evaluate command
ThomasLaPiana Feb 28, 2023
e1b0f89
docs: export and generate subcommands
ThomasLaPiana Mar 1, 2023
832e857
Merge branch 'main' into ThomasLaPiana-add-rich-click
ThomasLaPiana Mar 1, 2023
91e4298
docs: more docstring updates
ThomasLaPiana Mar 1, 2023
c8a92cc
feat: add a `fides view credentials` command
ThomasLaPiana Mar 1, 2023
26b1ad8
docs: options and scan commands
ThomasLaPiana Mar 1, 2023
c781c80
docs: change datamap -> data map everywhere
ThomasLaPiana Mar 1, 2023
31741ed
fix: errant find/replace
ThomasLaPiana Mar 1, 2023
f0ef506
docs: slight docstring tweak
ThomasLaPiana Mar 1, 2023
61f63f9
docs: changelog
ThomasLaPiana Mar 1, 2023
42ced75
fix: resource listing and static checks
ThomasLaPiana Mar 1, 2023
667c622
fix: mypy and stuff
ThomasLaPiana Mar 1, 2023
a26adf6
fix: typo
ThomasLaPiana Mar 1, 2023
a0df6ae
fix: consistent "data map"
ThomasLaPiana Mar 1, 2023
1616b68
fix: fides deploy check failure
ThomasLaPiana Mar 2, 2023
e1e246a
fix: review comments
ThomasLaPiana Mar 2, 2023
fe4da8f
fix: test coverage and docstring
ThomasLaPiana Mar 2, 2023
84af3c4
fix: test the verbose option
ThomasLaPiana Mar 2, 2023
ad2f7dc
Merge branch 'main' into ThomasLaPiana-add-rich-click
ThomasLaPiana Mar 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .fides/systems.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ system:
- fides_db

# System Info
- fides_key: privacy_request_fullfillment
- fides_key: privacy_request_fulfillment
name: Fides Privacy Request Fulfillment
organization_fides_key: default_organization
description: Privacy request fufillment.
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ The types of changes are:
* Add warning to 'fides deploy' when installed outside of a virtual environment [#2641](https://github.com/ethyca/fides/pull/2641)
* Redesigned the default/init config file to be auto-documented. Also updates the `fides init` logic and analytics consent logic [#2694](https://github.com/ethyca/fides/pull/2694)
* Change how config creation/import is handled across the application [#2622](https://github.com/ethyca/fides/pull/2622)
* Update the CLI aesthetics & docstrings [#2703](https://github.com/ethyca/fides/pull/2703)
* Updates Roles->Scopes Mapping [#2744](https://github.com/ethyca/fides/pull/2744)
* Return user scopes as an enum, as well as total scopes [#2741](https://github.com/ethyca/fides/pull/2741)

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ APScheduler==3.9.1.post1
asyncpg==0.25.0
boto3==1.26.1
celery[pytest]==5.2.7
click==8.1.3
colorama>=0.4.3
cryptography==38.0.3
dask==2022.9.2
Expand Down Expand Up @@ -35,6 +34,7 @@ PyMySQL==1.0.2
python-jose[cryptography]==3.3.0
pyyaml>=5,<6
redis==3.5.3
rich-click==1.6.1
sendgrid==6.9.7
slowapi==0.1.5
snowflake-sqlalchemy==1.4.3
Expand Down
21 changes: 14 additions & 7 deletions src/fides/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"""Contains the groups and setup for the CLI."""
"""
Entrypoint for the Fides command-line.
"""
from importlib.metadata import version
from platform import system

import click
import rich_click as click
from fideslog.sdk.python.client import AnalyticsClient

import fides
from fides.cli.utils import check_server
from fides.core.config import get_config

from . import cli_formatting
ThomasLaPiana marked this conversation as resolved.
Show resolved Hide resolved
from .commands.annotate import annotate
from .commands.core import evaluate, parse, pull, push
from .commands.crud import delete, get_resource, list_resources
Expand Down Expand Up @@ -58,24 +61,28 @@
"--config-path",
"-f",
"config_path",
default="",
help="Path to a configuration file. Use 'fides view-config' to print the config. Not compatible with the 'fides webserver' subcommand.",
show_default=True,
help="Path to a Fides config file. _Defaults to `.fides/fides.toml`._",
)
@click.option(
"--local",
is_flag=True,
help="Run in 'local_mode'. This mode doesn't make API calls and can be used without the API server/database.",
help="Run in `local_mode`. This mode doesn't make API calls and can be used without the API server/database.",
)
@click.pass_context
def cli(ctx: click.Context, config_path: str, local: bool) -> None:
"""
The parent group for the Fides CLI.
__Command-line tool for the Fides privacy engineering platform.__

---

_Note: The common MANIFESTS_DIR argument _always_ defaults to ".fides/" if not specified._
"""

ctx.ensure_object(dict)
ThomasLaPiana marked this conversation as resolved.
Show resolved Hide resolved
config = get_config(config_path, verbose=True)

# Dyanmically add commands to the CLI
# Dynamically add commands to the CLI
cli.commands = LOCAL_COMMAND_DICT

if not (local or config.cli.local_mode):
Expand Down
114 changes: 114 additions & 0 deletions src/fides/cli/cli_formatting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""
This is a configuration file for `rich_click`, used to customize the
visual aesthetic and output of the CLI.

This is the list of all documented configuration options for `rich_click`.

You can set a style attribute by adding one or more of the following words:

- "bold" or "b" for bold text.
- "blink" for text that flashes (use this one sparingly).
- "blink2" for text that flashes rapidly (not supported by most terminals).
- "conceal" for concealed text (not supported by most terminals).
- "italic" or "i" for italic text (not supported on Windows).
- "reverse" or "r" for text with foreground and background colors reversed.
- "strike" or "s" for text with a line through it.
- "underline" or "u" for underlined text.
- "underline2" or "uu" for doubly underlined text.
- "frame" for framed text.
- "encircle" for encircled text.
- "overline" or "o" for overlined text.

The list of valid colors is here:
- https://rich.readthedocs.io/en/stable/appendix/colors.html
"""

from rich_click import rich_click

# Default styles
rich_click.STYLE_OPTION = "bold #fca311"
rich_click.STYLE_SWITCH = "bold #fca311"
rich_click.STYLE_ARGUMENT = "bold #00ff5f"
rich_click.STYLE_METAVAR = "bold #8700af"
rich_click.STYLE_METAVAR_APPEND = "dim yellow"
rich_click.STYLE_METAVAR_SEPARATOR = "dim"
rich_click.STYLE_HEADER_TEXT = ""
rich_click.STYLE_FOOTER_TEXT = ""
rich_click.STYLE_USAGE = "yellow"
rich_click.STYLE_USAGE_COMMAND = "bold"
rich_click.STYLE_DEPRECATED = "red"
rich_click.STYLE_HELPTEXT_FIRST_LINE = ""
rich_click.STYLE_HELPTEXT = ""
rich_click.STYLE_OPTION_HELP = ""
rich_click.STYLE_OPTION_DEFAULT = "bold #8700af"
rich_click.STYLE_OPTION_ENVVAR = "dim yellow"
rich_click.STYLE_REQUIRED_SHORT = "red"
rich_click.STYLE_REQUIRED_LONG = "dim red"
rich_click.STYLE_OPTIONS_PANEL_BORDER = "dim"
rich_click.ALIGN_OPTIONS_PANEL = "left"
rich_click.STYLE_OPTIONS_TABLE_SHOW_LINES = False
rich_click.STYLE_OPTIONS_TABLE_LEADING = 0
rich_click.STYLE_OPTIONS_TABLE_PAD_EDGE = False
rich_click.STYLE_OPTIONS_TABLE_PADDING = (0, 1)
rich_click.STYLE_OPTIONS_TABLE_BOX = ""
rich_click.STYLE_OPTIONS_TABLE_ROW_STYLES = None
rich_click.STYLE_OPTIONS_TABLE_BORDER_STYLE = None
rich_click.STYLE_COMMANDS_PANEL_BORDER = "dim"
rich_click.ALIGN_COMMANDS_PANEL = "left"
rich_click.STYLE_COMMANDS_TABLE_SHOW_LINES = False
rich_click.STYLE_COMMANDS_TABLE_LEADING = 0
rich_click.STYLE_COMMANDS_TABLE_PAD_EDGE = False
rich_click.STYLE_COMMANDS_TABLE_PADDING = (0, 1)
rich_click.STYLE_COMMANDS_TABLE_BOX = ""
rich_click.STYLE_COMMANDS_TABLE_ROW_STYLES = None
rich_click.STYLE_COMMANDS_TABLE_BORDER_STYLE = None
rich_click.STYLE_ERRORS_PANEL_BORDER = "red"
rich_click.ALIGN_ERRORS_PANEL = "left"
rich_click.STYLE_ERRORS_SUGGESTION = "dim"
rich_click.STYLE_ABORTED = "red"
rich_click.MAX_WIDTH = None # Set to an int to limit to that many characters
rich_click.COLOR_SYSTEM = "auto" # Set to None to disable colors

# Fixed strings
rich_click.HEADER_TEXT = None
rich_click.FOOTER_TEXT = None
rich_click.DEPRECATED_STRING = "(Deprecated) "
rich_click.DEFAULT_STRING = "[default: {}]"
rich_click.ENVVAR_STRING = "[env var: {}]"
rich_click.REQUIRED_SHORT_STRING = "*"
rich_click.REQUIRED_LONG_STRING = "[required]"
rich_click.RANGE_STRING = " [{}]"
rich_click.APPEND_METAVARS_HELP_STRING = "({})"
rich_click.ARGUMENTS_PANEL_TITLE = "Arguments"
rich_click.OPTIONS_PANEL_TITLE = "Options"
rich_click.COMMANDS_PANEL_TITLE = "Commands"
rich_click.ERRORS_PANEL_TITLE = "Error"
rich_click.ERRORS_SUGGESTION = (
None # Default: Try 'cmd -h' for help. Set to False to disable.
)
rich_click.ERRORS_EPILOGUE = None
rich_click.ABORTED_TEXT = "Aborted."

# Behaviours
rich_click.SHOW_ARGUMENTS = True # Show positional arguments
rich_click.SHOW_METAVARS_COLUMN = (
True # Show a column with the option metavar (eg. INTEGER)
)
rich_click.APPEND_METAVARS_HELP = (
False # Append metavar (eg. [TEXT]) after the help text
)
rich_click.GROUP_ARGUMENTS_OPTIONS = (
False # Show arguments with options instead of in own panel
)
rich_click.USE_MARKDOWN = True # Parse help strings as markdown
rich_click.USE_MARKDOWN_EMOJI = True # Parse emoji codes in markdown :smile:
rich_click.USE_RICH_MARKUP = (
False # Parse help strings for rich markup (eg. [red]my text[/])
)
rich_click.COMMAND_GROUPS = {} # Define sorted groups of panels to display subcommands
rich_click.OPTION_GROUPS = (
{}
) # Define sorted groups of panels to display options and arguments
rich_click.USE_CLICK_SHORT_HELP = (
False # Use click's default function to truncate help text
)
10 changes: 5 additions & 5 deletions src/fides/cli/commands/annotate.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Contains the annotate group of CLI commands for fides."""

import click
import rich_click as click

from fides.cli.utils import with_analytics
from fides.core import annotate_dataset as _annotate_dataset
Expand All @@ -10,7 +10,7 @@
@click.pass_context
def annotate(ctx: click.Context) -> None:
"""
Annotate fides resource types
Interactively annotate Fides resources.
"""


Expand All @@ -21,21 +21,21 @@ def annotate(ctx: click.Context) -> None:
"-a",
"--all-members",
is_flag=True,
help="Annotate all dataset members, not just fields",
help="Annotate all parts of the dataset including schemas and tables.",
)
@click.option(
"-v",
"--validate",
is_flag=True,
default=False,
help="Strictly validate annotation inputs.",
help="Validate annotation inputs.",
)
@with_analytics
def annotate_dataset(
ctx: click.Context, input_filename: str, all_members: bool, validate: bool
) -> None:
"""
Guided flow for annotating datasets. The dataset file will be edited in-place.
Interactively annotate a dataset file in-place.
"""
config = ctx.obj["CONFIG"]
_annotate_dataset.annotate_dataset(
Expand Down
49 changes: 20 additions & 29 deletions src/fides/cli/commands/core.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
"""Contains all of the core CLI commands for fides."""
from typing import Optional

import click
import rich_click as click

from fides.cli.options import (
dry_flag,
fides_key_option,
manifests_dir_argument,
verbose_flag,
)
from fides.cli.options import dry_flag, manifests_dir_argument, verbose_flag
from fides.cli.utils import pretty_echo, print_divider, with_analytics
from fides.core import audit as _audit
from fides.core import evaluate as _evaluate
Expand All @@ -24,13 +19,13 @@
@click.option(
"--diff",
is_flag=True,
help="Include any changes between server and local resources in the command output",
help="Print any diffs between the local & server objects",
)
@manifests_dir_argument
@with_analytics
def push(ctx: click.Context, dry: bool, diff: bool, manifests_dir: str) -> None:
"""
Validate local manifest files and persist any changes via the API server.
Parse local manifest files and upload them to the server.
"""

config = ctx.obj["CONFIG"]
Expand All @@ -47,19 +42,28 @@ def push(ctx: click.Context, dry: bool, diff: bool, manifests_dir: str) -> None:
@click.command()
@click.pass_context
@manifests_dir_argument
@fides_key_option
@click.option(
"--fides-key",
"-k",
help="The fides_key of a specific policy to evaluate.",
default="",
)
@click.option(
"-m",
"--message",
help="A message that you can supply to describe the context of this evaluation.",
help="Describe the context of this evaluation.",
)
@click.option(
"-a",
"--audit",
is_flag=True,
help="Raise errors if resources are missing attributes required for building a data map.",
help="Validate that the objects in this evaluation produce a valid data map.",
)
@click.option(
"--dry",
is_flag=True,
help="Do not upload objects or results to the Fides webserver.",
)
@dry_flag
@with_analytics
def evaluate(
ctx: click.Context,
Expand All @@ -70,12 +74,7 @@ def evaluate(
dry: bool,
) -> None:
"""
Compare your System's Privacy Declarations with your Organization's Policy Rules.

All local resources are applied to the server before evaluation.

If your policy evaluation fails, it is expected that you will need to
either adjust your Privacy Declarations, Datasets, or Policies before trying again.
Evaluate System-level Privacy Declarations against Organization-level Policy Rules.
"""

config = ctx.obj["CONFIG"]
Expand Down Expand Up @@ -127,10 +126,7 @@ def evaluate(
@with_analytics
def parse(ctx: click.Context, manifests_dir: str, verbose: bool = False) -> None:
"""
Reads the resource files that are stored in MANIFESTS_DIR and its subdirectories to verify
the validity of all manifest files.

If the taxonomy is invalid, this command prints the error messages and triggers a non-zero exit code.
Parse all Fides objects located in the supplied directory.
"""
taxonomy = _parse.parse(manifests_dir=manifests_dir)
if verbose:
Expand All @@ -149,12 +145,7 @@ def parse(ctx: click.Context, manifests_dir: str, verbose: bool = False) -> None
@with_analytics
def pull(ctx: click.Context, manifests_dir: str, all_resources: Optional[str]) -> None:
"""
Update local resource files by their fides_key to match their server versions.

Alternatively, with the "--all" flag all resources from the server will be pulled
down into a local file.

The pull is aborted if there are unstaged or untracked files in the manifests dir.
Update local resource files based on the state of the objects on the server.
"""

# Make the resources that are pulled configurable
Expand Down
Loading