diff --git a/.github/workflows/create-devnet.yml b/.github/workflows/create-devnet.yml index c14755730..1df3d0f06 100644 --- a/.github/workflows/create-devnet.yml +++ b/.github/workflows/create-devnet.yml @@ -12,6 +12,11 @@ on: required: true type: string default: "2.0.0-rc.16" + deploy_tags: + description: "Ansible tags to run. Use full_deploy for full flow, or a narrower tag such as unban_hp_masternodes to resume faster." + required: true + type: string + default: "full_deploy" # Advanced options - sane defaults, only change if you know what you're doing hp_masternodes_arm_count: description: "Advanced: Number of ARM HP masternodes" @@ -52,7 +57,7 @@ on: jobs: create: name: Create Devnet - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 120 concurrency: group: "devnet-${{ github.event.inputs.devnet_name }}" @@ -112,7 +117,7 @@ jobs: - name: Install Ansible run: | python3 -m pip install --upgrade pip - python3 -m pip install ansible + python3 -m pip install ansible-core==2.16.3 jmespath - name: Install Ansible roles run: | @@ -124,6 +129,7 @@ jobs: env: DEPLOY_SERVER_KEY: ${{ secrets.DEPLOY_SERVER_KEY }} EVO_APP_DEPLOY_KEY: ${{ secrets.EVO_APP_DEPLOY_KEY }} + EVO_APP_DEPLOY_WRITE_KEY: ${{ secrets.EVO_APP_DEPLOY_WRITE_KEY }} run: | mkdir -p ~/.ssh @@ -139,6 +145,12 @@ jobs: printf '%s\n' "$EVO_APP_DEPLOY_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 + # Optional write key for pushing to configs repo + if [[ -n "$EVO_APP_DEPLOY_WRITE_KEY" ]]; then + printf '%s\n' "$EVO_APP_DEPLOY_WRITE_KEY" > ~/.ssh/id_ed25519_write + chmod 600 ~/.ssh/id_ed25519_write + fi + # SSH config cat > ~/.ssh/config << 'EOL' Host github.com @@ -168,7 +180,39 @@ jobs: TERRAFORM_DYNAMODB_TABLE=$TERRAFORM_DYNAMODB_TABLE EOF + - name: Check for existing devnet configs + id: existing_configs + run: | + git clone git@github.com:dashpay/dash-network-configs.git /tmp/dash-network-configs-source + + FOUND=0 + MISSING=0 + for ext in yml tfvars inventory; do + SRC="/tmp/dash-network-configs-source/$NETWORK_NAME.$ext" + if [[ -f "$SRC" ]]; then + FOUND=$((FOUND + 1)) + else + MISSING=$((MISSING + 1)) + fi + done + + if [[ $FOUND -eq 3 ]]; then + echo "resume_mode=true" >> "$GITHUB_OUTPUT" + echo "Found existing config set for $NETWORK_NAME. Reusing config repo files and skipping Terraform." + cp "/tmp/dash-network-configs-source/$NETWORK_NAME.yml" networks/ + cp "/tmp/dash-network-configs-source/$NETWORK_NAME.tfvars" networks/ + cp "/tmp/dash-network-configs-source/$NETWORK_NAME.inventory" networks/ + elif [[ $FOUND -eq 0 ]]; then + echo "resume_mode=false" >> "$GITHUB_OUTPUT" + echo "No existing config set found for $NETWORK_NAME. Running full create flow." + else + echo "Error: Partial config set found for $NETWORK_NAME in dash-network-configs." + ls -la /tmp/dash-network-configs-source/$NETWORK_NAME.* 2>/dev/null || true + exit 1 + fi + - name: Generate network configs + if: steps.existing_configs.outputs.resume_mode != 'true' env: MN_AMD: ${{ github.event.inputs.masternodes_amd_count }} MN_ARM: ${{ github.event.inputs.masternodes_arm_count }} @@ -236,9 +280,21 @@ jobs: DISK_SIZE: ${{ github.event.inputs.hpmn_disk_size }} run: | TFVARS_FILE="networks/$NETWORK_NAME.tfvars" + DEFAULT_MAIN_DOMAIN="networks.dash.org" # Read current value from file (empty if not set) CURRENT_SIZE=$(grep -oP 'hpmn_node_disk_size\s*=\s*\K[0-9]+' "$TFVARS_FILE" 2>/dev/null || echo "") + CURRENT_MAIN_DOMAIN=$(grep -oP 'main_domain\s*=\s*"\K[^"]*' "$TFVARS_FILE" 2>/dev/null || echo "") + + # Generated tfvars leaves main_domain empty; ensure ACM DNS names are valid. + if [[ -z "$CURRENT_MAIN_DOMAIN" ]]; then + echo "Setting main_domain to $DEFAULT_MAIN_DOMAIN..." + if grep -q '^main_domain\s*=' "$TFVARS_FILE"; then + sed -i "s|^main_domain\\s*=.*|main_domain = \"$DEFAULT_MAIN_DOMAIN\"|" "$TFVARS_FILE" + else + echo "main_domain = \"$DEFAULT_MAIN_DOMAIN\"" >> "$TFVARS_FILE" + fi + fi if [[ -n "$DISK_SIZE" && "$DISK_SIZE" != "$CURRENT_SIZE" ]]; then if [[ ! "$DISK_SIZE" =~ ^[0-9]+$ ]]; then @@ -257,24 +313,49 @@ jobs: cat "$TFVARS_FILE" - name: Deploy devnet (Terraform + Ansible) + env: + TF_IN_AUTOMATION: "true" + TF_CLI_ARGS_apply: "-auto-approve" + DEPLOY_TAGS: ${{ github.event.inputs.deploy_tags }} run: | echo "============================================" echo "Deploying $NETWORK_NAME" + echo "Ansible tags: $DEPLOY_TAGS" echo "============================================" chmod +x ./bin/deploy # GitHub Actions checks out a detached HEAD; bypass branch safety check. - ./bin/deploy -f "$NETWORK_NAME" + if [[ "${{ steps.existing_configs.outputs.resume_mode }}" == "true" ]]; then + echo "Resume mode enabled. Skipping Terraform and re-running provisioning only." + ./bin/deploy -p -f --tags="$DEPLOY_TAGS" "$NETWORK_NAME" + else + ./bin/deploy -f --tags="$DEPLOY_TAGS" "$NETWORK_NAME" + fi - name: Push configs to dash-network-configs + if: always() + env: + EVO_APP_DEPLOY_WRITE_KEY: ${{ secrets.EVO_APP_DEPLOY_WRITE_KEY }} run: | # Clone the configs repo to a temp directory git clone git@github.com:dashpay/dash-network-configs.git /tmp/dash-network-configs - # Copy generated config files - cp "networks/$NETWORK_NAME.yml" /tmp/dash-network-configs/ - cp "networks/$NETWORK_NAME.tfvars" /tmp/dash-network-configs/ - cp "networks/$NETWORK_NAME.inventory" /tmp/dash-network-configs/ + # Copy generated config files if present + COPIED=0 + for ext in yml tfvars inventory; do + SRC="networks/$NETWORK_NAME.$ext" + if [[ -f "$SRC" ]]; then + cp "$SRC" /tmp/dash-network-configs/ + COPIED=$((COPIED + 1)) + else + echo "Skipping missing file: $SRC" + fi + done + + if [[ $COPIED -eq 0 ]]; then + echo "No config files found to push" + exit 0 + fi # Commit and push cd /tmp/dash-network-configs @@ -282,7 +363,19 @@ jobs: git config user.email "actions@github.com" git add . git commit -m "Add configs for $NETWORK_NAME" || echo "No changes to commit" - git push + + # Use optional write key if configured; otherwise try default key. + if [[ -n "$EVO_APP_DEPLOY_WRITE_KEY" && -f "$HOME/.ssh/id_ed25519_write" ]]; then + GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_write -o StrictHostKeyChecking=no' git push || { + echo "::warning::Failed to push configs with EVO_APP_DEPLOY_WRITE_KEY" + exit 0 + } + else + git push || { + echo "::warning::Failed to push configs (likely read-only EVO_APP_DEPLOY_KEY). Configure secret EVO_APP_DEPLOY_WRITE_KEY with write access." + exit 0 + } + fi echo "Configs pushed to dash-network-configs repo" diff --git a/.github/workflows/destroy-devnet.yml b/.github/workflows/destroy-devnet.yml index a359bafa6..43fb7f96e 100644 --- a/.github/workflows/destroy-devnet.yml +++ b/.github/workflows/destroy-devnet.yml @@ -20,7 +20,7 @@ on: jobs: destroy: name: Destroy Devnet - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 60 concurrency: group: "devnet-${{ github.event.inputs.devnet_name }}" @@ -77,7 +77,7 @@ jobs: - name: Install Ansible run: | python3 -m pip install --upgrade pip - python3 -m pip install ansible + python3 -m pip install ansible-core==2.16.3 jmespath - name: Install Ansible roles run: | @@ -89,6 +89,7 @@ jobs: env: DEPLOY_SERVER_KEY: ${{ secrets.DEPLOY_SERVER_KEY }} EVO_APP_DEPLOY_KEY: ${{ secrets.EVO_APP_DEPLOY_KEY }} + EVO_APP_DEPLOY_WRITE_KEY: ${{ secrets.EVO_APP_DEPLOY_WRITE_KEY }} run: | mkdir -p ~/.ssh @@ -104,6 +105,12 @@ jobs: printf '%s\n' "$EVO_APP_DEPLOY_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 + # Optional write key for pushing to configs repo + if [[ -n "$EVO_APP_DEPLOY_WRITE_KEY" ]]; then + printf '%s\n' "$EVO_APP_DEPLOY_WRITE_KEY" > ~/.ssh/id_ed25519_write + chmod 600 ~/.ssh/id_ed25519_write + fi + # SSH config cat > ~/.ssh/config << 'EOL' Host github.com @@ -190,12 +197,17 @@ jobs: echo "" - name: Destroy devnet + env: + TF_IN_AUTOMATION: "true" + TF_CLI_ARGS_destroy: "-auto-approve" run: | chmod +x ./bin/destroy ./bin/destroy "$NETWORK_NAME" -t="$DESTROY_TARGET" - name: Remove configs from dash-network-configs if: github.event.inputs.destroy_target == 'all' + env: + EVO_APP_DEPLOY_WRITE_KEY: ${{ secrets.EVO_APP_DEPLOY_WRITE_KEY }} run: | cd /tmp/dash-network-configs git config user.name "GitHub Actions" @@ -207,7 +219,19 @@ jobs: git rm "$NETWORK_NAME.inventory" 2>/dev/null || true git commit -m "Remove configs for $NETWORK_NAME (destroyed)" || echo "No changes to commit" - git push + + # Use optional write key if configured; otherwise try default key. + if [[ -n "$EVO_APP_DEPLOY_WRITE_KEY" && -f "$HOME/.ssh/id_ed25519_write" ]]; then + GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_write -o StrictHostKeyChecking=no' git push || { + echo "::warning::Failed to push config removal with EVO_APP_DEPLOY_WRITE_KEY" + exit 0 + } + else + git push || { + echo "::warning::Failed to push config removal (likely read-only EVO_APP_DEPLOY_KEY). Configure secret EVO_APP_DEPLOY_WRITE_KEY with write access." + exit 0 + } + fi echo "Configs removed from dash-network-configs repo" diff --git a/ansible/deploy.yml b/ansible/deploy.yml index caf71d2dc..b68a98523 100644 --- a/ansible/deploy.yml +++ b/ansible/deploy.yml @@ -1,342 +1,6 @@ --- -# Bootstrap - -- name: Remove latency on masternodes before deployment starts - hosts: masternodes,hp_masternodes - become: true - roles: - - remove_fake_latency - tags: - - full_deploy - - maintenance - -- name: Set up swap and aws environment vars - hosts: all - gather_facts: true - become: true - pre_tasks: - - name: Check if inside AWS - ansible.builtin.uri: - url: http://169.254.169.254/latest/meta-data - timeout: 2 - register: aws_uri_check - failed_when: false - - name: Set AWS environment variable - ansible.builtin.set_fact: - is_aws_environment: '{{ aws_uri_check.status == 200 }}' - roles: - - role: aws - when: is_aws_environment - - swap - tags: - - full_deploy - - infra_setup - -- name: Setup VPN - hosts: vpn - become: true - roles: - - role: openvpn - when: openvpn_enabled - tags: - - full_deploy - - infra_setup - - vpn - -- name: Setup jq, Python, CWAgent and Docker - hosts: all - become: true - pre_tasks: - - name: Update apt cache and install jq - ansible.builtin.apt: - pkg: - - jq - - unzip - update_cache: true - vars: - pip_package: python3-pip - pip_install_packages: - - name: docker - version: "6.0.1" - - name: docker-compose - version: "1.29.2" - - name: requests - version: "2.31.0" - roles: - - geerlingguy.pip - - role: geerlingguy.docker - vars: - docker_apt_arch: "{{ 'amd64' if ansible_architecture == 'x86_64' else 'arm64' }}" - docker_install_compose: false - docker_users: - - ubuntu - - docker_options - - eternal_terminal - - cwagent - tags: - - full_deploy - - infra_setup - -- name: Configure tcpdump - hosts: all - become: true - roles: - - role: tcpdumpd - when: dashd_network_logging != 0 - tags: - - full_deploy - - infra_setup - -- name: Setup logs - hosts: logs_nodes - become: true - roles: - - elastic_stack - - metricbeat - tags: - - full_deploy - - infra_setup - -- name: Setup load tester - hosts: load_test - become: true - roles: - - role: protobuf_compiler - - role: load_tool - tags: - - full_deploy - - infra_setup - -- name: Setup metrics - hosts: metrics - become: true - roles: - - metrics - - metricbeat - tags: - - full_deploy - - infra_setup - -- name: Set up miners - hosts: miners - become: true - roles: - - role: dash_cli - - role: dashd - tags: - - dashd - - core_filebeat - - metricbeat - tags: - - full_deploy - -- name: Set up mixers - hosts: mixer_nodes - become: true - roles: - - role: dash_cli - - role: dashd - tags: - - dashd - - core_filebeat - - metricbeat - tags: - - full_deploy - -- name: Set up core and tenderdash on seed nodes - hosts: seed_nodes - become: true - pre_tasks: - - name: Set node variables for seed nodes - ansible.builtin.set_fact: - node: "{{ seed_nodes[inventory_hostname] }}" - mode: "seed" - tags: always - when: inventory_hostname in seed_nodes - roles: - - role: dash_cli - - role: dashd - dashd_listen: true - dashd_zmq: true - dashd_indexes: true - tags: - - dashd - - role: tenderdash - - core_filebeat - - metricbeat - tags: - - full_deploy - - update_seed_nodes - -- name: Set up core on masternodes - hosts: masternodes - become: true - pre_tasks: - - name: Check inventory for masternodes - ansible.builtin.set_fact: - masternode: "{{ masternodes[inventory_hostname] }}" - tags: always - when: inventory_hostname in masternodes - - name: Fail if no masternodes present - ansible.builtin.fail: - msg: Masternode not defined in network config - when: masternode is not defined - roles: - - role: dash_cli - - role: dashd - dashd_listen: true - dashd_zmq: true - dashd_indexes: true - tags: - - dashd - - mn_status_report - - core_filebeat - - metricbeat - tags: - - full_deploy - - core_update - - update_masternodes - - -# Start network - -- name: Generate first block to leave IBD mode - hosts: seed-1 - become: true - roles: - - role: generate_firstblock - when: dash_network == "devnet" or dash_network == "regtest" - tags: - - full_deploy - -- name: Start miner - hosts: miners - become: true - roles: - - role: dashd_generate_miner - when: dash_network != "mainnet" - tags: - - full_deploy - -- name: Setup faucet and insight - hosts: web - become: true - roles: - - multifaucet - - role: dash_cli - - role: dashd - dashd_indexes: true - dashd_zmq: true - dashd_listen: true - - insight - - role: status_dashboard - when: dash_network == "devnet" - - core_filebeat - - metricbeat - tags: - - full_deploy - - web - -- name: Deploy status monitoring to masternodes - hosts: masternodes,hp_masternodes - become: true - gather_facts: false - strategy: free - roles: - - status_monitoring - tags: - - full_deploy - - dashmate_deploy - - status_dashboard - -- name: Set up wallets - hosts: wallet_nodes - become: true - roles: - - role: dash_cli - - role: dashd - dashd_indexes: true - dashd_zmq: true - enable_wallet: true - tags: - - dashd - - core_filebeat - - metricbeat - tags: - - full_deploy - - core_update - -# Register masternodes and set sporks - -- name: Register masternodes - hosts: wallet_nodes - become: true - roles: - - role: mn_init - mnlist: "{{ masternodes }}" - funding_amount: "{{ masternode_collaterals.mn | int }}" - tags: - - full_deploy - - unban_masternodes - -- name: Update inventory with protx values - hosts: wallet_nodes - roles: - - role: mn_protx_config - mnlist: "{{ masternodes }}" - tags: - - full_deploy - - unban_masternodes - -- name: Register HP masternodes - hosts: wallet_nodes - become: true - roles: - - role: mn_init - mnlist: "{{ hp_masternodes }}" - funding_amount: "{{ masternode_collaterals.hpmn | int }}" - tags: - - full_deploy - - unban_hp_masternodes - -- name: Update inventory with HPMN protx values - hosts: wallet_nodes - roles: - - role: mn_protx_config - mnlist: "{{ hp_masternodes }}" - tags: - - full_deploy - - unban_hp_masternodes - - -- name: Fund load tester nodes - hosts: wallet_nodes - become: true - tasks: - - name: Extract load tester addresses - ansible.builtin.set_fact: - load_tester_addresses: "{{ load_testers.values() | map(attribute='wallet.address') | list }}" - when: load_testers is defined and load_testers | length > 0 - - - name: Include funding for load testers - ansible.builtin.include_tasks: ./roles/mn_fund_collateral/tasks/fund_collateral.yml - vars: - payment_targets: "{{ load_tester_addresses }}" - amount: "{{ load_tester_wallet_amount }}" - when: load_testers is defined and load_testers | length > 0 - tags: - - full_deploy - -- name: Activate sporks - hosts: wallet_nodes - become: true - roles: - - role: activate_dashd_sporks - when: dash_network != "mainnet" and dash_network != "testnet" - delegate_to: '{{ play_hosts | first }}' - tags: - - full_deploy +# TEMPORARY DEBUG MODE: resume from HP Dashmate setup # todo: partially working code causes errors in deploy, comment out for now and fix later # - name: Create governance proposals diff --git a/ansible/roles/activate_dashd_sporks/tasks/main.yml b/ansible/roles/activate_dashd_sporks/tasks/main.yml index bb299dd65..2287dc2d8 100644 --- a/ansible/roles/activate_dashd_sporks/tasks/main.yml +++ b/ansible/roles/activate_dashd_sporks/tasks/main.yml @@ -28,7 +28,7 @@ - SPORK_17_QUORUM_DKG_ENABLED - SPORK_19_CHAINLOCKS_ENABLED - SPORK_21_QUORUM_ALL_CONNECTED - when: not (active_sporks.stdout | from_json)[item] + when: not ((active_sporks.stdout | from_json).get(item, false)) changed_when: spork_update.stdout == "success" - name: Activate EHF @@ -37,4 +37,6 @@ vars: generate: spork_activation spork_name: SPORK_24_TEST_EHF - when: not (active_sporks.stdout | from_json)["SPORK_24_TEST_EHF"] + when: + - "'SPORK_24_TEST_EHF' in (active_sporks.stdout | from_json)" + - not ((active_sporks.stdout | from_json).get("SPORK_24_TEST_EHF", false)) diff --git a/ansible/roles/dashmate/tasks/build.yml b/ansible/roles/dashmate/tasks/build.yml index b7b673250..25436b07c 100644 --- a/ansible/roles/dashmate/tasks/build.yml +++ b/ansible/roles/dashmate/tasks/build.yml @@ -52,6 +52,7 @@ ansible.builtin.command: '{{ dashmate_home }}/rustup.sh -y' become: true become_user: dashmate + become_flags: '-H' when: - rustup.changed - dashmate_platform_enable @@ -73,6 +74,7 @@ cargo install wasm-bindgen-cli@0.2.86 become: true become_user: dashmate + become_flags: '-H' args: executable: /bin/bash changed_when: true @@ -110,6 +112,7 @@ - name: Clone dashmate source become: true become_user: dashmate + become_flags: '-H' ansible.builtin.git: repo: 'https://github.com/dashpay/platform' dest: '{{ dashmate_source_dir }}' @@ -132,6 +135,7 @@ ansible.builtin.command: yarn install become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_source_dir }}' creates: '{{ dashmate_source_dir }}/.yarn/unplugged' @@ -148,6 +152,7 @@ yarn workspace dash build become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_source_dir }}' executable: /bin/bash @@ -158,6 +163,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} config" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_config_result @@ -168,6 +174,7 @@ ansible.builtin.command: yarn dashmate config set dashmate.helper.docker.build.enabled true become: true become_user: dashmate + become_flags: '-H' register: build_dashmate_helper args: chdir: '{{ dashmate_source_dir }}' diff --git a/ansible/roles/dashmate/tasks/destroy_platform.yml b/ansible/roles/dashmate/tasks/destroy_platform.yml index 9a8d34421..ade6268ad 100644 --- a/ansible/roles/dashmate/tasks/destroy_platform.yml +++ b/ansible/roles/dashmate/tasks/destroy_platform.yml @@ -7,6 +7,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} reset --platform --force --hard" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_reset diff --git a/ansible/roles/dashmate/tasks/main.yml b/ansible/roles/dashmate/tasks/main.yml index 3bb030f36..a3d9e9ecc 100644 --- a/ansible/roles/dashmate/tasks/main.yml +++ b/ansible/roles/dashmate/tasks/main.yml @@ -22,6 +22,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} --version" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: current_dashmate_version @@ -255,6 +256,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} config" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_config_result @@ -266,6 +268,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} config get platform.gateway.ssl.providerConfigs.zerossl.id" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_zerossl_id_result @@ -292,6 +295,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} config get platform.gateway.ssl.providerConfigs.zerossl.id" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_zerossl_id_result_fast @@ -434,9 +438,10 @@ # .dashmate directory already created in early permission fixes section - name: Render service configs - ansible.builtin.command: "{{ dashmate_cmd }} config render" + ansible.builtin.command: "{{ dashmate_cmd }} config render {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_render_configs_result @@ -498,9 +503,10 @@ register: env_file_stat - name: Export current dashmate config - ansible.builtin.command: "{{ dashmate_cmd }} config envs" + ansible.builtin.command: "{{ dashmate_cmd }} config envs {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_envs_output @@ -524,9 +530,10 @@ skip_image_update: "{{ skip_dashmate_image_update | default(false) }}" - name: Update dashmate images - ansible.builtin.command: "{{ dashmate_cmd }} update --format=json" + ansible.builtin.command: "{{ dashmate_cmd }} update --format=json {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' register: dashmate_update args: chdir: '{{ dashmate_cwd }}' @@ -538,9 +545,10 @@ # ============================================================================ - name: Get service statuses - ansible.builtin.command: "{{ dashmate_cmd }} status services --format=json" + ansible.builtin.command: "{{ dashmate_cmd }} status services --format=json {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' changed_when: dashmate_services_status.rc == 0 args: chdir: '{{ dashmate_cwd }}' @@ -594,9 +602,10 @@ # Start all if everything is stopped (not started yet) - name: Start all dashmate services - ansible.builtin.command: "{{ dashmate_cmd }} start --verbose" + ansible.builtin.command: "{{ dashmate_cmd }} start --verbose {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_start_all @@ -611,9 +620,10 @@ # Fast deployment: each node restarts itself independently - name: Restart dashmate services (fast mode - individual restart) - ansible.builtin.command: "{{ dashmate_cmd }} restart --safe --verbose{{ '' if needs_core_restart | default(false) else ' --platform' }}" + ansible.builtin.command: "{{ dashmate_cmd }} restart --safe --verbose{{ '' if needs_core_restart | default(false) else ' --platform' }} {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_restart_all @@ -674,9 +684,10 @@ # Force start is equivalent to `docker compose up` and will replace services that have changed - name: Start not started services and replace updated services - ansible.builtin.command: "{{ dashmate_cmd }} start --force --verbose{{ '' if needs_core_restart | default(false) else ' --platform' }}" + ansible.builtin.command: "{{ dashmate_cmd }} start --force --verbose{{ '' if needs_core_restart | default(false) else ' --platform' }} {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_force_start @@ -687,9 +698,10 @@ changed_when: dashmate_force_start.rc == 0 - name: Disable dashmate helper build - ansible.builtin.command: "{{ dashmate_cmd }} config set dashmate.helper.docker.build.enabled false" + ansible.builtin.command: "{{ dashmate_cmd }} config set dashmate.helper.docker.build.enabled false {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' register: build_dashmate_helper args: chdir: '{{ dashmate_cwd }}' diff --git a/ansible/roles/dashmate/tasks/quick_update.yml b/ansible/roles/dashmate/tasks/quick_update.yml index 4b2589ae5..526845728 100644 --- a/ansible/roles/dashmate/tasks/quick_update.yml +++ b/ansible/roles/dashmate/tasks/quick_update.yml @@ -14,6 +14,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} --version" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: current_dashmate_version @@ -44,6 +45,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} restart --verbose" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_restart diff --git a/ansible/roles/dashmate/tasks/reindex.yml b/ansible/roles/dashmate/tasks/reindex.yml index 673a486e8..47f9f0873 100644 --- a/ansible/roles/dashmate/tasks/reindex.yml +++ b/ansible/roles/dashmate/tasks/reindex.yml @@ -6,6 +6,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} reindex -d --force" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_reindex diff --git a/ansible/roles/dashmate/tasks/rolling_restart.yml b/ansible/roles/dashmate/tasks/rolling_restart.yml index 9fb93b59e..e215872fa 100644 --- a/ansible/roles/dashmate/tasks/rolling_restart.yml +++ b/ansible/roles/dashmate/tasks/rolling_restart.yml @@ -4,6 +4,7 @@ ansible.builtin.command: "{{ dashmate_cmd }} restart --safe --verbose{{ '' if needs_core_restart | default(false) else ' --platform' }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_restart_all diff --git a/ansible/roles/dashmate/tasks/set_vars.yml b/ansible/roles/dashmate/tasks/set_vars.yml index 076437c06..76692a64e 100644 --- a/ansible/roles/dashmate/tasks/set_vars.yml +++ b/ansible/roles/dashmate/tasks/set_vars.yml @@ -9,3 +9,4 @@ ansible.builtin.set_fact: dashmate_cmd: "{{ 'yarn dashmate' if dashmate_branch is defined else 'dashmate' }}" dashmate_cwd: "{{ dashmate_source_dir if dashmate_branch is defined else dashmate_home }}" + dashmate_config_arg: "--config={{ dash_network_name }}" diff --git a/ansible/roles/dashmate/tasks/ssl/letsencrypt.yml b/ansible/roles/dashmate/tasks/ssl/letsencrypt.yml index 4e23733ff..c3a0c66b2 100644 --- a/ansible/roles/dashmate/tasks/ssl/letsencrypt.yml +++ b/ansible/roles/dashmate/tasks/ssl/letsencrypt.yml @@ -13,10 +13,14 @@ mode: "0750" - name: Obtain Let's Encrypt certificate for DAPI - ansible.builtin.command: "{{ dashmate_cmd }} ssl obtain --provider letsencrypt --verbose --no-retry" + ansible.builtin.command: "{{ dashmate_cmd }} ssl obtain --provider letsencrypt --verbose --no-retry {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_letsencrypt_obtain changed_when: dashmate_letsencrypt_obtain.rc == 0 + retries: 3 + delay: 20 + until: dashmate_letsencrypt_obtain.rc == 0 diff --git a/ansible/roles/dashmate/tasks/ssl/zerossl.yml b/ansible/roles/dashmate/tasks/ssl/zerossl.yml index 607880a44..ffcf400a8 100644 --- a/ansible/roles/dashmate/tasks/ssl/zerossl.yml +++ b/ansible/roles/dashmate/tasks/ssl/zerossl.yml @@ -26,9 +26,10 @@ dashmate_zerossl_ssm_certificate_id: "{{ lookup('aws_ssm', '{{ dashmate_zerossl_ssm_path }}-id', on_missing='skip') }}" - name: Set ZeroSSL certificate ID to dashmate config from SSM if not set - ansible.builtin.command: "{{ dashmate_cmd }} config set {{ dashmate_zerossl_config_path }}.id {{ dashmate_zerossl_ssm_certificate_id }}" + ansible.builtin.command: "{{ dashmate_cmd }} config set {{ dashmate_zerossl_config_path }}.id {{ dashmate_zerossl_ssm_certificate_id }} {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_zerossl_id @@ -67,9 +68,10 @@ register: zero_ssl_bundle_file - name: Obtain ZeroSSL certificate for DAPI - ansible.builtin.command: "{{ dashmate_cmd }} ssl obtain --verbose --no-retry" + ansible.builtin.command: "{{ dashmate_cmd }} ssl obtain --verbose --no-retry {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_obtain @@ -81,9 +83,10 @@ # Save new ZeroSSL information to SSM - name: Get new ZeroSSL certificate ID from dashmate config - ansible.builtin.command: "{{ dashmate_cmd }} config get {{ dashmate_zerossl_config_path }}.id" + ansible.builtin.command: "{{ dashmate_cmd }} config get {{ dashmate_zerossl_config_path }}.id {{ dashmate_config_arg }}" become: true become_user: dashmate + become_flags: '-H' args: chdir: '{{ dashmate_cwd }}' register: dashmate_zerossl_id diff --git a/ansible/roles/dashmate/templates/dashmate.json.j2 b/ansible/roles/dashmate/templates/dashmate.json.j2 index c3c571634..8cfcfc937 100644 --- a/ansible/roles/dashmate/templates/dashmate.json.j2 +++ b/ansible/roles/dashmate/templates/dashmate.json.j2 @@ -60,7 +60,7 @@ "lowPriority": false }, "quorum_list": { - "password": "{{ dashmate_core_rpc_quorum_list_password | default(dashmate_core_rpc_dashmate_password) }}", + "password": "{{ dashmate_core_rpc_quorum_list_password | default(dashmate_core_rpc_dashmate_password, true) }}", "whitelist": [ "quorum", "masternode", "getblockcount" ], diff --git a/ansible/roles/generate_blocks/tasks/main.yml b/ansible/roles/generate_blocks/tasks/main.yml index 650a4a1a4..e95890a02 100644 --- a/ansible/roles/generate_blocks/tasks/main.yml +++ b/ansible/roles/generate_blocks/tasks/main.yml @@ -70,7 +70,7 @@ ansible.builtin.command: dash-cli spork active when: generate == 'spork_activation' register: active_sporks - until: (active_sporks.stdout | from_json)[spork_name] + until: (active_sporks.stdout | from_json).get(spork_name, false) retries: 200 delay: 10 changed_when: active_sporks.rc == 0 diff --git a/ansible/roles/mn_fund_collateral/tasks/fund_collateral.yml b/ansible/roles/mn_fund_collateral/tasks/fund_collateral.yml index c804ddd85..1059ba3b8 100644 --- a/ansible/roles/mn_fund_collateral/tasks/fund_collateral.yml +++ b/ansible/roles/mn_fund_collateral/tasks/fund_collateral.yml @@ -17,14 +17,8 @@ var: payments - name: Fund listed masternodes with {{ amount ~ ' Dash'}} - ansible.builtin.command: "dash-cli -rpcwallet={{ wallet_rpc_wallet_faucet }} sendmany '' '{{ payments | to_json }}'" - register: fund_result - changed_when: fund_result.stdout | length == 64 - -- name: Produce blocks until funding transaction is confirmed - ansible.builtin.include_role: - name: generate_blocks - vars: - generate: confirmations - txid_list: "{{ [fund_result.stdout] }}" - tx_source: "{{ wallet_rpc_wallet_faucet }}" + ansible.builtin.include_tasks: "{{ playbook_dir }}/roles/mn_fund_collateral/tasks/fund_one_collateral.yml" + with_items: + - '{{ payment_targets }}' + loop_control: + loop_var: payment_target diff --git a/ansible/roles/mn_fund_collateral/tasks/fund_one_collateral.yml b/ansible/roles/mn_fund_collateral/tasks/fund_one_collateral.yml new file mode 100644 index 000000000..294a2004e --- /dev/null +++ b/ansible/roles/mn_fund_collateral/tasks/fund_one_collateral.yml @@ -0,0 +1,16 @@ +--- + +- name: Fund collateral address {{ payment_target }} with {{ amount }} Dash + ansible.builtin.command: > + dash-cli -rpcwallet={{ wallet_rpc_wallet_faucet }} sendtoaddress {{ payment_target }} {{ amount }} + register: fund_result + changed_when: fund_result.stdout | length == 64 + +- name: Produce blocks until funding transaction for {{ payment_target }} is confirmed + ansible.builtin.include_role: + name: generate_blocks + vars: + generate: confirmations + txid_list: "{{ [fund_result.stdout] }}" + tx_source: "{{ wallet_rpc_wallet_faucet }}" + when: fund_result.stdout is defined and fund_result.stdout | length > 0 diff --git a/ansible/roles/mn_init/tasks/main.yml b/ansible/roles/mn_init/tasks/main.yml index 2ec2d6713..9a8ff529a 100644 --- a/ansible/roles/mn_init/tasks/main.yml +++ b/ansible/roles/mn_init/tasks/main.yml @@ -39,10 +39,19 @@ ansible.builtin.set_fact: unimported_owner_addresses: [] +- name: Build masternode names list from mnlist + ansible.builtin.set_fact: + mn_names: >- + {{ + (mnlist | dict2items | map(attribute='key') | list) + if (mnlist is mapping) + else [] + }} + - name: Get list of info on owner addresses to be imported ansible.builtin.command: cmd: 'dash-cli -rpcwallet={{ wallet_rpc_wallet_mno }} getaddressinfo {{ mnlist[item].owner.address }}' - with_items: '{{ mnlist }}' + with_items: '{{ mn_names }}' register: owner_address_info changed_when: owner_address_info.rc == 0 @@ -63,7 +72,7 @@ - name: Get list of info on collateral addresses to be imported ansible.builtin.command: cmd: 'dash-cli -rpcwallet={{ wallet_rpc_wallet_mno }} getaddressinfo {{ mnlist[item].collateral.address }}' - with_items: '{{ mnlist }}' + with_items: '{{ mn_names }}' register: collateral_address_info changed_when: collateral_address_info.rc == 0 @@ -113,7 +122,7 @@ ansible.builtin.set_fact: registered_masternode_names: '{{ registered_masternode_names + [item] }}' when: get_protx_list_result.stdout | from_json | json_query("[?state.ownerAddress=='" + mnlist[item].owner.address + "']") - with_items: '{{ mnlist }}' + with_items: '{{ mn_names }}' - name: Registered masternodes list ansible.builtin.debug: @@ -123,7 +132,7 @@ - name: Determine new masternodes ansible.builtin.set_fact: - new_masternode_names: "{{ mnlist | difference(registered_masternode_names) }}" + new_masternode_names: "{{ mn_names | difference(registered_masternode_names) }}" - name: New masternodes list ansible.builtin.debug: @@ -179,7 +188,7 @@ - name: Populate fee payment targets ansible.builtin.set_fact: fee_target_addresses: "{{ fee_target_addresses + [mnlist[item].collateral.address] }}" - with_items: '{{ mnlist }}' + with_items: '{{ mn_names }}' - name: Check if address contains a suitable fee utxo ansible.builtin.command: > @@ -194,11 +203,30 @@ ansible.builtin.set_fact: fee_missing_addresses: "{{ fee_target_addresses | difference(funded_addresses.stdout) }}" +- name: Initialize fee payments + ansible.builtin.set_fact: + fee_payments: {} + when: fee_missing_addresses | length > 0 + +- name: Populate fee payments + ansible.builtin.set_fact: + fee_payments: "{{ fee_payments | combine({item: 1}) }}" + with_items: '{{ fee_missing_addresses }}' + when: fee_missing_addresses | length > 0 + - name: Fund 1 coin for ProTx fee - ansible.builtin.include_tasks: ./roles/mn_fund_collateral/tasks/fund_collateral.yml + ansible.builtin.command: "dash-cli -rpcwallet={{ wallet_rpc_wallet_faucet }} sendmany '' '{{ fee_payments | to_json }}'" + register: fee_fund_result + changed_when: fee_fund_result.stdout | length == 64 + when: fee_missing_addresses | length > 0 + +- name: Produce blocks until fee funding transaction is confirmed + ansible.builtin.include_role: + name: generate_blocks vars: - amount: 1 - payment_targets: '{{ fee_missing_addresses }}' + generate: confirmations + txid_list: "{{ [fee_fund_result.stdout] }}" + tx_source: "{{ wallet_rpc_wallet_faucet }}" when: fee_missing_addresses | length > 0 # Take action diff --git a/lib/configGenerator/generateAnsibleConfig.js b/lib/configGenerator/generateAnsibleConfig.js index 4143da2c1..46926504f 100644 --- a/lib/configGenerator/generateAnsibleConfig.js +++ b/lib/configGenerator/generateAnsibleConfig.js @@ -155,6 +155,7 @@ async function generateAnsibleConfig( config.dashmate_core_rpc_dashmate_password = crypto.randomBytes(32) .toString('base64').slice(0, 32); + config.dashmate_core_rpc_quorum_list_password = config.dashmate_core_rpc_dashmate_password; config.dashmate_core_rpc_dapi_password = crypto.randomBytes(32) .toString('base64').slice(0, 32); config.dashmate_core_rpc_drive_consensus_password = crypto.randomBytes(32) diff --git a/lib/configGenerator/generateTerraformConfig.js b/lib/configGenerator/generateTerraformConfig.js index 90834d311..235a62ed3 100644 --- a/lib/configGenerator/generateTerraformConfig.js +++ b/lib/configGenerator/generateTerraformConfig.js @@ -18,7 +18,7 @@ async function generateTerraformConfig( masternode_arm_count: masternodesArmCount, hp_masternode_amd_count: hpMasternodesAmdCount, hp_masternode_arm_count: hpMasternodesArmCount, - main_domain: '""', + main_domain: '"networks.dash.org"', main_host_arch: '"arm64"', create_eip: false, };