00_core.ymlΒΆ

---
- include_tasks: utils/once/flag.yml

- name: "πŸ“ Create LDIF dirs {{ OPENLDAP_LDIF_PATH_HOST }} before swarm bind-mount"
  directory_batch:
    paths: "{{ [OPENLDAP_LDIF_PATH_HOST] | product(OPENLDAP_LDIF_TYPES) | map('join') | list }}"
    mode: "0755"

- name: 🎬 Initialize docker
  include_tasks: 01_docker.yml

- name: πŸ“„ Render {{ lookup('domain',application_id) }}.conf if LDAP is public
  stack_host_template:
    src: "nginx.stream.conf.j2"
    dest: "{{ lookup('nginx','directories.configuration.streams') }}{{ lookup('domain',application_id) }}.conf"
  vars:
    domain: "{{ lookup('domain', application_id) }}"
  notify: restart-openresty
  when: OPENLDAP_NETWORK_SWITCH_PUBLIC | bool

- name: 🧹 Remove {{ lookup('domain',application_id) }}.conf if LDAP not public
  file:
    path: "{{ lookup('nginx','directories.configuration.streams') }}{{ lookup('domain',application_id) }}.conf"
    state: absent
  when: not OPENLDAP_NETWORK_SWITCH_PUBLIC | bool

- name: "⏳ Wait for LDAP to be available"
  wait_for:
    host: "{{ DOCKER_REACH_HOST }}"
    port: "{{ lookup('config', application_id, 'services.openldap.ports.local.ldap') }}"
    delay: 5
    timeout: "{{ lookup('timeout', 120) | int }}"
    state: started
  when: IS_COMPOSE_MODE

- name: πŸ”Ž Check if current RootDN/RootPW already work
  ansible.builtin.shell: >
    container exec -e OPENLDAP_BIND_PW {{ OPENLDAP_CONTAINER_ADDRESS }}
    sh -c 'exec ldapwhoami -x -H ldap://127.0.0.1:389 -D "{{ OPENLDAP_BIND_DN }}" -w "$OPENLDAP_BIND_PW"'
  environment:
    OPENLDAP_BIND_PW: "{{ OPENLDAP_BIND_PW }}"
  register: openldap_bind_check
  delegate_to: "{{ STACK_HOST }}"
  run_once: true
  changed_when: false
  failed_when: false

- name: βœ… Ensure LDAP RootPW is set on every deploy
  include_tasks: 02_credentials.yml
  when:
    - OPENLDAP_NETWORK_SWITCH_LOCAL | bool
    - OPENLDAP_PROVISION_CREDENTIALS | bool
    - openldap_bind_check.rc != 0

- name: πŸ”§ Set OPENLDAP_MODULE_DN (from filesystem)
  shell: >
    container exec {{ OPENLDAP_CONTAINER_ADDRESS }}
    sh -lc 'grep -m1 "^dn: " /etc/ldap/slapd.d/cn=config/cn=module{0}.ldif | sed "s/^dn: //"'
  register: openldap_module_dn_raw
  delegate_to: "{{ STACK_HOST }}"
  run_once: true
  changed_when: false
  retries: 30
  delay: 5
  until:
    - openldap_module_dn_raw.rc == 0
    - (openldap_module_dn_raw.stdout | trim) != ""

- name: πŸ“ Normalize OPENLDAP_MODULE_DN (ensure ,cn=config suffix)
  set_fact:
    OPENLDAP_MODULE_DN: >-
      {{
        (openldap_module_dn_raw.stdout | trim)
        ~ ('' if (openldap_module_dn_raw.stdout | trim) is search(',cn=config$') else ',cn=config')
      }}

- name: πŸ” Query available LDAP databases
  shell: >
    container exec {{ OPENLDAP_CONTAINER_ADDRESS }}
    ldapsearch -Q -Y EXTERNAL -H {{ OPENLDAP_CONFIG_URI }} -LLL -b cn=config "(olcDatabase=*)" dn
  register: ldap_databases
  delegate_to: "{{ STACK_HOST }}"
  run_once: true
  changed_when: false

- name: πŸ”§ Set OPENLDAP_DATA_BACKEND_DN (mdb preferred, hdb fallback)
  set_fact:
    OPENLDAP_DATA_BACKEND_DN: >-
      {{
        (
          ldap_databases.stdout_lines
          | select('search', '^dn: olcDatabase=.*mdb')
          | map('regex_replace', '^dn: ', '')
          | list
          | first
        )
        | default(
          (
            ldap_databases.stdout_lines
            | select('search', '^dn: olcDatabase=.*hdb')
            | map('regex_replace', '^dn: ', '')
            | list
            | first
          )
        )
      }}
- name: πŸ“ Normalize OPENLDAP_DATA_BACKEND_DN (ensure ,cn=config suffix)
  set_fact:
    OPENLDAP_DATA_BACKEND_DN: >-
      {{
        OPENLDAP_DATA_BACKEND_DN
        ~ ('' if OPENLDAP_DATA_BACKEND_DN is search(',cn=config$') else ',cn=config')
      }}
  when: OPENLDAP_DATA_BACKEND_DN | default('') | length > 0

- name: "πŸ“‚ Import LDIF Configuration"
  include_tasks: _ldifs_creation.yml
  loop:
    - configuration
  loop_control:
    loop_var: folder
  when: OPENLDAP_PROVISION_CONFIGURATION | bool

- name: 🚿 flush LDIF handlers
  meta: flush_handlers

- name: πŸ“₯ Load python-ldap build prerequisites
  include_tasks: _python_ldap_prerequisites.yml

- name: πŸ“₯ Load python-ldap header fallback when Python.h is missing
  include_tasks: _python_ldap_header_fallback.yml
  when: not openldap_python_header.stat.exists

- name: πŸ“¦ Install python-ldap in active Ansible interpreter
  include_role:
    name: sys-pip-install
  vars:
    package_name: python-ldap
    package_state: present
    global_install: true

- name: βœ… Sanity check python-ldap import (verbose)
  ansible.builtin.shell: |
    set -euo pipefail
    {{ ansible_python_interpreter }} - <<'EOF'
    import traceback
    try:
        import ldap
        print("python-ldap version:", ldap.__version__)
        print("ldap module:", ldap.__file__)
    except Exception:
        traceback.print_exc()
        raise
    EOF
  changed_when: false
  when: MODE_DEBUG | bool

- name: "πŸ“‚ Include Schemas (if enabled)"
  include_tasks:
    file: 03_schemas.yml
    apply:
      run_once: true
      delegate_to: "{{ STACK_HOST }}"
  when: OPENLDAP_PROVISION_SCHEMAS | bool

- name: "πŸ“‚ Import LDAP Entries (if enabled)"
  include_tasks:
    file: 04_users.yml
    apply:
      run_once: true
      delegate_to: "{{ STACK_HOST }}"
  when: OPENLDAP_PROVISION_USERS | bool

- name: "πŸ“‚ Import LDIF Data (if enabled)"
  include_tasks: _ldifs_creation.yml
  loop:
    - groups
  loop_control:
    loop_var: folder
  when: OPENLDAP_PROVISION_GROUPS | bool

- meta: flush_handlers

- name: "βž• Add Objects to all users"
  include_tasks:
    file: 05_update.yml
    apply:
      run_once: true
      delegate_to: "{{ STACK_HOST }}"
  when: OPENLDAP_PROVISION_UPDATE | bool