#Flansible
A super-simple rest api for Ansible
Flansible is a very simple rest api for executing Ansible ad-hoc-commands and playbooks. It it not a replacement for Ansible Tower.
Flansible is written in Flask, and uses celery for async task execution and optionally flower for real-time monitoring of celery.
Credits
Joerg Lehmann: Lots of feedback and help
Required python packages with tested versions (newer version should be fine):
ansible==2.1.0.0
celery==4.0.0
Flask==0.10.1
Flask-HTTPAuth==3.1.2
Flask-RESTful==0.3.5
flask-restful-swagger==0.19
flower==0.9.1
redis==2.10.5
Other things:
Celery requires a running datastore, either Redis or RabbitMQ - flansible does not configure this, and expects Redis or RabbitMQ to already be running and accessible.
Configuration
The config.ini file should be pretty self-explanatory. It's probably a good idea to remove lines 5-10 in app.py, as that's only a debug definition which probably won't make sense to you.
If you want to run the flask webserver on port 80 like I'm doing without running as root, you need to allow python to use priveliged ports:
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/python2.7
Setup
Setup tested on Ubuntu 14.04
from the Flansible/Flansible directory (where the .py files live), run the following (either using screen or in separate terminals):
celery worker -A flansible.celery --loglevel=info
(this starts the celery worker which will actually execute the things)
python runserver.py
(this starts the actual webserver. You're free to replace the built-in flask server with something else)
OPTIONAL: flower --broker=redis://localhost:6379/0
(this starts the flower web gui, which gives provides information for running tasks. Replace the value of --broker
with your own connection string for the redis/rabbitmq data store). Flower will be available on http://<hostname>:5555
.
Usage: Vagrant
To test the solution with vagrant, you can run vagrant up
from the root of the repo directory. I haven't set up the apache thingy yet, so you'll have to run the following inside vagrant (by using vagrant ssh
) after the box comes online:
cd /vagrant/Flansible
celery worker -A flansible.celery --loglevel=info
(use screen to run celery in a non-blocking way)
python runserver.py
(use screen to run the app in a non-blocking way)
you can now interact with the flansible rest api using http://localhost:3000/api
.
Usage: General
Flansible comes with swagger documentation, which can be reached at
http://<hostname>/api/spec.html
, with the json spec located at http://<hostname>/api/spec
. This should be your first stop for getting to know the
expected json payload when interacting with the api.
Usage: Role-based access
Flansible uses basic auth, with username/password configurable in the rbac.json file (default: admin/admin)
rbac.json allows linking usernames with a list of allowed inventories. The example provided shows how to configure a "devadmin" user which doesn't have access to Ansible's default inventory:
{
"rbac": [
{
"user": "admin",
"password": "admin",
"inventories": [
"username admin has implicit access to all inventories",
"no need to specify anything here"
]
},
{
"user": "devadmin",
"password": "devpassword",
"inventories": [
"/some/folder/dev",
"/home/thadministrator/hosts"
]
}
]
}
Not that the username "admin" is special, and is not subject to inventory access checking.
The idea behind this rbac implementation is to allow separate credentials for executing tasks and playbooks against dev/test environments without having access to make changes to production systems.
Usage: Ad-hoc commands
Issue a POST to http://<hostname>/api/ansiblecommand
with contenttype Application/Json
.
The body should contain the following (for updated info, see the swagger spec mentioned above):
{
"host_pattern": "localhost",
"module": "find",
"module_args": {
"paths": "/tmp",
"age": "2d",
"recurse" : true
}
}
where
- module: The ansible module to execute
- host_filter: The host or host filter to execute on (defaults to "localhost" if omitted)
- extra_args: array of objects containing any extra vars
Usage: Playbooks
Issue a POST to http://<hostname>/api/ansibleplaybook
with contenttype application/Json
.
This is an example of playbook execution:
{
"playbook_dir": "/home/thadministrator",
"playbook": "test.yml",
"become": true
}
Flansible will verify that the playbook dir/file exists before submitting the job for execution.
Usage: Getting status
both ansibleplaybook and ansiblecommand will return a task_id value. That value can be used to check the
status and output of the job. This is done by issuing a GET to
http://<hostname>/api/ansibletaskstatus/<task_id>
with contenttype Application/Json
.
Usage: Getting output
The output of the ansible command/playbook can be viewed live while the task is running, and afterwards.
Issue a GET cal to:
http://<hostname>/api/ansibletaskoutput/<task_id>
with contenttype Application/Json
.
The output from this call should resemble what you see in bash when executing Ansible interactively.
how it looks
- Execute an Ansible command (
/api/ansiblecommand
). The returning task_id is used to check status:
- Use the returned task_id to get the Ansible job output (
/api/ansibletaskoutput/<task-id>
):
- Use Flower to check job statuses:
- Use Swagger to get a feel for the api (this is very much work in progress):
how it works in docker
vagrant ssh docker-compose -f docker-compose.yml build docker-compose -f docker-compose.yml up -d sudo docker exec -it vagrant_flansible_1 bash ansible-playbook /home/flansible/playbook/site-docker.yml
cd /home/flansible/Flansible; python runserver.py cd /home/flansible/Flansible; C_FORCE_ROOT=1 celery worker -A flansible.celery --loglevel=info flower --broker=redis://localhost:6379/0