molecule.yml #4

  • //
  • guest/
  • russell_jackson/
  • ansible-sdp/
  • roles/
  • perforce-sdp-install/
  • molecule/
  • default/
  • molecule.yml
  • View
  • Commits
  • Open Download .zip Download (5 KB)
---
# Full-integration Molecule scenario for the perforce-sdp-install role.
#
# Brings up a real (unlicensed) p4d inside a systemd-enabled container on both
# Debian (Ubuntu) and RedHat/EL (Rocky) families, configures it with
# configure_new_server.sh, and runs the SDP functional test harness.
#
# Requires Docker with systemd-capable images (the geerlingguy *-ansible images
# run systemd as PID 1). The containers are privileged with the host cgroup
# mounted so systemctl can manage the p4d_1 service.
#
# Run:   molecule test                  # full create/converge/verify/destroy
#        molecule converge              # bring up p4d + configure
#        molecule verify                # assertions + SDP test harness
#        MOLECULE_NO_DESTROY=1 molecule converge   # keep the container for poking

dependency:
  name: galaxy

driver:
  name: docker

platforms:
  - name: sdp-ubuntu2204
    image: geerlingguy/docker-ubuntu2204-ansible:latest
    command: ${MOLECULE_DOCKER_COMMAND:-""}
    privileged: true
    cgroupns_mode: host
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:rw
    pre_build_image: true
    groups:
      - main

  - name: sdp-rocky9
    image: geerlingguy/docker-rockylinux9-ansible:latest
    command: ${MOLECULE_DOCKER_COMMAND:-""}
    privileged: true
    cgroupns_mode: host
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:rw
    pre_build_image: true
    groups:
      - main

provisioner:
  name: ansible
  config_options:
    defaults:
      # The role relies on facts (os_family, distribution_major_version, etc.).
      gathering: smart
      # SDP scripts and p4d are noisy; keep output readable. (community.general's
      # 'yaml' callback was removed; use the built-in default with YAML format.)
      stdout_callback: ansible.builtin.default
      result_format: yaml
  inventory:
    group_vars:
      all:
        # The geerlingguy images run as root. Declaring the connection user as
        # root lets Ansible skip 'become' for become_user: root tasks
        # (become_allow_same_user defaults to false), so the role does not depend
        # on a working sudo/PAM stack inside the container.
        ansible_user: root
        # Use su for root->non-root become (become_user: perforce). The
        # geerlingguy EL9 image's sudo PAM stack fails in-container; su
        # (root -> any user, no password) works. Real hosts use sudo.
        ansible_become_method: ansible.builtin.su
        # --- flow control: full fresh install, no broker/license for the test ---
        perforce_clean: false
        # main-playbook.yml sets this as a play var; the role references it bare
        # (sdp_upgrade), so provide it here when running the role standalone.
        update_perforce: false
        update_dependencies: true
        new_sdp: true
        new_p4d: false
        p4d_enabled: true
        install_broker: false
        copy_license: false
        dummy_interface: false
        perforce_depots_use_nfs: false
        # Map the configured DNS names to this container in /etc/hosts so the
        # master-targeting scripts and the harness can connect to themselves.
        manage_etc_hosts: true

        # --- identity / topology (single commit-server) ---
        perforce_id: "1"
        perforce_server_type: "p4d_master"
        perforce_master_id: "master"
        perforce_replica_id: "standby"
        p4serviceuser: "svc_master"
        perforce_dnsname: "{{ inventory_hostname }}"
        perforce_standby_dnsname: "{{ inventory_hostname }}-standby"
        commit_dns: "{{ inventory_hostname }}"
        target_server: "{{ commit_dns }}"

        # --- ports / server config ---
        perforce_case_sensitive: "0"
        perforce_service: "p4d_{{ perforce_id }}"
        perforce_ssl_prefix: ""
        perforce_p4_port: "1666"
        perforce_p4broker_port: "ssl:1667"
        perforce_p4broker_target_port: "1666"

        # --- OS user / group ---
        perforce_user: "perforce"
        perforce_uid: "10666"
        perforce_group: "perforce"
        perforce_gid: "10666"

        # --- binary versions (downloaded from ftp.perforce.com) ---
        perforce_version: "25.2"
        perforce_broker_version: "25.2"

        # --- volume path *fragments* (no leading slash; prepare.yml creates them) ---
        perforce_data_volume: "hxdepots"
        perforce_common_volume: "hxdepots"
        perforce_log_volume: "hxlogs"
        perforce_online_metadata_volume: "hxmetadata"
        perforce_offline_metadata_volume: "hxmetadata"

        # --- mail / domain (template values only) ---
        perforce_domain: "molecule.test"
        perforce_mailfrom_email: "perforce-admin@{{ perforce_domain }}"
        perforce_mailto_email: "perforce-admin@{{ perforce_domain }}"
        perforce_smtp_server: "smtp.{{ perforce_domain }}"

        # --- admin / passwords (test-only; never used in production) ---
        perforce_admin_user: "p4admin"
        perforce_admin_user_pass: "F@stSCM!"
        admin_users: []
        # perforce_user_password (a SHA-512 crypt hash) is defined in
        # molecule/default/group_vars/all.yml -- its leading dollar-sign
        # sequences cannot live here because Molecule interpolates this file.

verifier:
  name: ansible

scenario:
  # The role (and the converge's configure step) are guarded to be idempotent, so
  # the idempotence step re-runs converge and asserts zero changes.
  test_sequence:
    - dependency
    - destroy
    - syntax
    - create
    - prepare
    - converge
    - idempotence
    - verify
    - destroy
# Change User Description Committed
#4 32894 Russell C. Jackson (Rusty) Add group resource guardrails to perforce-sdp-install; inventory cleanup

Guardrails (gated on guardrails_enabled, commit server):
- New group_limits phase (thin orchestrator + group_limits/ subdir:
  deploy_scripts, set_limits, populate) included from main.yml. Templates the
  SDP keep_group_unset.py trigger and update_limits.py from inventory so no
  group/user name is hardcoded; sets Max* on each managed group via the new
  idempotent files/manage_p4group.py helper; populates the limits group once
  (marker-guarded). No new cron -- the SDP's hourly master cron maintains
  membership.
- Every group name is its own variable (p4_baseline_group, p4_integrators_group,
  p4_unlimited_group, p4_admins_group, p4_replicas_group); p4_group_limits is a
  list of {name, limits}. Naming convention in group_vars/main; per-environment
  values + enable flag in each commit server's host_vars; safe fallbacks in
  defaults.
- Molecule: install scenario now runs the guardrails phase after
  configure_new_server and verifies the scripts are deployed and the
  limits/p4-unlimited groups carry the expected values. README + docs updated.

Inventory cleanup:
- Removed the 2kgla1tst2 and la1v-rjackson commit hosts (host_vars + inventory).
- Renamed the top-level inventory group central -> main (group_vars dir moved,
  references updated across inventory, molecule, README, CLAUDE.md).

ansible-lint production-clean; playbooks syntax-check; helper/templates compile.
#3 32879 Russell C. Jackson (Rusty) Harness: tolerate optional/absent scripts + accept ccheck PASS (Grade A or B)
#2 32876 Russell C. Jackson (Rusty) Make both ansible roles idempotent (full converge re-runs cleanly)

Existence gate:
- main.yml: stat /p4/common/bin/p4_vars -> sdp_installed fact; gate the
  destructive cleanup (wipe sdp folder + crontab) on 'not sdp_installed' so a
  re-converge skips wipe/reinstall and only reconciles idempotent config.

Run-once installers gated with creates/checks:
- run_mkdirs.sh: creates /p4/common/bin/p4_vars (drop changed_when:true).
- pyenv: drop changed_when on the creates-guarded bootstrap; add creates for the
  Python build; gate p4python install on 'pip3 show p4python'.
- monitoring prometheus.yml: gate the p4prometheus install script on
  creates /usr/local/bin/p4prometheus.

changed_when:true lies fixed:
- login.yml: gate admin/service logins on 'p4 login -s' (only log in when no
  valid ticket); use command for the no-shell status check.
- network_interface.yml: ifup gated on the interface not already being UP.

touch/cron idempotence:
- authorized_keys touch: modification_time/access_time preserve.
- cron/common.yml: remove 'crontab -r' (cron/cronvar modules manage entries
  idempotently by name; cron.yml is now the authoritative crontab manager).
- install/crontab.yml removed + its include dropped: the SDP-generated p4.crontab
  load was redundant (cron.yml's reset discarded it every run).
- packages.yml: apt update_cache cache_valid_time=3600.

Molecule: configure_new_server gated behind a marker in the install converge and
monitoring prepare; re-added the 'idempotence' step to both scenarios'
test_sequence. ansible-lint production-clean; all playbooks syntax-check.
#1 32873 Russell C. Jackson (Rusty) Add full-integration Molecule scenarios for both ansible roles

roles/{perforce-sdp-install,perforce-sdp-monitoring}/molecule/default/ each with
molecule.yml + prepare.yml + converge.yml + verify.yml. Uses the docker driver
with geerlingguy systemd images on Ubuntu 22.04 and Rocky 9 (Debian + RedHat/EL).

- install: prepare creates SDP volume dirs; converge runs the role (fresh SDP
  install -> p4d up) then configure_new_server.sh; verify asserts the service is
  active, p4 info reports ServerID master, and runs the SDP functional test
  harness (run_sdp_tests).
- monitoring: prepare brings up + configures p4d via the install role; converge
  applies the monitoring role; verify checks the probe scripts/cron are deployed
  and runs p4_healthcheck.sh, asserting p4_up=1 against the live server.

Idempotence step omitted (a full p4d install is not idempotent). README documents
prerequisites and usage. Validated with ansible-playbook --syntax-check and
ansible-lint (production profile clean for both the scenarios and the whole
project).