gce-elastic-docker
Version:
A package to help setup Elasticsearch / Kibana clusters on Google Compute Engine.
166 lines (143 loc) • 6.1 kB
text/typescript
import { registries } from '../gce';
import { Utils } from '../utils';
const kibana_users_env_var = 'kibana_users';
const kibana_password_dir = '/kibana-users';
const kibana_password_file = `${kibana_password_dir}/.htpasswd`;
const kibana_password_set_file = `${kibana_password_dir}/.passwords-were-set`;
export {
kibana_users_env_var,
kibana_password_dir,
kibana_password_file
};
export interface IImage {
es_version: string;
kibana?: boolean;
name: string;
}
export class Image implements IImage {
es_version: string;
kibana: boolean;
name: string;
private _es_dockerfile: string;
private _kib_dockerfile: string;
private _kibana_entry: string;
constructor(v: IImage) {
this._set_es_version(v);
this._set_kibana(v);
this._set_name(v);
this._set_kibana_entry_file();
this._create_es_dockerfile();
this._create_kib_dockerfile();
}
async create(verbose?: boolean) {
const dockerfile = this.kibana ? this._kib_dockerfile : this._es_dockerfile;
const cmd = `docker build -t ${this.name} . -f-<<EOF\n${dockerfile}\nEOF`;
if (verbose) {
console.log(`creating image ${this.name} from the following dockerfile:\n`);
console.log(dockerfile + '\n');
}
// docker build requires u be in the directory u copy files from
await Utils.exec(cmd, verbose, __dirname);
if (verbose) {
console.log(`\nimage ${this.name} created!`);
}
}
async deploy(verbose?: boolean) {
const cmd = `docker push ${this.name}`;
if (verbose) {
console.log(`deploying ${this.name} to your google container registry`);
console.log(cmd);
}
await Utils.exec(cmd, verbose);
}
private _create_es_dockerfile() {
const startup_file = '/usr/local/bin/startup.sh';
this._es_dockerfile =
`FROM docker.elastic.co/elasticsearch/elasticsearch:${this.es_version}\n` +
'WORKDIR /usr/share\n' +
'RUN yum install epel-release -y\n' +
'RUN yum install jq -y\n' +
`RUN echo '#! /bin/bash' >> ${startup_file}\n` +
`RUN echo 'ulimit -l unlimited' >> ${startup_file}\n` +
`RUN echo '/usr/local/bin/docker-entrypoint.sh eswrapper' >> ${startup_file}\n` +
`RUN chmod 777 ${startup_file}\n` +
`ENTRYPOINT ${startup_file}`;
}
private _create_kib_dockerfile() {
const kurl = 'https://artifacts.elastic.co/downloads/kibana/kibana';
const startup_file = '/usr/local/bin/startup.sh';
const pfile = kibana_password_file;
const kenv = kibana_users_env_var;
const cmd = 'nginx & /usr/local/bin/kentry.sh --server.host=0.0.0.0 ' +
'& /usr/local/bin/docker-entrypoint.sh eswrapper ';
const psetfile = kibana_password_set_file;
const psetfile_msg = 'This file indicates to the startup script your initial ' +
'kibana users have been set. If you delete this, the next time the ' +
'startup script runs, your kibana users will be reset to the original ' +
'ones you gave on cluster creation.';
const nginx_key_file = '/etc/nginx/ssl.key';
const nginx_cert_file = '/etc/nginx/ssl.cert';
this._kib_dockerfile =
`FROM docker.elastic.co/elasticsearch/elasticsearch:${this.es_version}\n` +
'WORKDIR /usr/share/kibana\n' +
`RUN curl -Ls ${kurl}-${this.es_version}-linux-x86_64.tar.gz | ` +
'tar --strip-components=1 -zxf -\n' +
`COPY ${this._kibana_entry} /usr/local/bin/kentry.sh\n` +
'RUN chmod 777 /usr/local/bin/kentry.sh\n' +
'RUN yum install -y epel-release\n' +
'RUN yum install -y nginx\n' +
'RUN yum install -y httpd-tools\n' +
'RUN yum install jq -y\n' +
`RUN mkdir ${kibana_password_dir}\n` +
// handle nginx config
'COPY nginx.conf /etc/nginx/nginx.conf\n' +
'RUN openssl req -new -newkey rsa:4096 -days 20000 -nodes -x509 ' +
'-subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" ' +
`-keyout ${nginx_key_file} -out ${nginx_cert_file}\n` +
`RUN sed -i 's|~~pfile~~|'${pfile}'|g' /etc/nginx/nginx.conf\n` +
`RUN sed -i 's|~~keyfile~~|'${nginx_key_file}'|g' /etc/nginx/nginx.conf\n` +
`RUN sed -i 's|~~certfile~~|'${nginx_cert_file}'|g' /etc/nginx/nginx.conf\n` +
// handle startup script file
`RUN echo '#! /bin/bash' >> ${startup_file}\n` +
`RUN echo 'if [ -n "\\$${kenv}" ] && [ ! -f ${psetfile} ]; then' >> ${startup_file}\n` +
`RUN echo ' k=\\$(echo \\$${kenv} | base64 --decode);' >> ${startup_file}\n` +
`RUN echo ' IFS=" " read -r -a array <<< "\\$k";' >> ${startup_file}\n` +
`RUN echo ' printf "%s\\n" "\\$\{array[@]}" > ${pfile};' >> ${startup_file}\n` +
`RUN echo ' printf "${psetfile_msg}" > ${psetfile};' >> ${startup_file}\n` +
`RUN echo 'fi' >> ${startup_file}\n` +
`RUN echo 'ulimit -l unlimited' >> ${startup_file}\n` +
`RUN echo '${cmd}' >> ${startup_file}\n` +
`RUN chmod 777 ${startup_file}\n` +
'WORKDIR /usr/share\n' +
`ENTRYPOINT ${startup_file}`;
}
private _set_es_version(v: IImage) {
if (!/\d+.\d+.\d+/.test(v.es_version)) {
throw Error(`${v} is an invalid version.`);
}
this.es_version = v.es_version;
}
private _set_kibana(v: IImage) {
if (Utils.is_defined(v.kibana) && !Utils.is_bool(v.kibana)) {
throw Error('not a boolean.');
}
this.kibana = !!v.kibana;
}
private _set_kibana_entry_file() {
if (this.es_version[0] === '5') {
this._kibana_entry = 'kentry-5_x';
} else if (this.es_version[0] === '6') {
this._kibana_entry = 'kentry-6_x';
} else {
throw Error(`kibana ${this.es_version} not supported! ` +
'a startup script still has to be added for this major version.');
}
}
private _set_name(v: IImage) {
if (!Utils.is_valid_image_name(v.name)) {
throw Error(`${v.name} is an invalid image name. Make sure it looks like: ` +
`{${registries.join(' | ')}}/{gcloud-project-id}/{image_name}`);
}
this.name = v.name;
}
}