A CLI application and Python API for interacting with PlanDev.
Project description
Aerie-CLI
Aerie-CLI provides a command-line interface and user-extendable Python API for interacting with an instance of PlanDev.
Note: this project is an informal CLI and is not maintained by the MPSA PlanDev team.
Aerie -> PlanDev Rebrand
PlanDev was formerly known as Aerie and is now named PlanDev. While we've updated most documentation and external references, some legacy mentions of the old product name may remain as we complete the transition.
What to know:
- The planning product, including modeling, simulation, scheduling and constraint-checking, is now named PlanDev
- The sequencing product, including the sequence editor, workspaces, and actions, is now named SeqDev
- All features and functionality remain the same
- Currently, repository names, package names and other internal code references will retain their existing names, and deployment/migration procedures have not changed
- In a future release, our repository and/or package names may change. If so, this will be communicated to users via release notes and normal communication channels
For the latest documentation, visit: PlanDev Documentation
Getting Started
This short procedure will get you up and running with the basics of the CLI.
-
Install/update to Python >= 3.6
-
Install Aerie-CLI from Github:
python3 -m pip install git+https://github.com/NASA-AMMOS/aerie-cli.git@main
-
Configure access to an PlanDev host
-
If you've been provided a Configuration JSON, reference that file
-
If you don't have already have a Configuration JSON, copy the following to a JSON file for a local PlanDev deployment (replacing the username with your own):
[ { "name": "localhost", "graphql_url": "http://localhost:8080/v1/graphql", "gateway_url": "http://localhost:9000", "username": "my_username" } ]
-
Load either your given configuration(s) or the configuration above into Aerie-CLI:
aerie-cli configurations load -i JSON_FILE
-
-
Activate a configuration to start a session with a PlanDev host:
➜ aerie-cli activate 1) localhost Select an option: 1
-
Try out a command to list the plans in PlanDev:
aerie-cli plans list
-
Use the
--helpflag on any command to see available subcommands and parameters. For example:aerie-cli --help ... aerie-cli plans --help ... aerie-cli plans download --help
CLI Usage
Setup
Aerie-CLI uses configurations to define different PlanDev hosts. Define configurations by either loading JSON configurations or manually via the CLI. Configurations persist on a per-user basis and may be shared between installations.
Defining Hosts with a Configuration File
If you have a file of configurations to load, you can use the configurations load command:
aerie-cli configurations load -i JSON_FILE
You can view the configurations you've loaded with the configurations list command:
➜ aerie-cli configurations list
Configuration file location: /Users/<username>/Library/Application Support/aerie_cli/config.json
PlanDev Host Configurations
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Host Name ┃ GraphQL API URL ┃ PlanDev Gateway URL ┃ Username ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ localhost │ http://localhost:8080/v1/graphql │ http://localhost:9000 │ │
└───────────┴──────────────────────────────────┴───────────────────────┴──────────┘
Defining hosts via the CLI
If you haven't been provided a JSON configuration for a host, you can create a configuration by running aerie-cli configurations create and follow the prompts.
Full Specification
Each configuration is stored as JSON object list entry in the configuration file provided with the configurations list command. The full contents of a host configuration are:
| Field | Description | Required |
|---|---|---|
name |
User-facing name of the host | Yes |
graphql_url |
URL of the PlanDev instance's Hasura GraphQL API | Yes |
gateway_url |
URL of the PlanDev instance's Gateway | Yes |
username |
Username for authentication with PlanDev | No |
external_auth |
Specification for external authentication required to reach a PlanDev instance. See Configuring for External Authentication for details | No |
Sessions and Roles
Aerie-CLI maintains a persistent "session" with a PlanDev instance so multiple commands can run without needing to re-authenticate. To start a session, use the activate command:
➜ aerie-cli activate
1) localhost
...
Select an option: 1
PlanDev uses "roles" to adjust what a client is permitted to do. To view the active configuration name and current role, use the status command:
➜ aerie-cli status
Active configuration: localhost
Active role: viewer
The default role is configured by PlanDev. To change the selected role for the active Aerie-CLI session, use the role command:
➜ aerie-cli role
Active Role: viewer
1) aerie_admin
2) user
3) viewer
Select an option: 1
Changed role to: aerie_admin
At any time, the active session can be closed with the deactivate command.
Commands
Commands are the main functions available via the CLI and are broken down into several levels. For example, the top-level plans command has sub-commands for list, upload, simulate, and more. From any command or sub-command, use the --help flag to learn about what commands are available or what arguments are required.
Help at script level:
aerie-cli --help
Help at command level:
aerie-cli plans --help
Help at sub-command level:
aerie-cli plans download --help
Interactive vs. Non-Interactive
If a command is invoked without the necessary arugments, interactive prompts are provided:
➜ aerie-cli plans download
Id: 42
Output: sample-output.json
Alternatively, arguments can be provided using flags:
➜ aerie-cli plans download --id 42 --output sample-output.json
Advanced Topics
Configuring for External Authentication
Aerie-CLI configurations include a mechanism to authenticate against an external authentication service which may require additional credentials as cookies for accessing PlanDev. Aerie-CLI will issue a post request with given JSON data to a provided authentication endpoint and persist any returned cookies in a browser-like manner for the remainder of the Aerie-CLI session.
An external authentication service is configured using the key external_auth in the JSON configuration file as follows:
{
"name": "my_host",
"graphql_url": "https://hostname/v1/graphql",
"gateway_url": "https://hostname/gateway",
"username": "my_username",
"external_auth": {
"auth_url": "https://auth_service/route",
"static_post_vars": {
"username": "my_username"
},
"secret_post_vars": [
"password"
]
}
}
Here, static_post_vars is an object containing fixed values to include in the post request payload such as usernames and other persistent, non-sensitive fields. secret_post_vars is a list of keys for credentials which may be sensitive or time-varying. The user will be prompted to provide the "secret" values using hidden entry in the terminal when activating a session with external authentication.
In this example, the user would be prompted to enter a value for "password" and, assuming they enter "my_password", the post request JSON would include the following:
{
"username": "my_username",
"password": "my_password"
}
Using a Hasura Admin Secret
In some cases, an admin secret may be used to permit otherwise prohibited requests through Hasura (the software behind the PlanDev API). When running a command, the user may add the --hasura-admin-secret flag after the aerie-cli command to use these elevated privileges for the following command.
Python API
Quickstart Guide
Instead of using the CLI for interactive use cases, the underlying classes and methods behind Aerie-CLI can be invoked directly in Python scripts.
The key constructs are:
aerie_cli.aerie_host.AerieHost: An abstraction for a PlanDev Host, including methods for authentication and issuing requests to the PlanDev API.aerie_cli.aerie_client.AerieClient: A class containing common requests and reusable logic to interact with data in PlanDev.
The following example defines an AerieHost using the necessary URLs, authenticates with a command-line prompt for the user's password, and issues a simple request using one of the built-in requests.
from aerie_cli.aerie_client import AerieClient
from aerie_cli.aerie_host import AerieHost
from getpass import getpass
# These URLs define the PlanDev host
GRAPHQL_URL = "http://myhostname:8080/v1/graphql"
GATEWAY_URL = "http://myhostname:9000"
# User credentials. The password may be omitted on PlanDev instances with authentication disabled
USERNAME = "myusername"
PASSWORD = getpass(prompt='Password: ')
# Define the host and provide user credentials
aerie_host = AerieHost(GRAPHQL_URL, GATEWAY_URL)
aerie_host.authenticate(USERNAME, PASSWORD)
# AerieClient takes in a host and returns an object to issue requests to that host
client = AerieClient(aerie_host)
# Simple example of a request to get an activity plan using the plan ID
plan = client.get_activity_plan_by_id(42)
print(plan.name)
Look through the available methods in the provided AerieClient class to find ones that suit your needs.
Adding Methods
If you need to write a custom query, you can extend the AerieClient class and add your own method. Access the PlanDev host using the aerie_host property. For example:
# ...
class MyCustomAerieClient(AerieClient):
def get_plan_id_by_name(self, plan_name: str) -> int:
my_query = """
query GetPlanIdByName($plan_name: String!) {
plan(where: { name: { _eq: $plan_name } }) {
id
}
}
"""
# Pass variables for the query as keyword arguments
resp = self.aerie_host.post_to_graphql(
my_query,
plan_name=plan_name
)
return resp[0]["id"]
Now, you can use your custom method like any other:
# ...
client = MyCustomAerieClient(aerie_host)
plan_id = client.get_plan_id_by_name("my-plan-name")
print(plan_id)
Using the Active CLI Session
If your application will be run by a user who may also be using the CLI, you may reduce the amount of code required to configure an PlanDev host and instead just use the active session. Aerie-CLI provides a utility to retrieve an AerieClient instance from the active CLI session:
from aerie_cli.utils.sessions import get_active_session_client
# client is an instance of `AerieClient`
client = get_active_session_client()
# Issue requests like normal
plan = client.get_activity_plan_by_id(...)
Advanced Authentication
If you have needs for authentication (e.g., a custom token system) that aren't provided by Aerie-CLI, you can use any features supported by the Python requests module's Session class. Instantiate a session object, manipulate/add headers/cookies/SSL certificates/etc. as necessary, and use to instantiate an AerieHostSession:
# ...
from requests import Session
my_custom_requests_session = Session()
# Manipulate as necessary
# ...
aerie_host = AerieHost(
GRAPHQL_URL,
GATEWAY_URL,
session=my_custom_requests_session
)
aerie_host.authenticate(...)
client = AerieClient(aerie_host)
# Use client as normal
Contributing
Contributor Installation
The recommended develper installation method is in a virutual environment with an editatable install via Pip.
See this primer or virtual environments to get set up. A quick and easy method is using Python's native venv package from the root of the Aerie-CLI repo:
python3 -m venv venv
source venv/bin/activate
Then, install Aerie-CLI in editable mode via Pip:
python3 -m pip install -e .
Now, your installation of Aerie-CLI will update as you make changes to the source code.
Dependency Management
Dependencies are currently managed via Poetry. For more information on dependency and project management, see the poetry docs.
Testing
Aerie-CLI has unit tests and integration tests built with the pytest library.
Unit Tests
Unit tests can be run anytime and reference local test files. test_aerie_client.py is where unit tests are added to exercise particular methods of the AerieClient class using mocked PlanDev API responses.
Run the unit tests using pytest from the tests/unit_tests directory:
cd tests
python3 -m pytest .
Integration Tests
A separate suite of tests is designed to validate CLI functionality against a local instance of PlanDev. See the integration testing documentation for details.
The integration tests are based on Typer testing documentation found here.
Releases
Aerie-CLI generally follows the gitflow workflow model for managing releases:
- Features are merged to the
developbranch. - Release branches are made from develop and merge in
mainfor testing. - Releases are made from the tip of the
mainbranch. - Hotfix branches can be made from
mainto resolve bugs without needing to incorporate new features.
Version numbers are managed using semantic versioning in pyproject.toml:
- The version tag on
developis fixed at0.0.0-dev0 - Release versions are incremented on release branches before being merged to main.
The full workflow for releasing a new version of Aerie-CLI:
- Make a release branch from
develop - Merge
maininto the release branch - Commit a version increment in
pyproject.toml - Open a PR to merge the release branch into
mainand verify CI passes - Merge the PR and tag a release on
main
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aerie_cli-2.11.1.tar.gz.
File metadata
- Download URL: aerie_cli-2.11.1.tar.gz
- Upload date:
- Size: 49.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da7cc5f833555e473a42e7780344dfb6cd1e91ba69b97ed097701f0a3316fc68
|
|
| MD5 |
fb3fd7c5bcba7e33d924edaffabed063
|
|
| BLAKE2b-256 |
40df8c3d9986c158cbba0e166ad3cb8ddcacdea66aaf00f0717aedc6fa3fdf55
|
Provenance
The following attestation bundles were made for aerie_cli-2.11.1.tar.gz:
Publisher:
publish.yml on NASA-AMMOS/aerie-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aerie_cli-2.11.1.tar.gz -
Subject digest:
da7cc5f833555e473a42e7780344dfb6cd1e91ba69b97ed097701f0a3316fc68 - Sigstore transparency entry: 1479744843
- Sigstore integration time:
-
Permalink:
NASA-AMMOS/aerie-cli@7eab9d2ae8f01cdf20ab7213f2b1891ef3c00a3d -
Branch / Tag:
refs/tags/v2.11.1 - Owner: https://github.com/NASA-AMMOS
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7eab9d2ae8f01cdf20ab7213f2b1891ef3c00a3d -
Trigger Event:
push
-
Statement type:
File details
Details for the file aerie_cli-2.11.1-py3-none-any.whl.
File metadata
- Download URL: aerie_cli-2.11.1-py3-none-any.whl
- Upload date:
- Size: 54.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2dcfca09f5e2b8a25f4d5ffe18835d93de83af3a60dd00d97e4aca42b29dc0b2
|
|
| MD5 |
cc6fb9f25f3deba382ff44be1075fcf4
|
|
| BLAKE2b-256 |
4e59163d7f62a806518c450d91c65b9432b9bd40ddcc81bf4abb590e75a784d9
|
Provenance
The following attestation bundles were made for aerie_cli-2.11.1-py3-none-any.whl:
Publisher:
publish.yml on NASA-AMMOS/aerie-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aerie_cli-2.11.1-py3-none-any.whl -
Subject digest:
2dcfca09f5e2b8a25f4d5ffe18835d93de83af3a60dd00d97e4aca42b29dc0b2 - Sigstore transparency entry: 1479746804
- Sigstore integration time:
-
Permalink:
NASA-AMMOS/aerie-cli@7eab9d2ae8f01cdf20ab7213f2b1891ef3c00a3d -
Branch / Tag:
refs/tags/v2.11.1 - Owner: https://github.com/NASA-AMMOS
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7eab9d2ae8f01cdf20ab7213f2b1891ef3c00a3d -
Trigger Event:
push
-
Statement type: