This repository contains the application that serves Ansible task suggestions for consumption by the Ansible VS Code extension.
- Podman Desktop
- Ollama
- VS Code and the Ansible extension
export OLLAMA_HOST=0.0.0.0
ollama serve &
ollama run mistral:instruct
Populate the tools/docker-compose/.env
file with the following values:
DEPLOYMENT_MODE="upstream"
SECRET_KEY="somesecretvalue"
ENABLE_ARI_POSTPROCESS="False"
WCA_SECRET_BACKEND_TYPE="dummy"
# configure model server
ANSIBLE_AI_MODEL_MESH_HOST="http://host.containers.internal"
ANSIBLE_AI_MODEL_MESH_INFERENCE_PORT="11434"
ANSIBLE_AI_MODEL_MESH_API_TYPE="ollama"
ANSIBLE_AI_MODEL_NAME="mistral:instruct"
podman compose -f tools/docker-compose/compose.yaml up
TODO
podman compose -f tools/docker-compose/compose.yaml down
Path | Description |
---|---|
ansible_wisdom | Service backend application |
ansible_wisdom_console_react | Admin portal application |
For most development usages, you can skip the call to AWS Secrets Manager
and always use the dummy WCA_SECRET_BACKEND_TYPE
by setting the following in your
tools/docker-compose/.env
file:
WCA_SECRET_BACKEND_TYPE="dummy"
WCA_SECRET_DUMMY_SECRETS="11009103:valid"
In this example, 11009103`` is your organization id. In this case the model is set to
valid. You can also use the following syntax to set both the model and set key_id:
WCA_SECRET_DUMMY_SECRETS='11009103:ibm_api_keymodel_id<|sepofid|>model_name'`
For deployment and RH SSO integration test/development, add the following to your
tools/docker-compose/.env
file:
DEPLOYMENT_MODE=saas
WCA_SECRET_MANAGER_ACCESS_KEY=<access-key>
WCA_SECRET_MANAGER_KMS_KEY_ID=<kms-key-id>
WCA_SECRET_MANAGER_PRIMARY_REGION=us-east-2
WCA_SECRET_MANAGER_REPLICA_REGIONS=us-west-1
WCA_SECRET_MANAGER_SECRET_ACCESS_KEY=<secret-access-key>
See here for details.
This repository also contains a React/TypeScript webapp for the "Admin Portal". This is located in the ansible_wisdom_console_react
directory. Further details can be found in ansible_wisdom_console_react/README.md
. If you wish to run the "Admin Portal" locally it is important to read the instructions.
The service can be run in debug mode by exporting or adding to the
command line the variable DEBUG=True
.
The Django service listens on http://127.0.0.1:8000.
Note that there is no pytorch service defined in the docker-compose
file. You should adjust the ANSIBLE_AI_MODEL_MESH_HOST
configuration key to point on an existing service.
To interact with the WCA key management API, or use WCA commercial inference locally, you need to add the following variables to you environment file:
WCA_SECRET_MANAGER_ACCESS_KEY=<AWS access key>
WCA_SECRET_MANAGER_SECRET_ACCESS_KEY=<AWS secret access key>
WCA_SECRET_MANAGER_KMS_KEY_ID=<KMS key id or alias>
WCA_SECRET_MANAGER_PRIMARY_REGION=us-east-2
WCA_SECRET_MANAGER_REPLICA_REGIONS=us-west-1
The AWS key and secret key must belong to a user who has both the AnsibleWisdomWCASecretsReader
and
AnsibleWisdomWCASecretsWriter
policies.
The KMS Secret needs to either be a multi region secret (when using the id) or a secret with the same name in the primary and replica regions (when using the alias).
Note: when using a KMS key alias, prefix with alias/<actual alias>
.
Refer to the set up document for the AWS accounts and secrets.
oc new-build --strategy=docker --binary --name wisdom-service
oc start-build wisdom-service --from-dir . --exclude='(^|\/)(.git|.venv|.tox|model)(\/|$)' --wait=true
oc new-app wisdom-service
The sample request below tests the task suggestion prediction API provided by the Django application. This is the same request the VS Code extension will make.
Request:
# Post a request using curl
curl -X 'POST' \
'http://127.0.0.1:8000/api/v0/ai/completions/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"prompt": "---\n- hosts: all\n tasks:\n - name: Install nginx and nodejs 12 Packages\n"
}'
Response:
{
"predictions": [
"- name: ansible Convert instance config dict to a list\n set_fact:\n ansible_list: \"{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}\"\n when: server.changed | bool\n"
]
}
Pre-commit should be used before pushing a new PR. To use pre-commit, you need to first install the pre-commit package and its dependencies by running:
pip install -r requirements-dev.txt
To install pre-commit into your git hooks and run the checks on every commit, run the following each time you clone this repo:
pre-commit install
To update the pre-commit config to the latest repos' versions and run the precommit check across all files, run:
pre-commit autoupdate && pre-commit run -a
We are now using pip-compile in order to manage our Python dependencies for the x86_64 and ARM64/AArch64 architectures.
In order to generate requirements.txt files for both architectures, you must use a multi-arch capable virtual machine emulator (like QEMU) and enable multi-arch support.
To enable multi-arch support, run the instructions for your container engine and emulator from this table:
Container Engine | Emulator | Instructions |
podman | QEMU |
podman machine ssh
sudo rpm-ostree install qemu-user-static
sudo systemctl reboot |
The specification of what packages we need now live in the requirements.in and requirements-dev.in files. Use your preferred editor to make the needed changes in those files, then run
make pip-compile
This will spin up a container and run the equivalent of these commands to generate the updated files:
pip-compile requirements.in
pip-compile requirements-dev.in
These commands will produce fully populated and pinned requirements.txt and requirements-dev.txt files, containing all of the dependencies of our dependencies involved. Due to differences in architecture and version of Python between developers' machines, we do not recommend running the pip-compile commands directly.
Install the latest Ansible VS Code Extension from the Visual Studio Marketplace.
In order to successfully connect to your local dev environment using the plugin, you need to create the OAuth2 application in Django. Open a shell session in the Django container using
docker exec -it docker-compose_django_1 bash
and then run the Django command to create the application:
wisdom-manage createapplication \
--name "Ansible AI Connect for VS Code" \
--client-id Vu2gClkeR5qUJTUGHoFAePmBznd6RZjDdy5FW2wy \
--redirect-uris "vscode://redhat.ansible vscodium://redhat.ansible vscode-insiders://redhat.ansible code-oss://redhat.ansible checode://redhat.ansible" \
public authorization-code
This sets up a matching client ID to the one that is coded directly into the VS Code extension.
Review the screen recording for instruction on configuring the VS Code extension to access your running wisdom service.
Note: If, after running python manage.py runserver
you encounter an AssertionError, use the following
command: python manage.py runserver --noreload
. You can also disable it by
adding INSTALLED_APPS = [i for i in INSTALLED_APPS if i not in ["django_prometheus"]]
to
the ansible_wisdom/main/settings/development.py
file.
The wisdom service supports both GitHub and Red Hat authentication. GitHub authentication can be open to all GitHub users, or limited to a specific team. The following directions are for configuring the service to grant access to any GitHub user.
To test GitHub authentication locally, you will need to create a new OAuth App at
https://github.com/settings/developers. Provide an Authorization callback URL of
http://localhost:8000/complete/github/. Export Update SOCIAL_AUTH_GITHUB_KEY
and
SOCIAL_AUTH_GITHUB_SECRET
before starting your app. SOCIAL_AUTH_GITHUB_KEY
and
SOCIAL_AUTH_GITHUB_SECRET
correspond to the Client ID and Client Secret respectively,
both of which are provided after creating a new OAuth App. If you are running with the
compose development environment described below, put these
env vars in a .env file in the tools/docker-compose
directory.
To test Red Hat authentication locally, you will need to export 3 variables before start the application.
export SOCIAL_AUTH_OIDC_OIDC_ENDPOINT="https://sso.redhat.com/auth/realms/redhat-external"
export SOCIAL_AUTH_OIDC_KEY="ansible-wisdom-staging"
export SOCIAL_AUTH_OIDC_SECRET=secret_value
If, to run the application, you are using Makefile first two variables will be set automatically.
Third one should be set manually in either way: you are using Makefile or running
application directly. To get the secret value go to AWS Secret Manager
select it-cloud-aws-ansible-wisdom-staging
to log in. Click on Secrets Manager
than wisdom
and at last
Retrieve secret value
than copy value of SOCIAL_AUTH_OIDC_SECRET
.
Once you start the app, navigate to http://localhost:8000/ to log in. Once authenticated, you will be presented with an authentication token that will be configured in VS Code (coming soon) to access the task prediction API.
Warning: The Django
runserver
command launchesansible-wisdom-service
as http://127.0.0.1:8000. It is important that the host name used in your browser and that configured in GitHub OAuth Authorization callback URL are identical. Should you use Django's link the GitHub OAuth Authorization callback URL will need to use127.0.0.1
in lieu oflocalhost
too.
To get an authentication token, you can run the following command:
podman exec -it docker-compose-django-1 wisdom-manage createtoken --create-user
Note: If using docker-compose
, the container might have a different name such as docker-compose-django-1
in which
case the command would be:
podman exec -it docker-compose-django-1 wisdom-manage createtoken --create-user
my-test-user
will be create for youmy-token
is the name of the token
To get an authentication token without logging in via GitHub, you also:
- create an admin user
- navigate to http://localhost:8000/admin/
- and log in with your superuser credentials
- then navigate to http://localhost:8000/admin/oauth2_provider/accesstoken/
- create a new token.
To test the API with no authentication, you can empty out REST_FRAMEWORK.DEFAULT_PERMISSION_CLASSES
in base.py.
You can enable postprocess with Ansible Risk Insight (ARI) for improving the completion output just by following these 2 steps below.
-
Set the environment variable
ENABLE_ARI_POSTPROCESS
to True$ export ENABLE_ARI_POSTPROCESS=True
-
Prepare
rules
anddata
directory insideari/kb
directory.rules
should contain mutation rules for the postprocess, you can refer to here for some examples.data
should contain the backend data for ARI. We will host this data somewhere in the future, but currently this file must be placed manually if you want to enable the postprocess.Once the files are ready, the
ari/kb
directory should look like this.ari/kb/ ├── data │ ├── collections │ └── indices └── rules ├── W001_module_name_metrics.py ├── W002_module_key_metrics.py ├── ...
Then you can build the django image or just run make docker-compose
.
You can enable postprocess with Ansible Lint for improving the completion output just by setting the environment variable ENABLE_ANSIBLE_LINT_POSTPROCESS
to True
Note: Ansible lint post-processing is available only to commercial users.
We enabled the Prometheus endpoint to scrape the configuration and check the service status to build observability into the service for monitoring and measuring its availability.
To provide feedback for operational needs as well as for continuous service improvement.
Swagger UI is available at http://localhost:8000/api/schema/swagger-ui/ in the development environment only.
- Note: It is not enabled in the production environment regardless of any settings.
If you want to test APIs using Swagger UI,
- Open http://localhost:8000/ and get an authentication token by following the instructions described in the Authenticating with the completion API section.
- Open http://localhost:8000/api/schema/swagger-ui/
- Click the Authorize button.
- Input the authentication token for the tokenAuth as it is.
You do not need to add any prefixes, such as
Bearer
orToken
. - Click Authorize.
- Click Close to go back to the Swagger UI page.
- Expand a section for the API that you want to try and click Try it out.
- Input required parameters (if any) and click Execute.
Another OpenAPI UI in the ReDoc format is also available at http://localhost:8000/api/schema/redoc/ in the development environment only.
The static OpenAPI Schema YAML file is stored as /tools/openapi-schema/ansible-ai-connect-service.yaml in this repository.
When you make code changes, please update the static OpenAPI Schema YAML file with the following steps:
- Ensure the API metadata (description, version,
TAGS
used to organize API categories) are accurate; this requires updating theSPECTACULAR_SETTINGS
variable inansible_wisdom/main/settings/development.py
. - Run the wisdom service locally.
- Run
make update-openapi-schema
in the project root. - Commit the updated OpenAPI Schema YAML file with your API changes.
Also a dynamically generated OpenAPI 3.0 Schema YAML file can be downloaded either:
- Click the /api/schema/ link on Swagger UI, or
- Click the Download button on ReDoc UI
To connect to the Mistal 7b Instruct model running on locally on llama.cpp modelserver:
- Download the Mistral-7b-Instruct llamafile
- Make it executable and run it (
$YOUR_REAL_IP
is your local IP address, NOT 127.0.0.1 or localhost)chmod +x ./mistral-7b-instruct-v0.2-Q5_K_M-server.llamafile ./mistral-7b-instruct-v0.2-Q5_K_M-server.llamafile --host $YOUR_REAL_IP
- Set the appropriate environment variables
ANSIBLE_AI_MODEL_MESH_HOST=http://$YOUR_REAL_IP ANSIBLE_AI_MODEL_MESH_INFERENCE_PORT=8080 ANSIBLE_AI_MODEL_MESH_API_TYPE=llamacpp ANSIBLE_AI_MODEL_NAME=mistral-7b-instruct-v0.2.Q5_K_M.gguf ENABLE_ARI_POSTPROCESS=False
Unit-tests are based on Python's unittest library and rely on Django REST framework APIClient.
-
Use
reverse()
:Please make use of Django's reverse() function to specify which view you are hitting. If and when we change the path some endpoint is at, the person making the change will appreciate not having to search and replace all of those strings.
Additionally if you are hitting the same endpoint over a bunch of methods on the same test class, you can always store the results of
reverse()
in an attribute and make use of that, to reduce the repetition.
For running Unit Tests in this repository, you need to have backend services (Postgres, Prometheus and Grafana) running. Running them from container is one handy way for that requirement.
For getting the unit test code coverage,
install the coverage
module, which is included
in requirements-dev.txt
with the instructions in the
Using pre-commit section.
The easiest way to run unit tests and measure code coverage report is to run
make code-coverage
If the execution was successful, results in HTML are showin in Chrome.
For executing unit tests from command line,
You need to set some environment variables
that are read by the Service.
If you are using PyCharm
for development, you can use the EnvFile plugin
with the following .env
file:
LAUNCHDARKLY_SDK_KEY=flagdata.json
ANSIBLE_AI_DATABASE_HOST=localhost
ANSIBLE_AI_DATABASE_NAME=wisdom
ANSIBLE_AI_DATABASE_PASSWORD=wisdom
ANSIBLE_AI_DATABASE_USER=wisdom
ARI_KB_PATH=../ari/kb/
DJANGO_SETTINGS_MODULE=ansible_wisdom.main.settings.development
ENABLE_ARI_POSTPROCESS=True
PYTHONUNBUFFERED=1
SECRET_KEY=somesecret
Note that this .env
file assumes that the Django
service is executed in the ansible_wisdom
subdirectory
as ARI_KB_PATH
is defined as ../ari/kb
.
It is recommended to use make
to run unit tests since it helps to configure default values.
If you want to execute only specific file/class/method you can use $WISDOM_TEST variable:
make test
WISDOM_TEST="ansible_wisdom.main.tests.test_views.LogoutTest" make test
Alternatively if you want to run unit tests manually, export variables from .env
as environment variables.
It can be done with following commands:
set -o allexport
source .env
set +o allexport
After that, it is possible to run tests using standard django test mechanism:
cd ansible_wisdom
python3 manage.py test
If you want to get code coverage by running unit tests from command line, set environment variables listed in the section above and run following commands:
cd ansible_wisdom
coverage run --rcfile=../setup.cfg manage.py test
After tests completed, run
coverage report
for showing results on console, or
coverage html
to generate HTML reports under htmlcov
directory.
Alternatively you can run the following command for code coverage:
make code-coverage
You can do a backup and restore the database with the following scripts:
./tools/scripts/dump-db.sh
./tools/scripts/restore-db.sh
E.g:
./tools/scripts/dump-db.sh /tmp/my-backup.dump
./tools/scripts/restore-db.sh /tmp/my-backup.dump
If you get a permission denied error when attempting to start the
containers, you may need to set the permissions on the
ansible_wisdom/
, prometheus/
and ari/
directories:
chcon -t container_file_t -R ansible_wisdom/
chcon -t container_file_t -R prometheus/
chcon -t container_file_t -R grafana/
chcon -t container_file_t -R ari/
Also run chmod
against the ari/
directory so that ARI can
write temporary data in it:
chmod -R 777 ari/
If your django container build fails with the following error, you've probably run out of memory running webpack.
STEP 30/46: RUN npm --prefix /tmp/ansible_wisdom_console_react run build
> admin-portal@0.1.0 build
> node scripts/build.js
Creating an optimized production build...
npm ERR! path /tmp/ansible_wisdom_console_react
npm ERR! command failed
npm ERR! signal SIGKILL
npm ERR! command sh -c -- node scripts/build.js
You can increase the memory of your existing podman machine by issuing the following:
podman machine set --memory 8192
Recreating the dev containers might be useful:
podman compose -f tools/docker-compose/compose.yaml down
It may be necessary to recreate the dev image if anything has changed in the nginx settings:
podman rmi localhost/docker-compose_django_1