{"id":18265176,"url":"https://github.com/nasa-ammos/aerie-cli","last_synced_at":"2025-04-04T21:31:36.736Z","repository":{"id":141227578,"uuid":"564629574","full_name":"NASA-AMMOS/aerie-cli","owner":"NASA-AMMOS","description":"An unofficial CLI for interacting with Aerie planning software ","archived":false,"fork":false,"pushed_at":"2025-01-31T19:13:22.000Z","size":60962,"stargazers_count":3,"open_issues_count":52,"forks_count":4,"subscribers_count":18,"default_branch":"develop","last_synced_at":"2025-04-03T16:35:27.968Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NASA-AMMOS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-11-11T05:54:25.000Z","updated_at":"2025-01-31T19:13:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"88fd6375-6ffe-4d3e-8c76-ab8d7b65375d","html_url":"https://github.com/NASA-AMMOS/aerie-cli","commit_stats":null,"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NASA-AMMOS%2Faerie-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NASA-AMMOS%2Faerie-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NASA-AMMOS%2Faerie-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NASA-AMMOS%2Faerie-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NASA-AMMOS","download_url":"https://codeload.github.com/NASA-AMMOS/aerie-cli/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247252200,"owners_count":20908643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T11:17:22.098Z","updated_at":"2025-04-04T21:31:31.727Z","avatar_url":"https://github.com/NASA-AMMOS.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Aerie-CLI\n\nAerie-CLI provides a command-line interface and user-extendable Python API for interacting with an instance of Aerie.\n\n\u003e Note: this project is an informal CLI and is _not_ maintained by the MPSA Aerie team.\n\n## Getting Started\n\nThis short procedure will get you up and running with the basics of the CLI.\n\n1. Install/update to Python \u003e= 3.6\n\n2. Install Aerie-CLI from Github:\n\n   ```sh\n   python3 -m pip install git+https://github.com/NASA-AMMOS/aerie-cli.git@main\n   ```\n\n3. Configure access to an Aerie host\n\n   1. If you've been provided a Configuration JSON, reference that file\n\n   2. If you don't have already have a Configuration JSON, copy the following to a JSON file for a local Aerie deployment (replacing the username with your own):\n\n      ```json\n      [\n        {\n          \"name\": \"localhost\",\n          \"graphql_url\": \"http://localhost:8080/v1/graphql\",\n          \"gateway_url\": \"http://localhost:9000\",\n          \"username\": \"my_username\"\n        }\n      ]\n      ```\n\n   3. Load either your given configuration(s) or the configuration above into Aerie-CLI:\n\n      ```sh\n      aerie-cli configurations load -i JSON_FILE\n      ```\n\n4. Activate a configuration to start a session with an Aerie host:\n\n   ```sh\n   ➜  aerie-cli activate\n      1) localhost\n      Select an option: 1\n   ```\n\n5. Try out a command to list the plans in Aerie:\n\n   ```sh\n   aerie-cli plans list\n   ```\n\n6. Use the `--help` flag on any command to see available subcommands and parameters. For example:\n\n   ```sh\n   aerie-cli --help\n   ...\n   aerie-cli plans --help\n   ...\n   aerie-cli plans download --help\n   ```\n\n---\n\n## CLI Usage\n\n### Setup\n\nAerie-CLI uses configurations to define different Aerie 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.\n\n#### Defining Hosts with a Configuration File\n\nIf you have a file of configurations to load, you can use the `configurations load` command:\n\n```sh\naerie-cli configurations load -i JSON_FILE\n```\n\nYou can view the configurations you've loaded with the `configurations list` command:\n\n```sh\n➜  aerie-cli configurations list\nConfiguration file location: /Users/\u003cusername\u003e/Library/Application Support/aerie_cli/config.json\n\n                                         Aerie Host Configurations\n┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓\n┃ Host Name ┃ GraphQL API URL                  ┃ Aerie Gateway URL     ┃ Username ┃\n┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩\n│ localhost │ http://localhost:8080/v1/graphql │ http://localhost:9000 │          │\n└───────────┴──────────────────────────────────┴───────────────────────┴──────────┘\n```\n\n#### Defining hosts via the CLI\n\nIf 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. \n\n#### Full Specification\n\nEach 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:\n\n| Field           | Description                                                                                                                                                                        | Required |\n| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |\n| `name`          | User-facing name of the host                                                                                                                                                       | Yes      |\n| `graphql_url`   | URL of the Aerie instance's Hasura GraphQL API                                                                                                                                     | Yes      |\n| `gateway_url`   | URL of the Aerie instance's Gateway                                                                                                                                                | Yes      |\n| `username`      | Username for authentication with Aerie                                                                                                                                             | No       |\n| `external_auth` | Specification for external authentication required to reach an Aerie instance. See [Configuring for External Authentication](#configuring-for-external-authentication) for details | No       |\n\n### Sessions and Roles\n\nAerie-CLI maintains a persistent \"session\" with an Aerie instance so multiple commands can run without needing to re-authenticate. To start a session, use the `activate` command:\n\n```sh\n➜  aerie-cli activate\n    1) localhost\n    ...\n    Select an option: 1\n```\n\nAerie uses \"roles\" to adjust what a client is permitted to do. To view the active configuration name and current role, use the `status` command:\n\n```sh\n➜  aerie-cli status\nActive configuration: localhost\nActive role: viewer\n```\n\nThe default role is configured by Aerie. To change the selected role for the active Aerie-CLI session, use the `role` command:\n\n```sh\n➜  aerie-cli role\nActive Role: viewer\n\t1) aerie_admin\n\t2) user\n\t3) viewer\nSelect an option: 1\nChanged role to: aerie_admin\n```\n\nAt any time, the active session can be closed with the `deactivate` command.\n\n### Commands\n\nCommands 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.\n\nHelp at script level:\n\n```sh\naerie-cli --help\n```\n\nHelp at command level:\n\n```sh\naerie-cli plans --help\n```\n\nHelp at sub-command level:\n\n```sh\naerie-cli plans download --help\n```\n\n#### Interactive vs. Non-Interactive\n\nIf a command is invoked without the necessary arugments, interactive prompts are provided:\n\n```sh\n➜  aerie-cli plans download\n    Id: 42\n    Output: sample-output.json\n```\n\nAlternatively, arguments can be provided using flags:\n\n```sh\n➜  aerie-cli plans download --id 42 --output sample-output.json\n```\n\n### Advanced Topics\n\n#### Configuring for External Authentication\n\nAerie-CLI configurations include a mechanism to authenticate against an external authentication service which may require additional credentials as cookies for accessing Aerie. 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.\n\nAn external authentication service is configured using the key `external_auth` in the JSON configuration file as follows:\n\n```json\n\n  {\n    \"name\": \"my_host\",\n    \"graphql_url\": \"https://hostname/v1/graphql\",\n    \"gateway_url\": \"https://hostname/gateway\",\n    \"username\": \"my_username\",\n    \"external_auth\": {\n      \"auth_url\": \"https://auth_service/route\",\n      \"static_post_vars\": {\n        \"username\": \"my_username\"\n      },\n      \"secret_post_vars\": [\n        \"password\"\n      ]\n    }\n  }\n```\n\nHere, `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.\n\nIn 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:\n\n```json\n{\n  \"username\": \"my_username\",\n  \"password\": \"my_password\"\n}\n```\n\n#### Using a Hasura Admin Secret\n\nIn some cases, an admin secret may be used to permit otherwise prohibited requests through Hasura (the software behind the Aerie 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. \n\n---\n\n## Python API\n\n### Quickstart Guide\n\nInstead of using the CLI for interactive use cases, the underlying classes and methods behind Aerie-CLI can be invoked directly in Python scripts.\n\nThe key constructs are:\n\n- `aerie_cli.aerie_host.AerieHost`: An abstraction for an Aerie Host, including methods for authentication and issuing requests to the Aerie API.\n- `aerie_cli.aerie_client.AerieClient`: A class containing common requests and reusable logic to interact with data in Aerie. \n\nThe 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.\n\n```py\nfrom aerie_cli.aerie_client import AerieClient\nfrom aerie_cli.aerie_host import AerieHost\n\nfrom getpass import getpass\n\n# These URLs define the Aerie host\nGRAPHQL_URL = \"http://myhostname:8080/v1/graphql\"\nGATEWAY_URL = \"http://myhostname:9000\"\n\n# User credentials. The password may be omitted on Aerie instances with authentication disabled\nUSERNAME = \"myusername\"\nPASSWORD = getpass(prompt='Password: ')\n\n# Define the Aerie host and provide user credentials\naerie_host = AerieHost(GRAPHQL_URL, GATEWAY_URL)\naerie_host.authenticate(USERNAME, PASSWORD)\n\n# AerieClient takes in a host and returns an object to issue requests to that host\nclient = AerieClient(aerie_host)\n\n# Simple example of a request to get an activity plan using the plan ID\nplan = client.get_activity_plan_by_id(42)\nprint(plan.name)\n```\n\nLook through the available methods in the provided `AerieClient` class to find ones that suit your needs.\n\n### Adding Methods\n\nIf you need to write a custom query, you can extend the `AerieClient` class and add your own method. Access the Aerie host using the `aerie_host` property. For example:\n\n```py\n\n# ...\n\nclass MyCustomAerieClient(AerieClient):\n    def get_plan_id_by_name(self, plan_name: str) -\u003e int:\n        my_query = \"\"\"\n        query GetPlanIdByName($plan_name: String!) {\n            plan(where: { name: { _eq: $plan_name } }) {\n                id\n            }\n        }\n        \"\"\"\n\n        # Pass variables for the query as keyword arguments\n        resp = self.aerie_host.post_to_graphql(\n            my_query,\n            plan_name=plan_name\n        )\n        return resp[0][\"id\"]\n```\n\nNow, you can use your custom method like any other:\n\n```py\n# ...\nclient = MyCustomAerieClient(aerie_host)\nplan_id = client.get_plan_id_by_name(\"my-plan-name\")\nprint(plan_id)\n```\n\n### Using the Active CLI Session\n\nIf 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 Aerie host and instead just use the active session. Aerie-CLI provides a utility to retrieve an `AerieClient` instance from the active CLI session:\n\n```py\nfrom aerie_cli.utils.sessions import get_active_session_client\n\n# client is an instance of `AerieClient`\nclient = get_active_session_client()\n\n# Issue requests like normal\nplan = client.get_activity_plan_by_id(...)\n```\n\n### Advanced Authentication\n\nIf 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`](https://requests.readthedocs.io/en/latest/) module's [`Session` class](https://requests.readthedocs.io/en/latest/api/#request-sessions). Instantiate a session object, manipulate/add headers/cookies/SSL certificates/etc. as necessary, and use to instantiate an `AerieHostSession`:\n\n```py\n# ...\nfrom requests import Session\n\nmy_custom_requests_session = Session()\n# Manipulate as necessary\n# ...\n\naerie_host = AerieHost(\n    GRAPHQL_URL,\n    GATEWAY_URL,\n    session=my_custom_requests_session\n)\naerie_host.authenticate(...)\nclient = AerieClient(aerie_host)\n\n# Use client as normal\n```\n\n---\n\n## Contributing\n\n### Contributor Installation\n\nThe recommended develper installation method is in a [virutual environment](https://docs.python.org/3/library/venv.html) with an [editatable install via Pip](https://pip.pypa.io/en/latest/topics/local-project-installs/#editable-installs). \n\nSee this [primer](https://realpython.com/python-virtual-environments-a-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:\n\n```sh\npython3 -m venv venv\nsource venv/bin/activate\n```\n\nThen, install Aerie-CLI in editable mode via Pip:\n\n```sh\npython3 -m pip install -e .\n```\n\nNow, your installation of Aerie-CLI will update as you make changes to the source code.\n\n### Dependency Management\n\nDependencies are currently managed via Poetry. For more information on dependency and project management, see the [`poetry` docs](https://python-poetry.org/docs/master/).\n\n### Testing\n\nAerie-CLI has unit tests and integration tests built with the [pytest](https://docs.pytest.org/) library.\n\n#### Unit Tests\n\nUnit 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 Aerie API responses. \n\nRun the unit tests using `pytest` from the `tests/unit_tests` directory:\n\n```\ncd tests\npython3 -m pytest .\n```\n\n#### Integration Tests\n\nA separate suite of tests is designed to validate CLI functionality against a local instance of Aerie. See the [integration testing documentation](tests/integration_tests/README.md) for details.\n\nThe integration tests are based on `Typer` testing documentation found [here](https://typer.tiangolo.com/tutorial/testing/).\n\n### Releases\n\nAerie-CLI generally follows the [gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) workflow model for managing releases:\n\n- Features are merged to the `develop` branch.\n- Release branches are made from develop and merge in `main` for testing.\n- Releases are made from the tip of the `main` branch.\n- Hotfix branches can be made from `main` to resolve bugs without needing to incorporate new features.\n\nVersion numbers are managed using [semantic versioning](https://semver.org) in [`pyproject.toml`](pyproject.toml):\n\n- The version tag on `develop` is fixed at `0.0.0-dev0`\n- Release versions are incremented on release branches before being merged to main.\n\nThe full workflow for releasing a new version of Aerie-CLI: \n\n- Make a release branch from `develop`\n- Merge `main` into the release branch\n- Commit a version increment in `pyproject.toml`\n- Open a PR to merge the release branch into `main` and verify CI passes\n- Merge the PR and tag a release on `main`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnasa-ammos%2Faerie-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnasa-ammos%2Faerie-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnasa-ammos%2Faerie-cli/lists"}