Commits (6)
from .deploy import *
import docker
from deploy import *
import drush
import behat
import docker
import core
from .environments import e
from fabric.api import lcd, cd, task, roles, env, local, run, runs_once, execute
......@@ -72,3 +71,14 @@ def release():
execute(drush.archive_dump)
execute(drush.gen_doc)
@task
def deploy(environment):
"""Deploy code and run database updates on a target Drupal environment.
"""
execute(provision, environment)
execute(push, environment, host=env.hosts)
execute(migrate, environment, host=env.hosts)
......@@ -7,8 +7,8 @@ import helpers as h
import os.path
@task
@roles('local')
def db_import(filename, role='local'):
@roles('docker')
def db_import(filename=env.db_dump, role='docker'):
"""Import and restore the specified database dump.
$ fab core.db_import:/tmp/db_dump.sql.gz
......
......@@ -29,6 +29,10 @@ env.site_admin_pass = 'admin'
env.site_subdir = 'default'
# Database dump
# To enable it, replace the boolean value with the absolute path of a gzipped SQL dump file.
env.db_dump = False
# Docker
env.docker_workspace = '/opt/sfl'
......@@ -44,3 +48,11 @@ env.container_ip = '172.17.0.0'
env.hook_post_install = ['drush fra -y', 'drush cc all']
env.hook_post_update = ['drush fra -y', 'drush cc all']
# Aegir
env.aegir_server = 'local.aegir.sfl'
env.aegir_user = 'aegir'
env.aegir_path = '/var/aegir'
env.aegir_dest_server = 'server_master'
# coding: utf-8
#
# Copyright (C) 2016 Savoir-faire Linux Inc. (<www.savoirfairelinux.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import unicode_literals
from fabric.api import lcd, cd, task, roles, env, local, run, runs_once, execute
from fabric.contrib.project import rsync_project
from fabric.colors import red, green
from fabric.utils import abort
import helpers as h
import os, glob
@task
@roles('local')
def to_aegir(environement, build='0', role='local', migrate_sites=False, delete_old_platforms=False):
"""Deploy the artifact to the aegir server.
$ fab deploy.to_aegir
:param environement: the environnement (dev, stage, production)
:param build: the number of the build in Jenkins
:param role: the role to run the task in fabric
:param migrate_sites: if aegir should migrate the sites to the new platform
:param delete_old_platforms: if aegir should remove old platforms
"""
aegir_server = env.aegir_server
aegir_user = env.aegir_user
aegir_path = env.aegir_path
aegir_dest_server = env.aegir_dest_server
build_dir = '{}/build'.format(env.workspace)
if environement == 'dev' and aegir_server and aegir_user and aegir_path and aegir_dest_server:
os.chdir(build_dir)
for artifact in glob.glob("*.tar.gz"):
# Get platform name
platform_name = '{}-{}-{}'.format(environement, artifact.split('.')[0], build)
# Remove old platforms
if h.fab_exists(role, env.site_root):
h.fab_run(role, 'rm -rf {}'.format(env.site_root))
# Untar new platform
with h.fab_cd(role, '{}/src'.format(env.workspace)):
h.fab_run(role, 'tar -xvzf {}/build/{}'.format(env.workspace, artifact))
# Rsync new platform
with h.fab_cd(role, env.workspace):
print green('Rsync {} to aegir'.format(platform_name))
h.fab_run(role, 'rsync -a src/drupal/ {}@{}:{}/platforms/{}'.format(aegir_user, aegir_server,
aegir_path, platform_name))
# Declare platform in aegir
print green('Declaring {} in aegir'.format(platform_name))
h.fab_run(
role,
"""
ssh {}@{} "drush --root='{}/platforms/{}' provision-save '@platform_{}' --context_type='platform' --web_server=@{}"
""".format(aegir_user, aegir_server, aegir_path, platform_name, platform_name, aegir_dest_server)
)
h.fab_run(
role,
"""
ssh {}@{} "drush @hostmaster hosting-import platform_{}"
""".format(aegir_user, aegir_server, platform_name)
)
h.fab_run(
role,
"""
ssh {}@{} "drush @hostmaster hosting-dispatch"
""".format(aegir_user, aegir_server)
)
if migrate_sites == 'true':
print green("Migrating all websites currently on {} to {}".format(environement, platform_name))
h.fab_run(
role,
"""
ssh {}@{} "./migrateS.drush {} {}"
""".format(aegir_user, aegir_server, environement, platform_name))
# Remove old platforms
h.fab_run(role, 'rm -rf {}'.format(env.site_root))
h.fab_run(role, 'rm -rf {}/build/{}'.format(env.workspace, artifact))
# Delete old platforms in aegir
if delete_old_platforms == 'true':
print green("Deleting old platforms on {}".format(environement))
h.fab_run(
role,
"""
ssh {}@{} "./deleteP.drush {} {}"
""".format(aegir_user, aegir_server, environement, platform_name))
else:
print red('There are not enought information to deploy the platformt')
def set_hosts(environment):
if environment not in env.aliases:
abort('Environment {} could not be found in the aliases definition.'.format(environment))
alias = env.aliases.get(environment)
env.hosts = ['{}@{}'.format(alias.get('user'), alias.get('host'))]
def is_aegir_deployment(environment):
alias = env.aliases.get(environment)
return False if 'aegir' not in alias or alias.get('aegir') else True
def target_dir(environment):
alias = env.aliases.get(environment)
if not is_aegir_deployment(environment):
return alias.get('root')
else:
platform = alias.get('aegir_platform')
return platform.format(name=env.project_name, env=environment, build=env.build_number)
@task
def provision(environment, role='local'):
"""Provision a Jenkins deployment.
"""
os.chdir(env.builddir)
set_hosts(environment)
if environment not in env.aliases:
abort('Environment {} could not be found in the aliases definition.'.format(environment))
alias = env.aliases.get(environment)
print env.roledefs
artefact = 'sfl_boilerplate-20160329_205114.tar.gz'
with h.fab_cd(role, '{}/src'.format(env.workspace)):
# Clear the currently installed platform
if h.fab_exists(role, env.site_root):
h.fab_run(role, 'rm -rf {}'.format(env.site_root))
# Extract the platform to deploy
h.fab_run(role, 'tar -xzf {}/{}'.format(env.builddir, artefact))
if not h.fab_exists(role, '{}/src/drupal'.format(env.workspace)):
abort('The archive to deploy does not contain a drupal directory.')
if not os.path.isfile('{}/src/drupal/cron.php'.format(env.workspace)):
abort('The archive to deploy does not seem to contain a valid Drupal installation.')
print green('The platform {} is now ready to be deployed to the target environment {}.'.format(artefact, environment))
@task
def pwd():
run('pwd')
@task
def push(environment, role='local'):
"""Push the platform to the target environment.
:param environment: The target environment. It must match a valid Drush alias.
"""
if environment not in env.roledefs:
abort('Environment {} could not be found in the aliases definition.'.format(environment))
target = env.aliases.get(environment)
# Push platform
platform = target_dir(environment)
print green('{}'.format(platform))
local('rsync -a src/drupal/ {}@{}:{}/{}'.format(target.get('user'), target.get('host'), target.get('root'), platform))
if is_aegir_deployment(environment):
# execute(_aegir_provision_platform, platform, target.get('aegir_path'), target.get('aegir_destsrv'), hosts=env.hosts))
_aegir_provision_platform(platform, target.get('aegir_path'), target.get('aegir_destsrv'))
def _aegir_provision_platform(platform, aegir_path, aegir_destsrv):
# Provision the platform on Aegir
run('drush --root="{}/platforms/{}" provision-save "@platform_{}" --context_type="platform" --web_server=@{}'.format(aegir_path, platform, platform, aegir_destsrv))
run('drush @hostmaster hosting-import platform_{}'.format(platform))
run('drush @hostmaster hosting-dispatch')
def _aegir_migrate_sites(environment, platform):
run('{}/migrate-sites {} {}'.format(environment, platform))
@task
@roles('local')
def migrate(environment, role='local'):
"""Migrate the Drupal database on the target environment.
:param environment: The target environment. It must match a valid Drush alias.
"""
if is_aegir_deployment(environment) and env.migrate is True:
platform = target_dir(environment)
_aegir_migrate_sites(environment, platform)
# Run the updatedb script
# with h.fab_cd(role, env.site_root):
# Run the Drupal update script
# h.fab_run(
# role,
# 'drush --yes @{} updatedb'
# .format(environment)
# )
# print green('The target environment {} is up-to-date.'.format(environment))
#
# Clear caches
# h.fab_run(
# role,
# 'drush --yes @{} cache-clear all'
# .format(environment)
# )
# print green('The caches have been cleared on the target environment {}.'.format(environment))
@task
@roles('local')
def to_server(environement, role='local'):
"""Deploy the artifact to the aegir server.
$ fab deploy.to_aegir
:param environement: the environnement (dev, stage, production)
:param role: the role to run the task in fabric
"""
build_dir = '{}/build'.format(env.workspace)
os.chdir(build_dir)
for artifact in glob.glob("*.tar.gz"):
# Remove old platforms
if h.fab_exists(role, env.site_root):
h.fab_run(role, 'rm -rf {}'.format(env.site_root))
# Untar new platform
print green('Untar new platform')
with h.fab_cd(role, '{}/src'.format(env.workspace)):
h.fab_run(role, 'tar -xvzf {}/build/{}'.format(env.workspace, artifact))
d.aliases()
with h.fab_cd(role, env.site_root):
# Set the site in maintenance mode
print green('Set the site in maitenance mode')
h.fab_run(
role,
'drush --yes @{} vset site_offline 1'
.format(environement)
)
# rsync
print green('Rsync the site source code')
h.fab_run(
role,
'drush --yes rsync --exclude=sites/all/files --exclude-files --exclude=.htaccess --delete --verbose @self @{}'
.format(environement)
)
# update data base
print green('Update site database')
h.fab_run(
role,
'drush --yes @{} updatedb'
.format(environement)
)
# Set site online
print green('Set the site online')
h.fab_run(
role,
'drush --yes @{} vset site_offline 0'
.format(environement)
)
# clean cache
print green('Clear site cache')
h.fab_run(
role,
'drush --yes @{} cache-clear all'
.format(environement)
)
# Remove old platforms
h.fab_run(role, 'rm -rf {}'.format(env.site_root))
h.fab_run(role, 'rm -rf {}/build/{}'.format(env.workspace, artifact))
print green('Deployment in {} finished'.format(environement))
......@@ -116,7 +116,7 @@ def site_install():
with h.fab_cd(role, site_root):
locale = '--locale="fr"' if env.locale else ''
h.fab_run(role, 'sudo -u {} drush site-install {} {} --db-url=mysql://{}:{}@{}/{} --site-name={} '
'--account-name={} --account-pass={} --sites-subdir={} -y'.format(apache, profile, locale,
db_user, db_pass,
......@@ -124,7 +124,13 @@ def site_install():
site_admin_name,
site_admin_pass,
site_subdir))
print green('Site installed successfully!')
print green('Site installed successfully!')
# Import db_dump if it exists.
if 'db_dump' in env and env.db_dump is not False:
h._db_import(env.db_dump)
h.hook_execute('post_install', role)
......@@ -139,13 +145,12 @@ def archive_dump(role='docker'):
with h.fab_cd(role, env.docker_site_root):
platform = '{}-{}.tar.gz'.format(env.project_name, datetime.now().strftime('%Y%m%d_%H%M%S'))
print(green('Cleaning previous archives'))
h.fab_run(role, 'rm -f {}/build/*.tar.gz'.format(env.docker_workspace))
print(green('Archiving the platform'))
h.fab_run(role, 'rm -f {}/*.tar.gz'.format(env.builddir))
print green('All tar.gz archives found in {} have been deleted.'.format(env.builddir))
h.fab_run(
role,
'drush archive-dump --destination={}/build/{} --tar-options="--exclude=.git"'.format(env.docker_workspace,
platform)
'drush archive-dump --destination={}/build/{} --tags="sflinux {}" --generatorversion="2.x" --generator="Drupalizer::fab drush.archive_dump" --tar-options="--exclude=.git"'.format(env.docker_workspace, platform, env.project_name)
)
@task
......
......@@ -200,3 +200,15 @@ def _init_db(role='docker'):
def _db_import(filename, role='local'):
"""Import and restore the specified database dump.
:param filename: a full path to a gzipped sql dump.
"""
if path.isfile(filename):
print green('Database dump {} found.'.format(filename))
fab_run(role, 'zcat {} | mysql -u{} -p{} -h{} {}'.format(filename, env.site_db_user, env.site_db_pass, env.container_ip, env.site_db_name))
print green('Database dump successfully restored.')
else:
print red('Could not find database dump at {}'.format(filename))