first commit
This commit is contained in:
47
README.md
Normal file
47
README.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Application Consumption Demo Algorithm (Ansible)
|
||||||
|
|
||||||
|
Progetto Ansible simile a `appconsumption-demo-app`, orientato a SemaphoreUI:
|
||||||
|
- `test.yml`: verifica connettivita e prerequisiti Docker
|
||||||
|
- `deploy.yml`: deploy container Docker della ML app
|
||||||
|
- `undeploy.yml`: rimozione container e cleanup
|
||||||
|
|
||||||
|
## Struttura
|
||||||
|
|
||||||
|
```text
|
||||||
|
application-consumption-demo-algorithm/
|
||||||
|
ansible.cfg
|
||||||
|
inventory
|
||||||
|
requirements.yml
|
||||||
|
deploy.yml
|
||||||
|
test.yml
|
||||||
|
undeploy.yml
|
||||||
|
group_vars/
|
||||||
|
all.yml
|
||||||
|
secrets.yml
|
||||||
|
splash/
|
||||||
|
tasks/main.yml
|
||||||
|
templates/app.env.j2
|
||||||
|
semaphore_dagster_config.example.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Immagine Docker usata
|
||||||
|
|
||||||
|
- Registry: `gitea.dataprovider01.sandbox-cat-dat.simpl-europe.eu`
|
||||||
|
- Repository: `j.r/application-consumption-demo-algorithm`
|
||||||
|
- Tag: `optimized`
|
||||||
|
- Digest atteso: `sha256:6cc8ab7c08f195cb65c689255418652fdf0094acaaa4ef63475d594039cda2ab`
|
||||||
|
|
||||||
|
Pull manuale:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker pull gitea.dataprovider01.sandbox-cat-dat.simpl-europe.eu/j.r/application-consumption-demo-algorithm:optimized
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uso locale rapido
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-galaxy collection install -r requirements.yml
|
||||||
|
ansible-playbook -i inventory test.yml
|
||||||
|
ansible-playbook -i inventory deploy.yml
|
||||||
|
ansible-playbook -i inventory undeploy.yml
|
||||||
|
```
|
||||||
20
ansible.cfg
Normal file
20
ansible.cfg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[defaults]
|
||||||
|
inventory = ./inventory
|
||||||
|
host_key_checking = False
|
||||||
|
stdout_callback = default
|
||||||
|
callback_result_format = yaml
|
||||||
|
force_color = True
|
||||||
|
retry_files_enabled = False
|
||||||
|
gathering = smart
|
||||||
|
roles_path = ./
|
||||||
|
|
||||||
|
[privilege_escalation]
|
||||||
|
become = True
|
||||||
|
become_method = sudo
|
||||||
|
become_user = root
|
||||||
|
become_ask_pass = False
|
||||||
|
|
||||||
|
[ssh_connection]
|
||||||
|
timeout = 30
|
||||||
|
pipelining = True
|
||||||
|
control_path = /tmp/ansible-ssh-%%h-%%p-%%r
|
||||||
43
deploy.yml
Normal file
43
deploy.yml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
- name: Deploy ML app container
|
||||||
|
hosts: webservers
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- group_vars/all.yml
|
||||||
|
- group_vars/secrets.yml
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: Verifica che Docker CLI sia disponibile
|
||||||
|
ansible.builtin.command: docker --version
|
||||||
|
register: docker_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: docker_check.rc != 0
|
||||||
|
|
||||||
|
- name: Verifica che il servizio Docker sia in esecuzione
|
||||||
|
ansible.builtin.service_facts:
|
||||||
|
|
||||||
|
- name: Controlla stato Docker
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: ansible_facts.services['docker.service'].state == 'running'
|
||||||
|
fail_msg: "Docker non e' in esecuzione sul host target"
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: splash
|
||||||
|
|
||||||
|
post_tasks:
|
||||||
|
- name: Verifica che la porta applicativa sia in ascolto
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
host: 127.0.0.1
|
||||||
|
port: "{{ app_port }}"
|
||||||
|
timeout: 30
|
||||||
|
when: enable_health_check | bool
|
||||||
|
|
||||||
|
- name: Output finale
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "Deploy completato"
|
||||||
|
- "URL: http://{{ ansible_host }}:{{ app_port }}"
|
||||||
|
- "Container: {{ container_name }}"
|
||||||
|
- "Image: {{ container_image }}:{{ image_tag }}"
|
||||||
|
- "Digest atteso: sha256:6cc8ab7c08f195cb65c689255418652fdf0094acaaa4ef63475d594039cda2ab"
|
||||||
17
group_vars/all.yml
Normal file
17
group_vars/all.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
# Container settings
|
||||||
|
registry_url: gitea.dataprovider01.sandbox-cat-dat.simpl-europe.eu
|
||||||
|
repository_name: j.r/application-consumption-demo-algorithm
|
||||||
|
image_tag: optimized
|
||||||
|
container_image: "{{ registry_url }}/{{ repository_name }}"
|
||||||
|
container_name: example-ml-app
|
||||||
|
|
||||||
|
# App settings
|
||||||
|
app_environment: production
|
||||||
|
app_port: 5000
|
||||||
|
greeting_message: "Hello from SemaphoreUI Demo"
|
||||||
|
remove_image: false
|
||||||
|
|
||||||
|
enable_health_check: true
|
||||||
|
healthcheck_retries: 20
|
||||||
|
healthcheck_delay: 2
|
||||||
7
group_vars/secrets.yml
Normal file
7
group_vars/secrets.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
# Per demo: valori in chiaro.
|
||||||
|
# In produzione cifra questo file con ansible-vault.
|
||||||
|
app_secret: "demo-secret-change-me"
|
||||||
|
release_id: "optimized"
|
||||||
|
demo_api_key: "demo-api-key-123"
|
||||||
|
demo_db_password: "demo-db-pass-123"
|
||||||
11
inventory
Normal file
11
inventory
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[webservers]
|
||||||
|
# Sostituisci con il tuo host reale
|
||||||
|
server1 ansible_host=XXX.XXX.XXX.XXX ansible_user=root
|
||||||
|
|
||||||
|
[webservers:vars]
|
||||||
|
ansible_python_interpreter=/usr/bin/python3
|
||||||
|
# In SemaphoreUI configura la chiave SSH nella sezione Key,
|
||||||
|
# quindi normalmente non serve impostare ansible_ssh_private_key_file qui.
|
||||||
|
|
||||||
|
[all:vars]
|
||||||
|
ansible_connection=ssh
|
||||||
4
requirements.yml
Normal file
4
requirements.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
collections:
|
||||||
|
- name: community.docker
|
||||||
|
version: ">=3.0.0"
|
||||||
77
semaphore_dagster_config.example.yml
Normal file
77
semaphore_dagster_config.example.yml
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Configuration for SemaphoreUI + Ansible ML App Demo
|
||||||
|
# Aggiorna i campi in base al tuo ambiente
|
||||||
|
|
||||||
|
# SemaphoreUI connection settings
|
||||||
|
semaphore_url: "https://semaphore.common01.sandbox-cat-dat.simpl-europe.eu/semaphoreUI"
|
||||||
|
semaphore_token: "<REPLACE_WITH_SEMAPHORE_TOKEN>"
|
||||||
|
project_id: "10"
|
||||||
|
|
||||||
|
# Git repository configuration
|
||||||
|
git_provider: "gitea"
|
||||||
|
git_base_url: "http://dataprovider01-dataprovider-orchestration-platform-gitea-http.dataprovider01.svc.cluster.local:3000"
|
||||||
|
git_repo_url: "http://dataprovider01-dataprovider-orchestration-platform-gitea-http.dataprovider01.svc.cluster.local:3000/gitea_admin/application-consumption-demo-algorithm.git"
|
||||||
|
git_branch: "main"
|
||||||
|
|
||||||
|
# Git authentication (optional for private repos)
|
||||||
|
git_username: ""
|
||||||
|
git_access_token: ""
|
||||||
|
|
||||||
|
# Environment configuration
|
||||||
|
environment_name: "Ansible ML App Demo Environment"
|
||||||
|
environment_variables:
|
||||||
|
app_environment: "production"
|
||||||
|
|
||||||
|
container_name: "example-ml-app"
|
||||||
|
app_port: "5000"
|
||||||
|
remove_image: "false"
|
||||||
|
|
||||||
|
registry_url: "gitea.dataprovider01.sandbox-cat-dat.simpl-europe.eu"
|
||||||
|
repository_name: "j.r/application-consumption-demo-algorithm"
|
||||||
|
image_tag: "optimized"
|
||||||
|
|
||||||
|
greeting_message: "Hello from SemaphoreUI Demo"
|
||||||
|
enable_health_check: "true"
|
||||||
|
|
||||||
|
# Optional encrypted secrets in SemaphoreUI Environment
|
||||||
|
environment_secrets:
|
||||||
|
app_secret: "demo-secret-from-semaphore"
|
||||||
|
release_id: "optimized"
|
||||||
|
demo_api_key: "demo-api-key-123"
|
||||||
|
demo_db_password: "demo-db-pass-123"
|
||||||
|
|
||||||
|
# Inventory configuration
|
||||||
|
inventory_name: "ML App Demo Servers"
|
||||||
|
inventory_type: "static"
|
||||||
|
inventory_content: |
|
||||||
|
[webservers]
|
||||||
|
server1 ansible_host=217.154.255.66 ansible_user=root
|
||||||
|
|
||||||
|
[webservers:vars]
|
||||||
|
ansible_python_interpreter=/usr/bin/python3
|
||||||
|
|
||||||
|
[all:vars]
|
||||||
|
ansible_connection=ssh
|
||||||
|
|
||||||
|
# Integration flags
|
||||||
|
is_agent_sem_ui: "false"
|
||||||
|
|
||||||
|
# Ansible Vault configuration
|
||||||
|
vault_password: "<REPLACE_WITH_VAULT_PASSWORD>"
|
||||||
|
|
||||||
|
# Playbooks configuration
|
||||||
|
playbooks:
|
||||||
|
- name: "Test Connectivity"
|
||||||
|
description: "Test connectivity and verify prerequisites before deployment"
|
||||||
|
playbook_filename: "test.yml"
|
||||||
|
|
||||||
|
- name: "Deploy ML App Container"
|
||||||
|
description: "Deploy ML app Docker container from private registry"
|
||||||
|
playbook_filename: "deploy.yml"
|
||||||
|
|
||||||
|
- name: "Undeploy ML App Container"
|
||||||
|
description: "Remove ML app container and clean up resources"
|
||||||
|
playbook_filename: "undeploy.yml"
|
||||||
|
|
||||||
|
# Optional additional settings
|
||||||
|
timeout_seconds: 30
|
||||||
|
enable_health_check: true
|
||||||
33
splash/tasks/main.yml
Normal file
33
splash/tasks/main.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
- name: Crea cartella app
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /opt/application-consumption-demo-algorithm
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Render env file applicativo
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: app.env.j2
|
||||||
|
dest: /opt/application-consumption-demo-algorithm/app.env
|
||||||
|
mode: '0600'
|
||||||
|
|
||||||
|
- name: Ferma eventuale container precedente
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ container_name }}"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Scarica immagine ML app
|
||||||
|
community.docker.docker_image:
|
||||||
|
name: "{{ container_image }}"
|
||||||
|
tag: "{{ image_tag }}"
|
||||||
|
source: pull
|
||||||
|
|
||||||
|
- name: Avvia container ML app
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ container_name }}"
|
||||||
|
image: "{{ container_image }}:{{ image_tag }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "{{ app_port }}:5000"
|
||||||
|
env_file: /opt/application-consumption-demo-algorithm/app.env
|
||||||
6
splash/templates/app.env.j2
Normal file
6
splash/templates/app.env.j2
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
APP_ENV={{ app_environment }}
|
||||||
|
GREETING_MESSAGE={{ greeting_message }}
|
||||||
|
APP_SECRET={{ app_secret }}
|
||||||
|
RELEASE_ID={{ release_id }}
|
||||||
|
DEMO_API_KEY={{ demo_api_key }}
|
||||||
|
DEMO_DB_PASSWORD={{ demo_db_password }}
|
||||||
5
splash/templates/notes.txt.j2
Normal file
5
splash/templates/notes.txt.j2
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
Project: application-consumption-demo-algorithm
|
||||||
|
Image: {{ container_image }}:{{ image_tag }}
|
||||||
|
Digest: sha256:6cc8ab7c08f195cb65c689255418652fdf0094acaaa4ef63475d594039cda2ab
|
||||||
|
Container: {{ container_name }}
|
||||||
|
Port: {{ app_port }}
|
||||||
41
test.yml
Normal file
41
test.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
- name: Test host e prerequisiti Docker
|
||||||
|
hosts: webservers
|
||||||
|
become: yes
|
||||||
|
gather_facts: yes
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- group_vars/all.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Test SSH
|
||||||
|
ansible.builtin.ping:
|
||||||
|
|
||||||
|
- name: Mostra info host
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg:
|
||||||
|
- "Host: {{ ansible_hostname }}"
|
||||||
|
- "OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"
|
||||||
|
- "Python: {{ ansible_python_version }}"
|
||||||
|
|
||||||
|
- name: Controlla Docker CLI
|
||||||
|
ansible.builtin.command: docker --version
|
||||||
|
register: docker_version
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Stato Docker CLI
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ docker_version.stdout if docker_version.rc == 0 else 'Docker non trovato' }}"
|
||||||
|
|
||||||
|
- name: Verifica porta target disponibile
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
port: "{{ app_port }}"
|
||||||
|
state: stopped
|
||||||
|
timeout: 1
|
||||||
|
register: port_check
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Risultato porta
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Porta {{ app_port }} {{ 'libera' if port_check is not failed else 'gia in uso' }}"
|
||||||
29
undeploy.yml
Normal file
29
undeploy.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
- name: Undeploy ML app container
|
||||||
|
hosts: webservers
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- group_vars/all.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Rimuovi container ML app
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ container_name }}"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Rimuovi immagine (opzionale)
|
||||||
|
community.docker.docker_image:
|
||||||
|
name: "{{ container_image }}"
|
||||||
|
tag: "{{ image_tag }}"
|
||||||
|
state: absent
|
||||||
|
when: remove_image | bool
|
||||||
|
|
||||||
|
- name: Rimuovi directory applicazione
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /opt/application-consumption-demo-algorithm
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Conferma undeploy
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Container {{ container_name }} rimosso con successo"
|
||||||
Reference in New Issue
Block a user