Unverified Commit f910b3be authored by Jon Pugh's avatar Jon Pugh Committed by GitHub

Merge pull request #31 from aegir-project/4.x-cleanup

Issue #20: Remove all 7.x-3.x code
parents 3563c850 5d2d3692
#
# CI for Aegir Hosting System
#
# For docs see http://docs.aegirproject.org
# and http://docs.aegirproject.org/en/3.x/community/release-process/#setting-up-a-gitlab-runner
# Is performed before the scripts in the stages step
before_script:
- source /etc/profile
# Defines stages which are to be executed
stages:
- build
- test
- publish
- upgradetest
#
### Stage "build"
#
build:deb:
stage: build
image: aegir/hostmaster:packaging_base
script:
- export commit=$(git log -n 1 --oneline | sed 's/ .*$//')
- export version=$(sed -ne 's/^[^(]*(\([^)]*\)).*/\1/;1p' debian/changelog)
- export new_version="${version}+${CI_BUILD_ID}.${commit}"
- dch -D unstable --newversion "$new_version" "automatic GitLab CI build ${CI_BUILD_ID}"
- dpkg-buildpackage
- mkdir build
- mv -v ../aegir3*.deb build/
- mv -v ../aegir-archive-keyring*.deb build/
- mv -v ../aegir3*.tar.gz build/
- mv -v ../aegir3*.dsc build/
- mv -v ../aegir3*.changes build/
# The files which are to be made available in GitLab as artifacts.
artifacts:
paths:
- build/*
#
### Stage "test"
#
test:debian-jessie-aegir3-apt:
stage: test
image: debian:jessie
dependencies:
- build:deb
only:
- 7.x-3.x
before_script:
- apt-get update
# Avoid ERROR: invoke-rc.d: policy-rc.d denied execution of start.
- echo "#!/bin/sh" > /usr/sbin/policy-rc.d
- echo "exit 0" >> /usr/sbin/policy-rc.d
- apt-get install --yes sudo curl
script: "scripts/ci-aegir-dev-install-apt-debian8.sh"
test:debian-stretch-aegir3-apt:
stage: test
image: debian:stretch
allow_failure: true
dependencies:
- build:deb
before_script:
- apt-get update
# Avoid ERROR: invoke-rc.d: policy-rc.d denied execution of start.
- echo "#!/bin/sh" > /usr/sbin/policy-rc.d
- echo "exit 0" >> /usr/sbin/policy-rc.d
- apt-get install --yes sudo curl
script: "scripts/ci-aegir-dev-install-apt-debian9.sh"
test:ubuntu-xenial-aegir3-apt:
stage: test
image: ubuntu:xenial
dependencies:
- build:deb
only:
- 7.x-3.x
before_script:
- apt-get update
# Avoid ERROR: invoke-rc.d: policy-rc.d denied execution of start.
- echo "#!/bin/sh" > /usr/sbin/policy-rc.d
- echo "exit 0" >> /usr/sbin/policy-rc.d
- apt-get install --yes sudo curl
script: "scripts/ci-aegir-dev-install-apt-ubuntu-xenial.sh"
test:ubuntu-artful-aegir3-apt:
stage: test
image: ubuntu:artful
dependencies:
- build:deb
allow_failure: true
before_script:
- apt-get update
# Avoid ERROR: invoke-rc.d: policy-rc.d denied execution of start.
- echo "#!/bin/sh" > /usr/sbin/policy-rc.d
- echo "exit 0" >> /usr/sbin/policy-rc.d
- apt-get install --yes sudo curl
script: "scripts/ci-aegir-dev-install-apt-ubuntu-artful.sh"
test:behat:
stage: test
image: aegir/hostmaster:packaging_base
dependencies:
- build:deb
allow_failure: true
variables:
AEGIR_TESTS_VERSION: "master"
before_script:
- sudo apt-get update
- sudo apt-get install --yes apt-transport-https ca-certificates curl gnupg2 software-properties-common
- curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
- sudo apt-key fingerprint 0EBFCD88
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
- sudo apt-get update
- sudo apt-get install --yes docker-ce
- docker info
- git clone http://github.com/aegir-project/tests.git tests
- cd tests
- git checkout $AEGIR_TESTS_VERSION
# Run prepare scripts.
- cd travis
- sudo bash prepare-docker.sh
- bash prepare-testenv.sh
script:
# Tests are included in the docker-compose.yml file in the tests repo.
- sudo docker-compose -f docker-compose-provision.yml run hostmaster
#
### Stage "publish"
#
publish:unstable-repo:
stage: publish
dependencies:
- build:deb
allow_failure: true
only:
- 7.x-3.x
- /^7\.x-3\.\d+\.x/
image: ruby:2.1
before_script:
# install ssh-agent
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
# run ssh-agent
- eval $(ssh-agent -s)
# add ssh key stored in SSH_PRIVATE_KEY variable to the agent store
- ssh-add <(echo "$SSH_PRIVATE_KEY")
- mkdir -p ~/.ssh
- ls -la /.dockerenv
- echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts
- cat ~/.ssh/known_hosts
script:
- ls -lah build/*
- scp build/* ci@aegir0.aegir.coop:/var/www/repos/incoming/
# reprepro should pick this up in seconds and update the repository index.
#
### Stage "upgradetest"
#
# Upgrade the latest stable Aegir to our unstable repo.
upgradetest:debian-jessie-aegir3-apt-upgrade:
stage: upgradetest
image: debian:jessie
dependencies:
- publish:unstable-repo
when: manual
before_script:
- apt-get update
# Avoid ERROR: invoke-rc.d: policy-rc.d denied execution of start.
- echo "#!/bin/sh" > /usr/sbin/policy-rc.d
- echo "exit 0" >> /usr/sbin/policy-rc.d
- apt-get install --yes sudo curl cron
script:
- "scripts/ci-aegir-stable-install-apt-debian8.sh"
# extra step to run the task queue.
- sudo su aegir --login --command 'drush @hostmaster php-eval "echo hosting_task_count();"'
- sudo su aegir --login --command 'drush @hostmaster hosting-tasks --force'
- sudo su aegir --login --command 'drush @hostmaster php-eval "echo hosting_task_count();"'
- sudo su aegir --login --command 'drush @hostmaster hosting-tasks --force'
- sudo su aegir --login --command 'drush @hostmaster php-eval "echo hosting_task_count();"'
- sudo su aegir --login --command 'drush @hostmaster php-eval "echo hosting_task_count_running();"'
- sleep 2m
- sudo su aegir --login --command 'drush @hostmaster php-eval "echo hosting_task_count_running();"'
# upgrade to the latest version from the unstable repo.
- rm -v /etc/apt/sources.list.d/aegir-stable.list
- echo "deb http://debian.aegirproject.org unstable main" | sudo tee -a /etc/apt/sources.list.d/aegir-unstable.list
- sudo apt-get update
- sudo apt-get --yes upgrade
<?php
/**
* @file
* The Provision_ChainedState class.
*/
/**
* A base class for the service and file handling classes that implements
* chaining of methods.
*/
class Provision_ChainedState {
protected $last_status;
protected $tokens;
/**
* Clear internal state
*/
protected function _clear_state() {
$this->last_status = NULL;
$this->tokens = NULL;
}
/**
* Return the status of the last operation.
*
* @return
* TRUE or FALSE for success or failure; NULL if there was not a previous
* operation.
*/
function status() {
return $this->last_status;
}
/**
* Log a notice into the logging system, if the last operation completed
* succesfully.
*
* @param $message
* The message to log, a string.
*/
function succeed($message) {
if ($this->last_status === TRUE) {
drush_log(dt($message, $this->tokens), 'success');
}
return $this;
}
/**
* Log a notice into the logging system, if the last operation did not
* complete succesfully.
*
* @param $message
* Log this as a error to the logging system, if the $error_codes parameter
* has been set, otherwise, log this as a warning. If the operation
* specifies an additional reason for the operation failing, it will be
* appended to this message.
*
* @param error_codes
* Generate these system level errors using the provision error bitmasks.
*/
function fail($message, $error_codes = NULL) {
if (!empty($this->tokens['@reason'])) {
$message .= ' (@reason)';
}
if ($this->last_status === FALSE) {
if (is_null($error_codes)) {
// Trigger a warning
drush_log(dt($message, $this->tokens), 'warning');
}
else {
// Trigger a sysem halting error
drush_set_error($error_codes, dt($message, $this->tokens));
}
}
return $this;
}
}
<?php
/**
* @file
* Provision configuration generation classes.
*/
class Provision_Config {
/**
* Template file, a PHP file which will have access to $this and variables
* as defined in $data.
*/
public $template = NULL;
/**
* Associate array of variables to make available to the template.
*/
public $data = array();
/**
* A Provision_Context object thie configuration relates to.
*
* @var Provision_Context
*/
public $context = NULL;
/**
* If set, replaces file name in log messages.
*/
public $description = NULL;
/**
* Octal Unix mode for permissons of the created file.
*/
protected $mode = NULL;
/**
* Unix group name for the created file.
*/
protected $group = NULL;
/**
* An optional data store class to instantiate for this config.
*/
protected $data_store_class = NULL;
/**
* The data store.
*/
public $store = NULL;
/**
* Forward $this->... to $this->context->...
* object.
*/
function __get($name) {
if (isset($this->context)) {
return $this->context->$name;
}
}
/**
* Constructor, overriding not recommended.
*
* @param $context
* An alias name for d(), the Provision_Context that this configuration
* is relevant to.
* @param $data
* An associative array to potentially manipulate in process() and make
* available as variables to the template.
*/
function __construct($context, $data = array()) {
if (is_null($this->template)) {
throw new Exception(dt("No template specified for: %class", array('%class' => get_class($this))));
}
// Accept both a reference and an alias name for the context.
$this->context = is_object($context) ? $context : d($context);
if (sizeof($data)) {
$this->data = $data;
}
if (!is_null($this->data_store_class) && class_exists($this->data_store_class)) {
$class = $this->data_store_class;
$this->store = new $class($context, $data);
}
}
/**
* Process and add to $data before writing the configuration.
*
* This is a stub to be implemented by subclasses.
*/
function process() {
if (is_object($this->store)) {
$this->data['records'] = array_filter(array_merge($this->store->loaded_records, $this->store->records));
}
return TRUE;
}
/**
* The filename where the configuration is written.
*
* This is a stub to be implemented by subclasses.
*/
function filename() {
return FALSE;
}
/**
* Load template from filename().
*
* @see hook_provision_config_load_templates()
* @see hook_provision_config_load_templates_alter()
*/
private function load_template() {
// Allow other Drush commands to change the template used first.
$templates = drush_command_invoke_all('provision_config_load_templates', $this);
// Ensure that templates is at least an array.
if (!is_array($templates)) {
$templates = array();
}
// Allow other Drush commands to alter the templates from other commands.
drush_command_invoke_all_ref('provision_config_load_templates_alter', $templates, $this);
if (!empty($templates) && is_array($templates)) {
foreach ($templates as $file) {
if (is_readable($file)) {
drush_log(dt('Template loaded from hook(s): :file', array(
':file' => $file,
)));
return file_get_contents($file);
}
}
}
// If we've got this far, then try to find a template from this class or
// one of its parents.
if (isset($this->template)) {
$class_name = get_class($this);
while ($class_name) {
// Iterate through the config file's parent classes until we
// find the template file to use.
$base_dir = provision_class_directory($class_name);
$file = $base_dir . '/' . $this->template;
if (is_readable($file)) {
drush_log(dt('Template loaded from Provision Config class :class_name: :file', array(
':class_name' => $class_name,
':file' => $file,
)));
return file_get_contents($file);
}
$class_name = get_parent_class($class_name);
}
}
// We've failed to find a template if we've reached this far.
drush_log(dt('No template found for Provision Config class: ', array(':class' => get_class($this))), 'warning');
return FALSE;
}
/**
* Render template, making variables available from $variables associative
* array.
*/
private function render_template($template, $variables) {
// Allow modules to alter the variables before writing to the template.
// @see hook_provision_config_variables_alter()
drush_command_invoke_all_ref('provision_config_variables_alter', $variables, $template, $this);
drush_errors_off();
extract($variables, EXTR_SKIP); // Extract the variables to a local namespace
ob_start(); // Start output buffering
eval('?>' . $template); // Generate content
$contents = ob_get_contents(); // Get the contents of the buffer
ob_end_clean(); // End buffering and discard
drush_errors_on();
return $contents; // Return the contents
}
/**
* Write out this configuration.
*
* 1. Make sure parent directory exists and is writable.
* 2. Load template with load_template().
* 3. Process $data with process().
* 4. Make existing file writable if necessary and possible.
* 5. Render template with $this and $data and write out to filename().
* 6. If $mode and/or $group are set, apply them for the new file.
*/
function write() {
$filename = $this->filename();
// Make directory structure if it does not exist.
if ($filename && !provision_file()->exists(dirname($filename))->status()) {
provision_file()->mkdir(dirname($filename))
->succeed('Created directory @path.')
->fail('Could not create directory @path.');
}
$status = FALSE;
if ($filename && is_writeable(dirname($filename))) {
// manipulate data before passing to template.
$this->process();
if ($template = $this->load_template()) {
// Make sure we can write to the file
if (!is_null($this->mode) && !($this->mode & 0200) && provision_file()->exists($filename)->status()) {
provision_file()->chmod($filename, $this->mode | 0200)
->succeed('Changed permissions of @path to @perm')
->fail('Could not change permissions of @path to @perm');
}
$status = provision_file()->file_put_contents($filename, $this->render_template($template, $this->data))
->succeed('Generated config in write(): ' . (empty($this->description) ? $filename : $this->description . ' (' . $filename. ')'), 'success')
->fail('Could not generate in write(): ' . (empty($this->description) ? $filename : $this->description . ' (' . $filename. ')'))->status();
// Change the permissions of the file if needed
if (!is_null($this->mode)) {
provision_file()->chmod($filename, $this->mode)
->succeed('Changed permissions of @path to @perm')
->fail('Could not change permissions of @path to @perm');
}
if (!is_null($this->group)) {
provision_file()->chgrp($filename, $this->group)
->succeed('Change group ownership of @path to @gid')
->fail('Could not change group ownership of @path to @gid');
}
}
}
return $status;
}
// allow overriding w.r.t locking
function file_put_contents($filename, $text) {
provision_file()->file_put_contents($filename, $text)
->succeed('Generated config in file_put_contents()' . (empty($this->description) ? $filename : $this->description), 'success');
}
/**
* Remove configuration file as specified by filename().
*/
function unlink() {
return provision_file()->unlink($this->filename())->status();
}
}
<?php
/**
* @file
* Provides the Provision_Config_Data_Store class.
*/
/**
* Base class for data storage.
*
* This class provides a file locking mechanism for configuration
* files that may be susceptible to race conditions.
*
* The records loaded from the config and the records set in this
* instance are kept in separate arrays.
*
* When we lock the file, we load the latest stored info.
*/
class Provision_Config_Data_Store extends Provision_Config {
public $template = 'data_store.tpl.php';
public $key = 'record';
private $locked = FALSE;
protected $fp = NULL;
public $records = array();
public $loaded_records = array();
protected $mode = 0700;
function __construct($context, $data = array()) {
parent::__construct($context, $data);
$this->load_data();
}
/**
* Ensure the file pointer is closed and the lock released upon destruction.
*/
function __destruct() {
// release the file lock if we have it.
$this->close();
}
/**
* Open the file.
*/
function open() {
if (!is_resource($this->fp)) {
$this->fp = fopen($this->filename(), "w+");
}
}
/**
* Lock the file from other writes.
*
* After the file has been locked, we reload the data from the file
* so that any changes we make will not override previous changes.
*/
function lock() {
if (!$this->locked) {
$this->open();
flock($this->fp, LOCK_EX);
// Do one last load before setting our locked status.
$this->load_data();
$this->locked = TRUE;
}
}
/**
* Put the contents in the locked file.
*
* We call the lock method here to insure we have the lock.
*/
function file_put_contents($filename, $text) {
$this->lock();
fwrite($this->fp, $text);
fflush($this->fp);
}
/**
* Release the write log on the data store file.
*/
function unlock() {
if ($this->locked && is_resource($this->fp)) {
flock($this->fp, LOCK_UN);
$this->locked = FALSE;
}
}
/**
* Close the file pointer and release the lock (if applicable).
*/
function close() {
if (is_resource($this->fp)) {
fclose($this->fp);
}
}
/**
* Load the data from the data store into our loaded_records property.
*/
function load_data() {
if (!$this->locked) {
// Once w