ANSIBLE-PROJECT-DEPLOY a re-usable Ansible role to deploy projects
May 10, 2015
ANSIBLE-PROJECT-DEPLOYa re-usable Ansible role to deploy projects
ABOUT US
2
Ramon de la Fuente @f_u_e_n_t_e
Jasper N. Brouwer @jaspernbrouwer
Future500 B.V.
THE PROBLEM
3
THE PROBLEM• Continuous deployment
• Easy maintenance of the deploy procedure.
• Small learning curve.
• Reuse between projects with little effort.
4
WHAT IS A DEPLOY?
5
WHAT IS A DEPLOY?Directory structure:
.
!"" releases | !"" 20140415234508 | #"" 20140415235146 !"" shared | !"" sessions | !"" source | #"" uploads #"" current -> releases/20140415235146
6
WHAT IS A DEPLOY?Directory structure:
.
!"" releases | !"" 20140415234508 | #"" 20140415235146 !"" shared | !"" sessions | !"" source | #"" uploads #"" current -> releases/20140415235146
7
WHAT IS A DEPLOY?1. Update the codebase + configuration
8
WHAT IS A DEPLOY?1. Update the codebase + configuration
2. Install dependencies
9
WHAT IS A DEPLOY?1. Update the codebase + configuration
2. Install dependencies
3. Preserve shared resources
10
WHAT IS A DEPLOY?1. Update the codebase + configuration
2. Install dependencies
3. Preserve shared resources
4. Build tasks
11
WHAT IS A DEPLOY?1. Update the codebase + configuration
2. Install dependencies
3. Preserve shared resources
4. Build tasks
5. Finalize
12
THE ROLE
13
https://galaxy.ansible.com/list#/roles/732project_deploy
ROLE WALKTHROUGH
14
ROLE WALKTHROUGH! Deploy module variables: ! deploy: project_path current_path releases_path shared_path last_release last_release_path new_release new_release_path unfinished_filename !!
15
ROLE WALKTHROUGH! Deploy module variables: ! deploy: project_path: /path/to/project/ current_path: /path/to/project/current releases_path: /path/to/project/releases shared_path: /path/to/project/shared last_release: 20140415234508 last_release_path: /path/to/project/releases/20140415234508 new_release: 20140415235146 new_release_path: /path/to/project/releases/20140415235146 unfinished_filename: DEPLOY_UNFINISHED Used as: {{ deploy.new_release }}
16
1. UPDATE THE CODEBASE!- name: Clone project files git: repo={{ project_git_repo }} dest={{ project_source_path }} version={{ project_version }} when: project_deploy_strategy == 'git' !- name: Rsync project files synchronize: src={{ project_local_path }} dest={{ project_source_path }} rsync_timeout={{ project_deploy_synchronize_timeout }} recursive=yes when: project_deploy_strategy == 'synchronize' !
17
1. UPDATE THE CODEBASE!- name: Clone project files git: repo={{ project_git_repo }} dest={{ project_source_path }} version={{ project_version }} when: project_deploy_strategy == 'git' !- name: Rsync project files synchronize: src={{ project_local_path }} dest={{ project_source_path }} rsync_timeout={{ project_deploy_synchronize_timeout }} recursive=yes when: project_deploy_strategy == 'synchronize' !
18
1. UPDATE THE CODEBASE!- name: Clone project files git: repo={{ project_git_repo }} dest={{ project_source_path }} version={{ project_version }} when: project_deploy_strategy == 'git' !- name: Rsync project files synchronize: src={{ project_local_path }} dest={{ project_source_path }} rsync_timeout={{ project_deploy_synchronize_timeout }} recursive=yes when: project_deploy_strategy == 'synchronize' !
19
1. UPDATE THE CODEBASE!- name: Write unfinished file file: path={{ project_source_path }}/{{ deploy.unfinished_filename }} state=touch !- name: Copy files to new build dir command: "cp -pr {{ project_source_path }} {{ deploy.new_release_path }}" !- name: Remove unwanted files/folders from new release file: path={{ deploy.new_release_path }}/{{ item }} state=absent with_items: project_unwanted_items
20
1. UPDATE THE CONFIG FILES!- name: Copy project files copy: src={{ item.src }} dest={{ deploy.new_release_path }}/{{ item.dest }} mode={{ item.mode|default('0644') }} with_items: project_files !- name: Copy project templates template: src={{ item.src }} dest={{ deploy.new_release_path }}/{{ item.dest }} mode={{ item.mode|default('0644') }} with_items: project_templates
21
2. INSTALL DEPENDENCIES!- name: Do composer install command: "{{ project_command_for_composer_install }} chdir=…" environment: project_environment when: project_has_composer !- name: Do npm install command: "{{ project_command_for_npm_install }} chdir=…" environment: project_environment when: project_has_npm !- name: Do bower install command: "{{ project_command_for_bower_install }} chdir=…" environment: project_environment when: project_has_bower
22
2. INSTALL DEPENDENCIES!- name: Do composer install command: "{{ project_command_for_composer_install }} chdir=…" environment: project_environment when: project_has_composer !- name: Do npm install command: "{{ project_command_for_npm_install }} chdir=…" environment: project_environment when: project_has_npm !- name: Do bower install command: "{{ project_command_for_bower_install }} chdir=…" environment: project_environment when: project_has_bower
23
3. SHARED RESOURCES!- name: Ensure shared sources are present file: "path='{{ deploy.shared_path }}/{{ item.src }}' state={{ item.type }}“ with_items: project_shared_children !- name: Ensure shared paths are absent file: "path='{{ deploy.new_release_path }}/{{ item.path }}' state=absent" with_items: project_shared_children !- name: Create shared symlinks file: path='{{ deploy.new_release_path }}/{{ item.path }}' src='{{ deploy.shared_path }}/{{ item.src }}' state=link" with_items: project_shared_children
24
4. BUILD STEPS!- name: Run post_build_commands in the new_release_path command: "{{ item }} chdir={{ deploy.new_release_path }}" with_items: project_post_build_commands environment: project_environment
25
4. BUILD STEPS!- name: Run post_build_commands in the new_release_path command: "{{ item }} chdir={{ deploy.new_release_path }}" with_items: project_post_build_commands environment: project_environment
26
! project_post_build_commands: - "app/console cache:clear" - "app/console assets:install" - "app/console assetic:dump"
5. FINALIZE!- name: Remove unfinished file file: path={{ deploy.new_release_path }}/{{ deploy.unfinished_filename }} state=absent when: project_finalize !- name: Finalize the deploy file: src={{ deploy.new_release_path }} dest={{ deploy.current_path }} state=link when: project_finalize
27
28
IT’S NOT COMPLICATED!• Only 75 lines
• Number of tasks: 18
• Variables to configure: 24
29
EXAMPLE PLAYBOOK
30
EXAMPLE PLAYBOOK!- name: Deploy the application hosts: production remote_user: "{{ production_deploy_user }}" sudo: no ! vars: project_root: "{{ sweetlakephp_root }}" project_git_repo: "{{ sweetlakephp_github_repo }}" project_deploy_strategy: git
31
EXAMPLE PLAYBOOK!- name: Deploy the application hosts: production remote_user: "{{ production_deploy_user }}" sudo: no ! vars: project_root: "{{ sweetlakephp_root }}" project_git_repo: "{{ sweetlakephp_github_repo }}" project_deploy_strategy: git ! project_environment: SYMFONY_ENV: "prod"
32
EXAMPLE PLAYBOOK! project_environment: SYMFONY_ENV: "prod" ! project_shared_children: - path: "/app/sessions" src: "sessions" - path: "/web/uploads" src: "uploads" ! project_templates: - name: parameters.yml src: "templates/parameters_prod.yml.j2" dest: "/app/config/parameters_prod.yml" !
33
EXAMPLE PLAYBOOK! project_environment: SYMFONY_ENV: "prod" ! project_shared_children: - path: "/app/sessions" src: "sessions" - path: "/web/uploads" src: "uploads" ! project_templates: - name: parameters.yml src: "templates/parameters_prod.yml.j2" dest: "/app/config/parameters_prod.yml" !
34
EXAMPLE PLAYBOOK! project_has_composer: yes ! project_post_build_commands: - "php vendor/sensio/…/DistributionBundle/…/bin/build_bootstrap.php” - "app/console cache:clear" - "app/console doctrine:migrations:migrate --no-interaction" - "app/console assets:install" - "app/console assetic:dump" ! roles: - f500.project_deploy ! post_tasks: - name: Remove old releases deploy: "path={{ project_root }} state=clean"
35
EXAMPLE PLAYBOOK! project_has_composer: yes ! project_post_build_commands: - "php vendor/sensio/…/DistributionBundle/…/bin/build_bootstrap.php” - "app/console cache:clear" - "app/console doctrine:migrations:migrate --no-interaction" - "app/console assets:install" - "app/console assetic:dump" ! roles: - f500.project_deploy ! post_tasks: - name: Remove old releases deploy: "path={{ project_root }} state=clean"
36
THANK YOU!
37
Feedback: https://joind.in/11570
https://github.com/f500/ansible-project_deploy