Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[build] update install package paths, centralize config #7308

Merged
merged 15 commits into from Jun 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gruntfile.js
Expand Up @@ -69,7 +69,7 @@ module.exports = function (grunt) {

grunt.config.merge(config);

config.userScriptsDir = __dirname + '/build/userScripts';
config.packageScriptsDir = __dirname + '/tasks/build/package_scripts';
// ensure that these run first, other configs need them
config.services = require('./tasks/config/services')(grunt);
config.platforms = require('./tasks/config/platforms')(grunt);
Expand Down
103 changes: 61 additions & 42 deletions tasks/build/os_packages.js
@@ -1,55 +1,74 @@
module.exports = function (grunt) {
const { resolve } = require('path');
const { indexBy } = require('lodash');
import { resolve } from 'path';
import { indexBy } from 'lodash';
import exec from '../utils/exec';

const { config } = grunt;
const exec = require('../utils/exec');
const targetDir = config.get('target');
const version = config.get('pkg.version');
const userScriptsDir = config.get('userScriptsDir');
const servicesByName = indexBy(config.get('services'), 'name');
export default (grunt) => {
const targetDir = grunt.config.get('target');
const packageScriptsDir = grunt.config.get('packageScriptsDir');
const servicesByName = indexBy(grunt.config.get('services'), 'name');
const config = grunt.config.get('packages');
const fpm = args => exec('fpm', args);

grunt.registerTask('_build:osPackages', function () {
grunt.config.get('platforms').forEach(({ name, buildDir }) => {
// TODO(sissel): Check if `fpm` is available
if (!(/linux-x(86|64)$/.test(name))) return;

const arch = /x64$/.test(name) ? 'x86_64' : 'i386';
const fpm = args => exec('fpm', args);

const args = [
grunt.config.get('platforms')
.filter(({ name }) => /linux-x(86|64)$/.test(name))
.map(({ name, buildDir }) => {
const architecture = /x64$/.test(name) ? 'x86_64' : 'i386';
return {
buildDir,
architecture
};
})
.forEach(({ buildDir, architecture }) => {
const baseOptions = [
'--force',
'--package', targetDir,
'-s', 'dir', // input type
'--name', 'kibana',
'--description', 'Explore\ and\ visualize\ your\ Elasticsearch\ data.',
'--version', version,
'--url', 'https://www.elastic.co',
'--vendor', 'Elasticsearch,\ Inc.',
'--maintainer', 'Kibana Team\ \<info@elastic.co\>',
'--license', 'Apache\ 2.0',
'--after-install', resolve(userScriptsDir, 'installer.sh'),
'--after-remove', resolve(userScriptsDir, 'remover.sh'),
'--config-files', '/opt/kibana/config/kibana.yml'
];
'--architecture', architecture,
'--name', config.name,
'--description', config.description,
'--version', config.version,
'--url', config.site,
'--vendor', config.vendor,
'--maintainer', config.maintainer,
'--license', config.license,
'--after-install', resolve(packageScriptsDir, 'post_install.sh'),
'--before-install', resolve(packageScriptsDir, 'pre_install.sh'),
'--before-remove', resolve(packageScriptsDir, 'pre_remove.sh'),
'--after-remove', resolve(packageScriptsDir, 'post_remove.sh'),
'--config-files', config.path.kibanaConfig,
'--template-value', `user=${config.user}`,
'--template-value', `group=${config.group}`,
'--template-value', `optimizeDir=${config.path.home}/optimize`,

const files = buildDir + '/=/opt/kibana';
const sysv = servicesByName.sysv.outputDir + '/etc/=/etc/';
const systemd = servicesByName.systemd.outputDir + '/lib/=/lib/';
//config folder is moved to path.conf, exclude {path.home}/config
//uses relative path to --prefix, strip the leading /
'--exclude', `${config.path.home.slice(1)}/config`
];
const debOptions = [
'-t', 'deb',
'--deb-priority', 'optional'
];
const rpmOptions = [
'-t', 'rpm',
'--rpm-os', 'linux'
];
const args = [
`${buildDir}/=${config.path.home}/`,
`${buildDir}/config/=${config.path.conf}/`,
`${servicesByName.sysv.outputDir}/etc/=/etc/`,
`${servicesByName.systemd.outputDir}/lib/=/lib/`
];

//Manually find flags, multiple args without assignment are not entirely parsed
var flags = grunt.option.flags().join(',');

const buildDeb = !!flags.match('deb');
const buildRpm = !!flags.match('rpm');
const noneSpecified = !buildRpm && !buildDeb;

grunt.file.mkdir(targetDir);
if (buildDeb || noneSpecified) {
fpm(args.concat('-t', 'deb', '--deb-priority', 'optional', '-a', arch, files, sysv, systemd));
const flags = grunt.option.flags().filter(flag => /deb|rpm/.test(flag)).join(',');
const buildDeb = flags.includes('deb') || !flags.length;
const buildRpm = flags.includes('rpm') || !flags.length;
if (buildDeb) {
fpm([...baseOptions, ...debOptions, ...args]);
}
if (buildRpm || noneSpecified) {
fpm(args.concat('-t', 'rpm', '-a', arch, '--rpm-os', 'linux', files, sysv, systemd));
if (buildRpm) {
fpm([...baseOptions, ...rpmOptions, ...args]);
}

});
Expand Down
17 changes: 17 additions & 0 deletions tasks/build/package_scripts/post_install.sh
@@ -0,0 +1,17 @@
#!/bin/sh
set -e

user_check() {
getent passwd "$1" > /dev/null 2>&1
}

user_create() {
# Create a system user. A system user is one within the system uid range and
# has no expiration
useradd -r "$1"
}

if ! user_check "<%= user %>" ; then
user_create "<%= user %>"
fi
chown -R <%= user %>:<%= group %> <%= optimizeDir %>
42 changes: 42 additions & 0 deletions tasks/build/package_scripts/post_remove.sh
@@ -0,0 +1,42 @@
#!/bin/sh
set -e

user_check() {
getent passwd "$1" > /dev/null 2>&1
}

user_remove() {
userdel "$1"
}

REMOVE_USER=false

case $1 in
# Includes cases for all valid arguments, exit 1 otherwise
# Debian
purge)
REMOVE_USER=true
;;

remove|failed-upgrade|abort-install|abort-upgrade|disappear|upgrade|disappear)
;;

# Red Hat
0)
REMOVE_USER=true
;;

1)
;;

*)
echo "post remove script called with unknown argument \`$1'" >&2
exit 1
;;
esac

if [ "$REMOVE_USER" = "true" ]; then
if user_check "<%= user %>" ; then
user_remove "<%= user %>"
fi
fi
14 changes: 14 additions & 0 deletions tasks/build/package_scripts/pre_install.sh
@@ -0,0 +1,14 @@
#!/bin/sh
set -e

if command -v systemctl >/dev/null && systemctl is-active kibana.service >/dev/null; then
systemctl --no-reload stop kibana.service
elif [ -x /etc/init.d/kibana ]; then
if command -v invoke-rc.d >/dev/null; then
invoke-rc.d kibana stop
elif command -v service >/dev/null; then
service kibana stop
else
/etc/init.d/kibana stop
fi
fi
16 changes: 16 additions & 0 deletions tasks/build/package_scripts/pre_remove.sh
@@ -0,0 +1,16 @@
#!/bin/sh
set -e

echo -n "Stopping kibana service..."
if command -v systemctl >/dev/null && systemctl is-active kibana.service >/dev/null; then
systemctl --no-reload stop kibana.service
elif [ -x /etc/init.d/kibana ]; then
if command -v invoke-rc.d >/dev/null; then
invoke-rc.d kibana stop
elif command -v service >/dev/null; then
service kibana stop
else
/etc/init.d/kibana stop
fi
fi
echo " OK"
30 changes: 14 additions & 16 deletions tasks/build/pleaserun.js
@@ -1,31 +1,29 @@
module.exports = function createServices(grunt) {
const { resolve } = require('path');
const { appendFileSync } = require('fs');
const exec = require('../utils/exec');
import { resolve } from 'path';
import { appendFileSync } from 'fs';
import exec from '../utils/exec';

export default (grunt) => {
const userScriptsDir = grunt.config.get('userScriptsDir');
const { path, user, group, name, description } = grunt.config.get('packages');

grunt.registerTask('_build:pleaseRun', function () {
// TODO(sissel): Detect if 'pleaserun' is found, and provide a useful error
// to the user if it is missing.

grunt.config.get('services').forEach(function (service) {
grunt.config.get('services').forEach((service) => {
grunt.file.mkdir(service.outputDir);
exec('pleaserun', [
'--install',
'--no-install-actions',
'--install-prefix', service.outputDir,
'--overwrite',
'--user', 'kibana',
'--group', 'kibana',
'--sysv-log-path', '/var/log/kibana/',
'--name', name,
'--description', description,
'--user', user,
'--group', group,
'--sysv-log-path', path.logs,
'-p', service.name,
'-v', service.version,
'/opt/kibana/bin/kibana'
path.kibanaBin,
`-c ${path.kibanaConfig}`
]);
});

grunt.file.mkdir(userScriptsDir);
exec('please-manage-user', ['--output', userScriptsDir, 'kibana']);
appendFileSync(resolve(userScriptsDir, 'installer.sh'), 'chown kibana:kibana /opt/kibana/optimize');
});
};
58 changes: 45 additions & 13 deletions tasks/config/packages.js
@@ -1,20 +1,52 @@
export default (grunt) => {
const version = grunt.config.get('pkg.version');
const productionPath = `kibana/${version.match(/\d\.\d/)[0]}`;
const stagingPath = `kibana/staging/${version.match(/\d\.\d\.\d/)[0]}-XXXXXXX/repos/${version.match(/\d\./)[0]}x`;
const rpmFolder = 'centos';
const debFolder = 'debian';
const VERSION = grunt.config.get('pkg.version');

const FOLDER_STAGING = `kibana/staging/${VERSION.match(/\d\.\d\.\d/)[0]}-XXXXXXX/repos/${VERSION.match(/\d\./)[0]}x`;
const FOLDER_PRODUCTION = `kibana/${VERSION.match(/\d\.\d/)[0]}`;

const FOLDERNAME_DEB = 'debian';
const FOLDERNAME_RPM = 'centos';

const PREFIX_STAGING_DEB = `${FOLDER_STAGING}/${FOLDERNAME_DEB}`;
const PREFIX_STAGING_RPM = `${FOLDER_STAGING}/${FOLDERNAME_RPM}`;
const PREFIX_PRODUCTION_DEB = `${FOLDER_PRODUCTION}/${FOLDERNAME_DEB}`;
const PREFIX_PRODUCTION_RPM = `${FOLDER_PRODUCTION}/${FOLDERNAME_RPM}`;

const FOLDER_CONFIG = '/etc/kibana';
const FOLDER_LOGS = '/var/log/kibana';
const FOLDER_HOME = '/usr/share/kibana';

const FILE_KIBANA_CONF = `${FOLDER_CONFIG}/kibana.yml`;
const FILE_KIBANA_BINARY = `${FOLDER_HOME}/bin/kibana`;

return {
staging: {
bucket: 'download.elasticsearch.org',
debPrefix: `${stagingPath}/${debFolder}`,
rpmPrefix: `${stagingPath}/${rpmFolder}`
publish: {
staging: {
bucket: 'download.elasticsearch.org',
debPrefix: PREFIX_STAGING_DEB,
rpmPrefix: PREFIX_STAGING_RPM
},
production: {
bucket: 'packages.elasticsearch.org',
debPrefix: PREFIX_STAGING_DEB,
rpmPrefix: PREFIX_STAGING_RPM
}
},
production: {
bucket: 'packages.elasticsearch.org',
debPrefix: `${productionPath}/${debFolder}`,
rpmPrefix: `${productionPath}/${rpmFolder}`
user: 'kibana',
group: 'kibana',
name: 'kibana',
description: 'Explore\ and\ visualize\ your\ Elasticsearch\ data',
site: 'https://www.elastic.co',
vendor: 'Elasticsearch,\ Inc.',
maintainer: 'Kibana Team\ \<info@elastic.co\>',
license: 'Apache\ 2.0',
version: VERSION,
path: {
conf: FOLDER_CONFIG,
logs: FOLDER_LOGS,
home: FOLDER_HOME,
kibanaBin: FILE_KIBANA_BINARY,
kibanaConfig: FILE_KIBANA_CONF
}
};
};
10 changes: 5 additions & 5 deletions tasks/release_packages.js
Expand Up @@ -4,7 +4,7 @@ import { promisify } from 'bluebird';
import readline from 'readline';

export default (grunt) => {
const packages = grunt.config.get('packages');
const publishConfig = grunt.config.get('packages').publish;
const platforms = grunt.config.get('platforms');

function debS3(deb) {
Expand Down Expand Up @@ -87,8 +87,8 @@ export default (grunt) => {
if (platform.debPath) {
debS3({
filePath: platform.debPath,
bucket: packages[environment].bucket,
prefix: packages[environment].debPrefix.replace('XXXXXXX', trimmedHash),
bucket: publishConfig[environment].bucket,
prefix: publishConfig[environment].debPrefix.replace('XXXXXXX', trimmedHash),
signatureKeyId: signature.id,
arch: platform.name.match('x64') ? 'amd64' : 'i386',
awsKey: aws.key,
Expand All @@ -99,8 +99,8 @@ export default (grunt) => {
if (platform.rpmPath) {
rpmS3({
filePath: platform.rpmPath,
bucket: packages[environment].bucket,
prefix: packages[environment].rpmPrefix.replace('XXXXXXX', trimmedHash),
bucket: publishConfig[environment].bucket,
prefix: publishConfig[environment].rpmPrefix.replace('XXXXXXX', trimmedHash),
signingKeyName: signature.name,
awsKey: aws.key,
awsSecret: aws.secret
Expand Down