diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..da6f7977 --- /dev/null +++ b/.env.example @@ -0,0 +1,25 @@ +# Administration credentials +TEMP_ADMIN_EMAIL=admin@example.com +TEMP_ADMIN_PASSWORD=change-me-securely + +# UI Next configuration +# URL interne du réseau Docker pour accéder au service ui-next +# Format: http://ui-next:3000 (accès interne) ou http://localhost:3000 (accès local) +SIMPLE_STACK_UI_URL=http://ui-next:3000 + +# UI authentication (mapped from admin credentials) +SIMPLE_STACK_UI_USER=${TEMP_ADMIN_EMAIL} +SIMPLE_STACK_UI_PASSWORD=${TEMP_ADMIN_PASSWORD} + +# Terraform HTTP backend authentication +TF_HTTP_USERNAME=${TEMP_ADMIN_EMAIL} +TF_HTTP_PASSWORD=${TEMP_ADMIN_PASSWORD} + +# NextAuth secret for session encryption +NEXTAUTH_SECRET=your-secret-key-change-in-production + +# Optional: Custom ports +UI_NEXT_PORT=3000 + +# Optional: Ansible Java version +ANSIBLE_JAVA_VERSION=21 diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 00000000..55b0fa66 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,83 @@ +name: Reusable – Docker build and push + +on: + workflow_call: + inputs: + image_name: + description: "Full image name without registry prefix (e.g. owner/repo-ui)" + required: true + type: string + context: + description: "Docker build context path" + required: true + type: string + version: + description: "Image tag / version to apply" + required: true + type: string + registry: + description: "Container registry hostname" + required: false + type: string + default: ghcr.io + push: + description: "Whether to push and sign the image" + required: false + type: boolean + default: false + secrets: + registry_token: + required: true + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install cosign + if: ${{ inputs.push }} + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + with: + cosign-release: 'v2.2.4' + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + + - name: Log into registry ${{ inputs.registry }} + if: ${{ inputs.push }} + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ inputs.registry }} + username: ${{ github.actor }} + password: ${{ secrets.registry_token }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + with: + images: ${{ inputs.registry }}/${{ inputs.image_name }} + tags: ${{ inputs.version }} + + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + with: + context: ${{ inputs.context }} + push: ${{ inputs.push }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Sign the published Docker image + if: ${{ inputs.push }} + env: + TAGS: ${{ steps.meta.outputs.tags }} + DIGEST: ${{ steps.build-and-push.outputs.digest }} + run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index ced1a7c2..90d21ecb 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -2,16 +2,10 @@ name: Docker on: push: - branches: [ "main" ] - # Publish semver tags as releases. - tags: [ 'v*.*.*' ] + branches: ["main"] + tags: ["v*.*.*"] pull_request: - branches: [ "main" ] - -env: - REGISTRY: ghcr.io - IMAGE_NAME_UI: ${{ github.repository }}-ui - IMAGE_NAME_ANSIBLE: ${{ github.repository }}-ansible + branches: ["main"] permissions: contents: write @@ -19,136 +13,87 @@ permissions: id-token: write jobs: - build-ui: + setup: runs-on: ubuntu-latest - permissions: - contents: read - packages: write - id-token: write + outputs: + version: ${{ steps.version.outputs.value }} steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install cosign - if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 - with: - cosign-release: 'v2.2.4' - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - - - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set version (SemVer) - id: set_version - run: echo "VERSION=v0.0.${{ github.run_number }}" >> $GITHUB_ENV - - - name: Extract Docker UI metadata - id: meta-ui - uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_UI }} - tags: ${{ env.VERSION }} - - - name: Build and push UI Docker image - id: build-and-push-ui - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 - with: - context: ui/. - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta-ui.outputs.tags }} - labels: ${{ steps.meta-ui.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Sign the published UI Docker image - if: ${{ github.event_name != 'pull_request' }} - env: - TAGS: ${{ steps.meta-ui.outputs.tags }} - DIGEST: ${{ steps.build-and-push-ui.outputs.digest }} - run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} - - build-ansible: + - name: Compute version + id: version + run: | + if [[ "${{ github.ref }}" == refs/tags/v* ]]; then + echo "value=${{ github.ref_name }}" >> $GITHUB_OUTPUT + else + SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) + echo "value=sha-${SHORT_SHA}" >> $GITHUB_OUTPUT + fi + + quality: runs-on: ubuntu-latest - permissions: - contents: read - packages: write - id-token: write + defaults: + run: + working-directory: ui-next steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install cosign - if: github.event_name != 'pull_request' - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 - with: - cosign-release: 'v2.2.4' - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 - - - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set version (SemVer) - id: set_version - run: echo "VERSION=v0.0.${{ github.run_number }}" >> $GITHUB_ENV - - - name: Extract Docker Ansible metadata - id: meta-ansible - uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ANSIBLE }} - tags: ${{ env.VERSION }} + node-version: 22 + cache: npm + cache-dependency-path: ui-next/package-lock.json + - name: Install dependencies + run: npm install + - name: Lint + run: npm run lint + - name: Build check + run: npm run build + env: + AUTH_SECRET: ci-placeholder + DATABASE_URL: ":memory:" - - name: Build and push Ansible Docker image - id: build-and-push-ansible - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 - with: - context: ansible/. - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta-ansible.outputs.tags }} - labels: ${{ steps.meta-ansible.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max + build-ui: + needs: [setup, quality] + uses: ./.github/workflows/docker-build.yml + with: + image_name: ${{ github.repository }}-ui + context: ui/. + version: ${{ needs.setup.outputs.version }} + registry: ghcr.io + push: ${{ github.event_name != 'pull_request' }} + secrets: + registry_token: ${{ secrets.GITHUB_TOKEN }} + + build-ui-next: + needs: [setup, quality] + uses: ./.github/workflows/docker-build.yml + with: + image_name: ${{ github.repository }}-ui-next + context: ui-next/. + version: ${{ needs.setup.outputs.version }} + registry: ghcr.io + push: ${{ github.event_name != 'pull_request' }} + secrets: + registry_token: ${{ secrets.GITHUB_TOKEN }} - - name: Sign the published Ansible Docker image - if: ${{ github.event_name != 'pull_request' }} - env: - TAGS: ${{ steps.meta-ansible.outputs.tags }} - DIGEST: ${{ steps.build-and-push-ansible.outputs.digest }} - run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} + build-ansible: + needs: [setup, quality] + uses: ./.github/workflows/docker-build.yml + with: + image_name: ${{ github.repository }}-ansible + context: ansible/. + version: ${{ needs.setup.outputs.version }} + registry: ghcr.io + push: ${{ github.event_name != 'pull_request' }} + secrets: + registry_token: ${{ secrets.GITHUB_TOKEN }} release: - needs: [build-ui, build-ansible] + needs: [build-ui, build-ui-next, build-ansible] runs-on: ubuntu-latest permissions: contents: write - packages: write - id-token: write - if: github.ref == 'refs/heads/main' + if: startsWith(github.ref, 'refs/tags/v') steps: - - name: Set version (SemVer) for release - run: echo "VERSION=v0.0.${{ github.run_number }}" >> $GITHUB_ENV - - name: Create GitHub Release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: softprops/action-gh-release@v2 with: - tag_name: ${{ env.VERSION }} - release_name: Release ${{ env.VERSION }} - draft: false - prerelease: false \ No newline at end of file + generate_release_notes: true diff --git a/.gitignore b/.gitignore index 0f01f672..045c4a3a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ ansible/group_vars ansible/host_vars ansible/ssh ansible/inventory.yml + +.devcontainer + +ui-blueprint.md diff --git a/README.md b/README.md index c1441863..45be7584 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,236 @@ -# Simple Stack +# Wiseflat Simple Stack -![GitHub stars](https://img.shields.io/github/stars/your-repo/simple-stack?style=flat) -![License](https://img.shields.io/github/license/your-repo/simple-stack) +![GitHub stars](https://img.shields.io/github/stars/wiseflat/simple-stack?style=flat) +![License](https://img.shields.io/github/license/wiseflat/simple-stack) -**Simple Stack** is a reference implementation that shows how to self‑host modern web applications with minimal operational overhead. It combines Terraform for infrastructure, Ansible for configuration, and a lightweight UI for management. +**Simple Stack** is an integrated platform for running your entire stack — from infrastructure to applications to observability — on your own hardware or cloud accounts. No more vendor lock-in, no more scattered configuration across a dozen tools. -## Philosophy +--- + +## The Problem + +You want to host your own infrastructure and applications, but you don't want to: + +- Manually manage Terraform state files and infrastructure versions +- Write deployment scripts every time you add a new service +- Cobble together monitoring solutions across multiple dashboards +- Lose visibility into what's actually running on your servers + +## The Solution: One Integrated Platform + +Simple Stack unifies the entire deployment pipeline in a single, self-hosted interface: + +``` +Terraform States → Ansible Playbooks → Docker Registry → Application Deployments → Full Observability + (IaaS) (PaaS) (Catalog) (SaaS) (Built-in) +``` + +--- + +## Your Journey: From Infrastructure to Production + +### **1. Infrastructures – Define Your Foundation (IaaS)** + +Start by importing or provisioning your cloud infrastructure: + +- Store Terraform state files directly in Simple Stack's database +- Manage infrastructure versions and changes through a web interface +- Support for any Terraform provider: AWS, OVHcloud, Scaleway, on-premise, etc. +- Versioned history of all infrastructure changes + +**Result:** Your infrastructure is now version-controlled, auditable, and reproducible. + +--- + +### **2. Platforms & Configuration – Setup Your Servers (PaaS)** + +Define how your servers should be configured: + +- Use Ansible playbooks to install Docker and core dependencies +- Deploy and manage system-level services (databases, proxies, etc.) +- Nomad orchestrates the PaaS layer for you +- Pre-built roles for observability stack (Prometheus, Loki, Grafana) + +**Result:** Every new server gets the same solid, observability-ready foundation. + +--- + +### **3. Catalogs – Build Your Applications** + +Create reusable application containers: + +- Define service templates for your team to use +- Store Docker images in your own private registry (self-hosted) +- Share catalogs across projects using fork/inheritance patterns +- Document dependencies and environment requirements + +**Result:** A curated library of production-ready services, no external dependencies. + +--- + +### **4. Softwares – Deploy & Manage** + +Deploy applications on your infrastructure: + +- Choose which catalog items to deploy onto which servers +- Configure variables, secrets, and per-environment overrides +- Trigger deployments from the UI, no scripting required +- Track deployment history and operational actions + +**Result:** Modern application management meets your own infrastructure. + +--- -- **Simplicity first** – every component can be understood in a few minutes. -- **Transparency** – all code is declarative and version‑controlled. -- **Portability** – works on any major cloud provider or on‑premise hardware. -- **Extensibility** – add new services by extending the existing Ansible roles or Terraform modules. +### **5. Observability – See Everything** -## Project Goals +Monitor and troubleshoot your entire stack: -The project aims to give SREs and developers a solid, opinionated foundation for: +- **Prometheus** for metrics collection across all infrastructure +- **Loki** for log aggregation from all services and applications +- **Grafana** for unified dashboards and alerting +- All deployed and managed automatically as part of the PaaS foundation -- Managing and deploying cloud infrastructure with a mainstream IaC tool. -- Configuring servers using a widely adopted automation framework. -- Orchestrating the full application lifecycle with containers. -- Scaling up/down horizontally or vertically with proven patterns. +**Result:** End-to-end visibility without extra tools or vendor accounts. + +--- + +## Why Simple Stack? + +✅ **Self-Hosted** – Full control. No SaaS dependencies. +✅ **Unified** – One interface for infrastructure, configuration, and deployments. +✅ **Declarative** – All changes are version-controlled, auditable, and reproducible. +✅ **Extensible** – Add new services by extending Terraform, Ansible, or the Docker catalog. +✅ **Transparent** – No hidden magic. Every decision is documented and open. + +--- + +## Quick Start + +### Prerequisites + +- A cloud account (AWS, OVHcloud, Scaleway, etc.) or on-premise hardware +- Docker and Node.js installed locally for development +- A Git repository to version-control your infrastructure and configurations + +### Installation + +1. **Clone the repository** + ```bash + git clone https://github.com/your-repo/simple-stack.git + cd simple-stack + ``` + +2. **Deploy the platform** + ```bash + cd terraform/demo-standalone-instances + terraform init && terraform apply + ``` + +3. **Access the web UI** + ``` + https://your-domain.com + ``` + +4. **Import or create your first infrastructure** + - Upload a Terraform state file, or + - Use the built-in Terraform templates + +--- + +## Documentation + +More detailed guides are available in `/docs`: + +- **Intro** – Platform overview and mental model +- **Basic Usage** – First steps with Simple Stack +- **Infrastructures** – Deep dive into IaaS and Terraform +- **Catalogs** – Building and managing your application library +- **Softwares** – Deploying and managing services + +Full documentation with examples: https://your-domain.com/docs + +--- ## Project Structure -The repository is organised into three logical layers: +``` +simple-stack/ +├── terraform/ # IaaS – Cloud infrastructure provisioning +│ ├── modules/ +│ └── demo-*-instances/ # Example deployments +├── ansible/ # PaaS – Server configuration & observability +│ ├── playbooks/ +│ ├── roles/ +│ └── rulebook.yml # Event-driven automation (Ansible Runner) +├── ui/ # Legacy SaaS UI (being migrated to ui-next) +└── ui-next/ # New Next.js SaaS management platform + ├── app/ # Application pages & API routes + ├── components/ # Reusable React components + ├── lib/ # Shared logic and database layer + └── content/docs/ # Markdown documentation +``` + +--- + +## Architecture Highlights + +### Three Layers + +**IaC Layer (Terraform)** +Provisions compute, networking, and storage resources on any mainstream cloud provider. -### IaC – Terraform +**Config Layer (Ansible)** +Installs Docker, system services, and the observability stack on provisioned hosts. -Terraform modules provision a single compute instance on providers such as **OVHcloud**, **Infomaniak**, **AWS**, **Scaleway**, etc. The goal is to keep the footprint small while remaining provider‑agnostic. +**UI Layer (Next.js + SQLite)** +Provides a unified interface for managing infrastructure, deployments, and operations. -### Configuration – Ansible +### Built-In Observability -Ansible roles install Docker, pull the required images and configure the host. Roles are deliberately minimal to reduce attack surface and maintenance effort. +Every instance deployed through Simple Stack automatically gets: -### SaaS – UI +- **Prometheus** – Scrapes metrics from all services, infrastructure, and exporters +- **Loki** – Aggregates logs from Docker containers and system services +- **Grafana** – Pre-configured dashboards for infrastructure, platform, and application metrics +- **Alerting** – Out-of-the-box rules for common operational concerns -A small web UI (the `ui/` directory) lets you create projects, store all variables and trigger deployments without writing additional scripts. +--- -## Features +## Philosophy -- One‑click container deployment via Ansible. -- Basic container lifecycle management. -- Lightweight control plane for orchestrating deployments. -- Self‑hosted web UI for project administration. +- **Simplicity First** – Each component is understandable and maintainable +- **Transparency** – All configuration is version-controlled and auditable +- **Portability** – Works on any cloud or on-premise hardware +- **Extensibility** – Add new services without rewriting core systems +--- ## Contributing Contributions are welcome! Please: -- Fork the repository. -- Create a feature branch. -- Ensure code follows the existing style and passes `make lint`. -- Open a Pull Request with a clear description of the change. +- Fork the repository +- Create a feature branch +- Add tests and documentation for new features +- Open a Pull Request with a clear description + +For detailed guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md). + +--- ## License This project is licensed under the MIT License – see the [LICENSE](LICENSE) file for details. +--- + +## Get Support + +- 📖 **Documentation** – https://your-domain.com/docs +- 💬 **Discussions** – GitHub Discussions (coming soon) +- 🐛 **Issues** – Report bugs on GitHub Issues + + ## Acknowledgements Thanks to the open‑source community for the tools that make this stack possible: Terraform, Ansible, Docker and the many contributors of the underlying roles. diff --git a/ansible/.dockerignore b/ansible/.dockerignore new file mode 100644 index 00000000..18b5b75a --- /dev/null +++ b/ansible/.dockerignore @@ -0,0 +1,18 @@ +# dependencies +collections + +# env / secrets +ssh +tmp + +# vcs +.git +.gitignore + +# editor / os +.vscode +.idea +.DS_Store + +# docs +README.md diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg index 2d99263d..64413104 100644 --- a/ansible/ansible.cfg +++ b/ansible/ansible.cfg @@ -19,7 +19,7 @@ fact_caching_connection = tmp/facts [ssh_connection] retries = 5 scp_if_ssh = True -ssh_args = -F ssh/config +ssh_args = -F ~/.ssh/config pipelining = True [url_lookup] diff --git a/ansible/playbooks/debug.yml b/ansible/playbooks/debug.yml index b9a774ce..63bc5bb7 100644 --- a/ansible/playbooks/debug.yml +++ b/ansible/playbooks/debug.yml @@ -7,4 +7,4 @@ tasks: - name: Debug payload ansible.builtin.debug: - msg: "{{ event }}" \ No newline at end of file + msg: "{{ event }}" diff --git a/ansible/playbooks/paas/nvidia.yml b/ansible/playbooks/paas/nvidia.yml index bd950cf6..2796d11c 100644 --- a/ansible/playbooks/paas/nvidia.yml +++ b/ansible/playbooks/paas/nvidia.yml @@ -21,7 +21,7 @@ - name: End the play for hosts that don't have nvidia gpu ansible.builtin.meta: end_host when: not (nvidia_enable is defined and nvidia_enable) - + - name: Créer le répertoire du keyring s'il n'existe pas ansible.builtin.file: path: "{{ nvidia_keyring_path | dirname }}" diff --git a/ansible/playbooks/paas/roles/ansible-docker/tasks/install.yml b/ansible/playbooks/paas/roles/ansible-docker/tasks/install.yml index b99925af..7a727add 100644 --- a/ansible/playbooks/paas/roles/ansible-docker/tasks/install.yml +++ b/ansible/playbooks/paas/roles/ansible-docker/tasks/install.yml @@ -67,7 +67,7 @@ mode: '0755' loop: - /root/.docker - + - name: Copy config.json ansible.builtin.template: src: config.json.j2 diff --git a/ansible/playbooks/paas/roles/certificate/tasks/ca.yml b/ansible/playbooks/paas/roles/certificate/tasks/ca.yml index 2c634e6a..7d16388d 100644 --- a/ansible/playbooks/paas/roles/certificate/tasks/ca.yml +++ b/ansible/playbooks/paas/roles/certificate/tasks/ca.yml @@ -53,4 +53,3 @@ delegate_to: "{{ certificate_ca_host }}" become: false when: not cert_ca_tls_priv_present.stat.exists - diff --git a/ansible/playbooks/paas/roles/coredns/README.md b/ansible/playbooks/paas/roles/coredns/README.md index 55beefb1..04db6f14 100644 --- a/ansible/playbooks/paas/roles/coredns/README.md +++ b/ansible/playbooks/paas/roles/coredns/README.md @@ -4,4 +4,4 @@ ### nomad cluster mode -nomad_primary_master_node: Set a primary nomad master node to get nomad_management_token \ No newline at end of file +nomad_primary_master_node: Set a primary nomad master node to get nomad_management_token diff --git a/ansible/playbooks/paas/roles/dns_exporter/defaults/main.yml b/ansible/playbooks/paas/roles/dns_exporter/defaults/main.yml index c5bd8834..6ad03ab2 100644 --- a/ansible/playbooks/paas/roles/dns_exporter/defaults/main.yml +++ b/ansible/playbooks/paas/roles/dns_exporter/defaults/main.yml @@ -100,4 +100,4 @@ dns_exporter: - ".*[a-m].root-servers.net.*" socks1080: - proxy: "socks5://127.0.0.1:1080" \ No newline at end of file + proxy: "socks5://127.0.0.1:1080" diff --git a/ansible/playbooks/paas/roles/dns_exporter/tasks/build.yml b/ansible/playbooks/paas/roles/dns_exporter/tasks/build.yml index 6841e743..d81cf178 100644 --- a/ansible/playbooks/paas/roles/dns_exporter/tasks/build.yml +++ b/ansible/playbooks/paas/roles/dns_exporter/tasks/build.yml @@ -22,4 +22,4 @@ dest: "/etc/ansible/facts.d/{{ image.name }}.fact" owner: root group: root - mode: '0755' \ No newline at end of file + mode: '0755' diff --git a/ansible/playbooks/paas/roles/dns_exporter/templates/config.yml.j2 b/ansible/playbooks/paas/roles/dns_exporter/templates/config.yml.j2 index fb07ef60..7277b812 100644 --- a/ansible/playbooks/paas/roles/dns_exporter/templates/config.yml.j2 +++ b/ansible/playbooks/paas/roles/dns_exporter/templates/config.yml.j2 @@ -140,5 +140,5 @@ modules: # this is the only key currently read from the config kitchensink: <<: *kitchensink - + {{ dns_exporter.modules | to_nice_yaml | indent(2) }} diff --git a/ansible/playbooks/paas/roles/nomad/tasks/07_autoeligibility.yml b/ansible/playbooks/paas/roles/nomad/tasks/07_autoeligibility.yml index 31356c66..dcf859b4 100644 --- a/ansible/playbooks/paas/roles/nomad/tasks/07_autoeligibility.yml +++ b/ansible/playbooks/paas/roles/nomad/tasks/07_autoeligibility.yml @@ -103,4 +103,3 @@ - name: "Nomad Install | Save Nomad Autoeligibility token" ansible.builtin.set_fact: nomad_autoeligibility_token: "{{ lookup('simple-stack-ui', type='secret', key=inventory_hostname, subkey='nomad_autoeligibility_token', missing='create', userpass=nomad_new_token_name.json.SecretID) }}" - diff --git a/ansible/playbooks/paas/roles/nomad/templates/client.hcl.j2 b/ansible/playbooks/paas/roles/nomad/templates/client.hcl.j2 index 7732ea2d..c657f1dc 100644 --- a/ansible/playbooks/paas/roles/nomad/templates/client.hcl.j2 +++ b/ansible/playbooks/paas/roles/nomad/templates/client.hcl.j2 @@ -13,7 +13,7 @@ client { {%- for server in nomad_servers_advertise_address -%} {{ comma() }}"{{ server }}:{{ nomad_ports.rpc }}" {%- endfor -%} ] - + {% if nomad_client_network_interface is defined %} network_interface = "{{ nomad_client_network_interface }}" {% endif %} diff --git a/ansible/playbooks/paas/roles/nomad/templates/juicefs-controller.hcl.j2 b/ansible/playbooks/paas/roles/nomad/templates/juicefs-controller.hcl.j2 index c42da612..06f33644 100644 --- a/ansible/playbooks/paas/roles/nomad/templates/juicefs-controller.hcl.j2 +++ b/ansible/playbooks/paas/roles/nomad/templates/juicefs-controller.hcl.j2 @@ -3,7 +3,7 @@ job "jfs-controller" { type = "system" group "controller" { - + constraint { attribute = "${meta.instance}" set_contains = "{{ nomad_constraints_juicefs_controller_instance }}" @@ -40,4 +40,4 @@ job "jfs-controller" { } } } -} \ No newline at end of file +} diff --git a/ansible/playbooks/paas/roles/nomad/templates/juicefs-node.hcl.j2 b/ansible/playbooks/paas/roles/nomad/templates/juicefs-node.hcl.j2 index f503ef6d..26d285c7 100644 --- a/ansible/playbooks/paas/roles/nomad/templates/juicefs-node.hcl.j2 +++ b/ansible/playbooks/paas/roles/nomad/templates/juicefs-node.hcl.j2 @@ -45,4 +45,4 @@ job "jfs-node" { } } } -} \ No newline at end of file +} diff --git a/ansible/playbooks/paas/roles/nomad/templates/juicefs-volume.hcl.j2 b/ansible/playbooks/paas/roles/nomad/templates/juicefs-volume.hcl.j2 index f45cf80f..ad35426f 100644 --- a/ansible/playbooks/paas/roles/nomad/templates/juicefs-volume.hcl.j2 +++ b/ansible/playbooks/paas/roles/nomad/templates/juicefs-volume.hcl.j2 @@ -15,4 +15,4 @@ secrets { storage="minio" access-key="{{ lookup('simple-stack-ui', type='secret', key=nomad_juicefs_secrets.minio.domain, subkey='user', missing='error') }}" secret-key="{{ lookup('simple-stack-ui', type='secret', key=nomad_juicefs_secrets.minio.domain, subkey='passwd', missing='error') }}" -} \ No newline at end of file +} diff --git a/ansible/playbooks/paas/roles/nomad/templates/override.conf.j2 b/ansible/playbooks/paas/roles/nomad/templates/override.conf.j2 index 92231047..a9767b14 100644 --- a/ansible/playbooks/paas/roles/nomad/templates/override.conf.j2 +++ b/ansible/playbooks/paas/roles/nomad/templates/override.conf.j2 @@ -6,4 +6,4 @@ ExecReload=/bin/kill --signal HUP $MAINPID {% if nomad_node_role in ['both', 'client'] %} ExecStartPost=/usr/bin/nomad node eligibility -enable -address={{ nomad_http_scheme }}://{{ hostvars[nomad_primary_master_node | default(inventory_hostname)]['ansible_' + nomad_iface].ipv4.address | default('127.0.0.1') }}:{{ nomad_http_port }} -ca-cert={{ nomad_tls_host_certificate_dir }}/{{ nomad_tls_ca_pubkey }} -client-cert={{ nomad_tls_host_certificate_dir }}/{{ inventory_hostname }}-dc1-client-nomad.pem -client-key={{ nomad_tls_host_certificate_dir }}/{{ inventory_hostname }}-dc1-client-nomad.key -token={{ lookup('simple-stack-ui', type='secret', key=nomad_primary_master_node | default(inventory_hostname), subkey='nomad_management_token', missing='error') }} {{ node_id }} ExecStop=/usr/bin/nomad node drain -enable -address={{ nomad_http_scheme }}://{{ hostvars[nomad_primary_master_node | default(inventory_hostname)]['ansible_' + nomad_iface].ipv4.address | default('127.0.0.1') }}:{{ nomad_http_port }} -ca-cert={{ nomad_tls_host_certificate_dir }}/{{ nomad_tls_ca_pubkey }} -client-cert={{ nomad_tls_host_certificate_dir }}/{{ inventory_hostname }}-dc1-client-nomad.pem -client-key={{ nomad_tls_host_certificate_dir }}/{{ inventory_hostname }}-dc1-client-nomad.key -token={{ lookup('simple-stack-ui', type='secret', key=nomad_primary_master_node | default(inventory_hostname), subkey='nomad_management_token', missing='error') }} {{ node_id }} -{% endif %} \ No newline at end of file +{% endif %} diff --git a/ansible/playbooks/paas/roles/nvidia_gpu_exporter/templates/service.j2 b/ansible/playbooks/paas/roles/nvidia_gpu_exporter/templates/service.j2 index 1b213d68..cf91fa38 100644 --- a/ansible/playbooks/paas/roles/nvidia_gpu_exporter/templates/service.j2 +++ b/ansible/playbooks/paas/roles/nvidia_gpu_exporter/templates/service.j2 @@ -13,4 +13,4 @@ Restart=always RestartSec=10 [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target diff --git a/ansible/playbooks/paas/roles/prometheus/defaults/main.yml b/ansible/playbooks/paas/roles/prometheus/defaults/main.yml index acd2bfb8..e49c5685 100644 --- a/ansible/playbooks/paas/roles/prometheus/defaults/main.yml +++ b/ansible/playbooks/paas/roles/prometheus/defaults/main.yml @@ -6,4 +6,4 @@ prometheus_remote_password: prometheus_project: "{{ fact_instance.project }}" -prometheus_nodes_exporter: [] \ No newline at end of file +prometheus_nodes_exporter: [] diff --git a/ansible/playbooks/paas/roles/script_exporter/files/speedtest-exporter b/ansible/playbooks/paas/roles/script_exporter/files/speedtest-exporter index 5f569127..6a8b0fd7 100644 --- a/ansible/playbooks/paas/roles/script_exporter/files/speedtest-exporter +++ b/ansible/playbooks/paas/roles/script_exporter/files/speedtest-exporter @@ -35,4 +35,4 @@ else printMetric "speedtest_uploadedbytes_bytes" "Uploaded Bytes" "gauge" "$uploadedbytes" "$server_id" done < <(/usr/local/bin/speedtest --accept-license --accept-gdpr -f tsv --server-id $server_id) done -fi \ No newline at end of file +fi diff --git a/ansible/playbooks/paas/roles/script_exporter/tasks/speedtest.yml b/ansible/playbooks/paas/roles/script_exporter/tasks/speedtest.yml index 02f24233..089f4338 100644 --- a/ansible/playbooks/paas/roles/script_exporter/tasks/speedtest.yml +++ b/ansible/playbooks/paas/roles/script_exporter/tasks/speedtest.yml @@ -15,4 +15,4 @@ - name: Script_exporter | Remove old speedtest binary (TODO remove) ansible.builtin.file: path: /usr/local/bin/speedtest - state: absent \ No newline at end of file + state: absent diff --git a/ansible/playbooks/paas/roles/script_exporter/templates/config.yml.j2 b/ansible/playbooks/paas/roles/script_exporter/templates/config.yml.j2 index 1c493473..10579d13 100644 --- a/ansible/playbooks/paas/roles/script_exporter/templates/config.yml.j2 +++ b/ansible/playbooks/paas/roles/script_exporter/templates/config.yml.j2 @@ -1,5 +1,5 @@ --- scripts: - name: speedtest - command: - - /usr/local/bin/speedtest-exporter \ No newline at end of file + command: + - /usr/local/bin/speedtest-exporter diff --git a/ansible/playbooks/paas/scan_exporter.yml b/ansible/playbooks/paas/scan_exporter.yml index d199cf36..42d09d89 100644 --- a/ansible/playbooks/paas/scan_exporter.yml +++ b/ansible/playbooks/paas/scan_exporter.yml @@ -7,4 +7,4 @@ pre_tasks: - name: Install scan_exporter ansible.builtin.include_role: - name: scan_exporter \ No newline at end of file + name: scan_exporter diff --git a/ansible/playbooks/saas/image-forkable.yml b/ansible/playbooks/saas/image-forkable.yml index 13b6ae63..f3b7d27e 100644 --- a/ansible/playbooks/saas/image-forkable.yml +++ b/ansible/playbooks/saas/image-forkable.yml @@ -14,11 +14,11 @@ armv7l: arm aarch64: arm64 arm64: arm64 - catalog: "{{ catalog_response.json.origin | default(catalog_response.json.name) }}" + catalog: "{{ (catalog_response.json.origin is not none) | ternary(catalog_response.json.origin, catalog_response.json.name) }}" build_work_dir: "/tmp/{{ catalog }}" download_dir: "{{ build_work_dir }}/download" arch_dir: "{{ build_work_dir }}/{{ upstream_default_arch }}" - upstream_default_arch: "{{ architecture_map[ansible_facts.architecture] }}" + upstream_default_arch: "{{ architecture_map[ansible_facts.architecture] }}" ui_url: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_URL') }}" ui_user: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_USER') }}" ui_password: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_PASSWORD') }}" @@ -26,13 +26,10 @@ pre_tasks: - name: Retrieve catalog item from UI ansible.builtin.uri: - url: "{{ ui_url }}/api" + url: "{{ ui_url }}/api/catalogs/{{ catalog_id }}" user: "{{ ui_user }}" password: "{{ ui_password }}" - method: POST - body_format: json - body: - schema: "catalogs_read/{{ catalog_id }}" + method: GET force_basic_auth: true status_code: 200 delegate_to: localhost @@ -49,14 +46,18 @@ - "{{ arch_dir }}" tasks: + - name: Debug catalog + debug: + msg: "Build Catalog: {{ catalog }}" + - name: Build assets ansible.builtin.include_role: name: "{{ catalog }}" tasks_from: build vars: catalog_image_name: "{{ catalog_response.json.name }}" - dockerfile_root: "{{ catalog_response.json.dockerfile_root | default('') }}" - dockerfile_nonroot: "{{ catalog_response.json.dockerfile_nonroot | default('') }}" + dockerfileRoot: "{{ catalog_response.json.dockerfileRoot | default('') }}" + dockerfileNonroot: "{{ catalog_response.json.dockerfileNonroot | default('') }}" - name: Build and push Docker image community.docker.docker_image_build: @@ -75,17 +76,15 @@ - name: Update catalog item version on UI ansible.builtin.uri: - url: "{{ ui_url }}/api" + url: "{{ ui_url }}/api/catalogs" user: "{{ ui_user }}" password: "{{ ui_password }}" method: POST body_format: json body: - schema: catalogs_create - data: - name: "{{ catalog_response.json.name }}" - version: "{{ image_version }}" - forkable: "{{ image_forkable | default(false) }}" + name: "{{ catalog_response.json.name }}" + version: "{{ image_version }}" + forkable: "{{ image_forkable | default(false) }}" force_basic_auth: true status_code: 200 delegate_to: localhost diff --git a/ansible/playbooks/saas/image.yml b/ansible/playbooks/saas/image.yml index da6da51a..80c1b91c 100644 --- a/ansible/playbooks/saas/image.yml +++ b/ansible/playbooks/saas/image.yml @@ -35,8 +35,8 @@ tasks_from: build vars: catalog_image_name: "{{ catalog }}" - dockerfile_root: "" - dockerfile_nonroot: "" + dockerfileRoot: "" + dockerfileNonroot: "" - name: Debug latest version ansible.builtin.debug: diff --git a/ansible/playbooks/saas/main.yml b/ansible/playbooks/saas/main.yml index ea194516..7f1df3c9 100644 --- a/ansible/playbooks/saas/main.yml +++ b/ansible/playbooks/saas/main.yml @@ -33,6 +33,10 @@ ansible.builtin.debug: msg: "{{ software }}" + - name: Debug softwares + ansible.builtin.debug: + msg: "{{ softwares }}" + tasks: - name: Deploy service ansible.builtin.include_role: @@ -41,17 +45,14 @@ post_tasks: - name: Update software version ansible.builtin.uri: - url: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_URL') }}/api" + url: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_URL') }}/api/softwares/{{ software.id }}" user: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_USER') }}" password: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_PASSWORD') }}" - method: POST + method: PUT body_format: json body: - schema: softwares_update_version/{{ software.id }} - data: - version: "{{ softwares[catalog].version }}" + version: "{{ catalogs[catalog].version }}" force_basic_auth: true status_code: 200 - ignore_errors: true delegate_to: localhost become: false diff --git a/ansible/playbooks/saas/operate.yml b/ansible/playbooks/saas/operate.yml index 9259fba0..00504466 100644 --- a/ansible/playbooks/saas/operate.yml +++ b/ansible/playbooks/saas/operate.yml @@ -36,15 +36,13 @@ post_tasks: - name: Update software version ansible.builtin.uri: - url: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_URL') }}/api" + url: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_URL') }}/api/softwares/{{ software.id }}" user: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_USER') }}" password: "{{ lookup('ansible.builtin.env', 'SIMPLE_STACK_UI_PASSWORD') }}" - method: POST + method: PUT body_format: json body: - schema: softwares_update_version/{{ software.id }} - data: - version: "{{ softwares[catalog].version }}" + version: "{{ catalogs[catalog].version }}" force_basic_auth: true status_code: 200 ignore_errors: true @@ -66,4 +64,4 @@ ignore_errors: true delegate_to: localhost become: false - when: task == "destroy" \ No newline at end of file + when: task == "destroy" diff --git a/ansible/playbooks/saas/query_registry.yml b/ansible/playbooks/saas/query_registry.yml index 9f68ec44..291f5fef 100644 --- a/ansible/playbooks/saas/query_registry.yml +++ b/ansible/playbooks/saas/query_registry.yml @@ -41,4 +41,4 @@ register: register_uri - debug: - msg: "{{ register_uri.json.tags | sort }}" \ No newline at end of file + msg: "{{ register_uri.json.tags | sort }}" diff --git a/ansible/playbooks/saas/roles/adguard/tasks/build.yml b/ansible/playbooks/saas/roles/adguard/tasks/build.yml index f48c8f22..223e9820 100644 --- a/ansible/playbooks/saas/roles/adguard/tasks/build.yml +++ b/ansible/playbooks/saas/roles/adguard/tasks/build.yml @@ -9,10 +9,10 @@ image_forkable: "{{ image.forkable }}" upstream_file_url: "{{ upstream_file_url }}" upstream_file_name: "{{ upstream_file_name }}" - + - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Copy dockerfile ansible.builtin.template: diff --git a/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl b/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl index 26129dc0..3d318228 100644 --- a/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl @@ -45,7 +45,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "{{ docker_private_registry.url }}/adguard:{{ softwares.adguard.version }}" + image = "{{ docker_private_registry.url }}/adguard:{{ catalogs.adguard.version }}" network_mode = "host" privileged = "true" volumes = [ diff --git a/ansible/playbooks/saas/roles/arangodb/tasks/build.yml b/ansible/playbooks/saas/roles/arangodb/tasks/build.yml index bcf1b930..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/arangodb/tasks/build.yml +++ b/ansible/playbooks/saas/roles/arangodb/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version \ No newline at end of file + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/arangodb/templates/nomad.hcl b/ansible/playbooks/saas/roles/arangodb/templates/nomad.hcl index ccd7cace..62649096 100644 --- a/ansible/playbooks/saas/roles/arangodb/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/arangodb/templates/nomad.hcl @@ -53,7 +53,7 @@ job "{{ domain }}" { } config { - image = "arangodb:{{ softwares.arangodb.version }}" + image = "arangodb:{{ catalogs.arangodb.version }}" volumes = [ "{{ software_path }}/var/lib/arangodb3:/var/lib/arangodb3:rw", diff --git a/ansible/playbooks/saas/roles/arangodb/vars/actions.yml b/ansible/playbooks/saas/roles/arangodb/vars/actions.yml index c4db4bb2..a9f3d5e7 100644 --- a/ansible/playbooks/saas/roles/arangodb/vars/actions.yml +++ b/ansible/playbooks/saas/roles/arangodb/vars/actions.yml @@ -9,4 +9,4 @@ arangodb_actions: - "{{ software_path }}/run:/run:rw" - "/usr/local/bin/arangodb-backup:/usr/local/bin/arangodb-backup:ro" - "/usr/local/bin/arangodb-restore:/usr/local/bin/arangodb-restore:ro" - image: "arangodb:{{ softwares.arangodb.version }}" + image: "arangodb:{{ catalogs.arangodb.version }}" diff --git a/ansible/playbooks/saas/roles/caddy/tasks/build.yml b/ansible/playbooks/saas/roles/caddy/tasks/build.yml index 28013d4a..96c8c57e 100644 --- a/ansible/playbooks/saas/roles/caddy/tasks/build.yml +++ b/ansible/playbooks/saas/roles/caddy/tasks/build.yml @@ -10,7 +10,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Unarchive GitHub release ansible.builtin.unarchive: diff --git a/ansible/playbooks/saas/roles/caddy/templates/Dockerfile.j2 b/ansible/playbooks/saas/roles/caddy/templates/Dockerfile.j2 index f21f7848..6dccbb9b 100644 --- a/ansible/playbooks/saas/roles/caddy/templates/Dockerfile.j2 +++ b/ansible/playbooks/saas/roles/caddy/templates/Dockerfile.j2 @@ -4,7 +4,7 @@ FROM {{ image.origin }} ARG TARGETARCH -{{ dockerfile_root | default('') }} +{{ dockerfileRoot | default('') }} COPY ./${TARGETARCH}/caddy /usr/local/bin/caddy @@ -17,6 +17,6 @@ RUN mkdir -p /var/log/caddy /var/lib/caddy /etc/caddy \ USER caddy -{{ dockerfile_nonroot | default('') }} +{{ dockerfileNonroot | default('') }} CMD ["caddy", "run"] diff --git a/ansible/playbooks/saas/roles/caddy/templates/nomad.hcl b/ansible/playbooks/saas/roles/caddy/templates/nomad.hcl index cb828014..d7864139 100644 --- a/ansible/playbooks/saas/roles/caddy/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/caddy/templates/nomad.hcl @@ -61,12 +61,12 @@ job "{{ domain }}" { } config { - image = "{{ docker_private_registry.url }}/caddy:{{ softwares.caddy.version }}" + image = "{{ docker_private_registry.url }}/caddy:{{ catalogs.caddy.version }}" ports = ["caddy", "metrics"] command = "caddy" args = [ "run", - "--config", + "--config", "/local/Caddyfile" ] } diff --git a/ansible/playbooks/saas/roles/code_server/tasks/build.yml b/ansible/playbooks/saas/roles/code_server/tasks/build.yml index de163a2c..2dcf74eb 100644 --- a/ansible/playbooks/saas/roles/code_server/tasks/build.yml +++ b/ansible/playbooks/saas/roles/code_server/tasks/build.yml @@ -10,4 +10,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/code_server/tasks/main.yml b/ansible/playbooks/saas/roles/code_server/tasks/main.yml index 04059eae..5b6eb81a 100644 --- a/ansible/playbooks/saas/roles/code_server/tasks/main.yml +++ b/ansible/playbooks/saas/roles/code_server/tasks/main.yml @@ -27,4 +27,3 @@ ansible.builtin.include_role: name: nomad tasks_from: job_run.yml - diff --git a/ansible/playbooks/saas/roles/code_server/templates/nomad.hcl b/ansible/playbooks/saas/roles/code_server/templates/nomad.hcl index 58f4cf3f..40c5bb12 100644 --- a/ansible/playbooks/saas/roles/code_server/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/code_server/templates/nomad.hcl @@ -34,7 +34,7 @@ job "{{ domain }}" { port = "code_server" provider = "nomad" tags = [ - {{ lookup('ansible.builtin.template', '../../traefik/templates/traefik_tag.j2') | indent(8) }} + {{ lookup('ansible.builtin.template', '../../traefik/templates/traefik_tag.j2') }} ] check { type = "http" @@ -49,7 +49,7 @@ job "{{ domain }}" { port = "http_dev" provider = "nomad" tags = [ - {{ lookup('ansible.builtin.template', 'templates/traefik_tag.j2', template_vars={'prefix': 'dev'}) | indent(8) }} + {{ lookup('ansible.builtin.template', 'templates/traefik_tag.j2', template_vars={'prefix': 'dev'}) }} ] } @@ -67,7 +67,7 @@ job "{{ domain }}" { } config { - image = "codercom/code-server:{{ softwares.code_server.version }}-ubuntu" + image = "codercom/code-server:{{ catalogs.code_server.version }}-ubuntu" volumes = [ "/usr/bin/docker:/usr/bin/docker", @@ -79,6 +79,10 @@ job "{{ domain }}" { "{{ software_path }}/home/coder/.cache:/home/coder/.local", "{{ software_path }}/home/coder/.ssh:/home/coder/.ssh", "{{ software_path }}/projects:/home/coder/projects", + {% if software.volumes is defined %} + {% for volume in software.volumes %}{{ volume | to_json }}{% if not loop.last %},{% endif %} + {% endfor %} + {% endif %} ] ports = ["code_server", "http_dev"] } diff --git a/ansible/playbooks/saas/roles/code_server/templates/traefik_tag.j2 b/ansible/playbooks/saas/roles/code_server/templates/traefik_tag.j2 index d5d20835..e1c354e3 100644 --- a/ansible/playbooks/saas/roles/code_server/templates/traefik_tag.j2 +++ b/ansible/playbooks/saas/roles/code_server/templates/traefik_tag.j2 @@ -35,4 +35,4 @@ {% elif (software.ipfilter is not defined and software.basic_auth is defined) %} "traefik.http.routers.{{ prefix }}-{{ service_name }}.middlewares={{ prefix }}-{{ service_name }}-basicauth@nomad" {% endif %} -{% endif %} \ No newline at end of file +{% endif %} diff --git a/ansible/playbooks/saas/roles/code_server/vars/main.yml b/ansible/playbooks/saas/roles/code_server/vars/main.yml index 0aeaed2b..4c36b03e 100644 --- a/ansible/playbooks/saas/roles/code_server/vars/main.yml +++ b/ansible/playbooks/saas/roles/code_server/vars/main.yml @@ -13,4 +13,4 @@ image: labels: {} name: code_server -traefik_x_robots_tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex \ No newline at end of file +traefik_x_robots_tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex diff --git a/ansible/playbooks/saas/roles/code_server/vars/upstream.yml b/ansible/playbooks/saas/roles/code_server/vars/upstream.yml index c856b01f..32006b02 100644 --- a/ansible/playbooks/saas/roles/code_server/vars/upstream.yml +++ b/ansible/playbooks/saas/roles/code_server/vars/upstream.yml @@ -1,2 +1,2 @@ --- -latest_version: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/releases/latest', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN')}) | from_json).get('tag_name') | replace('v', '') }}" \ No newline at end of file +latest_version: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/releases/latest', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN')}) | from_json).get('tag_name') | replace('v', '') }}" diff --git a/ansible/playbooks/saas/roles/dolibarr/tasks/build.yml b/ansible/playbooks/saas/roles/dolibarr/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/dolibarr/tasks/build.yml +++ b/ansible/playbooks/saas/roles/dolibarr/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/dolibarr/templates/nomad.hcl b/ansible/playbooks/saas/roles/dolibarr/templates/nomad.hcl index a3c77c12..bddc96e4 100644 --- a/ansible/playbooks/saas/roles/dolibarr/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/dolibarr/templates/nomad.hcl @@ -57,7 +57,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "dolibarr/dolibarr:{{ softwares.dolibarr.version }}" + image = "dolibarr/dolibarr:{{ catalogs.dolibarr.version }}" volumes = [ "{{ software_path }}/var/www/html/documents:/var/www/html/documents:rw", diff --git a/ansible/playbooks/saas/roles/dolibarr/vars/actions.yml b/ansible/playbooks/saas/roles/dolibarr/vars/actions.yml index b270b514..5dc745b9 100644 --- a/ansible/playbooks/saas/roles/dolibarr/vars/actions.yml +++ b/ansible/playbooks/saas/roles/dolibarr/vars/actions.yml @@ -8,4 +8,4 @@ dolibarr_actions: - "{{ software_path }}/var/backup:/var/backup:rw" - "/usr/local/bin/dolibarr-backup:/usr/local/bin/dolibarr-backup:ro" - "/usr/local/bin/dolibarr-restore:/usr/local/bin/dolibarr-restore:ro" - image: "mariadb:{{ softwares.mariadb.version }}" + image: "mariadb:{{ catalogs.mariadb.version }}" diff --git a/ansible/playbooks/saas/roles/forgejo/tasks/build.yml b/ansible/playbooks/saas/roles/forgejo/tasks/build.yml index 796ce846..e7e52b29 100644 --- a/ansible/playbooks/saas/roles/forgejo/tasks/build.yml +++ b/ansible/playbooks/saas/roles/forgejo/tasks/build.yml @@ -9,7 +9,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Download Github release ansible.builtin.get_url: diff --git a/ansible/playbooks/saas/roles/forgejo/tasks/first-user.yml b/ansible/playbooks/saas/roles/forgejo/tasks/first-user.yml index f48c6790..fa11fe65 100644 --- a/ansible/playbooks/saas/roles/forgejo/tasks/first-user.yml +++ b/ansible/playbooks/saas/roles/forgejo/tasks/first-user.yml @@ -5,7 +5,7 @@ - name: Create first user when email is defined community.docker.docker_container: name: "{{ domain }}-firstuser" - image: "forgejo:{{ softwares.forgejo.version }}" + image: "forgejo:{{ catalogs.forgejo.version }}" detach: false cleanup: true env: diff --git a/ansible/playbooks/saas/roles/forgejo/templates/nomad.hcl b/ansible/playbooks/saas/roles/forgejo/templates/nomad.hcl index 0a93e435..558ca021 100644 --- a/ansible/playbooks/saas/roles/forgejo/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/forgejo/templates/nomad.hcl @@ -41,7 +41,7 @@ job "{{ domain }}" { } config { - image = "{{ docker_private_registry.url }}/forgejo:{{ softwares.forgejo.version }}" + image = "{{ docker_private_registry.url }}/forgejo:{{ catalogs.forgejo.version }}" volumes = [ "/etc/timezone:/etc/timezone:ro", "/etc/localtime:/etc/localtime:ro", diff --git a/ansible/playbooks/saas/roles/forgejo/vars/actions.yml b/ansible/playbooks/saas/roles/forgejo/vars/actions.yml index 75c901c5..eb730b23 100644 --- a/ansible/playbooks/saas/roles/forgejo/vars/actions.yml +++ b/ansible/playbooks/saas/roles/forgejo/vars/actions.yml @@ -13,4 +13,4 @@ forgejo_actions: - "/data/{{ software.dbhost }}/root:/root:ro" - "/usr/local/bin/forgejo-backup:/usr/local/bin/forgejo-backup:ro" - "/usr/local/bin/forgejo-restore:/usr/local/bin/forgejo-restore:ro" - image: "mariadb:{{ softwares.mariadb.version }}" + image: "mariadb:{{ catalogs.mariadb.version }}" diff --git a/ansible/playbooks/saas/roles/freqtrade/README.md b/ansible/playbooks/saas/roles/freqtrade/README.md index f680977e..a2a2f946 100644 --- a/ansible/playbooks/saas/roles/freqtrade/README.md +++ b/ansible/playbooks/saas/roles/freqtrade/README.md @@ -11,11 +11,11 @@ strategy: MyCustomStrategy config: myconfig ``` -3. Configure your secret yaml configuration +3. Configure your secret yaml configuration ``` git_user_data: repo: http://mydomain.com/muser/myrepo.git version: latest token: s3cret! -``` \ No newline at end of file +``` diff --git a/ansible/playbooks/saas/roles/freqtrade/tasks/build.yml b/ansible/playbooks/saas/roles/freqtrade/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/freqtrade/tasks/build.yml +++ b/ansible/playbooks/saas/roles/freqtrade/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/freqtrade/templates/nomad.hcl b/ansible/playbooks/saas/roles/freqtrade/templates/nomad.hcl index dd2425c8..8dc1016c 100644 --- a/ansible/playbooks/saas/roles/freqtrade/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/freqtrade/templates/nomad.hcl @@ -64,7 +64,7 @@ job "{{ domain }}" { {% endfor %} } config { - image = "freqtradeorg/freqtrade:{{ softwares.freqtrade.version }}" + image = "freqtradeorg/freqtrade:{{ catalogs.freqtrade.version }}" volumes = [ "{{ software_path }}/freqtrade/user_data:/freqtrade/user_data:rw", "{{ software_path }}/db:/db:rw" diff --git a/ansible/playbooks/saas/roles/freshrss/tasks/build.yml b/ansible/playbooks/saas/roles/freshrss/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/freshrss/tasks/build.yml +++ b/ansible/playbooks/saas/roles/freshrss/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/freshrss/templates/nomad.hcl b/ansible/playbooks/saas/roles/freshrss/templates/nomad.hcl index 466b31ea..170e28b4 100644 --- a/ansible/playbooks/saas/roles/freshrss/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/freshrss/templates/nomad.hcl @@ -54,7 +54,7 @@ job "{{ domain }}" { } config { - image = "freshrss/freshrss:{{ softwares.freshrss.version }}" + image = "freshrss/freshrss:{{ catalogs.freshrss.version }}" volumes = [ "/data/{{ domain }}/data:/var/www/FreshRSS/data:rw", "/data/{{ domain }}/extensions:/var/www/FreshRSS/extensions:rw" diff --git a/ansible/playbooks/saas/roles/freshrss/vars/upstream.yml b/ansible/playbooks/saas/roles/freshrss/vars/upstream.yml index 75bb1771..64224769 100644 --- a/ansible/playbooks/saas/roles/freshrss/vars/upstream.yml +++ b/ansible/playbooks/saas/roles/freshrss/vars/upstream.yml @@ -3,5 +3,3 @@ upstream_version: "{{ lookup('url', 'https://api.github.com/repos/' + image.upst latest_version: "{{ upstream_version | community.general.json_query('[].name') | select('match', '^(v|r)?\\d{1,4}(\\.\\d{1,4})(\\.\\d{1,4})$') | community.general.version_sort | last | replace('v', '') }}" upstream_file_name: "{{ upstream.source.file | replace('REPO', image.upstream.repo) | replace('VERSION', latest_version) | replace('OS', upstream.source.os) | replace('ARCH', upstream_default_arch) | replace('FORMAT', upstream.source.format) }}" upstream_file_url: "https://github.com/{{ image.upstream.user }}/{{ image.upstream.repo }}/archive/{{ upstream_file_name }}" - - diff --git a/ansible/playbooks/saas/roles/grafana/README.md b/ansible/playbooks/saas/roles/grafana/README.md index bc2400eb..23a9e05c 100644 --- a/ansible/playbooks/saas/roles/grafana/README.md +++ b/ansible/playbooks/saas/roles/grafana/README.md @@ -52,4 +52,4 @@ plugins: secureJsonData: openAIKey: type: grafana-llm-app -``` \ No newline at end of file +``` diff --git a/ansible/playbooks/saas/roles/grafana/files/dashboards/nomad/nomad.json b/ansible/playbooks/saas/roles/grafana/files/dashboards/nomad/nomad.json index 2c2798fe..84ed841e 100644 --- a/ansible/playbooks/saas/roles/grafana/files/dashboards/nomad/nomad.json +++ b/ansible/playbooks/saas/roles/grafana/files/dashboards/nomad/nomad.json @@ -918,4 +918,4 @@ "title": "Nomad Copy2", "uid": "hrvzvk7", "version": 1 -} \ No newline at end of file +} diff --git a/ansible/playbooks/saas/roles/grafana/files/dashboards/nvidia/nvidia.json b/ansible/playbooks/saas/roles/grafana/files/dashboards/nvidia/nvidia.json index a5d821e7..19a14c66 100644 --- a/ansible/playbooks/saas/roles/grafana/files/dashboards/nvidia/nvidia.json +++ b/ansible/playbooks/saas/roles/grafana/files/dashboards/nvidia/nvidia.json @@ -1,50 +1,50 @@ { + "__elements": {}, "__inputs": [ { - "name": "DS_PROMETHEUS", - "label": "Prometheus", "description": "", - "type": "datasource", + "label": "Prometheus", + "name": "DS_PROMETHEUS", "pluginId": "prometheus", - "pluginName": "Prometheus" + "pluginName": "Prometheus", + "type": "datasource" } ], - "__elements": {}, "__requires": [ { - "type": "panel", "id": "bargauge", "name": "Bar gauge", + "type": "panel", "version": "" }, { - "type": "panel", "id": "gauge", "name": "Gauge", + "type": "panel", "version": "" }, { - "type": "grafana", "id": "grafana", "name": "Grafana", + "type": "grafana", "version": "11.2.0" }, { - "type": "datasource", "id": "prometheus", "name": "Prometheus", + "type": "datasource", "version": "1.0.0" }, { - "type": "panel", "id": "stat", "name": "Stat", + "type": "panel", "version": "" }, { - "type": "panel", "id": "timeseries", "name": "Time series", + "type": "panel", "version": "" } ], @@ -2223,4 +2223,4 @@ "uid": "vlvPlrgnk", "version": 8, "weekStart": "" -} \ No newline at end of file +} diff --git a/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/official-dashboard.json b/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/official-dashboard.json index 35b921de..d3610a90 100644 --- a/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/official-dashboard.json +++ b/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/official-dashboard.json @@ -1350,4 +1350,4 @@ "title": "vLLM Dashboard", "uid": "750918234", "version": 2 -} \ No newline at end of file +} diff --git a/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/vllm.json b/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/vllm.json index 7b5fc131..38bd3c0d 100644 --- a/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/vllm.json +++ b/ansible/playbooks/saas/roles/grafana/files/dashboards/vllm/vllm.json @@ -933,7 +933,7 @@ "color": "rgba(255,0,255,0.7)" }, "filterValues": { - "le": 1e-9 + "le": 1e-09 }, "legend": { "show": true @@ -1026,7 +1026,7 @@ "color": "rgba(255,0,255,0.7)" }, "filterValues": { - "le": 1e-9 + "le": 1e-09 }, "legend": { "show": true @@ -1558,4 +1558,4 @@ "title": "vLLM", "uid": "b281712d-8bff-41ef-9f3f-71ad43c05e9b", "version": 9 -} \ No newline at end of file +} diff --git a/ansible/playbooks/saas/roles/grafana/tasks/build.yml b/ansible/playbooks/saas/roles/grafana/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/grafana/tasks/build.yml +++ b/ansible/playbooks/saas/roles/grafana/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/grafana/tasks/destroy.yml b/ansible/playbooks/saas/roles/grafana/tasks/destroy.yml index e00b7de1..15f1ec71 100644 --- a/ansible/playbooks/saas/roles/grafana/tasks/destroy.yml +++ b/ansible/playbooks/saas/roles/grafana/tasks/destroy.yml @@ -8,4 +8,4 @@ ansible.builtin.file: path: "{{ software_path }}" state: absent - delegate_to: "{{ software.instance }}" \ No newline at end of file + delegate_to: "{{ software.instance }}" diff --git a/ansible/playbooks/saas/roles/grafana/templates/nomad.hcl b/ansible/playbooks/saas/roles/grafana/templates/nomad.hcl index 2b68803f..c25c1530 100644 --- a/ansible/playbooks/saas/roles/grafana/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/grafana/templates/nomad.hcl @@ -48,7 +48,7 @@ job "{{ domain }}" { } config { - image = "grafana/grafana:{{ softwares.grafana.version }}" + image = "grafana/grafana:{{ catalogs.grafana.version }}" volumes = [ "{{ software_path }}/provisioning:/etc/grafana/provisioning:ro", "{{ software_path }}/dashboards:/local/dashboards:ro" diff --git a/ansible/playbooks/saas/roles/grafana/templates/provisioning/datasources/prometheus.yaml.j2 b/ansible/playbooks/saas/roles/grafana/templates/provisioning/datasources/prometheus.yaml.j2 index 539aa307..e26009d3 100644 --- a/ansible/playbooks/saas/roles/grafana/templates/provisioning/datasources/prometheus.yaml.j2 +++ b/ansible/playbooks/saas/roles/grafana/templates/provisioning/datasources/prometheus.yaml.j2 @@ -50,4 +50,4 @@ datasources: {% endif %} {% else %} datasources: [] -{% endif %} \ No newline at end of file +{% endif %} diff --git a/ansible/playbooks/saas/roles/grafana/templates/provisioning/plugins/llm.yaml.j2 b/ansible/playbooks/saas/roles/grafana/templates/provisioning/plugins/llm.yaml.j2 index fc1d0196..d6b9e629 100644 --- a/ansible/playbooks/saas/roles/grafana/templates/provisioning/plugins/llm.yaml.j2 +++ b/ansible/playbooks/saas/roles/grafana/templates/provisioning/plugins/llm.yaml.j2 @@ -1,4 +1,4 @@ apiVersion: 1 apps: -{{ (lookup('simple-stack-ui', type='secret', key=domain, subkey='plugins', missing='error') | from_json) | to_nice_yaml | default() }} \ No newline at end of file +{{ (lookup('simple-stack-ui', type='secret', key=domain, subkey='plugins', missing='error') | from_json) | to_nice_yaml | default() }} diff --git a/ansible/playbooks/saas/roles/homeassistant/tasks/build.yml b/ansible/playbooks/saas/roles/homeassistant/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/homeassistant/tasks/build.yml +++ b/ansible/playbooks/saas/roles/homeassistant/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl b/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl index 663016dd..a31ea735 100644 --- a/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl @@ -65,7 +65,7 @@ job "{{ domain }}" { } config { - image = "homeassistant/home-assistant:{{ softwares.homeassistant.version }}" + image = "homeassistant/home-assistant:{{ catalogs.homeassistant.version }}" privileged = "true" volumes = [ diff --git a/ansible/playbooks/saas/roles/kresus/tasks/build.yml b/ansible/playbooks/saas/roles/kresus/tasks/build.yml index 2208cecf..36ce6878 100644 --- a/ansible/playbooks/saas/roles/kresus/tasks/build.yml +++ b/ansible/playbooks/saas/roles/kresus/tasks/build.yml @@ -9,7 +9,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Copy config file ansible.builtin.copy: diff --git a/ansible/playbooks/saas/roles/kresus/templates/nomad.hcl b/ansible/playbooks/saas/roles/kresus/templates/nomad.hcl index 1e8d7e7d..bb98811b 100644 --- a/ansible/playbooks/saas/roles/kresus/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/kresus/templates/nomad.hcl @@ -46,7 +46,7 @@ job "{{ domain }}" { } config { - image = "{{ docker_private_registry.url }}/kresus:{{ softwares.kresus.version }}" + image = "{{ docker_private_registry.url }}/kresus:{{ catalogs.kresus.version }}" volumes = [ "{{ software_path }}/opt/kresus/data:/home/user/data:rw", diff --git a/ansible/playbooks/saas/roles/litellm/README.md b/ansible/playbooks/saas/roles/litellm/README.md index 32ff3ce4..8febc864 100644 --- a/ansible/playbooks/saas/roles/litellm/README.md +++ b/ansible/playbooks/saas/roles/litellm/README.md @@ -50,4 +50,4 @@ litellm_env: value: true - key: OVHCLOUD_API_KEY value: APIKEY -``` \ No newline at end of file +``` diff --git a/ansible/playbooks/saas/roles/litellm/tasks/build.yml b/ansible/playbooks/saas/roles/litellm/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/litellm/tasks/build.yml +++ b/ansible/playbooks/saas/roles/litellm/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/litellm/tasks/destroy.yml b/ansible/playbooks/saas/roles/litellm/tasks/destroy.yml index e00b7de1..15f1ec71 100644 --- a/ansible/playbooks/saas/roles/litellm/tasks/destroy.yml +++ b/ansible/playbooks/saas/roles/litellm/tasks/destroy.yml @@ -8,4 +8,4 @@ ansible.builtin.file: path: "{{ software_path }}" state: absent - delegate_to: "{{ software.instance }}" \ No newline at end of file + delegate_to: "{{ software.instance }}" diff --git a/ansible/playbooks/saas/roles/litellm/templates/nomad.hcl b/ansible/playbooks/saas/roles/litellm/templates/nomad.hcl index 4e805497..b4a61e07 100644 --- a/ansible/playbooks/saas/roles/litellm/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/litellm/templates/nomad.hcl @@ -55,7 +55,7 @@ job "{{ domain }}" { } config { - image = "ghcr.io/berriai/litellm:v{{ softwares.litellm.version }}" + image = "ghcr.io/berriai/litellm:v{{ catalogs.litellm.version }}" ports = ["litellm"] args = [ "--config=/local/config.yaml" diff --git a/ansible/playbooks/saas/roles/litellm/vars/upstream.yml b/ansible/playbooks/saas/roles/litellm/vars/upstream.yml index 95b30dd7..124100ea 100644 --- a/ansible/playbooks/saas/roles/litellm/vars/upstream.yml +++ b/ansible/playbooks/saas/roles/litellm/vars/upstream.yml @@ -1,3 +1,3 @@ --- upstream_versions: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/tags', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN') })) }}" -latest_version: "{{ upstream_versions | from_json | community.general.json_query('[].name') | select('match', '^(v)?\\d{1,4}(\\.\\d{1,4})(\\.\\d{1,4})(-stable)$') | community.general.version_sort | last | replace('v', '') }}" \ No newline at end of file +latest_version: "{{ upstream_versions | from_json | community.general.json_query('[].name') | select('match', '^(v)?\\d{1,4}(\\.\\d{1,4})(\\.\\d{1,4})(-stable)$') | community.general.version_sort | last | replace('v', '') }}" diff --git a/ansible/playbooks/saas/roles/loki/tasks/build.yml b/ansible/playbooks/saas/roles/loki/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/loki/tasks/build.yml +++ b/ansible/playbooks/saas/roles/loki/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/loki/templates/nomad.hcl b/ansible/playbooks/saas/roles/loki/templates/nomad.hcl index 514509d3..8e160e1c 100644 --- a/ansible/playbooks/saas/roles/loki/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/loki/templates/nomad.hcl @@ -38,7 +38,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "grafana/loki:{{ softwares.loki.version }}" + image = "grafana/loki:{{ catalogs.loki.version }}" volumes = [ "{{ software_path }}/var/lib/loki:/var/lib/loki:rw" ] diff --git a/ansible/playbooks/saas/roles/mariadb/tasks/build.yml b/ansible/playbooks/saas/roles/mariadb/tasks/build.yml index a2675eb6..d739f1d0 100644 --- a/ansible/playbooks/saas/roles/mariadb/tasks/build.yml +++ b/ansible/playbooks/saas/roles/mariadb/tasks/build.yml @@ -6,4 +6,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/mariadb/templates/nomad.hcl b/ansible/playbooks/saas/roles/mariadb/templates/nomad.hcl index ffd8ebe5..838c0212 100644 --- a/ansible/playbooks/saas/roles/mariadb/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/mariadb/templates/nomad.hcl @@ -113,7 +113,7 @@ job "{{ domain }}" { } config { - image = "mariadb:{{ softwares.mariadb.version }}" + image = "mariadb:{{ catalogs.mariadb.version }}" volumes = [ "{{ software_path }}/var/lib/mysql:/var/lib/mysql:Z", "{{ software_path }}/etc/mysql/conf.d:/etc/mysql/conf.d:ro", diff --git a/ansible/playbooks/saas/roles/mariadb/vars/actions.yml b/ansible/playbooks/saas/roles/mariadb/vars/actions.yml index de28ab47..d1c17554 100644 --- a/ansible/playbooks/saas/roles/mariadb/vars/actions.yml +++ b/ansible/playbooks/saas/roles/mariadb/vars/actions.yml @@ -7,4 +7,4 @@ mariadb_actions: - "{{ software_path }}/var/backup:/var/backup:rw" - "/usr/local/bin/mariadb-backup:/usr/local/bin/mariadb-backup:ro" - "/usr/local/bin/mariadb-restore:/usr/local/bin/mariadb-restore:ro" - image: "mariadb:{{ softwares.mariadb.version }}" + image: "mariadb:{{ catalogs.mariadb.version }}" diff --git a/ansible/playbooks/saas/roles/milvus/README.md b/ansible/playbooks/saas/roles/milvus/README.md index 370e59b6..88d99ba9 100644 --- a/ansible/playbooks/saas/roles/milvus/README.md +++ b/ansible/playbooks/saas/roles/milvus/README.md @@ -5,4 +5,4 @@ ```yaml passwd: 123456 -``` \ No newline at end of file +``` diff --git a/ansible/playbooks/saas/roles/milvus/tasks/build.yml b/ansible/playbooks/saas/roles/milvus/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/milvus/tasks/build.yml +++ b/ansible/playbooks/saas/roles/milvus/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/milvus/tasks/destroy.yml b/ansible/playbooks/saas/roles/milvus/tasks/destroy.yml index e00b7de1..15f1ec71 100644 --- a/ansible/playbooks/saas/roles/milvus/tasks/destroy.yml +++ b/ansible/playbooks/saas/roles/milvus/tasks/destroy.yml @@ -8,4 +8,4 @@ ansible.builtin.file: path: "{{ software_path }}" state: absent - delegate_to: "{{ software.instance }}" \ No newline at end of file + delegate_to: "{{ software.instance }}" diff --git a/ansible/playbooks/saas/roles/milvus/templates/nomad.hcl b/ansible/playbooks/saas/roles/milvus/templates/nomad.hcl index c449b59b..ed474d27 100644 --- a/ansible/playbooks/saas/roles/milvus/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/milvus/templates/nomad.hcl @@ -58,7 +58,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "milvusdb/milvus:v{{ softwares.milvus.version }}" + image = "milvusdb/milvus:v{{ catalogs.milvus.version }}" security_opt = [ "seccomp=unconfined" ] diff --git a/ansible/playbooks/saas/roles/milvus/templates/user.yaml.j2 b/ansible/playbooks/saas/roles/milvus/templates/user.yaml.j2 index db77cc8b..35de0f79 100644 --- a/ansible/playbooks/saas/roles/milvus/templates/user.yaml.j2 +++ b/ansible/playbooks/saas/roles/milvus/templates/user.yaml.j2 @@ -1,3 +1,3 @@ # Extra config to override default milvus.yaml proxy: - healthCheckTimeout: 1000 # ms, the interval that to do component healthy check \ No newline at end of file + healthCheckTimeout: 1000 # ms, the interval that to do component healthy check diff --git a/ansible/playbooks/saas/roles/milvus/vars/main.yml b/ansible/playbooks/saas/roles/milvus/vars/main.yml index dc15db50..43875f2c 100644 --- a/ansible/playbooks/saas/roles/milvus/vars/main.yml +++ b/ansible/playbooks/saas/roles/milvus/vars/main.yml @@ -10,4 +10,4 @@ image: file: milvus_VERSION_ARCH.FORMAT os: linux labels: {} - name: milvus \ No newline at end of file + name: milvus diff --git a/ansible/playbooks/saas/roles/mimir/README.md b/ansible/playbooks/saas/roles/mimir/README.md index 11baffa9..aaa645e4 100644 --- a/ansible/playbooks/saas/roles/mimir/README.md +++ b/ansible/playbooks/saas/roles/mimir/README.md @@ -25,4 +25,4 @@ alertmanager: webhook_configs: - url: https://www.myreceiver.com/api/webhook/ send_resolved: true -``` \ No newline at end of file +``` diff --git a/ansible/playbooks/saas/roles/mimir/defaults/main.yml b/ansible/playbooks/saas/roles/mimir/defaults/main.yml index 38eab856..06b2036f 100644 --- a/ansible/playbooks/saas/roles/mimir/defaults/main.yml +++ b/ansible/playbooks/saas/roles/mimir/defaults/main.yml @@ -1,2 +1,2 @@ --- -mimir_install_node: "{{ software.install_node |default('singlenode') }}" \ No newline at end of file +mimir_install_node: "{{ software.install_node |default('singlenode') }}" diff --git a/ansible/playbooks/saas/roles/mimir/tasks/build.yml b/ansible/playbooks/saas/roles/mimir/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/mimir/tasks/build.yml +++ b/ansible/playbooks/saas/roles/mimir/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-multinodes.j2 b/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-multinodes.j2 index 2083a297..342c1c88 100644 --- a/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-multinodes.j2 +++ b/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-multinodes.j2 @@ -48,7 +48,7 @@ compactor: instance_addr: {% raw %}{{env "attr.unique.network.ip-address"}}{% endraw %} -distributor: +distributor: ring: instance_addr: {% raw %}{{env "attr.unique.network.ip-address"}}{% endraw %} @@ -56,12 +56,12 @@ distributor: server: log_level: warn -store_gateway: +store_gateway: sharding_ring: instance_addr: {% raw %}{{env "attr.unique.network.ip-address"}}{% endraw %} -ingester: +ingester: ring: instance_addr: {% raw %}{{env "attr.unique.network.ip-address"}}{% endraw %} diff --git a/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-singlenode.j2 b/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-singlenode.j2 index d4af5d24..1b57822b 100644 --- a/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-singlenode.j2 +++ b/ansible/playbooks/saas/roles/mimir/templates/mimir.yaml-singlenode.j2 @@ -46,14 +46,14 @@ alertmanager: compactor: -distributor: +distributor: ring: instance_addr: {% raw %}{{env "attr.unique.network.ip-address"}}{% endraw %} server: log_level: warn -ingester: +ingester: ring: replication_factor: 1 diff --git a/ansible/playbooks/saas/roles/mimir/templates/nomad.hcl b/ansible/playbooks/saas/roles/mimir/templates/nomad.hcl index 8c759b4f..d904bbc8 100644 --- a/ansible/playbooks/saas/roles/mimir/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/mimir/templates/nomad.hcl @@ -50,7 +50,7 @@ job "{{ domain }}" { } config { - image = "{{ docker_private_registry.url_project | default(docker_private_registry.url) }}/minio:{{ softwares.minio.version }}" + image = "{{ docker_private_registry.url_project | default(docker_private_registry.url) }}/minio:{{ catalogs.minio.version }}" volumes = [ "{{ software_path }}/data/minio:/data:rw" ] @@ -121,7 +121,7 @@ job "{{ domain }}" { } config { - image = "grafana/mimir:{{ softwares.mimir.version }}" + image = "grafana/mimir:{{ catalogs.mimir.version }}" # network_mode = "host" volumes = [ "{{ software_path }}/mimir-${NOMAD_ALLOC_INDEX}:/data", diff --git a/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 b/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 index c3422568..2ec31ae0 100644 --- a/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 +++ b/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 @@ -26,4 +26,3 @@ inhibit_rules: receivers: {% if alertmanager.receivers is not defined %}[]{% endif %} {{ alertmanager.receivers | default('') | to_nice_yaml(indent=4) }} - diff --git a/ansible/playbooks/saas/roles/minio/tasks/build.yml b/ansible/playbooks/saas/roles/minio/tasks/build.yml index 6d2745af..55d164e0 100644 --- a/ansible/playbooks/saas/roles/minio/tasks/build.yml +++ b/ansible/playbooks/saas/roles/minio/tasks/build.yml @@ -9,7 +9,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Download latest release ansible.builtin.get_url: diff --git a/ansible/playbooks/saas/roles/minio/templates/nomad.hcl b/ansible/playbooks/saas/roles/minio/templates/nomad.hcl index e9a92136..5240d4fb 100644 --- a/ansible/playbooks/saas/roles/minio/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/minio/templates/nomad.hcl @@ -56,7 +56,7 @@ job "{{ domain }}" { } config { - image = "{{ docker_private_registry.url_project | default(docker_private_registry.url) }}/minio:{{ softwares.minio.version }}" + image = "{{ docker_private_registry.url_project | default(docker_private_registry.url) }}/minio:{{ catalogs.minio.version }}" volumes = [ "{{ software_path }}/data:/data:rw", "{{ software_path }}/var/backup:/var/backup:rw" diff --git a/ansible/playbooks/saas/roles/mosquitto/tasks/build.yml b/ansible/playbooks/saas/roles/mosquitto/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/mosquitto/tasks/build.yml +++ b/ansible/playbooks/saas/roles/mosquitto/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/mosquitto/templates/nomad.hcl b/ansible/playbooks/saas/roles/mosquitto/templates/nomad.hcl index 44264b10..3c16f08a 100644 --- a/ansible/playbooks/saas/roles/mosquitto/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/mosquitto/templates/nomad.hcl @@ -30,7 +30,7 @@ job "{{ domain }}" { port = "mosquitto" provider = "nomad" tags = [ - {{ lookup('template', '../../traefik/templates/traefik_tag.j2') | indent(8) }} + {{ lookup('template', '../../traefik/templates/traefik_tag.j2') }} ] } @@ -53,7 +53,7 @@ job "{{ domain }}" { } config { - image = "eclipse-mosquitto:{{ softwares.mosquitto.version }}" + image = "eclipse-mosquitto:{{ catalogs.mosquitto.version }}-alpine" volumes = [ "{{ software_path }}/mosquitto/config:/mosquitto/config:rw", diff --git a/ansible/playbooks/saas/roles/nextcloud/tasks/build.yml b/ansible/playbooks/saas/roles/nextcloud/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/nextcloud/tasks/build.yml +++ b/ansible/playbooks/saas/roles/nextcloud/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/nextcloud/templates/nomad.hcl b/ansible/playbooks/saas/roles/nextcloud/templates/nomad.hcl index 4e8bf378..6be4747c 100644 --- a/ansible/playbooks/saas/roles/nextcloud/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/nextcloud/templates/nomad.hcl @@ -49,7 +49,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "nextcloud:{{ softwares.nextcloud.version }}" + image = "nextcloud:{{ catalogs.nextcloud.version }}" volumes = [ "{{ software_path }}/var/www/html:/var/www/html:rw", diff --git a/ansible/playbooks/saas/roles/nextcloud/vars/actions.yml b/ansible/playbooks/saas/roles/nextcloud/vars/actions.yml index 9a4fa94e..afd198a1 100644 --- a/ansible/playbooks/saas/roles/nextcloud/vars/actions.yml +++ b/ansible/playbooks/saas/roles/nextcloud/vars/actions.yml @@ -10,4 +10,4 @@ nextcloud_actions: - "/data/{{ software.dbhost }}/root:/root:ro" - "/usr/local/bin/nextcloud-backup:/usr/local/bin/nextcloud-backup:ro" - "/usr/local/bin/nextcloud-restore:/usr/local/bin/nextcloud-restore:ro" - image: "nextcloud:{{ softwares.nextcloud.version }}" + image: "nextcloud:{{ catalogs.nextcloud.version }}" diff --git a/ansible/playbooks/saas/roles/nginx/tasks/build.yml b/ansible/playbooks/saas/roles/nginx/tasks/build.yml index d199d571..1a55d9fd 100644 --- a/ansible/playbooks/saas/roles/nginx/tasks/build.yml +++ b/ansible/playbooks/saas/roles/nginx/tasks/build.yml @@ -11,7 +11,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Copy boilerplate configuration snippets files ansible.builtin.copy: diff --git a/ansible/playbooks/saas/roles/nginx/templates/nomad.hcl b/ansible/playbooks/saas/roles/nginx/templates/nomad.hcl index 340167f2..ea9b058b 100644 --- a/ansible/playbooks/saas/roles/nginx/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/nginx/templates/nomad.hcl @@ -63,7 +63,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "{{ docker_private_registry.url }}/nginx:{{ softwares.nginx.version }}" + image = "{{ docker_private_registry.url }}/nginx:{{ catalogs.nginx.version }}" volumes = [ "{{ software_path }}/var/www/html:/var/www/html:ro", "{{ software_path }}/var/log/nginx:/var/log/nginx:rw", diff --git a/ansible/playbooks/saas/roles/nodejs/tasks/build.yml b/ansible/playbooks/saas/roles/nodejs/tasks/build.yml index be443eb3..77bc370c 100644 --- a/ansible/playbooks/saas/roles/nodejs/tasks/build.yml +++ b/ansible/playbooks/saas/roles/nodejs/tasks/build.yml @@ -11,7 +11,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Copy dockerfile ansible.builtin.template: diff --git a/ansible/playbooks/saas/roles/open-webui/tasks/build.yml b/ansible/playbooks/saas/roles/open-webui/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/open-webui/tasks/build.yml +++ b/ansible/playbooks/saas/roles/open-webui/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/open-webui/templates/nomad.hcl b/ansible/playbooks/saas/roles/open-webui/templates/nomad.hcl index 39a276cf..d140f4b5 100644 --- a/ansible/playbooks/saas/roles/open-webui/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/open-webui/templates/nomad.hcl @@ -48,7 +48,7 @@ job "{{ domain }}" { } config { - image = "ghcr.io/open-webui/open-webui:{{ softwares.open-webui.version }}" + image = "ghcr.io/open-webui/open-webui:{{ catalogs.open-webui.version }}" mount { type = "bind" diff --git a/ansible/playbooks/saas/roles/phpfpm/tasks/build.yml b/ansible/playbooks/saas/roles/phpfpm/tasks/build.yml index be443eb3..77bc370c 100644 --- a/ansible/playbooks/saas/roles/phpfpm/tasks/build.yml +++ b/ansible/playbooks/saas/roles/phpfpm/tasks/build.yml @@ -11,7 +11,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Copy dockerfile ansible.builtin.template: diff --git a/ansible/playbooks/saas/roles/postgresql/README.md b/ansible/playbooks/saas/roles/postgresql/README.md index 85c6ec61..38167dc2 100644 --- a/ansible/playbooks/saas/roles/postgresql/README.md +++ b/ansible/playbooks/saas/roles/postgresql/README.md @@ -26,4 +26,3 @@ static_port: 5432 ```yaml passwd: 123456 ``` - diff --git a/ansible/playbooks/saas/roles/postgresql/tasks/build.yml b/ansible/playbooks/saas/roles/postgresql/tasks/build.yml index 350ed624..eb5c1a68 100644 --- a/ansible/playbooks/saas/roles/postgresql/tasks/build.yml +++ b/ansible/playbooks/saas/roles/postgresql/tasks/build.yml @@ -6,4 +6,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/postgresql/templates/nomad.hcl b/ansible/playbooks/saas/roles/postgresql/templates/nomad.hcl index 1368f368..94761abf 100644 --- a/ansible/playbooks/saas/roles/postgresql/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/postgresql/templates/nomad.hcl @@ -44,7 +44,7 @@ job "{{ domain }}" { } config { - image = "postgres:{{ softwares.postgresql.version }}" + image = "postgres:{{ catalogs.postgresql.version }}" ports = ["postgresql"] volumes = [ "{{ software_path }}/var/lib/postgresql:/var/lib/postgresql:rw", diff --git a/ansible/playbooks/saas/roles/postgresql/vars/actions.yml b/ansible/playbooks/saas/roles/postgresql/vars/actions.yml index 1d0c805b..b75c17a2 100644 --- a/ansible/playbooks/saas/roles/postgresql/vars/actions.yml +++ b/ansible/playbooks/saas/roles/postgresql/vars/actions.yml @@ -8,5 +8,5 @@ postgresql_actions: - "{{ software_path }}/tmp:/tmp:rw" - "/usr/local/bin/postgresql-backup:/usr/local/bin/postgresql-backup:ro" - "/usr/local/bin/postgresql-restore:/usr/local/bin/postgresql-restore:ro" - image: "bitnami/postgresql:{{ softwares.postgresql.version }}" + image: "bitnami/postgresql:{{ catalogs.postgresql.version }}" user: postgres diff --git a/ansible/playbooks/saas/roles/registry/tasks/build.yml b/ansible/playbooks/saas/roles/registry/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/registry/tasks/build.yml +++ b/ansible/playbooks/saas/roles/registry/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/registry/tasks/main.yml b/ansible/playbooks/saas/roles/registry/tasks/main.yml index 20e53c27..c51f72d2 100644 --- a/ansible/playbooks/saas/roles/registry/tasks/main.yml +++ b/ansible/playbooks/saas/roles/registry/tasks/main.yml @@ -30,7 +30,7 @@ # - debug: # msg: -# - "{{ softwares.registry }}" +# - "{{ catalogs.registry }}" - name: Copy nomad job to destination ansible.builtin.template: diff --git a/ansible/playbooks/saas/roles/registry/templates/nomad.hcl b/ansible/playbooks/saas/roles/registry/templates/nomad.hcl index be570e06..302d9a1d 100644 --- a/ansible/playbooks/saas/roles/registry/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/registry/templates/nomad.hcl @@ -66,7 +66,7 @@ job "{{ domain }}" { } config { - image = "registry:{{ softwares.registry.version }}" + image = "registry:{{ catalogs.registry.version }}" volumes = [ "{{ software_path }}/data:/data", "{{ software_path }}/var/lib/registry:/var/lib/registry" diff --git a/ansible/playbooks/saas/roles/rocketchat/tasks/build.yml b/ansible/playbooks/saas/roles/rocketchat/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/rocketchat/tasks/build.yml +++ b/ansible/playbooks/saas/roles/rocketchat/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/rocketchat/templates/nomad.hcl b/ansible/playbooks/saas/roles/rocketchat/templates/nomad.hcl index 95c78511..720106a2 100644 --- a/ansible/playbooks/saas/roles/rocketchat/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/rocketchat/templates/nomad.hcl @@ -126,7 +126,7 @@ EOH } config { - image = "rocketchat/rocket.chat:{{ softwares.rocketchat.version }}" + image = "rocketchat/rocket.chat:{{ catalogs.rocketchat.version }}" ports = ["rocketchat"] } resources { diff --git a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/backup.yml b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/backup.yml index 73b314ff..ed97d539 100644 --- a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/backup.yml +++ b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/backup.yml @@ -1 +1 @@ ---- \ No newline at end of file +--- diff --git a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/build.yml b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/build.yml index efb0d7c9..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/build.yml +++ b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/build.yml @@ -9,5 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version - + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/main.yml b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/main.yml index 687e4f0a..f61aa1fa 100644 --- a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/main.yml +++ b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/main.yml @@ -12,4 +12,3 @@ ansible.builtin.include_role: name: nomad tasks_from: job_run.yml - diff --git a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/restore.yml b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/restore.yml index 73b314ff..ed97d539 100644 --- a/ansible/playbooks/saas/roles/simplestack_ansible/tasks/restore.yml +++ b/ansible/playbooks/saas/roles/simplestack_ansible/tasks/restore.yml @@ -1 +1 @@ ---- \ No newline at end of file +--- diff --git a/ansible/playbooks/saas/roles/simplestack_ansible/templates/nomad.hcl b/ansible/playbooks/saas/roles/simplestack_ansible/templates/nomad.hcl index c7fa2cd5..fa3887ba 100644 --- a/ansible/playbooks/saas/roles/simplestack_ansible/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/simplestack_ansible/templates/nomad.hcl @@ -49,7 +49,7 @@ job "{{ domain }}" { } config { - image = "ghcr.io/wiseflat/simple-stack-ansible:v{{ softwares.simplestack_ui.version }}" + image = "ghcr.io/wiseflat/simple-stack-ansible:v{{ catalogs.simplestack_ui.version }}" ports = ["http"] volumes = [ "/root/.ssh:/root/.ssh:ro" diff --git a/ansible/playbooks/saas/roles/simplestack_ansible/vars/main.yml b/ansible/playbooks/saas/roles/simplestack_ansible/vars/main.yml index 307e3dfd..7fc5ac35 100644 --- a/ansible/playbooks/saas/roles/simplestack_ansible/vars/main.yml +++ b/ansible/playbooks/saas/roles/simplestack_ansible/vars/main.yml @@ -9,4 +9,4 @@ image: labels: {} name: simplestack_ansible -traefik_x_robots_tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex \ No newline at end of file +traefik_x_robots_tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex diff --git a/ansible/playbooks/saas/roles/simplestack_ansible/vars/upstream.yml b/ansible/playbooks/saas/roles/simplestack_ansible/vars/upstream.yml index bd4fe371..74d50b0a 100644 --- a/ansible/playbooks/saas/roles/simplestack_ansible/vars/upstream.yml +++ b/ansible/playbooks/saas/roles/simplestack_ansible/vars/upstream.yml @@ -1,2 +1,2 @@ --- -latest_version: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/releases/latest', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN') }) | from_json).get('tag_name') | replace('v', '') }}" \ No newline at end of file +latest_version: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/releases/latest', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN') }) | from_json).get('tag_name') | replace('v', '') }}" diff --git a/ansible/playbooks/saas/roles/simplestack_ui/tasks/backup.yml b/ansible/playbooks/saas/roles/simplestack_ui/tasks/backup.yml index 73b314ff..ed97d539 100644 --- a/ansible/playbooks/saas/roles/simplestack_ui/tasks/backup.yml +++ b/ansible/playbooks/saas/roles/simplestack_ui/tasks/backup.yml @@ -1 +1 @@ ---- \ No newline at end of file +--- diff --git a/ansible/playbooks/saas/roles/simplestack_ui/tasks/build.yml b/ansible/playbooks/saas/roles/simplestack_ui/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/simplestack_ui/tasks/build.yml +++ b/ansible/playbooks/saas/roles/simplestack_ui/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/simplestack_ui/tasks/main.yml b/ansible/playbooks/saas/roles/simplestack_ui/tasks/main.yml index e5adee3b..a3a42eb4 100644 --- a/ansible/playbooks/saas/roles/simplestack_ui/tasks/main.yml +++ b/ansible/playbooks/saas/roles/simplestack_ui/tasks/main.yml @@ -22,4 +22,3 @@ ansible.builtin.include_role: name: nomad tasks_from: job_run.yml - diff --git a/ansible/playbooks/saas/roles/simplestack_ui/tasks/restore.yml b/ansible/playbooks/saas/roles/simplestack_ui/tasks/restore.yml index 73b314ff..ed97d539 100644 --- a/ansible/playbooks/saas/roles/simplestack_ui/tasks/restore.yml +++ b/ansible/playbooks/saas/roles/simplestack_ui/tasks/restore.yml @@ -1 +1 @@ ---- \ No newline at end of file +--- diff --git a/ansible/playbooks/saas/roles/simplestack_ui/templates/nomad.hcl b/ansible/playbooks/saas/roles/simplestack_ui/templates/nomad.hcl index 872b79fd..95eab812 100644 --- a/ansible/playbooks/saas/roles/simplestack_ui/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/simplestack_ui/templates/nomad.hcl @@ -46,7 +46,7 @@ job "{{ domain }}" { user = "nodejs" config { - image = "ghcr.io/wiseflat/simple-stack-ui:v{{ softwares.simplestack_ui.version }}" + image = "ghcr.io/wiseflat/simple-stack-ui:v{{ catalogs.simplestack_ui.version }}" ports = ["http"] volumes = [ "{{ software_path }}/databases:/www/databases:rw" diff --git a/ansible/playbooks/saas/roles/simplestack_ui/vars/main.yml b/ansible/playbooks/saas/roles/simplestack_ui/vars/main.yml index 4e74c688..f44b2c62 100644 --- a/ansible/playbooks/saas/roles/simplestack_ui/vars/main.yml +++ b/ansible/playbooks/saas/roles/simplestack_ui/vars/main.yml @@ -9,4 +9,4 @@ image: labels: {} name: simplestack_ui -traefik_x_robots_tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex \ No newline at end of file +traefik_x_robots_tag: noindex,nofollow,nosnippet,noarchive,notranslate,noimageindex diff --git a/ansible/playbooks/saas/roles/simplestack_ui/vars/upstream.yml b/ansible/playbooks/saas/roles/simplestack_ui/vars/upstream.yml index bd4fe371..74d50b0a 100644 --- a/ansible/playbooks/saas/roles/simplestack_ui/vars/upstream.yml +++ b/ansible/playbooks/saas/roles/simplestack_ui/vars/upstream.yml @@ -1,2 +1,2 @@ --- -latest_version: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/releases/latest', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN') }) | from_json).get('tag_name') | replace('v', '') }}" \ No newline at end of file +latest_version: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/releases/latest', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN') }) | from_json).get('tag_name') | replace('v', '') }}" diff --git a/ansible/playbooks/saas/roles/traefik/tasks/build.yml b/ansible/playbooks/saas/roles/traefik/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/traefik/tasks/build.yml +++ b/ansible/playbooks/saas/roles/traefik/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl b/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl index b083df5f..2b978b01 100644 --- a/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl @@ -66,7 +66,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "traefik:{{ softwares.traefik.version }}" + image = "traefik:{{ catalogs.traefik.version }}" network_mode = "host" volumes = [ "{{ software_path }}/etc/traefik:/etc/traefik:rw", diff --git a/ansible/playbooks/saas/roles/traefik/templates/traefik.toml b/ansible/playbooks/saas/roles/traefik/templates/traefik.toml index e4500e99..72347538 100644 --- a/ansible/playbooks/saas/roles/traefik/templates/traefik.toml +++ b/ansible/playbooks/saas/roles/traefik/templates/traefik.toml @@ -5,7 +5,7 @@ #[api] # dashboard = true # insecure = true - + [entryPoints] [entryPoints.http] address = ":80" diff --git a/ansible/playbooks/saas/roles/traefik/templates/traefik_tag.j2 b/ansible/playbooks/saas/roles/traefik/templates/traefik_tag.j2 index 6807b530..0a2b1558 100644 --- a/ansible/playbooks/saas/roles/traefik/templates/traefik_tag.j2 +++ b/ansible/playbooks/saas/roles/traefik/templates/traefik_tag.j2 @@ -34,4 +34,4 @@ {% elif (software.ipfilter is not defined and software.basic_auth is defined) %} "traefik.http.routers.{{ service_name }}.middlewares={{ service_name }}-basicauth@nomad" {% endif %} -{% endif %} \ No newline at end of file +{% endif %} diff --git a/ansible/playbooks/saas/roles/valkey/tasks/build.yml b/ansible/playbooks/saas/roles/valkey/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/valkey/tasks/build.yml +++ b/ansible/playbooks/saas/roles/valkey/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/valkey/templates/nomad.hcl b/ansible/playbooks/saas/roles/valkey/templates/nomad.hcl index 026e2b06..8844a941 100644 --- a/ansible/playbooks/saas/roles/valkey/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/valkey/templates/nomad.hcl @@ -38,7 +38,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "valkey/valkey:{{ softwares.valkey.version }}" + image = "valkey/valkey:{{ catalogs.valkey.version }}" volumes = [ "{{ software_path }}/data:/data:rw", "{{ software_path }}/etc/valkey:/etc/valkey:ro", diff --git a/ansible/playbooks/saas/roles/valkey/templates/valkey.conf b/ansible/playbooks/saas/roles/valkey/templates/valkey.conf index d754a3aa..0f57bca8 100644 --- a/ansible/playbooks/saas/roles/valkey/templates/valkey.conf +++ b/ansible/playbooks/saas/roles/valkey/templates/valkey.conf @@ -86,7 +86,7 @@ # mode. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # bind 127.0.0.1 -::1 -bind * -::* +bind * -::* # By default, outgoing connections (from replica to primary, from Sentinel to # instances, cluster bus, etc.) are not bound to a specific local address. In diff --git a/ansible/playbooks/saas/roles/vector/tasks/build.yml b/ansible/playbooks/saas/roles/vector/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/vector/tasks/build.yml +++ b/ansible/playbooks/saas/roles/vector/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/vector/tasks/destroy.yml b/ansible/playbooks/saas/roles/vector/tasks/destroy.yml index e00b7de1..15f1ec71 100644 --- a/ansible/playbooks/saas/roles/vector/tasks/destroy.yml +++ b/ansible/playbooks/saas/roles/vector/tasks/destroy.yml @@ -8,4 +8,4 @@ ansible.builtin.file: path: "{{ software_path }}" state: absent - delegate_to: "{{ software.instance }}" \ No newline at end of file + delegate_to: "{{ software.instance }}" diff --git a/ansible/playbooks/saas/roles/vector/templates/nomad.hcl b/ansible/playbooks/saas/roles/vector/templates/nomad.hcl index ed39381a..e6cc7504 100644 --- a/ansible/playbooks/saas/roles/vector/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/vector/templates/nomad.hcl @@ -54,7 +54,7 @@ job "{{ domain }}" { } config { - image = "timberio/vector:{{ softwares.vector.version }}-alpine" + image = "timberio/vector:{{ catalogs.vector.version }}-alpine" volumes = [ "{{ software_path }}/var/lib/vector:/var/lib/vector:rw" ] diff --git a/ansible/playbooks/saas/roles/vector/templates/vector.yaml.j2 b/ansible/playbooks/saas/roles/vector/templates/vector.yaml.j2 index 27332fff..bdba7f75 100644 --- a/ansible/playbooks/saas/roles/vector/templates/vector.yaml.j2 +++ b/ansible/playbooks/saas/roles/vector/templates/vector.yaml.j2 @@ -22,4 +22,4 @@ sinks: target: stdout type: console encoding: - codec: json \ No newline at end of file + codec: json diff --git a/ansible/playbooks/saas/roles/vllm/tasks/build.yml b/ansible/playbooks/saas/roles/vllm/tasks/build.yml index f1029407..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/vllm/tasks/build.yml +++ b/ansible/playbooks/saas/roles/vllm/tasks/build.yml @@ -9,4 +9,4 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/vllm/templates/entrypoint-llm.sh b/ansible/playbooks/saas/roles/vllm/templates/entrypoint-llm.sh index a4d522d8..28d65ae6 100644 --- a/ansible/playbooks/saas/roles/vllm/templates/entrypoint-llm.sh +++ b/ansible/playbooks/saas/roles/vllm/templates/entrypoint-llm.sh @@ -7,4 +7,4 @@ pip install --break-system-packages -U "huggingface_hub[cli]" hf-transfer mkdir -p /models/${MODEL} echo "Download model ..." -hf download meta-llama/${MODEL} --local-dir /models/${MODEL} \ No newline at end of file +hf download meta-llama/${MODEL} --local-dir /models/${MODEL} diff --git a/ansible/playbooks/saas/roles/vllm/templates/nomad.hcl b/ansible/playbooks/saas/roles/vllm/templates/nomad.hcl index da4017b0..092140fc 100644 --- a/ansible/playbooks/saas/roles/vllm/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/vllm/templates/nomad.hcl @@ -79,7 +79,7 @@ job "{{ domain }}" { } config { - image = "vllm/vllm-openai:v{{ software.image_version | default(softwares.vllm.version) }}" + image = "vllm/vllm-openai:v{{ software.image_version | default(catalogs.vllm.version) }}" ports = ["vllm"] ipc_mode = "host" @@ -99,7 +99,7 @@ job "{{ domain }}" { resources { cpu = {{ size[software.size2 | default(software.size)].cpu }} memory = {{ size[software.size2 | default(software.size)].memory }} - + device "nvidia/gpu" { count = 1 affinity { diff --git a/ansible/playbooks/saas/roles/wordpress/files/backup b/ansible/playbooks/saas/roles/wordpress/files/backup index 9012362b..7f1fd201 100644 --- a/ansible/playbooks/saas/roles/wordpress/files/backup +++ b/ansible/playbooks/saas/roles/wordpress/files/backup @@ -14,4 +14,4 @@ echo "Upgrade plugins..." /usr/bin/wp-cli plugin update --all --allow-root --path=/var/www/html echo "Upgrade themes..." -/usr/bin/wp-cli theme update --all --allow-root --path=/var/www/html \ No newline at end of file +/usr/bin/wp-cli theme update --all --allow-root --path=/var/www/html diff --git a/ansible/playbooks/saas/roles/wordpress/tasks/build.yml b/ansible/playbooks/saas/roles/wordpress/tasks/build.yml index eb4be163..7cbbd745 100644 --- a/ansible/playbooks/saas/roles/wordpress/tasks/build.yml +++ b/ansible/playbooks/saas/roles/wordpress/tasks/build.yml @@ -11,7 +11,7 @@ - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version - name: Download wp-cli ansible.builtin.get_url: diff --git a/ansible/playbooks/saas/roles/wordpress/tasks/install.yml b/ansible/playbooks/saas/roles/wordpress/tasks/install.yml index 897cbf06..5eaabc80 100644 --- a/ansible/playbooks/saas/roles/wordpress/tasks/install.yml +++ b/ansible/playbooks/saas/roles/wordpress/tasks/install.yml @@ -40,7 +40,7 @@ - name: Install wordpress community.docker.docker_container: name: "{{ domain }}-install" - image: "phpfpm-wordpress:{{ softwares.wordpress.version }}" + image: "phpfpm-wordpress:{{ catalogs.wordpress.version }}" detach: false cleanup: true command: "{{ item }}" diff --git a/ansible/playbooks/saas/roles/wordpress/templates/nomad.hcl b/ansible/playbooks/saas/roles/wordpress/templates/nomad.hcl index 2e615550..7a90dc26 100644 --- a/ansible/playbooks/saas/roles/wordpress/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/wordpress/templates/nomad.hcl @@ -39,10 +39,10 @@ job "{{ domain }}" { driver = "docker" config { - image = "{{ docker_private_registry.url }}/wordpress:{{ softwares.wordpress.version }}" + image = "{{ docker_private_registry.url }}/wordpress:{{ catalogs.wordpress.version }}" volumes = [ - "{{ software_path }}/etc/php-fpm.d:/etc/php{{ softwares.wordpress.version.split('.')[:2] | join('') }}/php-fpm.d:ro", + "{{ software_path }}/etc/php-fpm.d:/etc/php{{ catalogs.wordpress.version.split('.')[:2] | join('') }}/php-fpm.d:ro", "{{ software_path }}/var/www/html:/var/www/html:rw", "{{ software_path }}/var/run/php-fpm:/run/php-fpm:rw", "{{ software_path }}/var/log/php-fpm:/var/log/php-fpm:rw", @@ -140,7 +140,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "{{ docker_private_registry.url }}/nginx:{{ softwares.nginx.version }}" + image = "{{ docker_private_registry.url }}/nginx:{{ catalogs.nginx.version }}" volumes = [ "{{ software_path }}/var/www/html:/var/www/html:ro", "{{ software_path }}/var/run/php-fpm:/var/run/php-fpm:ro", diff --git a/ansible/playbooks/saas/roles/wordpress/vars/actions.yml b/ansible/playbooks/saas/roles/wordpress/vars/actions.yml index c4caf77b..5ab21003 100644 --- a/ansible/playbooks/saas/roles/wordpress/vars/actions.yml +++ b/ansible/playbooks/saas/roles/wordpress/vars/actions.yml @@ -7,4 +7,4 @@ wordpress_actions: - "{{ software_path }}/var/backup:/var/backup:rw" - "/usr/local/bin/wordpress-backup:/usr/local/bin/wordpress-backup:ro" - "/usr/local/bin/wordpress-restore:/usr/local/bin/wordpress-restore:ro" - image: "{{ docker_private_registry.url }}/wordpress:{{ softwares.wordpress.version }}" + image: "{{ docker_private_registry.url }}/wordpress:{{ catalogs.wordpress.version }}" diff --git a/ansible/playbooks/saas/roles/zigbee2mqtt/tasks/build.yml b/ansible/playbooks/saas/roles/zigbee2mqtt/tasks/build.yml index 5d53ad8d..c8c8cb30 100644 --- a/ansible/playbooks/saas/roles/zigbee2mqtt/tasks/build.yml +++ b/ansible/playbooks/saas/roles/zigbee2mqtt/tasks/build.yml @@ -5,10 +5,8 @@ - name: Set custom variables ansible.builtin.set_fact: image_version: "{{ latest_version }}" - image_name: "{{ image.name }}" - image_labels: "{{ image.labels }}" - image_build: "{{ image.build }}" + image_definition: "{{ image }}" - name: End playbook if no new version ansible.builtin.meta: end_host - when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version + when: catalogs[catalog_image_name] is defined and catalogs[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/zigbee2mqtt/templates/nomad.hcl b/ansible/playbooks/saas/roles/zigbee2mqtt/templates/nomad.hcl index 1bfb7ec2..6efbf122 100644 --- a/ansible/playbooks/saas/roles/zigbee2mqtt/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/zigbee2mqtt/templates/nomad.hcl @@ -32,7 +32,7 @@ job "{{ domain }}" { port = "http" provider = "nomad" tags = [ - {{ lookup('template', '../../traefik/templates/traefik_tag.j2') | indent(8) }} + {{ lookup('template', '../../traefik/templates/traefik_tag.j2') | ansible.builtin.indent(8) }} ] } @@ -52,7 +52,7 @@ job "{{ domain }}" { user = "1001:1001" config { - image = "koenkk/zigbee2mqtt:{{ softwares.zigbee2mqtt.version }}" + image = "koenkk/zigbee2mqtt:{{ catalogs.zigbee2mqtt.version }}" volumes = [ "{{ software_path }}/app/data:/app/data:rw", diff --git a/ansible/playbooks/saas/setup-buildx.yml b/ansible/playbooks/saas/setup-buildx.yml index 3f78dcc2..9491ece3 100644 --- a/ansible/playbooks/saas/setup-buildx.yml +++ b/ansible/playbooks/saas/setup-buildx.yml @@ -62,4 +62,3 @@ - name: Show buildx configuration ansible.builtin.debug: var: buildx_ls.stdout_lines - diff --git a/ansible/plugins/callback/webhook_notifier.py b/ansible/plugins/callback/webhook_notifier.py index e9e9711c..81a05c25 100644 --- a/ansible/plugins/callback/webhook_notifier.py +++ b/ansible/plugins/callback/webhook_notifier.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import (absolute_import, annotations, division, print_function) __metaclass__ = type @@ -39,7 +38,7 @@ class CallbackModule(CallbackBase): """ Plugin de callback pour envoyer des notifications webhook lors des différentes étapes d'exécution d'un playbook Ansible. - + Configuration via variables d'environnement ou variables Ansible: - SIMPLE_STACK_UI_URL / webhook_api_url - SIMPLE_STACK_UI_USER / webhook_user @@ -110,36 +109,33 @@ def _send_webhook(self, event_type: str, status: str, message: str, extra_data: return payload = { - "schema": "events_create", - "data": { - "event_type": event_type, - "status": status, - "message": message, - "timestamp": datetime.datetime.utcnow().isoformat() + "Z", - "playbook": { - "name": self.playbook_name or "unknown", - "path": self.playbook_path or "unknown", - }, - "execution": { - "hostname": socket.gethostname(), - "user": os.environ.get("USER", "unknown"), - } + "event_type": event_type, + "status": status, + "message": message, + "timestamp": datetime.datetime.utcnow().isoformat() + "Z", + "playbook": { + "name": self.playbook_name or "unknown", + "path": self.playbook_path or "unknown", + }, + "execution": { + "hostname": socket.gethostname(), + "user": os.environ.get("USER", "unknown"), } } - + if self.start_time: - payload["data"]["execution"]["start_time"] = self.start_time.isoformat() + "Z" - payload["data"]["duration_seconds"] = ( + payload["execution"]["start_time"] = self.start_time.isoformat() + "Z" + payload["duration_seconds"] = ( datetime.datetime.utcnow() - self.start_time ).total_seconds() if self.hosts: - payload["data"]["hosts"] = [str(h) for h in self.hosts] + payload["hosts"] = [str(h) for h in self.hosts] if extra_data: - payload["data"].update(extra_data) + payload.update(extra_data) - webhook_endpoint = f"{api_url}/api" + webhook_endpoint = f"{api_url}/api/events" json_payload = json.dumps(payload) display.vvv(f"webhook_notifier: Envoi vers {webhook_endpoint}") @@ -159,7 +155,7 @@ def _send_webhook(self, event_type: str, status: str, message: str, extra_data: # Ajouter l'authentification si configurée if username and password: token = base64.b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8") - curl_cmd.extend(["-H", f"Authorization: Bearer {token}"]) + curl_cmd.extend(["-H", f"Authorization: Basic {token}"]) curl_cmd.append(webhook_endpoint) @@ -270,7 +266,7 @@ def v2_playbook_on_play_start(self, play): try: variable_manager = play.get_variable_manager() raw_vars = variable_manager.get_vars() or {} - + self.play_vars = {} for key in ['webhook_api_url', 'webhook_user', 'webhook_password']: if key in raw_vars: @@ -288,7 +284,7 @@ def v2_playbook_on_play_start(self, play): self.hosts = [str(h) for h in hosts] else: self.hosts = [str(play.hosts)] - + except Exception as e: display.vvvv(f"webhook_notifier: Impossible de récupérer les variables: {e}") self.play_vars = {} diff --git a/ansible/plugins/lookup/simple-stack-ui.py b/ansible/plugins/lookup/simple-stack-ui.py index 401ebe73..54f55edd 100644 --- a/ansible/plugins/lookup/simple-stack-ui.py +++ b/ansible/plugins/lookup/simple-stack-ui.py @@ -2,6 +2,7 @@ __metaclass__ = type import base64 +import json import os import string import random @@ -42,7 +43,9 @@ def run(self, terms, variables=None, **kwargs): token = base64.b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8") headers = {} - headers["Authorization"] = f"Bearer {token}" + headers["Authorization"] = f"Basic {token}" + headers["Content-Type"] = "application/json" + headers["Accept"] = "application/json" display.vvvv(f"mylookup2: Authorization headers {headers}") @@ -65,22 +68,25 @@ def run(self, terms, variables=None, **kwargs): if "delete" not in data: data["delete"] = False + if "missing" not in data: + data["missing"] = "error" + if data['missing'] not in ['error', 'warn', 'create']: raise AnsibleError(f"{data['missing']} is not a valid option for missing") split_lines = kwargs.pop("split_lines", False) try: - data_bytes = urllib.parse.urlencode(data).encode("utf-8") + data_bytes = json.dumps(data).encode("utf-8") except Exception as exc: - raise AnsibleError(f"mylookup2: error encoding POST data: {to_native(exc)}") + raise AnsibleError(f"mylookup2: error encoding JSON POST data: {to_native(exc)}") display.vvvv(f"mylookup2: POSTing to {api_url} with data={data}") try: response = open_url( - f"{api_url}/api/secret", + f"{api_url}/api/variables/secret", headers=headers, data=data_bytes, method="POST", @@ -91,11 +97,20 @@ def run(self, terms, variables=None, **kwargs): body = e.read().decode(errors='replace') if status == 460: - display.warning("key or subkey does not exist") + display.warning( + f"mylookup2: missing key/subkey (type={data.get('type')}, key={data.get('key')}, subkey={data.get('subkey')})" + ) return [{}] if status == 461: - raise AnsibleError("key or subkey does not exist") + raise AnsibleError( + f"key or subkey does not exist (type={data.get('type')}, key={data.get('key')}, subkey={data.get('subkey')})" + ) + + if status == 401: + raise AnsibleError( + "Unauthorized on simple-stack-ui API (expected Basic auth with email:password user credentials)" + ) raise AnsibleError(f"HTTP {status} for {api_url}: {body}") diff --git a/ansible/rulebook.yml b/ansible/rulebook.yml index 5f55dfe1..4bef2b38 100644 --- a/ansible/rulebook.yml +++ b/ansible/rulebook.yml @@ -36,6 +36,30 @@ extra_vars: hosts_limit: "{{ event.payload.meta.hosts }}" + - name: paas-docker + condition: event.payload.type == "paas-docker" + actions: + - run_playbook: + name: playbooks/paas/docker.yml + extra_vars: + hosts_limit: "{{ event.payload.meta.hosts }}" + + - name: paas-nomad + condition: event.payload.type == "paas-nomad" + actions: + - run_playbook: + name: playbooks/paas/nomad.yml + extra_vars: + hosts_limit: "{{ event.payload.meta.hosts }}" + + - name: paas-coredns + condition: event.payload.type == "paas-coredns" + actions: + - run_playbook: + name: playbooks/paas/coredns.yml + extra_vars: + hosts_limit: "{{ event.payload.meta.hosts }}" + - name: paas-nomad-clean-errors condition: event.payload.type == "paas-nomad-clean-errors" actions: @@ -90,4 +114,4 @@ - run_playbook: name: playbooks/saas/nomad-clean-errors.yml extra_vars: - hosts_limit: "{{ event.payload.meta.hosts }}" \ No newline at end of file + hosts_limit: "{{ event.payload.meta.hosts }}" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..a8a993ef --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,59 @@ +services: + ui-next: + build: + context: ./ui-next + dockerfile: Dockerfile + image: simple-stack/ui-next:local + container_name: simple-stack-ui-next + environment: + NODE_ENV: production + PORT: 3000 + HOSTNAME: 0.0.0.0 + NEXTAUTH_URL: http://localhost:${UI_NEXT_PORT:-3000} + NEXTAUTH_SECRET: ${NEXTAUTH_SECRET:-change-me-in-env} + AUTH_SECRET: ${NEXTAUTH_SECRET:-change-me-in-env} + AUTH_TRUST_HOST: "true" + TEMP_ADMIN_EMAIL: ${TEMP_ADMIN_EMAIL} + TEMP_ADMIN_PASSWORD: ${TEMP_ADMIN_PASSWORD} + SIMPLE_STACK_UI_USER: ${TEMP_ADMIN_EMAIL} + SIMPLE_STACK_UI_PASSWORD: ${TEMP_ADMIN_PASSWORD} + DATABASE_URL: /app/data/simple-stack.db + ports: + - "${UI_NEXT_PORT:-3000}:3000" + volumes: + - ./ui-next/data:/app/data + restart: unless-stopped + networks: + - simple-stack-net + + ansible: + build: + context: ./ansible + dockerfile: Dockerfile + args: + JAVA_VERSION: ${ANSIBLE_JAVA_VERSION:-21} + image: simple-stack/ansible:local + container_name: simple-stack-ansible + environment: + ANSIBLE_FORCE_COLOR: "true" + PYTHONUNBUFFERED: "1" + SIMPLE_STACK_UI_URL: ${SIMPLE_STACK_UI_URL} + SIMPLE_STACK_UI_USER: ${TEMP_ADMIN_EMAIL} + SIMPLE_STACK_UI_PASSWORD: ${TEMP_ADMIN_PASSWORD} + TF_HTTP_USERNAME: ${TEMP_ADMIN_EMAIL} + TF_HTTP_PASSWORD: ${TEMP_ADMIN_PASSWORD} + ANSIBLE_LOOKUP_PLUGINS: "/ansible/plugins/lookup" + ANSIBLE_CALLBACK_PLUGINS: "/ansible/plugins/callback" + ANSIBLE_CALLBACKS_ENABLED: "minimal,webhook_notifier" + depends_on: + - ui-next + volumes: + - ./terraform:/terraform + - ~/.ssh:/root/.ssh:ro + restart: unless-stopped + networks: + - simple-stack-net + +networks: + simple-stack-net: + driver: bridge diff --git a/ui-next/.dockerignore b/ui-next/.dockerignore new file mode 100644 index 00000000..775b36fc --- /dev/null +++ b/ui-next/.dockerignore @@ -0,0 +1,46 @@ +# dependencies +node_modules + +# build outputs +.next +out +dist +build +.turbo +.cache +coverage + +# logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env / secrets +.env +.env.* + +# vcs +.git +.gitignore + +# editor / os +.vscode +.idea +.DS_Store + +# local data / runtime +data +databases +tmp +logs + +# tests +*.test.ts +*.test.tsx +*.spec.ts +*.spec.tsx + +# docs +README.md diff --git a/ui-next/.gitignore b/ui-next/.gitignore new file mode 100644 index 00000000..665a7be9 --- /dev/null +++ b/ui-next/.gitignore @@ -0,0 +1,55 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ +/.turbo/ + +# production +/build +/dist/ + +# misc +.DS_Store +*.pem +*.log + +# local runtime / temp +/tmp/ +/logs/ + +# local data stores +/data/ +/databases/ + +# cache +/.cache/ + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/ui-next/Dockerfile b/ui-next/Dockerfile new file mode 100644 index 00000000..5df843e3 --- /dev/null +++ b/ui-next/Dockerfile @@ -0,0 +1,36 @@ +# syntax=docker/dockerfile:1 + +FROM node:24-alpine AS deps +WORKDIR /app +COPY package.json package-lock.json* ./ +RUN npm install + +FROM node:24-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN npm run build + +FROM node:24-alpine AS runner +WORKDIR /app +ENV NODE_ENV=production +ENV PORT=3000 +ENV HOSTNAME=0.0.0.0 + +# Run as non-root user +RUN addgroup -S nodejs && adduser -S nextjs -G nodejs + +# Create data directory and give ownership to nextjs user +RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data + +COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/public ./public +COPY --from=builder /app/next.config.ts ./next.config.ts +COPY --from=builder /app/messages ./messages + +USER nextjs +EXPOSE 3000 + +CMD ["npm", "run", "start"] diff --git a/ui-next/README.md b/ui-next/README.md new file mode 100644 index 00000000..e215bc4c --- /dev/null +++ b/ui-next/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/ui-next/app/(app)/api-interne/api-tester.tsx b/ui-next/app/(app)/api-interne/api-tester.tsx new file mode 100644 index 00000000..d96fabac --- /dev/null +++ b/ui-next/app/(app)/api-interne/api-tester.tsx @@ -0,0 +1,758 @@ +"use client"; + +import type { LucideIcon } from "lucide-react"; +import { + BookCopy, + Boxes, + LayoutDashboard, + Network, + ScrollText, + Settings, + UserCog, + Users, + Variable, +} from "lucide-react"; +import { useEffect, useMemo, useState } from "react"; + +type HttpMethod = "get" | "post" | "put" | "delete" | "patch"; + +type OpenApiOperation = { + summary?: string; + tags?: string[]; + responses?: Record; + requestBody?: { + required?: boolean; + content?: Record; + }; +}; + +type OpenApiPathItem = Partial>; + +type OpenApiDoc = { + paths?: Record; +}; + +type RouteItem = { + feature: string; + path: string; + method: HttpMethod; + summary: string; + needsBody: boolean; + responseCodes: string[]; +}; + +type ApiResponse = { + status: number; + durationMs: number; + contentType: string; + bodyText: string; +}; + +const methodOrder: HttpMethod[] = ["get", "post", "put", "patch", "delete"]; + +function extractPathParams(path: string): string[] { + const matches = path.match(/\{[^}]+\}/g) ?? []; + return matches.map((raw) => raw.slice(1, -1)); +} + +function buildPathFromTemplate(path: string, pathParams: Record): string { + return path.replace(/\{([^}]+)\}/g, (_, key: string) => { + const value = pathParams[key] ?? ""; + return encodeURIComponent(value); + }); +} + +function prettyPrint(value: string): string { + try { + return JSON.stringify(JSON.parse(value), null, 2); + } catch { + return value; + } +} + +function toFeatureLabel(feature: string): string { + const label = feature.replace(/[-_]/g, " "); + return label.charAt(0).toUpperCase() + label.slice(1); +} + +function getFeatureIcon(feature: string): LucideIcon { + const featureIcons: Record = { + account: UserCog, + catalogs: BookCopy, + events: ScrollText, + graphs: Network, + infrastructures: Network, + inventory: Boxes, + settings: Settings, + softwares: Boxes, + system: LayoutDashboard, + users: Users, + variables: Variable, + }; + + return featureIcons[feature] ?? LayoutDashboard; +} + +function getMethodBadgeClass(method: HttpMethod): string { + const base = "rounded-full px-2 py-0.5 text-[10px] font-bold tracking-wide"; + const colors: Record = { + get: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300", + post: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300", + put: "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300", + patch: "bg-fuchsia-100 text-fuchsia-700 dark:bg-fuchsia-900/30 dark:text-fuchsia-300", + delete: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300", + }; + + return `${base} ${colors[method]}`; +} + +function getResponseStatusBadgeClass(status: number): string { + const base = "rounded-full px-2 py-1 font-semibold"; + + if (status >= 200 && status < 300) { + return `${base} bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300`; + } + + if (status >= 300 && status < 400) { + return `${base} bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300`; + } + + if (status >= 400 && status < 500) { + return `${base} bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300`; + } + + if (status >= 500) { + return `${base} bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300`; + } + + return `${base} bg-zinc-200 text-zinc-700 dark:bg-zinc-700 dark:text-zinc-200`; +} + +function getRequestExample(path: string, method: HttpMethod): unknown { + const key = `${method.toUpperCase()} ${path}`; + + const examples: Record = { + "POST /api/account": { + email: "admin@example.local", + password: "Password123", + }, + "POST /api/events": { + event_type: "deploy", + status: "success", + message: "Deployment completed", + timestamp: new Date().toISOString(), + }, + "POST /api/catalogs": { + name: "my_catalog", + version: "1.0.0", + forkable: true, + }, + "PUT /api/catalogs/{id}": { + alias: "My Catalog", + description: "Catalog update description", + documentation: "https://docs.example.com/catalog", + cron: false, + crontab: "* * * * *", + }, + "POST /api/catalogs/{id}/fork": { + origin: "catalog-origin-id", + version: "1.0.0", + suffix: "custom", + alias: "My Fork", + description: "Forked catalog", + cron: false, + crontab: "* * * * *", + dockerfile_root: "FROM ubuntu:24.04", + dockerfile_nonroot: "FROM ubuntu:24.04", + }, + "PUT /api/catalogs/{id}/fork": { + origin: "catalog-origin-id", + suffix: "custom", + alias: "My Fork", + description: "Updated forked catalog", + cron: false, + crontab: "* * * * *", + dockerfile_root: "FROM ubuntu:24.04", + dockerfile_nonroot: "FROM ubuntu:24.04", + }, + "POST /api/infrastructures": { + name: "frontends-main", + description: "Main frontend infrastructure", + icon: "server", + color: "#1d4ed8", + }, + "PUT /api/infrastructures/{id}": { + name: "frontends-main", + description: "Updated infrastructure description", + icon: "server", + color: "#1d4ed8", + }, + "POST /api/infrastructures/{id}/tfstates": { + version: 4, + resources: [], + }, + "POST /api/settings/export": { + projects: ["infrastructure-id"], + }, + "POST /api/settings/import": { + projects: [ + { + infrastructure: { + name: "Imported project", + description: "Imported from backup", + icon: "server", + color: "#1d4ed8", + tfstate: {}, + }, + softwares: [], + variables: [], + }, + ], + }, + "POST /api/softwares": { + instance: "instance001.frontends.local", + software: "catalog-software-id", + size: "small", + domain: "app.example.com", + domain_alias: "", + exposition: "public", + }, + "PUT /api/softwares/{id}": { + instance: "instance001.frontends.local", + software: "catalog-software-id", + size: "medium", + domain: "app.example.com", + domain_alias: "", + exposition: "public", + }, + "POST /api/softwares/{id}": { + action: "start", + }, + "POST /api/users": { + first_name: "John", + last_name: "Doe", + email: "john.doe@example.com", + language: "en", + password: "Password123", + token: "", + isdisabled: false, + sa: false, + }, + "PUT /api/users/{id}": { + first_name: "John", + last_name: "Doe", + email: "john.doe@example.com", + language: "en", + password: "Password123", + token: "", + sa: false, + isdisabled: false, + isinactive: false, + notifications: true, + }, + "PUT /api/users/profile": { + first_name: "John", + last_name: "Doe", + email: "john.doe@example.com", + language: "en", + }, + "PUT /api/users/password": { + password: "NewPassword123", + }, + "POST /api/variables": { + type: "project", + key: "my.project.example", + value: "secret-value", + }, + "PUT /api/variables/{id}": { + type: "project", + key: "my.project.example", + value: "updated-secret-value", + }, + "POST /api/variables/{id}": { + mode: "read2", + key2: "my_project_example", + }, + "POST /api/variables/secret": { + type: "project", + key: "my.project.example", + subkey: "password", + missing: "warn", + nosymbols: false, + length: 24, + }, + }; + + return examples[key] ?? {}; +} + +function getResponseExample(path: string, method: HttpMethod, statusCode: string): unknown { + const key = `${method.toUpperCase()} ${path} ${statusCode}`; + + const specificExamples: Record = { + "GET /api/ping 200": { ok: true }, + "GET /api/events 200": [{ type: "info", body: "15/03/2026 14:45:00 - Deployment completed" }], + "POST /api/events 201": { ok: true }, + "GET /api/catalogs 200": [{ id: "catalog-id", name: "my_catalog", version: "1.0.0" }], + "GET /api/infrastructures 200": [ + { id: "infra-id", name: "frontends-main", description: "Main infrastructure" }, + ], + "GET /api/users 200": [ + { id: "user-id", first_name: "John", last_name: "Doe", email: "john.doe@example.com" }, + ], + "GET /api/variables 200": [{ id: "var-id", type: "project", key: "my.project.example" }], + }; + + if (specificExamples[key]) { + return specificExamples[key]; + } + + const code = Number(statusCode); + if (code === 201) return { ok: true }; + if (code === 400) return { error: "Bad Request" }; + if (code === 401) return { error: "Unauthorized" }; + if (code === 403) return { error: "Forbidden" }; + if (code === 404) return { error: "Not found" }; + if (code >= 500) return { error: "Internal Server Error" }; + return { ok: true }; +} + +export default function ApiTester() { + const [routes, setRoutes] = useState([]); + const [selectedRouteKey, setSelectedRouteKey] = useState(""); + const [pathParams, setPathParams] = useState>({}); + const [payload, setPayload] = useState("{}"); + const [isLoadingSpec, setIsLoadingSpec] = useState(true); + const [isRunning, setIsRunning] = useState(false); + const [specError, setSpecError] = useState(""); + const [requestError, setRequestError] = useState(""); + const [selectedExampleCode, setSelectedExampleCode] = useState(""); + const [response, setResponse] = useState(null); + const [copyState, setCopyState] = useState<"idle" | "success" | "error">("idle"); + + useEffect(() => { + let cancelled = false; + + const loadSpec = async () => { + setIsLoadingSpec(true); + setSpecError(""); + try { + const res = await fetch("/api/openapi-internal", { + method: "GET", + cache: "no-store", + credentials: "same-origin", + }); + + if (!res.ok) { + throw new Error(`Impossible de charger la spec (${res.status})`); + } + + const doc = (await res.json()) as OpenApiDoc; + const nextRoutes: RouteItem[] = []; + + for (const [path, pathItem] of Object.entries(doc.paths ?? {})) { + for (const method of methodOrder) { + const operation = pathItem?.[method]; + if (!operation) continue; + + const defaultSummary = `${method.toUpperCase()} ${path}`; + const feature = (operation.tags?.[0] ?? "other").toLowerCase(); + nextRoutes.push({ + feature, + path, + method, + summary: operation.summary ?? defaultSummary, + needsBody: !!operation.requestBody, + responseCodes: Object.keys(operation.responses ?? {}).sort(), + }); + } + } + + nextRoutes.sort((a, b) => { + if (a.feature !== b.feature) { + return a.feature.localeCompare(b.feature); + } + if (a.path === b.path) { + return methodOrder.indexOf(a.method) - methodOrder.indexOf(b.method); + } + return a.path.localeCompare(b.path); + }); + + if (cancelled) return; + + setRoutes(nextRoutes); + if (nextRoutes.length > 0) { + setSelectedRouteKey(`${nextRoutes[0].method} ${nextRoutes[0].path}`); + } + } catch (error) { + if (!cancelled) { + setSpecError(error instanceof Error ? error.message : "Erreur inconnue"); + } + } finally { + if (!cancelled) { + setIsLoadingSpec(false); + } + } + }; + + loadSpec(); + + return () => { + cancelled = true; + }; + }, []); + + const selectedRoute = useMemo(() => { + return routes.find((route) => `${route.method} ${route.path}` === selectedRouteKey) ?? null; + }, [routes, selectedRouteKey]); + + const groupedRoutes = useMemo(() => { + const groups = new Map(); + for (const route of routes) { + const existing = groups.get(route.feature) ?? []; + existing.push(route); + groups.set(route.feature, existing); + } + + return [...groups.entries()] + .sort(([a], [b]) => a.localeCompare(b)) + .map(([feature, items]) => ({ feature, items })); + }, [routes]); + + const selectedPathParamKeys = useMemo(() => { + if (!selectedRoute) return []; + return extractPathParams(selectedRoute.path); + }, [selectedRoute]); + + const selectedExamplePayload = useMemo(() => { + if (!selectedRoute) return "{}"; + return prettyPrint(JSON.stringify(getRequestExample(selectedRoute.path, selectedRoute.method))); + }, [selectedRoute]); + + const selectedResponseExample = useMemo(() => { + if (!selectedRoute || !selectedExampleCode) return "{}"; + return prettyPrint( + JSON.stringify(getResponseExample(selectedRoute.path, selectedRoute.method, selectedExampleCode)), + ); + }, [selectedRoute, selectedExampleCode]); + + useEffect(() => { + setPathParams((prev) => { + const defaults: Record = {}; + for (const key of selectedPathParamKeys) { + defaults[key] = prev[key] ?? ""; + } + return defaults; + }); + setRequestError(""); + setResponse(null); + if (selectedRoute?.responseCodes?.length) { + setSelectedExampleCode(selectedRoute.responseCodes[0]); + } else { + setSelectedExampleCode("200"); + } + setPayload(selectedExamplePayload); + }, [selectedPathParamKeys, selectedExamplePayload, selectedRoute]); + + const finalUrl = useMemo(() => { + if (!selectedRoute) return ""; + return buildPathFromTemplate(selectedRoute.path, pathParams); + }, [selectedRoute, pathParams]); + + const canRun = !!selectedRoute && !isRunning; + + async function copyResponseToClipboard() { + if (!response) return; + + try { + await navigator.clipboard.writeText(response.bodyText || "(Reponse vide)"); + setCopyState("success"); + } catch { + setCopyState("error"); + } + } + + async function runRequest() { + if (!selectedRoute) return; + + setRequestError(""); + setResponse(null); + + for (const key of selectedPathParamKeys) { + if (!pathParams[key]?.trim()) { + setRequestError(`Le parametre de chemin \"${key}\" est obligatoire.`); + return; + } + } + + let parsedBody: unknown = undefined; + if (selectedRoute.needsBody) { + try { + parsedBody = payload.trim() ? JSON.parse(payload) : {}; + } catch { + setRequestError("Payload JSON invalide."); + return; + } + } + + const headers: HeadersInit = {}; + if (selectedRoute.needsBody) { + headers["Content-Type"] = "application/json"; + } + + setIsRunning(true); + + const startedAt = performance.now(); + try { + const res = await fetch(finalUrl, { + method: selectedRoute.method.toUpperCase(), + headers, + body: selectedRoute.needsBody ? JSON.stringify(parsedBody) : undefined, + credentials: "same-origin", + cache: "no-store", + }); + + const rawText = await res.text(); + const durationMs = Math.round(performance.now() - startedAt); + + setResponse({ + status: res.status, + durationMs, + contentType: res.headers.get("content-type") ?? "", + bodyText: prettyPrint(rawText), + }); + setCopyState("idle"); + } catch (error) { + setRequestError(error instanceof Error ? error.message : "Echec de la requete"); + } finally { + setIsRunning(false); + } + } + + return ( +
+ + +
+
+

API interne

+

+ Teste les endpoints directement avec ta session active. +

+
+ + +
+
+ + {!selectedRoute ? ( +
Selectionne une route pour continuer.
+ ) : ( +
+
+ {selectedPathParamKeys.length > 0 && ( +
+

+ Parametres de chemin +

+ {selectedPathParamKeys.map((key) => ( + + setPathParams((prev) => ({ + ...prev, + [key]: event.target.value, + })) + } + placeholder={key} + className="w-full rounded-md border border-zinc-300 bg-white px-3 py-2 text-sm outline-none ring-zinc-500 focus:ring-2 dark:border-zinc-700 dark:bg-zinc-900" + /> + ))} +
+ )} + + {selectedRoute.method !== "get" && ( +
+ +