-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: automate cmd reference docs generation (#458)
A script to help generate CLI CMD reference docs.
- Loading branch information
1 parent
59cada8
commit d826556
Showing
35 changed files
with
840 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
"""This module generates reference docs for pebble CLI commands.""" | ||
|
||
import logging | ||
import os | ||
import re | ||
import subprocess | ||
import typing | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
logging.basicConfig(level=logging.INFO) | ||
|
||
AUTOMATED_START_MARKER = "<!-- START AUTOMATED OUTPUT -->" | ||
AUTOMATED_STOP_MARKER = "<!-- END AUTOMATED OUTPUT -->" | ||
|
||
TEMPLATE = """\ | ||
(reference_pebble_{command}_command)= | ||
# {command} command | ||
{description} | ||
## Usage | ||
<!-- START AUTOMATED OUTPUT --> | ||
```{{terminal}} | ||
:input: command | ||
``` | ||
<!-- END AUTOMATED OUTPUT --> | ||
""" | ||
|
||
|
||
def get_all_commands() -> typing.List[typing.Tuple[str, str]]: | ||
process = subprocess.run( | ||
["go", "run", "../cmd/pebble", "help", "--all"], | ||
text=True, | ||
capture_output=True, | ||
check=True, | ||
) | ||
return sorted( | ||
line.split(maxsplit=1) | ||
for line in process.stdout.splitlines() | ||
if line.startswith(" ") | ||
) | ||
|
||
|
||
def get_command_help_output(cmd: typing.List[str]) -> str: | ||
return subprocess.run(cmd, text=True, capture_output=True, check=True).stdout | ||
|
||
|
||
def render_code_block_cmd(text: str, cmd: str) -> str: | ||
return re.sub(r"(:input: ).*$", rf"\1{cmd}", text, count=1, flags=re.MULTILINE) | ||
|
||
|
||
def render_code_block_output(text: str, output: str) -> str: | ||
start_pos = text.find(AUTOMATED_START_MARKER) | ||
end_pos = text.find(AUTOMATED_STOP_MARKER) + len(AUTOMATED_STOP_MARKER) | ||
return text[:start_pos] + output + text[end_pos:] | ||
|
||
|
||
def update_toc(cmds: typing.List[typing.Tuple[str, str]]): | ||
index_page = "reference/cli-commands/cli-commands.md" | ||
with open(index_page, "r") as file: | ||
text = file.read() | ||
|
||
start_index = text.find("```{toctree}") | ||
end_index = text.find("```", start_index + 1) + 3 | ||
cmd_list = "\n".join(f"{cmd[0]} <{cmd[0]}>" for cmd in cmds) | ||
|
||
toc_tree = f"""\ | ||
```{{toctree}} | ||
:titlesonly: | ||
:maxdepth: 1 | ||
{cmd_list} | ||
```""" | ||
|
||
text = text[:start_index] + toc_tree + text[end_index:] | ||
with open(index_page, "w") as file: | ||
file.write(text) | ||
|
||
|
||
def create_file_if_not_exist(filepath: str, cmd: str) -> bool: | ||
file_existed = os.path.exists(filepath) | ||
if not file_existed: | ||
logger.info( | ||
"The doc for command %s doesn't exist, creating from the template.", cmd | ||
) | ||
with open(filepath, "w") as file: | ||
file.write(TEMPLATE) | ||
return file_existed | ||
|
||
|
||
def generate_help_command_and_output(cmd: str) -> typing.Tuple[str, str]: | ||
help_cmd = ["pebble", "help"] if cmd == "help" else ["pebble", cmd, "--help"] | ||
help_cmd_str = " ".join(help_cmd) | ||
help_cmd_output = get_command_help_output(help_cmd).strip() | ||
|
||
output = f"""\ | ||
<!-- START AUTOMATED OUTPUT --> | ||
```{{terminal}} | ||
:input: {help_cmd_str} | ||
{help_cmd_output} | ||
``` | ||
<!-- END AUTOMATED OUTPUT -->""" | ||
|
||
return help_cmd, output | ||
|
||
|
||
def process_command(cmd: str, description: str): | ||
logger.info("Processing doc for command %s.", cmd) | ||
|
||
file_path = f"reference/cli-commands/{cmd}.md" | ||
file_existed = create_file_if_not_exist(file_path, cmd) | ||
|
||
with open(file_path, "r") as file: | ||
text = file.read() | ||
|
||
if AUTOMATED_START_MARKER not in text: | ||
logger.info( | ||
'The marker for automated doc generation is not found in the "%s" doc, ignore.', | ||
cmd, | ||
) | ||
return | ||
|
||
help_cmd, help_cmd_output = generate_help_command_and_output(cmd) | ||
description = f"The `{cmd}` command is used to {description.lower()}." | ||
|
||
if not file_existed: | ||
text = text.format(command=cmd, description=description) | ||
|
||
text = render_code_block_cmd(text, help_cmd) | ||
text = render_code_block_output(text, help_cmd_output) | ||
|
||
with open(file_path, "w") as file: | ||
file.write(text) | ||
|
||
|
||
def main(): | ||
cmds = get_all_commands() | ||
for cmd, description in cmds: | ||
process_command(cmd, description) | ||
|
||
logger.info("Update toc tree.") | ||
update_toc(cmds) | ||
logger.info("Done!") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
(reference_pebble_add-identities_command)= | ||
# add-identities command | ||
|
||
The `add-identities` command is used to add new identities. | ||
|
||
## Usage | ||
|
||
<!-- START AUTOMATED OUTPUT --> | ||
```{terminal} | ||
:input: pebble add-identities --help | ||
Usage: | ||
pebble add-identities [add-identities-OPTIONS] | ||
The add-identities command adds one or more new identities. | ||
The named identities must not yet exist. | ||
For example, to add a local admin named "bob", use YAML like this: | ||
> identities: | ||
> bob: | ||
> access: admin | ||
> local: | ||
> user-id: 42 | ||
[add-identities command options] | ||
--from= Path of YAML file to read identities from (required) | ||
``` | ||
<!-- END AUTOMATED OUTPUT --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
(reference_pebble_add_command)= | ||
# add command | ||
|
||
The `add` command is used to dynamically add a layer to the plan's layers. | ||
|
||
## Usage | ||
|
||
<!-- START AUTOMATED OUTPUT --> | ||
```{terminal} | ||
:input: pebble add --help | ||
Usage: | ||
pebble add [add-OPTIONS] <label> <layer-path> | ||
The add command reads the plan's layer YAML from the path specified and | ||
appends a layer with the given label to the plan's layers. If --combine | ||
is specified, combine the layer with an existing layer that has the given | ||
label (or append if the label is not found). | ||
[add command options] | ||
--combine Combine the new layer with an existing layer that has the given label (default is to append) | ||
``` | ||
<!-- END AUTOMATED OUTPUT --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
(reference_pebble_changes_command)= | ||
# changes command | ||
|
||
The `changes` command is used to list system changes. | ||
|
||
## Usage | ||
|
||
<!-- START AUTOMATED OUTPUT --> | ||
```{terminal} | ||
:input: pebble changes --help | ||
Usage: | ||
pebble changes [changes-OPTIONS] [<service>] | ||
The changes command displays a summary of system changes performed recently. | ||
[changes command options] | ||
--abs-time Display absolute times (in RFC 3339 format). Otherwise, display relative times up to 60 days, then YYYY-MM-DD. | ||
``` | ||
<!-- END AUTOMATED OUTPUT --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
(reference_pebble_checks_command)= | ||
# checks command | ||
|
||
The `checks` command is used to query the status of configured health checks. | ||
|
||
## Usage | ||
|
||
<!-- START AUTOMATED OUTPUT --> | ||
```{terminal} | ||
:input: pebble checks --help | ||
Usage: | ||
pebble checks [checks-OPTIONS] [<check>...] | ||
The checks command lists status information about the configured health | ||
checks, optionally filtered by level and check names provided as positional | ||
arguments. | ||
[checks command options] | ||
--level=[alive|ready] Check level to filter for | ||
``` | ||
<!-- END AUTOMATED OUTPUT --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,45 @@ | ||
# CLI Commands | ||
|
||
Pebble uses subcommands, like some other command-line tools such as go tool or git. | ||
|
||
Subcommands are keywords that invoke a new set of options and features, and each Pebble subcommand has its own set of flags. | ||
|
||
Here's the list of all Pebble subcommands: | ||
|
||
```{toctree} | ||
:titlesonly: | ||
:maxdepth: 1 | ||
add <add> | ||
add-identities <add-identities> | ||
changes <changes> | ||
checks <checks> | ||
exec <exec> | ||
health <health> | ||
help <help> | ||
identities <identities> | ||
identity <identity> | ||
logs <logs> | ||
ls <ls> | ||
mkdir <mkdir> | ||
notice <notice> | ||
notices <notices> | ||
notify <notify> | ||
okay <okay> | ||
plan <plan> | ||
pull <pull> | ||
push <push> | ||
remove-identities <remove-identities> | ||
replan <replan> | ||
restart <restart> | ||
rm <rm> | ||
run <run> | ||
services <services> | ||
signal <signal> | ||
start <start> | ||
stop <stop> | ||
tasks <tasks> | ||
update-identities <update-identities> | ||
version <version> | ||
warnings <warnings> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
(reference_pebble_exec_command)= | ||
# exec command | ||
|
||
The `exec` command is used to execute a remote command and wait for it to finish. | ||
|
||
## Usage | ||
|
||
<!-- START AUTOMATED OUTPUT --> | ||
```{terminal} | ||
:input: pebble exec --help | ||
Usage: | ||
pebble exec [exec-OPTIONS] <command> | ||
The exec command runs a remote command and waits for it to finish. The local | ||
stdin is sent as the input to the remote process, while the remote stdout and | ||
stderr are output locally. | ||
To avoid confusion, exec options may be separated from the command and its | ||
arguments using "--", for example: | ||
pebble exec --timeout 10s -- echo -n foo bar | ||
[exec command options] | ||
-w= Working directory to run command in | ||
--env= Environment variable to set (in 'FOO=bar' format) | ||
--uid= User ID to run command as | ||
--user= Username to run command as (user's UID must match uid if both present) | ||
--gid= Group ID to run command as | ||
--group= Group name to run command as (group's GID must match gid if both present) | ||
--timeout= Timeout after which to terminate command | ||
--context= Inherit the context of the named service (overridden by -w, --env, --uid/user, --gid/group) | ||
-t Allocate remote pseudo-terminal and connect stdout to it (default if stdout is a TTY) | ||
-T Disable remote pseudo-terminal allocation | ||
-i Interactive mode: connect stdin to the pseudo-terminal (default if stdin and stdout are TTYs) | ||
-I Disable interactive mode and use a pipe for stdin | ||
``` | ||
<!-- END AUTOMATED OUTPUT --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
(reference_pebble_health_command)= | ||
# health command | ||
|
||
The `health` command is used to query health of checks. | ||
|
||
## Usage | ||
|
||
<!-- START AUTOMATED OUTPUT --> | ||
```{terminal} | ||
:input: pebble health --help | ||
Usage: | ||
pebble health [health-OPTIONS] [<check>...] | ||
The health command queries the health of configured checks. | ||
It returns an exit code 0 if all the requested checks are healthy, or | ||
an exit code 1 if at least one of the requested checks are unhealthy. | ||
[health command options] | ||
--level=[alive|ready] Check level to filter for | ||
``` | ||
<!-- END AUTOMATED OUTPUT --> |
Oops, something went wrong.