hosts.yml
all: children: app_myApp: hosts: host_myApp_master: ansible_host: 10.10.40.204
hosts/myApp
--- myApp_path: "/tank/secure/test_myApp/" myApp_appname: "test_myApp.jar"
group/all.yml
#ansible_connection: winrm #ansible_port: 5985 #ansible_winrm_transport: basic #ansible_winrm_server_cert_validation: ignore ansible_connection: ssh ansible_ssh_port: 22 ansible_user: ansible ansible_password: !vault | $ANSIBLE_VAULT;1.1;AES256 31323664336536....... nexus_base_url: 'https://mysite.ru/repository' nexus_username: jenkins nexus_password: !vault | $ANSIBLE_VAULT;1.1;AES256 3534534534......
Backup.yml
--- - name: "Удаляем старый архив" file: path: '{{ myService_path }}/../{{ myService_appname }}.tar.gz' state: absent register: remove_backup - name: "Архивируем папку приложения" shell: cmd: 'tar -czvf {{ myService_path }}/../{{ myService_appname }}.tar.gz --exclude={logs,properties} -C {{ myService_path }} . && echo OK' warn: false register: result failed_when: '"OK" not in result.stdout' changed_when: '"OK" in result.stdout' when: remove_backup is not failed any_errors_fatal: true
Stop_service.yml
--- - name: "Получаем информацию о сервисах в системе" ansible.builtin.service_facts: - name: "Останавливаем myService.service если он есть в ОС" systemd: name: 'myService.service' state: stopped register: myServiceInfo until: myServiceInfo.state == "stopped" retries: 5 delay: 10 when: "'myService.service' in services"
Download.yml
--- - name: "Скачиваем jar из Nexus" maven_artifact: group_id: 'com.gmware.applications' artifact_id: 'myService_group' version: '{{ myService_version | default(omit) }}' repository_url: '{{ "%s/myService-snapshots" | format(nexus_base_url) }}' username: '{{ nexus_username }}' password: '{{ nexus_password }}' dest: '{{ "%s/%s.jar" | format(myService_path, myService_appname) }}' owner: '{{ myService_user }}' group: '{{ myService_group }}' mode: '640' verify_checksum: 'always'
handler/main.yml
--- - name: "Запуск службы myService" systemd: name: myService state: restarted enabled: true daemon_reload: yes listen: "start_restart_myService"
Restart_and_check.yml
При запуске скрипта лучше сменить директорию, потом запустить, т.к. могут быть вские косяки из за системного каталога
--- - name: "Рестарт приложения" win_shell: | cd {{ myapp_path }} ./restartMyApp.ps1 async: 5 ignore_errors: yes register: start_app failed_when: start_app.started != 1 - name: "Ожидаем 5 сек" pause: seconds: 5 - name: "Проверяем запущен ли процесс" win_shell: "Get-Process -Id $(cat {{ myapp_path }}MyApp.pid) -ErrorAction SilentlyContinue | Format-Table -Property ProcessName register: check_pid failed_when: check_pid.rc < 0 - block: - name: "Процесс отсутствует, откат обновления" import_tasks: 70-rollback.yml when: check_pid.stdout == ''
--- - name: "Восстановливаем из бекапа" shell: cmd: "tar -xzvf {{ myService_path }}/backups/{{ myService_appname }}.tar.gz -C {{ myService_path }} && echo OK" warn: false register: result changed_when: '"OK" in result.stdout' failed_when: '"OK" not in result.stdout'
Бекап на винде
--- - name: "Создаем бекап" win_shell: | "Get-ChildItem -Path {{ myService_path }} -Exclude @('backups', 'logs') | Compress-Archive -Force -DestinationPath {{ myService_path }}'backups\\prev_version.zip'"
плейбук:
--- - hosts: myapp_group gather_facts: no become: yes become_method: runas become_user: "{{ ansible_user }}" roles: - myapp_deploy
main
--- - name: "Подготовка окружения" import_tasks: 10-prepare_host.yml - name: "Создаем бекап" import_tasks: 20-backup.yml - name: "Скачиваем новый jar-файл" import_tasks: 30-download.yml - name: "Обновляем конфиги" import_tasks: 40-config.yml - name: "Перезапускаем приложения" import_tasks: 50-restart_and_check.yml - block: - name: "Разворачиваем бекап" win_shell: "Expand-Archive -Force -LiteralPath {{ myapp_path }}'backups\\prev_version.zip' -DestinationPath {{ myapp_path }}" - name: "Перезапускаем приложения" import_tasks: 50-restart_and_check.yml when: not process_running
prepare
--- - name: "Создание директорий" win_file: path: '{{ item }}' state: directory loop: - '{{ myapp_path }}' - '{{ myapp_path }}logs' - '{{ myapp_path }}backups' - '{{ myapp_path }}conf'
backup
--- - name: "Создаем бекап" win_shell: "Get-ChildItem -Path {{ myapp_path }} -Exclude @('backups', 'logs') | Compress-Archive -Force -DestinationPath {{ myapp_path }}backups\\prev_version.zip"
download
--- - name: "Скачиваем jar из Nexus" maven_artifact: group_id: 'ru.myapp' artifact_id: 'myapp_id' version: '{{ myapp_version | default(omit) }}' repository_url: '{{ "%s/myapp-snapshots" | format(nexs_base_url) }}' username: '{{ nexs_username }}' password: '{{ nexs_password }}' dest: '{{ myapp_name }}' verify_checksum: 'always' delegate_to: localhost - name: "Копируем на целевой хост" copy: src: '{{ myapp_name }}' dest: '{{ "%s/%s" | format(myapp_path, myapp_name) }}'
configs
--- - name: "Скрипты запуска" win_template: src: '{{ item }}.j2' dest: '{{ "%s%s" | format(myapp_path, item) }}' loop: - start.ps1 - restart.ps1 - name: "Конфигурация приложения" win_template: src: '{{ item }}.j2' dest: '{{ "%s\conf\%s" | format(myapp_path, item) }}' loop: - config.toml - name: "Сертификаты" win_copy: src: '{{ item }}' dest: '{{ "%s%s" | format(myapp_path, item) }}' loop: - cacerts - cert.jks - _certs
restart and check
--- - name: "Перезапускаем приложение" win_shell: "{{ myapp_path }}restartmyApp.ps1" async: 5 register: start_app failed_when: start_app.started != 1 ignore_errors: true - name: "Пауза перед проверкой состояния" pause: seconds: 10 - name: "Инициализация переменной" set_fact: process_running=false - name: "Проверяем запущен ли процесс" win_shell: "Get-Process -Id $(cat {{ myapp_path }}myapp.pid) -ErrorAction SilentlyContinue | Format-Table -Property ProcessName" register: check_pid failed_when: check_pid.rc < 0 ignore_errors: true - name: "Флаг работающего процесса" set_fact: process_running=true when: check_pid.stdout != ''
start.ps1.j2
cd {{ myApp_path}} (Start-Process java -ArgumentList "-Xmx4096m -Dapplication.env=PROD -jar {{ myapp_name }}" -passthru).ID > myApp.pid
Проверка существования
Встречал вариант «when: item is not defined», но он очевидно не работает, проверка спокойно проходит
Хотя «is not defined» довольно распространено, оно похоже в цикле не применимо, она проверяет существование «item» а не то что в нее передаем, точно
А вариант с «in vars» работает даже с экстра переменными
--- - name: "10-check_vars | Проверка переменных" ansible.builtin.fail: msg: "{{ item }} is not defined" when: item not in vars loop: - my_var1 - my_var2 - my_var3
Развертывание словаря в шаблоне джинджи
В инвентори например такой словарь, точнее это список словарей
my_dict_dests: - name: "dest_1" destDir: "/mytank/DEST/dest_1" transferType: "sftp" host: "10.10.10.40" user: "---" pass: "---" - name: "dest_2" destDir: "/mytank/DEST/dest_2"
Перечисляем все имеющиеся параметры в файле шаблона j2
т.к. фактически это список словарей, поэтому нужен вложенный цикл
{% for dest in my_dict_dests%} [[DestDir]] {% for item in dest.items() %} {{ item[0] }} = "{{ item[1] }}" {% endfor %} {% endfor %}
https://docs.ansible.com/ansible/latest/plugins/lookup.html
https://github.com/morphje/ansible_pass_lookup/blob/master/README.md
Python скрипт нужно поместить в папку «lookup_plugins» в папку с ролью
- debug: msg: "{{ lookup('pass', 'example/test create=true length=42')}}" - debug: msg: "{{ lookup('custom_var', 'my_variable')}}"
https://www.dmosk.ru/miniinstruktions.php?mini=ansible-examples#files
- name: "find files" find: path: "/my-folder/" file_type: file patterns: "*.yml,*.yaml" recurse: true register: list_files - name: "show list" debug: msg: "file: {{ item }}" loop: "{{ list_files.files | map(attribute='path') | list }}"