基于输入值的ansible jinja2模板文件创建

Posted

技术标签:

【中文标题】基于输入值的ansible jinja2模板文件创建【英文标题】:ansible jinja2 template file creation based on input values 【发布时间】:2020-11-17 01:58:00 【问题描述】:

我想创建一个文件 application.properties 文件并将其复制到特定位置。我使用相同的模板模块。但我想根据逗号分隔的输入 IP 地址计数/值创建文件内容

文件的内容应该在下面。

conf_pg_hba_replication.connection=主机复制oracle IP1/32 信任\n主机复制oracle IP2/32 信任\n主机复制oracle IP3/32......... ....

所以我希望使用基于逗号分隔的输入 IP 地址值的动态内容创建我的文件。

如果我输入的ip值为127.0.0.1,123.123.123.123 文件内容应该是

conf_pg_hba_replication.connection=主机复制 oracle 127.0.0.1/32 信任\n主机复制 oracle 123.123.123.123/32 信任

所以同样我需要创建文件的内容。

请帮帮我。

---
- name: pp
  hosts: localhost
  tasks:
   - name: pp
     template:
      src: pp.j2
      dest: pp.properties
      newline_sequence: \n

-bash-4.2$ cat pp.j2
conf_pg_hba_replication.connection=host    replication     oracle       slave_ip/32      trust

我通过一个变量将 ips 列表传递给 ansible playbook,如下所示 ansible-playbook postgres.yml -e "ips_list=ip1,ip2,ip3"

【问题讨论】:

如何加载ips列表? 我通过一个变量将它传递给 ansible playbook,ansible-playbook postgres.yml -e "ips_list=ip1,ip2,ip3" 这不应该是评论,而是对您的问题的编辑。当您使用它时,您还可以正确格式化您的第一个代码块以使其更具可读性。 谢谢,编辑了问题。我还没有开始编码,需要输入来编写 jinja2 模板来实现。 请正确格式化您的代码,无论是块还是内联。编辑器窗口顶部有格式按钮,屏幕右侧有帮助。另外,请注意,SO 往往以相反的方式发挥作用:您编写代码并展示您所做的工作,并就您在尝试制定解决方案时面临的特定问题提出问题。这里很短很容易,所以我还是决定回答。但请记住这一点,以备将来的问题。 【参考方案1】:

您在 ansible 命令行上将逗号分隔的 ip 列表作为额外的 var 传递。

要满足您的要求,您需要:

    使用split 函数将包含逗号分隔列表的字符串转换为真实列表。 循环遍历模板中的列表以输出结果。

这实际上可以在一个任务中完成。鉴于以下templates/pp.j2...

% for slave_ip in ip_list %
conf_pg_hba_replication.connection=host    replication     oracle         slave_ip /32      trust
% endfor %

还有下面的剧本……

---
- name: template our pp file
  hosts: localhost
  gather_facts: false
  tasks:
    - name: pp
      template:
        src: pp.j2
        dest: pp.properties
      vars:
        ip_list: " ip_list_raw.split(',') "

你这样称呼...

ansible-playbook test.yml -e "ip_list_raw=127.0.0.1,1.2.3.4,5.6.7.8"

你会得到以下结果

$ cat pp.properties 
conf_pg_hba_replication.connection=host    replication     oracle        127.0.0.1/32      trust
conf_pg_hba_replication.connection=host    replication     oracle        1.2.3.4/32      trust
conf_pg_hba_replication.connection=host    replication     oracle        5.6.7.8/32      trust

请注意,您也可以在模板任务中删除带有split 的 vars 声明,方法是在命令行上直接将 ips 列表作为 json 数组传递

ansible-playbook test.yml -e '"ip_list":["127.0.0.1","1.2.3.4","5.6.7.8"]'

或者甚至从外部 yaml 文件加载它们,例如my_ip_list.yml

---
ip_list:
  - 127.0.0.1
  - 1.2.3.4
  - 5.6.7.8

像这样:

ansible-playbook test.yml -e @my_ip_list.yml'

【讨论】:

非常感谢,我的输出属性文件应采用以下格式conf_pg_hba_replication.connection=host replication oracle 127.0.0.1/32 trust \nhost replication oracle 1.2.3.4/32 trust\nhost replication oracle 5.6.7.8/32 trust 我在下面尝试并能够以某种方式获得,我正在寻找一行中的输出和 \n 作为每个条目的分隔符conf_pg_hba_replication.connection=% for slave_ip in ip_list % host replication oracle slave_ip /32 trust % endfor % \n 在您查看文件时显示为正常的换行符...... 下面是输出下面是输出conf_pg_hba_replication.connection=host replication oracle 127.0.0.1/32 trust host replication oracle 1.2.3.4/32 trust host replication oracle 5.6.7.8/32 trust 酷,如果我可以忽略文件中的 \n 并继续进行上述更改,可以吗?假设如果我们将 \n 保留在单行中,则两个文件相同,并删除 \n 并具有不同的行。【参考方案2】:
---
     - name: check for postgresql standby
       command: " service  postgres-check-standby"
       ignore_errors: yes
       register: check_standby
     - set_fact:
         is_standby: "N"
       when:
          - '"Error: Cannot get status of postgres server" in check_standby.stdout or "Error: Postgres-Server reports being" in check_standby.stdout'
          - '" pg_last_xlog_receive_location \n-------------------------------\n \n(1 row)" in check_standby.stdout'
     - set_fact:
         is_standby: "Y"
       when:
          - '"postgres-server is slave/standby" in check_standby.stdout or "Error: Cannot get status of postgres server" in check_standby.stdout'
          - '" pg_last_xlog_receive_location \n-------------------------------\n \n(1 row)" not in check_standby.stdout'
     - set_fact:
         is_standby: "D"
       when:
          - '"ERROR: postgres server is down or does not seem be standby" in check_standby.stdout'
          - '"Is the server running locally and accepting" in check_standby.stderr'
     - name: print if standby
       command: echo "postgres-server is slave/standby"
       when: is_standby == "Y"
     - name: print if not standby
       command: echo "postgres-server is not slave/standby"
       when: is_standby == "N"
     - name: print if component is down
       command: echo "postgresql component is down"
       when: is_standby == "D"

---
     - name: check for postgresql master
       command: " service  postgres-check-master"
       ignore_errors: yes
       register: check_master
     - set_fact:
        is_master: "Y"
       when:
          - '" pg_current_xlog_location \n--------------------------\n \n(1 row)" not in check_master.stdout'
          - '"postgres-server is master" in check_master.stdout or "Cannot get status of postgres server" in check_master.stdout'
     - set_fact:
        is_master: "N"
       when:
          - '"postgres server is down or does not seem be" in check_master.stdout'
          - '"ERROR:  recovery is in progress" in check_master.stderr'
     - set_fact:
        is_master: "D"
       when: 
          - '"postgres server is down or does not seem be" in check_master.stdout'
          - '"Is the server running locally and accepting" in check_master.stderr'
     - name: print if master
       command: echo "postgres-server is master"
       when: is_master == "Y"
     - name: print if not master
       command: echo "postgres-server is not master"
       when: is_master == "N"
     - name: print if component is down
       command: echo "postgresql component is down"
       when: is_master == "D"

---
        - name: check postgresql status
          command: " service  status"
          ignore_errors: yes
          register: postgresql_status
        - name: start if its down
          command: " service  start"
          when:
          - 'postgresql_status is failed or postgresql_status.rc != 0 or "apigee-service: apigee-postgresql: OK" not in postgresql_status.stderr'
        - name: validate it is a standby node
          include: check_standby.yml
        - fail:
            msg: postgres-server is not standby or down - please check"
          when: is_standby != "Y"
        - name: get ip address of old_master
          shell: host OLD_MASTER_FQDN | awk -F"has address " 'print$2'
          ignore_errors: yes
          register: old_master_ip
        - name: get no of octet in ip address
          shell: echo old_master_ip.stdout | sed s'/\./ /g' | wc -w
          ignore_errors: yes
          register: ip_octet_count
        - name: echo old_master_ip
          command: echo Old Master Node Ip address:- old_master_ip.stdout
          when: old_master_ip.stdout != "" and ip_octet_count.stdout == "4"
        - name: fail if unable to get ip address
          fail:
            msg: failed to get the ip address, please check and enter FQDN of old master postgres node
          when: old_master_ip.stdout == "" or ip_octet_count.stdout != "4"
        - name: Switching standby to master
          shell: " service promote-standby-to-master old_master_ip.stdout"
        - name: validate master post swap
          include: check_master.yml
        - fail:
           msg: postgresql is not master. please check microservice logs for error details.
          when: is_master != "Y"

        - name: backup existing file 
          command: "mv properties_file properties_file_backupansible_date_time.date"
          when: postgres_properties_file.stat.exists
        - name: download properties file from Bitbucket
          shell: "curl -k -v -u  username : passwd  POSTGRESQL_PROPERTIES_BB_URL?raw -o properties_file"
          args:
           warn: no
        - name: restart postgresql component
          command: " service  restart"
        - name: print Outcome
          command: echo "Successfully converted postgresql slave to master"

---
        - name: check whether node is master node
          include: check_master.yml
        - name: bring down node if master is up and running
          command: " service  stop"
          when: is_master != "D"
        - name: get ip address of new_master
          shell: host NEW_MASTER_FQDN | awk -F"has address " 'print$2'
          ignore_errors: yes
          register: new_master_ip
        - name: get slave ip
          shell: hostname -i
          ignore_errors: yes
          register: slave_ip
        - name: get no of octet in slave ip address
          shell: echo slave_ip.stdout | sed s'/\./ /g' | wc -w
          ignore_errors: yes
          register: slave_ip_octet_count
        - name: get no of octet in new master ip address
          shell: echo new_master_ip.stdout | sed s'/\./ /g' | wc -w
          ignore_errors: yes
          register: ip_octet_count_m
        - name: echo new_master_ip and slave ip
          command: " item "
          with_items:
           - echo New Master Node Ip address:- new_master_ip.stdout
           - echo Slave Ip address:- slave_ip.stdout
          when: new_master_ip.stdout != "" and ip_octet_count_m.stdout == "4" and slave_ip.stdout != "" and slave_ip_octet_count.stdout == "4"
        - name: fail if unable to get ip address
          fail:
            msg: failed to get the ip addresses, please check and enter FQDN of postgresql node
          when: new_master_ip.stdout == "" or ip_octet_count_m.stdout != "4" or slave_ip.stdout == "" or slave_ip_octet_count.stdout != "4"
        - name: create temp replication config file
          copy:
            dest: /tmp/setup_replication.txt
            content: |
              PG_MASTER=new_master_ip.stdout
              PG_STANDBY=slave_ip.stdout
            mode: 0750
        - name: comment out the conf_pg_hba_replication.connection property in postgresql properties file
          replace:
             path: "properties_file"
             regexp: 'conf_pg_hba_replication.connection='
             replace: '#conf_pg_hba_replication.connection='
             backup: yes
          when: postgres_properties_file.stat.exists
        - name: remove data folder
          file: 
            path: /opt/apigee/data/apigee-postgresql
            state: absent
        - name: perform postgresql standby replication
          shell: nohup service setup-replication-on-standby -f /tmp/setup_replication.txt >/tmp/standby_replication.log &
          register: nohup_rep
        - name: get PID of replication progress
          shell: ps -eaf|grep -i setup-replication-on-standby|grep -v grep
          ignore_errors: true
          register: PID
        - name: get PID count
          shell: ps -eaf|grep -i setup-replication-on-standby|grep -v grep|wc -l
          ignore_errors: true
          register: PID_COUNT
        - fail:
           msg: There is an issue with replication - Please check the logs.
          when: PID_COUNT.stdout == "0"
        - name: print PID of replication process
          command: " item "
          with_items:
            - "echo nohup_rep.cmd"
            - "echo PID.stdout"

【讨论】:

欢迎来到 ***!虽然此答案可能会为 OP 的需求提供解决方案,但请添加解释以使其更易于理解,不仅适用于 OP,而且适用于整个社区

以上是关于基于输入值的ansible jinja2模板文件创建的主要内容,如果未能解决你的问题,请参考以下文章

自动化运维工具-Ansible Jinja2模板

Ansible Jinja2 模板概述 --01

[RHCE学习笔记] ansible使用jinja2 生成hosts主机文件

Ansible之templates模板

ansible-playbook模板化(jinja2)

ansible自动化运维详解ansible中变量的设定使用JINJA2模板的使用以及ansible的加密控制