CLI: Port "ara playbook list" command from ara 0.x

This is the first command being ported and so it includes the base
framework for integrating other commands with cliff.

The docs are also re-arranged to include the new commands, some
examples, as well as the existing ara-manage commands.

Change-Id: Ia758e4b70ec0a6821e97b5b66d123dfe33cc63d3
This commit is contained in:
David Moreau Simard 2020-07-08 20:18:38 -04:00
parent d247f6c0f8
commit 201a8d95f4
No known key found for this signature in database
GPG Key ID: 7D4729EC4E64E8B7
7 changed files with 235 additions and 3 deletions

0
ara/cli/__init__.py Normal file
View File

89
ara/cli/base.py Normal file
View File

@ -0,0 +1,89 @@
# Copyright (c) 2020 The ARA Records Ansible authors
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import logging
import os
import sys
import pbr.version
from cliff.app import App
from cliff.commandmanager import CommandManager
CLIENT_VERSION = pbr.version.VersionInfo("ara").release_string()
log = logging.getLogger(__name__)
def global_arguments(parser):
# fmt: off
parser.add_argument(
"--client",
metavar="<client>",
default=os.environ.get("ARA_API_CLIENT", "offline"),
help=("API client to use, defaults to ARA_API_CLIENT or 'offline'"),
)
parser.add_argument(
"--server",
metavar="<url>",
default=os.environ.get("ARA_API_SERVER", "http://127.0.0.1:8000"),
help=("API server endpoint if using http client, defaults to ARA_API_SERVER or 'http://127.0.0.1:8000'"),
)
parser.add_argument(
"--timeout",
metavar="<seconds>",
default=os.environ.get("ARA_API_TIMEOUT", 30),
help=("Timeout for requests to API server, defaults to ARA_API_TIMEOUT or 30"),
)
parser.add_argument(
"--username",
metavar="<username>",
default=os.environ.get("ARA_API_USERNAME", None),
help=("API server username for authentication, defaults to ARA_API_USERNAME or None"),
)
parser.add_argument(
"--password",
metavar="<password>",
default=os.environ.get("ARA_API_PASSWORD", None),
help=("API server password for authentication, defaults to ARA_API_PASSWORD or None"),
)
parser.add_argument(
"--insecure",
action="store_true",
default=os.environ.get("ARA_API_INSECURE", False),
help=("Ignore SSL certificate validation, defaults to ARA_API_INSECURE or False"),
)
# fmt: on
return parser
class AraCli(App):
def __init__(self):
super(AraCli, self).__init__(
description="A CLI client to query ARA API servers",
version=CLIENT_VERSION,
command_manager=CommandManager("ara.cli"),
deferred_help=True,
)
def build_option_parser(self, description, version):
parser = super(AraCli, self).build_option_parser(description, version)
return parser
def initialize_app(self, argv):
log.debug("initialize_app")
def prepare_to_run_command(self, cmd):
log.debug("prepare_to_run_command: %s", cmd.__class__.__name__)
def clean_up(self, cmd, result, err):
log.debug("clean_up %s", cmd.__class__.__name__)
if err:
log.debug("got an error: %s", err)
def main(argv=sys.argv[1:]):
aracli = AraCli()
return aracli.run(argv)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))

99
ara/cli/playbook.py Normal file
View File

@ -0,0 +1,99 @@
# Copyright (c) 2020 The ARA Records Ansible authors
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import logging
from cliff.lister import Lister
from ara.cli.base import global_arguments
from ara.clients.utils import get_client
class PlaybookList(Lister):
""" Returns a list of playbooks based on search queries """
log = logging.getLogger(__name__)
def get_parser(self, prog_name):
parser = super(PlaybookList, self).get_parser(prog_name)
parser = global_arguments(parser)
# fmt: off
# Playbook search arguments and ordering as per ara.api.filters.PlaybookFilter
parser.add_argument(
"--label",
metavar="<label>",
default=None,
help=("List playbooks matching the provided label"),
)
parser.add_argument(
"--name",
metavar="<name>",
default=None,
help=("List playbooks matching the provided name (full or partial)"),
)
parser.add_argument(
"--path",
metavar="<path>",
default=None,
help=("List playbooks matching the provided path (full or partial)"),
)
parser.add_argument(
"--status",
metavar="<status>",
default=None,
help=("List playbooks matching a specific status ('completed', 'running', 'failed')"),
)
parser.add_argument(
"--order",
metavar="<order>",
default="-started",
help=(
"Orders results by a field ('id', 'created', 'updated', 'started', 'ended', 'duration')\n"
"Defaults to '-started' descending so the most recent playbook is at the top.\n"
"The order can be reversed by omitting the '-': ara playbook list --order=started"
),
)
parser.add_argument(
"--limit",
metavar="<limit>",
default=100,
help=("Returns the first <limit> determined by the ordering. Defaults to 100.")
)
# fmt: on
return parser
def take_action(self, args):
client = get_client(
client=args.client,
endpoint=args.server,
timeout=args.timeout,
username=args.username,
password=args.password,
verify=False if args.insecure else True,
)
query = {}
if args.label is not None:
query["label"] = args.label
if args.name is not None:
query["name"] = args.name
if args.path is not None:
query["path"] = args.path
if args.status is not None:
query["status"] = args.status
query["order"] = args.order
query["limit"] = args.limit
playbooks = client.get("/api/v1/playbooks", **query)
columns = ("id", "status", "path", "started", "duration")
# fmt: off
return (
columns, (
[playbook[column] for column in columns]
for playbook in playbooks["results"]
)
)
# fmt: on

View File

@ -1,5 +1,44 @@
ara-manage commandline interface
================================
CLI: ara API client
===================
Installing ara provides an ``ara`` command line interface client in order to
query API servers from shell scripts or from the terminal.
ara
---
.. command-output:: ara --help
ara playbook list
-----------------
.. command-output:: ara playbook list --help
Query a running API server for the 10 latest failed playbooks:
.. code-block:: bash
ara playbook list --client http \
--server https://api.demo.recordsansible.org \
--status failed \
--limit 10
Get a list of playbooks matching a partial path and order the results by
duration using the default offline API client:
.. code-block:: bash
ara playbook list --path="playbooks/site.yaml" --order=duration
Get a list of playbooks and format the results as json or yaml instead of pretty tables:
.. code-block:: bash
ara playbook list -f json
ara playbook list -f yaml
CLI: ara-manage (django)
========================
``ara-manage`` is a command provided by ARA when the API server dependencies
are installed.

View File

@ -10,10 +10,10 @@ Table of Contents
Frequently asked questions <faq>
Installing ARA <installation>
CLI: ara-manage <ara-manage>
Configuring Ansible to use ARA <ansible-configuration>
Configuring the ARA Ansible plugins <ara-plugin-configuration>
Configuring the ARA API server <api-configuration>
CLI: ara and ara-manage <cli>
API: Authentication and security <api-security>
API: Endpoint documentation <api-documentation>
API: Usage with built-in clients <api-usage>

View File

@ -1,5 +1,6 @@
pbr!=2.1.0,>=2.0.0 # Apache-2.0
cliff
requests>=2.14.2
# API server dependencies can be found in setup.cfg extras

View File

@ -31,8 +31,12 @@ packages =
[entry_points]
console_scripts =
ara = ara.cli.base:main
ara-manage = ara.server.__main__:main
ara.cli =
playbook list = ara.cli.playbook:PlaybookList
[extras]
server=
Django>=2.1.5,<3.0