Skip to content

Updating the switchover_patroni_leader ansible runbook to update the leader

What

Updating the switchover_patroni_leader ansible runbook to update the leader with accurate tags on a old leader

Why

Original Code - https://gitlab.com/gitlab-com/gl-infra/db-migration/-/blob/master/dbre-toolkit/switchover_patroni_leader.yml?ref_type=heads#466~489

    # Perform tasks after switchover
    ####################################################################

    - name: "[Post-Switchover] Prevent former patroni leader from being read from before it is in streaming mode - Step 1 Formatting Tags"
      lineinfile:
        path: "{{ patroni_config_file }}"
        regexp: '^tags: \{'
        line: 'tags:'
      when:
        - original_patroni_leader_name is defined
        - inventory_hostname == original_patroni_leader_name

    - name: "[Post-Switchover] Prevent former patroni leader from being read from before it is in streaming mode - Step 2 Adding nofailover and noloadbalance"
      lineinfile:
        path: "{{ patroni_config_file }}"
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
        insertafter: '^tags:'
      loop:
        - { regexp: '^nofailover:', line: '  nofailover: true' }
        - { regexp: '^noloadbalance:', line: '  noloadbalance: true' }
      when:
        - original_patroni_leader_name is defined
        - inventory_hostname == original_patroni_leader_name

Problems:

  • insertafter limitation: The insertafter: '^tags:' only works if the lines don't already exist. If either nofailover or noloadbalance already exists in the file, the regexp will match and update them in place, potentially not under the tags: section.
  • No validation of tags: section existence: If tags: doesn't exist in the config file, the task will fail or insert the lines in the wrong location.
  • Issues with '^nofailover:' and '^noloadbalance:':
    1. Doesn't account for indentation: The ^ anchor matches the start of the line, but in YAML files under a tags: section, these keys are typically indented with spaces. So a line like nofailover: true would NOT match '^nofailover:'.
    2. Will only match if at column 0: This regex only matches if nofailover: or noloadbalance: appears at the very beginning of the line with no leading whitespace.
    • If the tags already exist with proper indentation (e.g., nofailover: false), the regex won't match them
    • The insertafter will then add a duplicate line: nofailover: true
    • You'll end up with both lines in the file, which may cause parsing errors

What's Changed

    - name: "[Post-Switchover] Prevent former patroni leader from being read from before it is in streaming mode"
      block:
        - name: "Format tags section"
          lineinfile:
            path: "{{ patroni_config_file }}"
            regexp: '^tags: \{'
            line: 'tags:'
        
        - name: "Add nofailover and noloadbalance tags"
          lineinfile:
            path: "{{ patroni_config_file }}"
            regexp: "{{ item.regexp }}"
            line: "{{ item.line }}"
            insertafter: '^tags:'
            state: present
            create: no
          loop:
            - { regexp: '^[\s]*nofailover[\s]*:', line: '  nofailover: true' }
            - { regexp: '^[\s]*noloadbalance[\s]*:', line: '  noloadbalance: true' }
      when:
        - original_patroni_leader_name is defined
        - inventory_hostname == original_patroni_leader_name

Key features:

  1. Uses block: Groups both tasks under a single when condition
  2. Preserves existing values: The regexp patterns will match existing tags and update them with line content. If you want to preserve existing values and only add if missing, see alternative below.
  3. Use blockinfile or ensure tags: section exists first, then add the nested values to guarantee proper structure.
  4. The ^\s* pattern matches the start of the line followed by zero or more whitespace characters, making it work whether the keys are indented or not.

Related Issue : gitlab-com/gl-infra/data-access/dbo/dbo-issue-tracker#601 (closed)

Edited by Vamshidhar Poralla

Merge request reports

Loading