#!/usr/bin/env ansible-playbook
---
#==============================================================#
# File      :   app.yml
# Desc      :   copy and launch docker compose app
# Ctime     :   2025-01-11
# Mtime     :   2025-06-17
# Path      :   app.yml
# Docs      :   https://pigsty.io/docs/app
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng (rh@vonng.com)
#==============================================================#


#--------------------------------------------------------------#
# Usage
#--------------------------------------------------------------#
#  1.  specify the `app` param
#      by default, it's a docker compose app in the app/ folder
#      configure it in the pigsty.yml or pass it as `-e app=<name>`
#
#  2.  OPTIONAL, specify app details with apps:
#
#  This playbook relies on the DOCKER module to work
#  This playbook will:
#   1. copy docker compose resource from app/<appname> to /opt/<appname>
#   2. create required dirs with app.file (optional)
#   3. overwrite .env config with app.conf (optional)
#   4. launch app with docker compose up
#
#--------------------------------------------------------------#
# Example
#--------------------------------------------------------------#
#  ./app.yml -e app=pgweb          # simple app can be launched directly
#  ./app.yml -e app=pgadmin        # without any further configuration
#
#  ./app.yml -e app=bytebase       # for sophisticated software
#  ./app.yml -e app=odoo           # configure pigsty.yml `apps`
#  ./app.yml -e app=dify           # to have fine-grained control
#--------------------------------------------------------------#

- name: NODE ID
  become: true
  hosts: all
  gather_facts: no
  roles:
    - { role: node_id ,tags: id }
    #- { role: docker  ,tags: docker }

# Run docker compose application (require the docker module)
- name: APP INSTALL
  hosts: all
  gather_facts: no
  become: true
  tasks:

    #----------------------------------------------------------#
    # Validate app and app definition                [preflight]
    #----------------------------------------------------------#
    - name: preflight
      tags: [ app_check, preflight, always ]
      connection: local
      block:
        - name: validate app  parameter
          assert:
            that:
              - app is defined
              - app != ''
            fail_msg: "the 'app' arg is not given (-e app=<name>)"

        - name: validate docker exists
          assert:
            that:
              - docker_enabled is defined and docker_enabled
            fail_msg: "docker_enabled is required to install app"

        - name: fetch app definition
          set_fact:
            app_def: "{{ apps[app] | default({}) }}"

        - name: set app properties
          set_fact:
            app_name: "{{ app }}"
            app_src:  "{{ app_def.src | default(playbook_dir + '/app/' + app) }}" # override src name with app.src
            app_dest: "{{ app_def.dest | default('/opt/' + app) }}"               # override dest name with app.dest
            app_conf: "{{ app_def.conf | default({}) }}"                          # application configuration
            app_file: "{{ app_def.file | default([]) }}"                          # application files & directories
            app_args: "{{ app_def.args | default('') }}"                          # application makefile shortcuts

        - name: print app details
          debug:
            msg: "app: {{ app_name }}, src: {{ app_src }}, dest: {{ app_dest }}, conf: {{ app_conf }}, file: {{ app_file }}"

    #----------------------------------------------------------#
    # Install app resources to /opt                [app_install]
    #----------------------------------------------------------#
    # copy docker app folder to /opt/<app.dest> or /opt/<app.name>
    # this will fail if the app/<appname> folder does not exist
    - name: install app resource to /opt
      tags: app_install
      copy: src="{{ app_src }}/" dest="/{{ app_dest }}/"

    #----------------------------------------------------------#
    # Prepare files & directories                     [app_file]
    #----------------------------------------------------------#
    - name: setup app files & directories
      tags: app_file
      when: app_file | length > 0
      file: "{{ item }}"
      with_items: "{{ app_file }}"

    #----------------------------------------------------------#
    # Configure app with .env                       [app_config]
    #----------------------------------------------------------#
    # append entries to app .env config (override existing entries)
    - name: configure app by updating .env
      tags: app_config
      when: app_conf | length > 0
      lineinfile:
        path: "{{ app_dest }}/.env"
        regexp: '^{{ item.key | upper }}='
        line: '{{ item.key | upper }}={{ item.value if item.value is not boolean else item.value | string | lower }}'
        create: yes
      loop: "{{ app_conf | dict2items }}"

    #----------------------------------------------------------#
    # Launch app with make command                  [app_launch]
    #----------------------------------------------------------#
    # it may take a while to pull images, or very fast if you already have local image loaded, or proxy, mirror.
    - name: launch app
      tags: app_launch
      shell:
        cmd: make {{ app_args }}
        chdir: "{{ app_dest }}"

...