Skip to content

Commit

Permalink
Saas-7129 runner init (#454)
Browse files Browse the repository at this point in the history
  • Loading branch information
roi-codefresh authored May 14, 2020
1 parent b7a4de8 commit 893fcca
Show file tree
Hide file tree
Showing 9 changed files with 654 additions and 736 deletions.
2 changes: 1 addition & 1 deletion docs/docs.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const docs = require('../docs');

describe('docs generation', () => {
jest.setTimeout(10000);
jest.setTimeout(20000);
it('should generate docs', async () => {
await docs();
});
Expand Down
8 changes: 2 additions & 6 deletions lib/interface/cli/commands/agent/install.cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ const installAgentCmd = new Command({
'skip-cluster-test': skipClusterTest,
verbose,
terminateProcess,
createDemoPipeline,
executeDemoPipeline,
} = argv;
let agent;
let {
Expand All @@ -108,7 +106,7 @@ const installAgentCmd = new Command({
agent = await sdk.agents.create({ name });
// eslint-disable-next-line prefer-destructuring
token = agent.token;
console.log(`A Codefresh Runner with name: ${colors.cyan(name)} has been created.\n${colors.yellow('*IMPORTANT*')} Make sure to copy your access token now and store it in a safe location. You won’t be able to see it again.`);
console.log(`A Codefresh Runner with the name: ${colors.cyan(name)} has been created.\n${colors.yellow('*IMPORTANT*')} Make sure to copy your access token now and store it in a safe location. You won’t be able to see it again.`);
console.log(token);
} else {
// take the agent id from the token
Expand Down Expand Up @@ -166,7 +164,7 @@ const installAgentCmd = new Command({
throw new Error(`\nRunner installation failed with code ${agentInstallStatusCode}`);
}
if (installRuntime) {
await installRuntimeCmd.handler({
return installRuntimeCmd.handler({
'runtime-kube-context-name': kubeContextName,
'runtime-kube-namespace': kubeNamespace,
'agent-name': name,
Expand All @@ -177,8 +175,6 @@ const installAgentCmd = new Command({
'skip-cluster-test': skipClusterTest,
verbose,
terminateProcess,
createDemoPipeline,
executeDemoPipeline,
});
}
},
Expand Down
2 changes: 1 addition & 1 deletion lib/interface/cli/commands/cluster/create.cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const command = new Command({
console.log('\n');
}
});
await sdk.clusters.create({
return sdk.clusters.create({
contextName,
context,
namespace,
Expand Down
256 changes: 179 additions & 77 deletions lib/interface/cli/commands/hybrid/init.cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const runnerRoot = require('../root/runner.cmd');
const inquirer = require('inquirer');
const { getAllKubeContexts, getKubeContext } = require('../../helpers/kubernetes');
const installAgent = require('../agent/install.cmd');
const pipelinesRunCmd = require('../pipeline/run.cmd');
const installMonitoring = require('../monitor/install.cmd');
const createContext = require('../auth/create-context.cmd');
const getAgents = require('../agent/get.cmd');
const { getConfigForSdk } = require('../../commad-line-interface');
Expand All @@ -16,8 +18,79 @@ const INSTALLATION_DEFAULTS = {
NAMESPACE: 'codefresh',
MAKE_DEFAULT_RE: true,
RUN_DEMO_PIPELINE: true,
DEMO_PIPELINE_NAME: 'Hello Codefresh',
CF_CONTEXT_NAME: 'cf-runner',
};

function prettyError(error) {
try {
const errMsg = _.get(error, 'message', error);
let errObj = JSON.parse(errMsg);
if (typeof errObj === 'string') {
errObj = JSON.parse(errObj);
}
return _.get(errObj, 'message', error);
} catch (e) {
return _.get(error, 'message', JSON.stringify(error));
}
}

async function createDemoPipeline(runtimeName) {
const pipeline = await sdk.pipelines.create({ metadata: { name: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME } });
pipeline.spec.runtimeEnvironment = {
name: runtimeName,
};
pipeline.spec.steps = {};
pipeline.spec.stages = ['test'];
pipeline.spec.steps.test = {
stage: 'test',
title: 'test',
image: 'ubuntu:latest',
commands: ['echo hello codefresh'],
};

await sdk.pipelines.replace(
{ name: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME },
{
kind: pipeline.kind,
spec: pipeline.spec,
metadata: pipeline.metadata,
version: pipeline.version,
},
);
}

async function createAndExecuteDemoPipeline(runtimeName) {
let demoPipelineExists = false;

try {
const pipelines = await sdk.pipelines.list({ id: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME });
if (_.get(pipelines, 'docs.length')) {
demoPipelineExists = true;
}
} catch (error) {
console.log(`Failed to fetch account pipelines, cause: ${error.message}`);
}

if (!demoPipelineExists) {
console.log(`Creating demo pipeline with the name: "${colors.cyan(INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME)}"`);
try {
await createDemoPipeline(runtimeName);
} catch (error) {
console.log(`${colors.red('Error: ')} Failed to create demo pipeline, cause: ${prettyError(error)}`);
}
} else {
console.log(`Demo pipeline with the name: "${colors.cyan(INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME)}" already exists`);
}

console.log(`${colors.yellow('*NOTE* Running a pipeline for the first time might take a longer than usual')}`);
console.log(`Executing pipeline "${colors.cyan(INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME)}"`);
await pipelinesRunCmd.handler({
name: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME,
exitProcess: false,
});
}

const initCmd = new Command({
root: false,
parent: runnerRoot,
Expand Down Expand Up @@ -100,13 +173,14 @@ const initCmd = new Command({
'skip-version-check': skipVersionCheck,
yes: noQuestions,
verbose,
name, token, url,
name, url,
} = argv;
let {
'kube-context-name': kubeContextName,
'kube-namespace': kubeNamespace,
'set-default-runtime': shouldMakeDefaultRe,
'exec-demo-pipeline': shouldExecutePipeline,
token,
} = argv;

if (_.get(sdk, 'config.context.isNoAuth') && !token) {
Expand All @@ -123,98 +197,126 @@ const initCmd = new Command({
kubeNamespace = INSTALLATION_DEFAULTS.NAMESPACE;
shouldMakeDefaultRe = INSTALLATION_DEFAULTS.MAKE_DEFAULT_RE;
shouldExecutePipeline = INSTALLATION_DEFAULTS.RUN_DEMO_PIPELINE;
}
} else {
const questions = [];
if (!kubeContextName && !noQuestions) {
const contexts = getAllKubeContexts(kubeConfigPath);
const currentKubeContext = getKubeContext(kubeConfigPath);

const questions = [];
if (!kubeContextName && !noQuestions) {
const contexts = getAllKubeContexts(kubeConfigPath);
const currentKubeContext = getKubeContext(kubeConfigPath);

questions.push({
type: 'list',
name: 'context',
message: 'Name of Kubernetes context to use',
default: currentKubeContext,
choices: contexts,
});
}
if (!kubeNamespace && !noQuestions) {
questions.push({
type: 'input',
name: 'namespace',
default: INSTALLATION_DEFAULTS.NAMESPACE,
message: 'Kubernetes namespace to install into (will be created if it does not exist)',
validate: value => (value !== undefined && value !== '') || 'Please enter namespace\'s name',
});
}
questions.push({
type: 'list',
name: 'context',
message: 'Name of Kubernetes context to use',
default: currentKubeContext,
choices: contexts,
});
}
if (!kubeNamespace && !noQuestions) {
questions.push({
type: 'input',
name: 'namespace',
default: INSTALLATION_DEFAULTS.NAMESPACE,
message: 'Kubernetes namespace to install into (will be created if it does not exist)',
validate: value => (value !== undefined && value !== '') || 'Please enter namespace\'s name',
});
}

if (_.isUndefined(shouldMakeDefaultRe) && !noQuestions) {
questions.push({
type: 'confirm',
name: 'shouldMakeDefaultRe',
default: INSTALLATION_DEFAULTS.MAKE_DEFAULT_RE,
message: 'Set this as the default runtime environment for your Codefresh account? (Y/N)',
});
}
if (_.isUndefined(shouldMakeDefaultRe) && !noQuestions) {
questions.push({
type: 'confirm',
name: 'shouldMakeDefaultRe',
default: INSTALLATION_DEFAULTS.MAKE_DEFAULT_RE,
message: 'Set this as the default runtime environment for your Codefresh account? (Y/N)',
});
}

if (_.isUndefined(shouldExecutePipeline) && !noQuestions) {
questions.push({
type: 'confirm',
name: 'shouldExecutePipeline',
default: INSTALLATION_DEFAULTS.RUN_DEMO_PIPELINE,
message: 'Run demo pipeline after install? (Y/N)',
});
}
if (_.isUndefined(shouldExecutePipeline) && !noQuestions) {
questions.push({
type: 'confirm',
name: 'shouldExecutePipeline',
default: INSTALLATION_DEFAULTS.RUN_DEMO_PIPELINE,
message: 'Run demo pipeline after install? (Y/N)',
});
}

console.log(colors.green('This installer will guide you through the Codefresh Runner installation process'));
const answers = await inquirer.prompt(questions);
kubeContextName = kubeContextName || answers.context;
kubeNamespace = kubeNamespace || answers.namespace;
shouldMakeDefaultRe = shouldMakeDefaultRe || answers.shouldMakeDefaultRe;
shouldExecutePipeline = shouldExecutePipeline || answers.shouldExecutePipeline;
console.log(colors.green('This installer will guide you through the Codefresh Runner installation process'));
const answers = await inquirer.prompt(questions);
kubeContextName = kubeContextName || answers.context;
kubeNamespace = kubeNamespace || answers.namespace;
shouldMakeDefaultRe = shouldMakeDefaultRe || answers.shouldMakeDefaultRe;
shouldExecutePipeline = shouldExecutePipeline || answers.shouldExecutePipeline;
}

console.log(colors.green(`\nInstallation options summary:
${colors.white('1. Kubernetes Context:')} ${colors.cyan(kubeContextName)}
${colors.white('2. Kubernetes Namespace:')} ${colors.cyan(kubeNamespace)}
${colors.white('3. Set this as default account runtime-environment:')} ${colors.cyan(shouldMakeDefaultRe)}
${colors.white('4. Execute demo pipeline after install:')} ${colors.cyan(shouldExecutePipeline)}
`));
console.log(`\n${colors.green('Installation options summary:')}
1. Kubernetes Context: ${colors.cyan(kubeContextName)}
2. Kubernetes Namespace: ${colors.cyan(kubeNamespace)}
3. Set this as default account runtime-environment: ${colors.cyan(shouldMakeDefaultRe)}
4. Execute demo pipeline after install: ${colors.cyan(shouldExecutePipeline)}
`);

if (token) { // Add context
await createContext.handler({
apiKey: token,
name: 'cf-runner',
url,
});
const config = await getConfigForSdk();
await sdk.configure(config);
console.log('A Codefresh context named "cf-runner" was added to your "cfconfig" file.');
try {
await createContext.handler({
apiKey: token,
name: INSTALLATION_DEFAULTS.CF_CONTEXT_NAME,
url,
});
const config = await getConfigForSdk();
await sdk.configure(config);
console.log(`A Codefresh context named '${INSTALLATION_DEFAULTS.CF_CONTEXT_NAME}' was added to your "cfconfig" file.`);
} catch (error) {
console.log(`${colors.red('Error:')} Could not use the provided token, failed with error: ${prettyError(error)}`);
process.exit(1);
}
} else {
token = _.get(sdk, 'config.context.token');
}

// Install runner and runtime
await installAgent.handler({
name,
let runtimeName;
try {
runtimeName = await installAgent.handler({
name,
'kube-context-name': kubeContextName,
'kube-node-selector': kubeNodeSelector,
'dry-run': dryRun,
'in-cluster': inCluster,
'kube-namespace': kubeNamespace,
'kubernetes-runner-type': kubernetesRunnerType,
tolerations,
'venona-version': venonaVersion,
'kube-config-path': kubeConfigPath,
'skip-version-check': skipVersionCheck,
'install-runtime': true,
verbose,
'make-default-runtime': shouldMakeDefaultRe,
terminateProcess: false,
});
} catch (error) {
console.log(`${colors.red('Error: ')} Runner installation failed with error: ${prettyError(error)}`);
process.exit(1);
}

// Install monitoring
await installMonitoring.handler({
'kube-config-path': kubeConfigPath,
'cluster-id': kubeContextName,
'kube-context-name': kubeContextName,
'kube-node-selector': kubeNodeSelector,
'dry-run': dryRun,
'in-cluster': inCluster,
'kube-namespace': kubeNamespace,
'kubernetes-runner-type': kubernetesRunnerType,
tolerations,
'venona-version': venonaVersion,
'kube-config-path': kubeConfigPath,
'skip-version-check': skipVersionCheck,
'install-runtime': true,
token,
verbose,
'make-default-runtime': shouldMakeDefaultRe,
terminateProcess: false,
createDemoPipeline: true,
executeDemoPipeline: shouldExecutePipeline,
noExit: true, // to prevent if from calling: process.exit()
});
console.log(colors.green('Runner Status:\n'));

// Post Installation
if (shouldExecutePipeline) {
await createAndExecuteDemoPipeline(runtimeName);
}

console.log(colors.green('\nRunner Status:'));
await getAgents.handler({});
console.log(colors.green(`\nDocumenation link: ${colors.blue('https://codefresh.io/docs/docs/enterprise/codefresh-runner/#codefresh-runner-preview-release')}`));
console.log(colors.green(`\nIf you had any issues with the installation please report them at: ${colors.blue('https://github.com/codefresh-io/cli/issues/new')}`));
console.log(colors.green(`If you had any issues with the installation please report them at: ${colors.blue('https://github.com/codefresh-io/cli/issues/new')}`));
process.exit(); // TODO : This is not needed - needed to be fixed
},
});
Expand Down
8 changes: 6 additions & 2 deletions lib/interface/cli/commands/monitor/install.cmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const installMonitorCmd = new Command({
'kube-context-name': kubeContextName,
'kube-namespace': kubeNamespace,
verbose,
noExit,
} = argv;
const apiHost = sdk.config.context.url;
const events = new ProgressEvents();
Expand Down Expand Up @@ -73,9 +74,12 @@ const installMonitorCmd = new Command({
events,
});
if (monitorInstallStatusCode !== 0) {
throw new Error(`\nAgent installation failed with code ${monitorInstallStatusCode}`);
throw new Error(`\nCodefresh Monitoring installation failed with code ${monitorInstallStatusCode}`);
}

if (!noExit) {
process.exit(0);
}
process.exit(0);
},
});

Expand Down
Loading

0 comments on commit 893fcca

Please sign in to comment.