【问题标题】:Backup configuration file changes in Ansible with auto-remove of backup if file unchangedAnsible 中的备份配置文件更改,如果文件未更改,则自动删除备份
【发布时间】:2019-08-10 09:13:23
【问题描述】:

这是我想要的剧本流程:

  1. 备份我打算(可能)的远程 Linux 配置文件 调整。备份应持久保存到磁盘(在远程服务器上) 在运行我的主要更改任务之前(以防剧本崩溃 中途)。

  2. 执行几个可能会更改文件的 Ansible 任务。例如, 2 个 lineinfile 和 3 个 blockinfile 任务。

  3. 如果文件已被 (2.) 中的任务更改,我想保留我的 备份文件。否则应该删除该文件。

另外,我想对多个配置文件(大约10个)做同样的事情,例如/etc/ssh/sshd_config/etc/ntp.conf等。我希望备份代码尽可能简洁。如何以最佳方式执行步骤 (1.) 和 (3.)?

我尝试过/调查过的内容:

  • 很多文件修改中存在的backup参数 模块(lineinfile、blockinfile 等)不是最优的,因为它会 每个任务调用创建一个备份。
  • 我宁愿避免 post_tasks,因为我希望我的主要任务在一个角色中执行,而角色没有任何好的方法来执行 post_tasks(?)。
  • 我查看了开发文档并考虑了 编写模块、动作插件或回调插件。但我没有 发现任何现有的 API 钩子可以很好地将所有内容结合在一起。

下面是一个简单而详细的示例,说明如何仅针对 1 个配置文件执行此操作。如果再添加 9 个配置文件,代码会变得更大。

---
- hosts: all
  gather_facts: False
  become: yes

  tasks:
    - name: Create temporary backup of /etc/ssh/sshd_config
      copy:
        src: "/etc/ssh/sshd_config"
        remote_src: yes
        dest: "/etc/ssh/sshd_config_{{ now().strftime('%Y-%m-%d_%H_%M_%S') }}.bak"
      register: "sshd_config_backup"
      changed_when: false

    - name: Change sshd ciphers
      lineinfile:
        dest: /etc/ssh/sshd_config
        regexp: '^Ciphers '
        line: "Ciphers aes192-ctr"
      notify: "sshd config changed"

    # 3 more lineinfile/blockinfile tasks that (may) change the same file
    # name: ...
    # name: ...
    # name: ...

    # Removing backup file if not changed
    - name: Get checksum of /etc/ssh/sshd_config
      stat:
        path: "/etc/ssh/sshd_config"
        get_checksum: yes    
      register: sshd_config_stat

    - name: Remove backup of /etc/ssh/sshd_config if there are no changes
      file:
        path: "{{ sshd_config_backup.dest }}"
        state: absent
      changed_when: false
      when: sshd_config_stat.stat.checksum == sshd_config_backup.checksum

  handlers:
    - name: Reload sshd service
      listen: sshd config changed
      service:
        name: sshd
        state: reloaded

【问题讨论】:

    标签: ansible


    【解决方案1】:

    下面的剧本可能完成了你描述的工作

    - name: conf_light
      hosts: all
      gather_facts: no
      become: yes
    
      vars_files:
        - data1.yml
      vars:
        cl_backup: yes
    
      tasks:
        - name: Create time-stamp
          when: cl_backup
          set_fact:
            cl_timestamp: "{{ '%Y-%m-%d_%H_%M_%S'|strftime }}"
    
        - name: Create backup files
          when: cl_backup
          copy:
            remote_src: yes
            src: "{{ item.value.path }}"
            dest: "{{ item.value.path }}_{{ cl_timestamp }}.bak"
          loop: "{{ cl_confs|dict2items }}"
    
        - name: Configure lines in files
          lineinfile:
            path: "{{ item.0.path }}"
            regexp: "{{ item.1.regexp }}"
            line: "{{ item.1.line }}"
          loop: "{{ cl_confs|subelements('lines') }}"
          notify: "{{ item.0.handler|default(omit) }}"
          register: cl_results_lines
    
        - name: Configure blocks in files
          blockinfile:
            path: "{{ item.0.path }}"
            marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.1.marker }}"
            block: "{{ item.1.block }}"
          loop: "{{ cl_confs|subelements('blocks') }}"
          notify: "{{ item.0.handler|default(omit) }}"
          register: cl_results_blocks
    
        - name: Remove backup files that did not change
          when: cl_backup
          file:
            state: absent
            path: "{{ item }}_{{ cl_timestamp }}.bak"
          loop: "{{ cl_confs|
                    json_query('*.path')|
                    difference(cl_results_lines.results|default([])|
                    json_query('[?changed==`true`].invocation.module_args.path'))|
                    difference(cl_results_blocks.results|default([])|
                    json_query('[?changed==`true`].invocation.module_args.path'))
                    }}"
    
      handlers:
        - name: ssh reload
          service:
            name: ssh
            state: reloaded
    

    我已经在 Ubuntu 18.04 中使用以下数据对其进行了测试。 (将数据适合任何其他 Linux 应该不是问题)

    shell> cat data1.yml 
    cl_confs:
      sshd_config:
        path: /etc/ssh/sshd_config
        handler: ssh reload
        lines:
          - regexp: '^Ciphers '
            line: 'Ciphers aes192-ctr'
        blocks: []
      ssh_config:
        path: /etc/ssh/ssh_config
        lines: []
        blocks:
          - marker: 'srv1.example.com'
            block: |2
              Host srv1.example.com
                  Protocol 2
                  ForwardAgent no
    

    简单的role 似乎是个好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-05
      • 1970-01-01
      相关资源
      最近更新 更多