Skip to content

Commit fb0d88d

Browse files
Saas 6939 (#449)
* runner init
1 parent 935c698 commit fb0d88d

File tree

14 files changed

+446
-48
lines changed

14 files changed

+446
-48
lines changed

lib/interface/cli/codefresh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ if (process.argv.includes('--get-yargs-completions')) {
1616
const completionInterface = require('./completion');
1717
completionInterface().argv; // eslint-disable-line
1818
} else {
19-
const commandLineInterface = require('./commad-line-interface');
20-
commandLineInterface().catch((err) => {
19+
const { startCommandLine } = require('./commad-line-interface');
20+
startCommandLine().catch((err) => {
2121
Output.printError(err);
2222
process.exit(1);
2323
});

lib/interface/cli/commad-line-interface.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ const sdk = require('../../logic/sdk');
1212

1313
const PROCESS_ARGV = require('yargs-parser')(process.argv);
1414

15-
async function startCommandLine() {
16-
const cliConfig = configManager.config();
15+
const cliConfig = configManager.config();
1716

17+
async function getConfigForSdk() {
1818
const configOptions = {
1919
configPath: PROCESS_ARGV.cfconfig,
2020
spec: { json: openapi },
@@ -27,10 +27,12 @@ async function startCommandLine() {
2727
},
2828
}, cliConfig.request),
2929
};
30-
30+
return Config.load(configOptions);
31+
}
32+
async function startCommandLine() {
3133
const [files, config] = await Promise.all([
3234
recursive(path.resolve(__dirname, 'commands')),
33-
Config.load(configOptions),
35+
getConfigForSdk(),
3436
]);
3537

3638
sdk.configure(config);
@@ -73,4 +75,5 @@ async function startCommandLine() {
7375
.argv;
7476
}
7577

76-
module.exports = startCommandLine;
78+
module.exports = { startCommandLine, getConfigForSdk };
79+

lib/interface/cli/commands/agent/install.cmd.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const installRuntimeCmd = require('../runtimeEnvironments/install.cmd');
66
const { getKubeContext } = require('../../helpers/kubernetes');
77
const ProgressEvents = require('../../helpers/progressEvents');
88
const cliProgress = require('cli-progress');
9+
const colors = require('colors');
910

1011
const defaultNamespace = 'codefresh';
1112

@@ -60,6 +61,9 @@ const installAgentCmd = new Command({
6061
.option('install-runtime', {
6162
describe: 'Install and attach runtime on the same namespace as the agent (default is false)',
6263
})
64+
.option('make-default-runtime', {
65+
describe: 'should all pipelines run on the hybrid runtime (default is false)',
66+
})
6367
.option('skip-cluster-test', {
6468
describe: 'Do not run cluster acceptance test',
6569
})
@@ -80,8 +84,12 @@ const installAgentCmd = new Command({
8084
'kube-config-path': kubeConfigPath,
8185
'skip-version-check': skipVersionCheck,
8286
'install-runtime': installRuntime,
87+
'make-default-runtime': shouldMakeDefaultRe,
8388
'skip-cluster-test': skipClusterTest,
8489
verbose,
90+
terminateProcess,
91+
createDemoPipeline,
92+
executeDemoPipeline,
8593
} = argv;
8694
let agent;
8795
let {
@@ -100,7 +108,7 @@ const installAgentCmd = new Command({
100108
agent = await sdk.agents.create({ name });
101109
// eslint-disable-next-line prefer-destructuring
102110
token = agent.token;
103-
console.log(`An agent with name: ${name} was created\n note this the last only time the token will be printed`);
111+
console.log(`An agent with name: ${colors.blue(name)} has been created\nMake sure to copy your access token now. You won’t be able to see it again`);
104112
console.log(token);
105113
} else {
106114
// take the agent id from the token
@@ -165,8 +173,12 @@ const installAgentCmd = new Command({
165173
'runtime-kube-config-path': kubeConfigPath,
166174
'attach-runtime': true,
167175
'restart-agent': true,
176+
'make-default-runtime': shouldMakeDefaultRe,
168177
'skip-cluster-test': skipClusterTest,
169178
verbose,
179+
terminateProcess,
180+
createDemoPipeline,
181+
executeDemoPipeline,
170182
});
171183
}
172184
},

lib/interface/cli/commands/helm/helm.sdk.spec.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,10 @@ jest.spyOn(process, 'exit').mockImplementation();
1010

1111
const request = require('requestretry');
1212

13-
jest.mock('../../../../logic', () => {
14-
const mockPipelinesList = jest.fn();
15-
mockPipelinesList.mockReturnValue(Promise.resolve([{
16-
metadata: {
17-
name: 'pip1',
18-
id: 'pip1',
19-
},
20-
}]));
2113

14+
jest.mock('../../../../logic', () => {
2215
// eslint-disable-next-line global-require
2316
const sdk = require('../../../../logic/sdk');
24-
sdk.pipelines = {
25-
getNames: mockPipelinesList,
26-
};
2717
return { sdk };
2818
});
2919

@@ -34,10 +24,19 @@ describe('helm commands', () => {
3424
request.__reset();
3525
request.mockClear();
3626
await configureSdk(); // eslint-disable-line
27+
// eslint-disable-next-line global-require
28+
const sdk = require('../../../../logic/sdk');
29+
const mockPipelinesList = jest.fn();
30+
mockPipelinesList.mockReturnValue(Promise.resolve([{
31+
metadata: {
32+
name: 'pip1',
33+
id: 'pip1',
34+
},
35+
}]));
36+
sdk.pipelines.getNames = mockPipelinesList;
3737
});
3838

3939
describe('set-helm-config', () => {
40-
4140
it('should set config', async () => {
4241
const argv = {
4342
cluster: 'selector',
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/* eslint-disable max-len */
2+
const Command = require('../../Command');
3+
const runnerRoot = require('../root/runner.cmd');
4+
const inquirer = require('inquirer');
5+
const { getAllKubeContexts, getKubeContext } = require('../../helpers/kubernetes');
6+
const installAgent = require('../agent/install.cmd');
7+
const createContext = require('../auth/create-context.cmd');
8+
const getAgents = require('../agent/get.cmd');
9+
const { getConfigForSdk } = require('../../commad-line-interface');
10+
const colors = require('colors');
11+
const DEFAULTS = require('../../defaults');
12+
const sdk = require('../../../../logic/sdk');
13+
14+
const defaultNamespace = 'codefresh';
15+
16+
const initCmd = new Command({
17+
root: false,
18+
parent: runnerRoot,
19+
command: 'init',
20+
description: 'Install codefresh runner solution\'s components on kubernetes cluster',
21+
webDocs: {
22+
category: 'Runner',
23+
title: 'Init',
24+
weight: 100,
25+
},
26+
// requiresAuthentication: argv => argv && !argv.token,
27+
builder: yargs => yargs
28+
.env('CF_ARG_') // this means that every process.env.CF_ARG_* will be passed to argv
29+
.option('name', {
30+
describe: 'Agent\'s name to be created if token is not provided',
31+
})
32+
.option('token', {
33+
describe: 'Registration\'s token',
34+
})
35+
.option('url', {
36+
describe: 'Codefresh system custom url',
37+
default: DEFAULTS.URL,
38+
})
39+
.option('kube-context-name', {
40+
describe: 'Name of the kubernetes context on which venona should be installed [$CF_ARG_KUBE_CONTEXT_NAME]',
41+
})
42+
.option('kube-node-selector', {
43+
describe: 'The kubernetes node selector "key=value" to be used by venona build resources (default is no node selector) (string)',
44+
})
45+
.option('dry-run', {
46+
describe: 'Set to true to simulate installation',
47+
})
48+
.option('in-cluster', {
49+
describe: 'Set flag if venona is been installed from inside a cluster',
50+
})
51+
.option('kube-namespace', {
52+
describe: 'Name of the namespace on which venona should be installed [$CF_ARG_KUBE_NAMESPACE]',
53+
})
54+
.option('kubernetes-runner-type', {
55+
describe: 'Set the runner type to kubernetes (alpha feature)',
56+
})
57+
.option('tolerations', {
58+
describe: 'The kubernetes tolerations as path to a JSON file to be used by venona resources (default is no tolerations) (string)',
59+
})
60+
.option('venona-version', {
61+
describe: 'Version of venona to install (default is the latest)',
62+
})
63+
.option('kube-config-path', {
64+
describe: 'Path to kubeconfig file (default is $HOME/.kube/config)',
65+
})
66+
.option('skip-version-check', {
67+
describe: 'Do not compare current Venona\'s version with latest',
68+
})
69+
.option('verbose', {
70+
describe: 'Print logs',
71+
}),
72+
handler: async (argv) => {
73+
const {
74+
'kube-node-selector': kubeNodeSelector,
75+
'dry-run': dryRun,
76+
'in-cluster': inCluster,
77+
'kubernetes-runner-type': kubernetesRunnerType,
78+
tolerations,
79+
'venona-version': venonaVersion,
80+
'kube-config-path': kubeConfigPath,
81+
'skip-version-check': skipVersionCheck,
82+
verbose,
83+
name, token, url,
84+
} = argv;
85+
let {
86+
'kube-context-name': kubeContextName,
87+
'kube-namespace': kubeNamespace,
88+
} = argv;
89+
const questions = [];
90+
if (!kubeContextName) {
91+
const contexts = getAllKubeContexts(kubeConfigPath);
92+
const currentKubeContext = getKubeContext(kubeConfigPath);
93+
94+
questions.push({
95+
type: 'list',
96+
name: 'context',
97+
message: 'Select Kubernetes context',
98+
default: currentKubeContext,
99+
choices: contexts,
100+
});
101+
}
102+
if (!kubeNamespace) {
103+
questions.push({
104+
type: 'input',
105+
name: 'namespace',
106+
default: defaultNamespace,
107+
message: 'Insert Kubernetes namespace (will be created if not exists) ',
108+
validate: value => (value !== undefined && value !== '') || 'Please enter namespace\'s name',
109+
});
110+
}
111+
112+
questions.push({
113+
type: 'confirm',
114+
name: 'shouldMakeDefaultRe',
115+
default: true,
116+
message: 'Should mark the hybrid runtime as default runtime ?',
117+
118+
});
119+
120+
questions.push({
121+
type: 'confirm',
122+
name: 'shouldExecutePipeline',
123+
default: true,
124+
message: 'Run demo pipeline ?',
125+
126+
});
127+
128+
console.log(colors.green('This installer will guide you through the hybrid installation process'));
129+
const answers = await inquirer.prompt(questions);
130+
kubeContextName = kubeContextName || answers.context;
131+
kubeNamespace = kubeNamespace || answers.namespace;
132+
const { shouldMakeDefaultRe, shouldExecutePipeline } = answers;
133+
console.log(colors.green(`Installation options summary : \n Context: ${colors.blue(kubeContextName)} \n Namespace: ${colors.blue(kubeNamespace)} \n Make hybrid runime as default: ${colors.blue(shouldMakeDefaultRe)}\nExecute hello hyrbird pipeline: ${colors.blue(shouldExecutePipeline)}`));
134+
if (token) { // Add context
135+
await createContext.handler({
136+
apiKey: token,
137+
name: 'hybrid',
138+
url,
139+
});
140+
const config = await getConfigForSdk();
141+
await sdk.configure(config);
142+
console.log('A codefresh context named hybrid was added in your $HOME folder');
143+
}
144+
await installAgent.handler({
145+
name,
146+
'kube-context-name': kubeContextName,
147+
'kube-node-selector': kubeNodeSelector,
148+
'dry-run': dryRun,
149+
'in-cluster': inCluster,
150+
'kube-namespace': kubeNamespace,
151+
'kubernetes-runner-type': kubernetesRunnerType,
152+
tolerations,
153+
'venona-version': venonaVersion,
154+
'kube-config-path': kubeConfigPath,
155+
'skip-version-check': skipVersionCheck,
156+
'install-runtime': true,
157+
verbose,
158+
'make-default-runtime': shouldMakeDefaultRe,
159+
terminateProcess: false,
160+
createDemoPipeline: true,
161+
executeDemoPipeline: shouldExecutePipeline,
162+
});
163+
console.log(colors.green('Agent Status:\n'));
164+
await getAgents.handler({});
165+
console.log(colors.green(`\nDocumenation link: ${colors.blue('https://codefresh.io/docs/docs/enterprise/codefresh-runner/#codefresh-runner-preview-release')}`));
166+
console.log(colors.green('\nTo report issues please follow this link: https://github.com/codefresh-io/cli/issues/new'));
167+
process.exit(); // TODO : This is not needed - needed to be fixed
168+
},
169+
});
170+
171+
module.exports = initCmd;

lib/interface/cli/commands/pipeline/run.cmd.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,14 @@ const run = new Command({
145145
return yargs;
146146
},
147147
handler: async (argv) => {
148+
const exitProcess = (argv && argv.exitProcess);
148149
const flavor = getCommandFlavor(argv);
149150
await flavor.preRunAll();
150151
const exitCode = await flavor.run();
151152
await flavor.postRunAll();
152-
process.exit(exitCode);
153+
if (exitProcess !== false) {
154+
process.exit(exitCode);
155+
}
153156
},
154157
});
155158

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const Command = require('../../Command');
2+
3+
4+
const runner = new Command({
5+
root: true,
6+
command: 'runner',
7+
description: 'Manage runner resources',
8+
requiresAuthentication: argv => argv && !argv.token,
9+
usage: 'Manage codefresh runner solution\'s components on kubernetes cluster',
10+
webDocs: {
11+
description: 'Manage and install runner resources',
12+
category: 'Runner Resources',
13+
title: 'Runner',
14+
weight: 40,
15+
},
16+
});
17+
18+
module.exports = runner;

lib/interface/cli/commands/runtimeEnvironments/attach.cmd.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ const attachRuntimeCmd = new Command({
147147
}
148148
if (terminateProcess || terminateProcess === undefined) {
149149
process.exit();
150+
} else {
151+
return 0;
150152
}
151153
},
152154
});

0 commit comments

Comments
 (0)