Skip to content

Commit 1f099fc

Browse files
committed
playbooks endpoint, socket to tcp
1 parent 212a73d commit 1f099fc

File tree

6 files changed

+53
-17
lines changed

6 files changed

+53
-17
lines changed

CHANGELOG.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#### General 🚀
2-
- Install script now sets up a production-ready installation of ansible-link
3-
- Fetches the latest version of ansible-link from GitHub
4-
- Includes Gunicorn for handling requests
5-
- Configures Unix sockets for communication
6-
- Sets up a Python virtual environment (venv)
7-
- Updated README for install script instructions
2+
- Updated gunicorn to use TCP instead of socket
3+
- Minor fixes in README
4+
- `/available-playbooks` can now be used to query available playbooks (inkl. subdirs)
5+
- Added tests for `/available-playbooks`

README.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ Searched for a way to run our playbooks automated without the need of AWX or oth
3434
## Installation
3535
The fastest way to set up Ansible-Link is by using the provided `install.sh` script:
3636

37-
1. **Download and run the install script:**
38-
```shell
39-
wget https://raw.githubusercontent.com/lfkdev/ansible-link/main/install.sh
40-
sudo bash install.sh
41-
```
37+
**Download and run the install script:**
38+
```shell
39+
wget https://raw.githubusercontent.com/lfkdev/ansible-link/main/install.sh
40+
sudo bash install.sh
41+
```
4242

4343
This script will:
4444
- Check for necessary dependencies and install them if missing.
@@ -134,18 +134,25 @@ You can use the install script `install.sh` to get a production-ready environmen
134134
The install script will:
135135
- Set up a Python VENV
136136
- Configure a systemd service to manage Ansible-Link
137-
- Utilize Gunicorn as the WSGI server.
137+
- Utilize Gunicorn as the WSGI server
138+
- Start Ansible-Link to liste only on localhost
138139

139140
You can use a webserver like Caddy to add Basic Authentication and TLS to your Ansible-Link setup.
140141

142+
Also, if you're using a webserver, you can change Gunicorn to use sockets instead. For example:
143+
```shell
144+
ExecStart=$VENV_DIR/bin/gunicorn --workers 1 --bind unix:$INSTALL_DIR/ansible_link.sock -m 007 wsgi:application
145+
```
146+
147+
141148
### unitD example
142149
```
143150
[Unit]
144151
Description=Ansible Link Service
145152
After=network.target
146153

147154
[Service]
148-
ExecStart=$VENV_DIR/bin/gunicorn --workers 1 --bind unix:$INSTALL_DIR/ansible_link.sock -m 007 wsgi:application
155+
ExecStart=$VENV_DIR/bin/gunicorn --workers 1 --bind 127.0.0.1:$ANSIBLE_LINK_PORT wsgi:application
149156
WorkingDirectory=$INSTALL_DIR
150157
Restart=always
151158
User=root

install.sh

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
set -e
55

66
ANSIBLE_LINK_VERSION="2.1.1"
7+
ANSIBLE_LINK_PORT=5001
78
INSTALL_DIR="/opt/ansible-link"
89
TEMP_DIR="/tmp/ansible-link-install$RANDOM"
910
VENV_DIR="$INSTALL_DIR/venv"
@@ -136,7 +137,7 @@ Description=Ansible Link Service
136137
After=network.target
137138
138139
[Service]
139-
ExecStart=$VENV_DIR/bin/gunicorn --workers 1 --bind unix:$INSTALL_DIR/ansible_link.sock -m 007 wsgi:application
140+
ExecStart=$VENV_DIR/bin/gunicorn --workers 1 --bind 127.0.0.1:$ANSIBLE_LINK_PORT wsgi:application
140141
WorkingDirectory=$INSTALL_DIR
141142
Restart=always
142143
User=root
@@ -199,14 +200,14 @@ main() {
199200
update_config
200201
setup_service
201202
cleanup
202-
203+
echo
203204
log "INFO" "Ansible-Link has been installed and configured. ✔"
204205
log "INFO" "The service is running and will start automatically on boot. ✔"
205206
log "INFO" "You can check the status with: systemctl status ansible-link. ✔"
206207
log "WARN" "Ansible user defaults to root. ⚠"
207208
log "INFO" "Change the default values in $INSTALL_DIR/config.yml if needed."
208209
echo
209-
log "INFO" "To access Ansible-Link, go to: http://localhost:9090. ✔"
210+
log "INFO" "To access Ansible-Link, go to: http://localhost:${ANSIBLE_LINK_PORT}. ✔"
210211
}
211212

212213
main

src/ansible_link.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
'errors': fields.List(fields.String, description='List of error messages, if any', allow_none=True)
5757
})
5858

59+
available_playbooks_model = api.model('AvailablePlaybooks', {
60+
'playbooks': fields.List(fields.String, description='List of available playbook paths')
61+
})
62+
5963
def load_config():
6064
current_dir = Path(__file__).parent.absolute()
6165
default_config_path = current_dir / 'config.yml'
@@ -286,6 +290,20 @@ def get(self, job_id):
286290
api.abort(404, f"Job {job_id} not found")
287291
return job
288292

293+
@ns.route('/available-playbooks')
294+
class AvailablePlaybooks(Resource):
295+
@ns.marshal_with(available_playbooks_model)
296+
def get(self):
297+
playbook_dir = Path(config['playbook_dir'])
298+
available_playbooks = []
299+
300+
for file in playbook_dir.glob('**/*.yml'):
301+
relative_path = file.relative_to(playbook_dir)
302+
if file.is_file() and (not compiled_whitelist or any(pattern.match(str(relative_path)) for pattern in compiled_whitelist)):
303+
available_playbooks.append(str(relative_path))
304+
305+
return {'playbooks': available_playbooks}
306+
289307
# simple healthcheck placeholder
290308
@app.route('/health')
291309
def health_check():

src/test_ansible_link.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,17 @@ def test_job_creation_and_retrieval(self):
104104
for key in expected_keys:
105105
self.assertIn(key, file_data, f"Expected key '{key}' not found in job file")
106106

107+
def test_available_playbooks_endpoint(self):
108+
response = self.client.get(f'{API_PATH}/ansible/available-playbooks')
109+
self.assertEqual(response.status_code, 200)
110+
data = json.loads(response.data)
111+
self.assertIn('playbooks', data)
112+
self.assertIsInstance(data['playbooks'], list)
113+
114+
self.assertIn('test_playbook.yml', data['playbooks'], "test_playbook.yml is not in the list of available playbooks")
115+
116+
for playbook in data['playbooks']:
117+
self.assertTrue(playbook.endswith('.yml'), f"Playbook {playbook} does not end with .yml")
118+
107119
if __name__ == '__main__':
108120
unittest.main()

src/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION = "2.1.3"
1+
VERSION = "2.2.0"
22

33
def get_version():
44
return VERSION

0 commit comments

Comments
 (0)