commit af525dfd06d836cef4d5313deb983fa62394c5e6 Author: Matteo Basile Date: Thu Jul 16 08:46:35 2026 +0200 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..1519b6b --- /dev/null +++ b/README.md @@ -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 +``` diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..f6f3bbe --- /dev/null +++ b/ansible.cfg @@ -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 diff --git a/deploy.yml b/deploy.yml new file mode 100644 index 0000000..d16e500 --- /dev/null +++ b/deploy.yml @@ -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" diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..a533ffc --- /dev/null +++ b/group_vars/all.yml @@ -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 diff --git a/group_vars/secrets.yml b/group_vars/secrets.yml new file mode 100644 index 0000000..7f3cd3a --- /dev/null +++ b/group_vars/secrets.yml @@ -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" diff --git a/inventory b/inventory new file mode 100644 index 0000000..d316246 --- /dev/null +++ b/inventory @@ -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 diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..3b6b63f --- /dev/null +++ b/requirements.yml @@ -0,0 +1,4 @@ +--- +collections: + - name: community.docker + version: ">=3.0.0" diff --git a/semaphore_dagster_config.example.yml b/semaphore_dagster_config.example.yml new file mode 100644 index 0000000..ae79c0f --- /dev/null +++ b/semaphore_dagster_config.example.yml @@ -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: "" +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: "" + +# 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 diff --git a/splash/tasks/main.yml b/splash/tasks/main.yml new file mode 100644 index 0000000..5971d71 --- /dev/null +++ b/splash/tasks/main.yml @@ -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 diff --git a/splash/templates/app.env.j2 b/splash/templates/app.env.j2 new file mode 100644 index 0000000..4a7eb1c --- /dev/null +++ b/splash/templates/app.env.j2 @@ -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 }} diff --git a/splash/templates/notes.txt.j2 b/splash/templates/notes.txt.j2 new file mode 100644 index 0000000..fdcb8d1 --- /dev/null +++ b/splash/templates/notes.txt.j2 @@ -0,0 +1,5 @@ +Project: application-consumption-demo-algorithm +Image: {{ container_image }}:{{ image_tag }} +Digest: sha256:6cc8ab7c08f195cb65c689255418652fdf0094acaaa4ef63475d594039cda2ab +Container: {{ container_name }} +Port: {{ app_port }} diff --git a/test.yml b/test.yml new file mode 100644 index 0000000..38a01bb --- /dev/null +++ b/test.yml @@ -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' }}" diff --git a/undeploy.yml b/undeploy.yml new file mode 100644 index 0000000..035288e --- /dev/null +++ b/undeploy.yml @@ -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"