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: Theinsertafter: '^tags:'
only works if the lines don't already exist. If eithernofailover
ornoloadbalance
already exists in the file, theregexp
will match and update them in place, potentially not under thetags:
section. -
No validation of
tags:
section existence: Iftags:
doesn't exist in the config file, the task will fail or insert the lines in the wrong location. - Issues with
'^nofailover:'
and'^noloadbalance:'
:-
Doesn't account for indentation: The
^
anchor matches the start of the line, but in YAML files under atags:
section, these keys are typically indented with spaces. So a line likenofailover: true
would NOT match'^nofailover:'
. -
Will only match if at column 0: This regex only matches if
nofailover:
ornoloadbalance:
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
-
Doesn't account for indentation: The
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:
-
Uses
block
: Groups both tasks under a singlewhen
condition -
Preserves existing values: The
regexp
patterns will match existing tags and update them withline
content. If you want to preserve existing values and only add if missing, see alternative below. - Use
blockinfile
or ensuretags:
section exists first, then add the nested values to guarantee proper structure. - 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