Skip to content

Commit a281b04

Browse files
runner upgrade (#524)
* runner upgrade * proxy support in runner init
1 parent 5d85d8f commit a281b04

File tree

7 files changed

+114
-42
lines changed

7 files changed

+114
-42
lines changed

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

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,34 +31,31 @@ const installAgentCmd = new Command({
3131
describe: 'Agent\'s token',
3232
})
3333
.option('kube-context-name', {
34-
describe: 'Name of the kubernetes context on which venona should be installed [$CF_ARG_KUBE_CONTEXT_NAME]',
34+
describe: 'Name of the kubernetes context on which runner should be installed [$CF_ARG_KUBE_CONTEXT_NAME]',
3535
})
3636
.option('kube-node-selector', {
37-
describe: 'The kubernetes node selector "key=value" to be used by venona build resources (default is no node selector) (string)',
37+
describe: 'The kubernetes node selector "key=value" to be used by runner build resources (default is no node selector) (string)',
3838
})
3939
.option('dry-run', {
4040
describe: 'Set to true to simulate installation',
4141
})
4242
.option('in-cluster', {
43-
describe: 'Set flag if venona is been installed from inside a cluster',
43+
describe: 'Set flag if runner is been installed from inside a cluster',
4444
})
4545
.option('kube-namespace', {
46-
describe: 'Name of the namespace on which venona should be installed [$CF_ARG_KUBE_NAMESPACE]',
46+
describe: 'Name of the namespace on which runner should be installed [$CF_ARG_KUBE_NAMESPACE]',
4747
})
4848
.option('kubernetes-runner-type', {
4949
describe: 'Set the runner type to kubernetes (alpha feature)',
5050
})
5151
.option('tolerations', {
52-
describe: 'The kubernetes tolerations as path to a JSON file to be used by venona resources (default is no tolerations) (string)',
53-
})
54-
.option('venona-version', {
55-
describe: 'Version of venona to install (default is the latest)',
52+
describe: 'The kubernetes tolerations as path to a JSON file to be used by runner resources (default is no tolerations) (string)',
5653
})
5754
.option('kube-config-path', {
5855
describe: 'Path to kubeconfig file (default is $HOME/.kube/config)',
5956
})
6057
.option('skip-version-check', {
61-
describe: 'Do not compare current Venona\'s version with latest',
58+
describe: 'Do not compare current runner\'s version with latest',
6259
})
6360
.option('install-runtime', {
6461
describe: 'Install and attach runtime on the same namespace as the agent (default is false)',
@@ -91,7 +88,6 @@ const installAgentCmd = new Command({
9188
'in-cluster': inCluster,
9289
'kubernetes-runner-type': kubernetesRunnerType,
9390
tolerations,
94-
'venona-version': venonaVersion,
9591
'kube-config-path': kubeConfigPath,
9692
'skip-version-check': skipVersionCheck,
9793
'install-runtime': installRuntime,
@@ -103,6 +99,7 @@ const installAgentCmd = new Command({
10399
'set-file': setFile,
104100
'agent-kube-context-name': agentKubeContextName,
105101
'agent-kube-namespace': agentKubeNamespace,
102+
envVars,
106103
} = argv;
107104
let agent;
108105
let {
@@ -168,14 +165,14 @@ const installAgentCmd = new Command({
168165
kubeNodeSelector,
169166
kubernetesRunnerType,
170167
tolerations,
171-
venonaVersion,
172168
kubeConfigPath,
173169
skipVersionCheck,
174170
verbose,
175171
agentId: name,
176172
terminateProcess,
177173
events,
178174
logFormatting: DefaultLogFormatter,
175+
envVars,
179176
});
180177
if (agentInstallStatusCode !== 0) {
181178
throw new Error(`\nRunner installation failed with code ${agentInstallStatusCode}`);

lib/interface/cli/commands/hybrid/helper.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,21 @@ async function runClusterAcceptanceTests({ kubeNamespace, kubeConfigPath }) {
385385
await componentRunner.run(components.venona, cmd);
386386
}
387387

388+
async function runUpgrade({ kubeNamespace, kubeContextName }) {
389+
const binLocation = await downloadVeonona();
390+
const componentRunner = new Runner(binLocation);
391+
const cmd = ['upgrade', '--log-formtter', DefaultLogFormatter];
392+
if (kubeNamespace) {
393+
cmd.push('--kube-namespace');
394+
cmd.push(kubeNamespace);
395+
}
396+
if (kubeContextName) {
397+
cmd.push('--kube-context-name');
398+
cmd.push(kubeContextName);
399+
}
400+
await componentRunner.run(components.venona, cmd);
401+
}
402+
388403
async function installAgent({
389404
apiHost, // --api-host
390405
agentId, // --agnetId
@@ -401,6 +416,7 @@ async function installAgent({
401416
skipVersionCheck, // --skip-version-check
402417
verbose, // --verbose
403418
logFormatting = DefaultLogFormatter, // --log-formtter
419+
envVars,
404420
}) {
405421
const binLocation = await downloadVeonona();
406422
const componentRunner = new Runner(binLocation);
@@ -450,6 +466,9 @@ async function installAgent({
450466
if (verbose) {
451467
cmd.push('--verbose');
452468
}
469+
if (envVars) {
470+
cmd.push(`--envVars=${envVars}`);
471+
}
453472

454473
await componentRunner.run(components.venona, cmd);
455474
}
@@ -626,7 +645,7 @@ async function newAgentName(kubeContextName, kubeNamespace, agents) {
626645
return name;
627646
}
628647

629-
function parseNodeSelector(nodeSelectorStr) {
648+
function keyValueAsStringToObject(nodeSelectorStr) {
630649
if (nodeSelectorStr) {
631650
const kubeNodeSelectorObj = {};
632651
const nsSplitParts = nodeSelectorStr.split(',');
@@ -642,6 +661,24 @@ function parseNodeSelector(nodeSelectorStr) {
642661
}
643662
}
644663

664+
function serealizeToKeyValuePairs(obj) {
665+
return _.keys(obj).reduce((acc, key) => {
666+
if (acc) {
667+
return `${acc},${key}=${obj[key]}`;
668+
}
669+
return `${key}=${obj[key]}`;
670+
}, '');
671+
}
672+
673+
function detectProxy() {
674+
const httpProxy = process.env.http_proxy || process.env.HTTP_PROXY;
675+
const httpsProxy = process.env.https_proxy || process.env.HTTPS_PROXY;
676+
return {
677+
httpProxy,
678+
httpsProxy,
679+
};
680+
}
681+
645682
module.exports = {
646683
getRelatedAgents,
647684
createErrorHandler,
@@ -663,10 +700,13 @@ module.exports = {
663700
attachRuntime,
664701
newRuntimeName,
665702
newAgentName,
666-
parseNodeSelector,
703+
keyValueAsStringToObject,
667704
downloadRelatedComponents: downloadHybridComponents,
668705
downloadSteveDore,
669706
downloadVeonona,
707+
runUpgrade,
708+
detectProxy,
709+
serealizeToKeyValuePairs,
670710
INSTALLATION_DEFAULTS,
671711
DefaultLogFormatter,
672712
};

lib/interface/cli/commands/hybrid/init.cmd.js

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ const {
2828
attachRuntime,
2929
newRuntimeName,
3030
newAgentName,
31-
parseNodeSelector,
31+
detectProxy,
32+
keyValueAsStringToObject,
33+
serealizeToKeyValuePairs,
3234
INSTALLATION_DEFAULTS,
3335
} = require('./helper');
3436
const InstallationPlan = require('./InstallationPlan');
37+
const { array } = require('yargs');
3538

3639
const handleError = createErrorHandler(`\nIf you had any issues with the installation please report them at: ${colors.blue('https://github.com/codefresh-io/cli/issues/new')}`);
3740

@@ -83,10 +86,10 @@ const initCmd = new Command({
8386
default: DEFAULTS.URL,
8487
})
8588
.option('kube-context-name', {
86-
describe: 'Name of the Kubernetes context on which venona should be installed [$CF_ARG_KUBE_CONTEXT_NAME]',
89+
describe: 'Name of the Kubernetes context on which runner should be installed [$CF_ARG_KUBE_CONTEXT_NAME]',
8790
})
8891
.option('kube-node-selector', {
89-
describe: 'The Kubernetes node selector "key=value" to be used by venona build resources (default is no node selector) (string)',
92+
describe: 'The Kubernetes node selector "key=value" to be used by runner build resources (default is no node selector) (string)',
9093
})
9194
.option('build-node-selector', {
9295
describe: 'The Kubernetes node selector "key=value" to be used by the Codefresh build resources (default is no node selector)',
@@ -114,10 +117,10 @@ const initCmd = new Command({
114117
default: true,
115118
})
116119
.option('kube-namespace', {
117-
describe: 'Name of the namespace on which venona should be installed [$CF_ARG_KUBE_NAMESPACE]',
120+
describe: 'Name of the namespace on which runner should be installed [$CF_ARG_KUBE_NAMESPACE]',
118121
})
119122
.option('tolerations', {
120-
describe: 'The Kubernetes tolerations as path to a JSON file to be used by venona resources (default is no tolerations) (string)',
123+
describe: 'The Kubernetes tolerations as path to a JSON file prefixed with @ to be used by runner resources (default is no tolerations) (string)',
121124
})
122125
.option('storage-class-name', {
123126
describe: 'Set a name of your custom storage class',
@@ -133,6 +136,10 @@ const initCmd = new Command({
133136
})
134137
.option('verbose', {
135138
describe: 'Print logs',
139+
})
140+
.option('env-vars', {
141+
describe: 'Addiontal env vars to be used in agent\'s pod',
142+
type: array,
136143
}),
137144
handler: async (argv) => {
138145
let resumedInstallation = false;
@@ -176,16 +183,21 @@ const initCmd = new Command({
176183
'kube-namespace': kubeNamespace,
177184
'set-default-runtime': shouldMakeDefaultRe,
178185
'exec-demo-pipeline': shouldExecutePipeline,
186+
'env-vars': envVars,
179187
} = _argv;
180188

189+
if (envVars) {
190+
envVars = keyValueAsStringToObject(envVars.join(','));
191+
}
192+
181193
if (_.get(sdk, 'config.context.isNoAuth') && !token) {
182194
console.log('Not authenticated as a Codefresh account: ');
183195
console.log('In order to install a Codefresh Runner you need to provide ' +
184196
`an authentication token which can be generated here: ${colors.blue(`${_argv.url}/user/settings`)}` +
185197
'\nAfter getting the token you may run this command again with the [--token] option or use the \'codefresh auth\' command to create an authenticated context.');
186198
process.exit(1);
187199
}
188-
200+
let { httpProxy, httpsProxy } = detectProxy();
189201
if (noQuestions) {
190202
// use defaults
191203
kubeContextName = getKubeContext(kubeConfigPath);
@@ -218,6 +230,20 @@ const initCmd = new Command({
218230
validate: value => (value !== undefined && value !== '') || 'Please enter namespace\'s name',
219231
});
220232
}
233+
questions.push({
234+
type: 'input',
235+
name: 'httpProxy',
236+
default: httpProxy,
237+
message: 'HTTP proxy to be used by runner inside Kubernetes ?',
238+
239+
});
240+
questions.push({
241+
type: 'input',
242+
name: 'httpsProxy',
243+
default: httpsProxy,
244+
message: 'HTTPS proxy to be used by runner inside Kubernetes ?',
245+
246+
});
221247

222248
if (_.isUndefined(shouldMakeDefaultRe)) {
223249
if (!_.get(sdk, 'config.context.isNoAuth') && await isNewAccount()) {
@@ -252,6 +278,7 @@ const initCmd = new Command({
252278
kubeNamespace = kubeNamespace || answers.namespace;
253279
shouldMakeDefaultRe = _.isUndefined(shouldMakeDefaultRe) ? answers.shouldMakeDefaultRe : shouldMakeDefaultRe;
254280
shouldExecutePipeline = _.isUndefined(shouldExecutePipeline) ? answers.shouldExecutePipeline : shouldExecutePipeline;
281+
({ httpProxy, httpsProxy } = answers);
255282
}
256283

257284
printInstallationOptionsSummary({
@@ -293,11 +320,19 @@ const initCmd = new Command({
293320
installationPlan = new InstallationPlan({ progressReporter, errHandler: handleError });
294321
}
295322

323+
if (httpProxy) {
324+
envVars = _.merge(envVars || {}, { http_proxy: httpProxy, HTTP_PROXY: httpProxy });
325+
}
326+
if (httpsProxy) {
327+
envVars = _.merge(envVars || {}, { https_proxy: httpsProxy, HTTPS_PROXY: httpsProxy });
328+
}
329+
296330
// save the answers for backup
297331
_argv['kube-context-name'] = kubeContextName;
298332
_argv['kube-namespace'] = kubeNamespace;
299333
_argv['set-default-runtime'] = shouldMakeDefaultRe;
300334
_argv['exec-demo-pipeline'] = shouldExecutePipeline;
335+
_argv['env-vars'] = envVars;
301336
installationPlan.addContext('argv', _argv);
302337

303338
// run cluster acceptance tests
@@ -350,6 +385,7 @@ const initCmd = new Command({
350385
kubeConfigPath,
351386
verbose,
352387
agentId: installationPlan.getContext('agentName'),
388+
envVars: serealizeToKeyValuePairs(envVars),
353389
});
354390
},
355391
installationEvent: installationProgress.events.AGENT_INSTALLED,
@@ -380,7 +416,7 @@ const initCmd = new Command({
380416
};
381417

382418
if (buildNodeSelector) {
383-
runtimeCreateOpt.nodeSelector = parseNodeSelector(buildNodeSelector);
419+
runtimeCreateOpt.nodeSelector = keyValueAsStringToObject(buildNodeSelector);
384420
}
385421

386422
await sdk.cluster.create(runtimeCreateOpt);

lib/interface/cli/commands/hybrid/migration.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,14 @@ const {
1212
createTestPipeline,
1313
executeTestPipeline,
1414
createProgressBar,
15+
runUpgrade,
16+
serealizeToKeyValuePairs,
1517
} = require('./helper');
1618
const { getNewAgentName } = require('../agent/helper');
1719

1820

1921
const TEST_PIPELINE_NAME = 'CF_Runner_Migration_test';
2022

21-
function serealizeNodeSelector(objNodeSelector) {
22-
return _.keys(objNodeSelector).reduce((acc, key) => {
23-
if (acc) {
24-
return `${acc},${key}=${objNodeSelector[key]}`;
25-
}
26-
return `${key}=${objNodeSelector[key]}`;
27-
}, '');
28-
}
29-
3023
async function createAndRunTestPipeline(runtimeName, errHandler) {
3124
let testPipeline;
3225
const [getPipelineErr, _testPipeline] = await to(getTestPipeline(TEST_PIPELINE_NAME));
@@ -119,6 +112,7 @@ async function migrate({
119112
// read old deploment configuration
120113
const filename = './migration.json';
121114
let oldConfig = {};
115+
let oldEnv;
122116
try {
123117
const data = fs.readFileSync(filename).toString('utf-8');
124118
oldConfig = JSON.parse(data);
@@ -131,11 +125,14 @@ async function migrate({
131125
}
132126

133127
if (oldConfig.nodeSelector) {
134-
oldConfig.nodeSelector = serealizeNodeSelector(oldConfig.nodeSelector);
128+
oldConfig.nodeSelector = serealizeToKeyValuePairs(oldConfig.nodeSelector);
135129
}
136130

137131
if (oldNodeSelector) {
138-
oldNodeSelector = serealizeNodeSelector(oldNodeSelector);
132+
oldNodeSelector = serealizeToKeyValuePairs(oldNodeSelector);
133+
}
134+
if (oldConfig.env) {
135+
oldEnv = serealizeToKeyValuePairs(oldConfig.env);
139136
}
140137

141138
// install new agent and runtime
@@ -160,6 +157,7 @@ async function migrate({
160157
terminateProcess: false,
161158
'set-value': setValue,
162159
'set-file': setFile,
160+
envVars: oldEnv,
163161
};
164162
const [agentInstallErr] = await to(installAgent.handler(agentInstallOptions));
165163
handleError(agentInstallErr, 'Failed to install new agent and runtime');
@@ -184,8 +182,9 @@ async function migrate({
184182
await createAndRunTestPipeline(runtimeName, handleError);
185183
}
186184

187-
async function upgrade({ kubeContextName, kubeNamespace, agentName }) {
188-
console.log('Upgrade is not yet supported. You can manually upgrade your Codefresh runner by reinstalling it.');
185+
async function upgrade({ kubeContextName, kubeNamespace, handleError }) {
186+
const [err] = await to(runUpgrade({ kubeNamespace, kubeContextName }));
187+
await handleError(err, 'Upgrade failed');
189188
}
190189
module.exports = {
191190
migrate,

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const installRuntimeCmd = new Command({
6464
describe: 'Name of the kubernetes context on which the runtime should be installed (default is current-context) [$CF_ARG_KUBE_CONTEXT_NAME]',
6565
})
6666
.option('kube-node-selector', {
67-
describe: 'The kubernetes node selector "key=value" to be used by venona build resources (default is no node selector) (string)',
67+
describe: 'The kubernetes node selector "key=value" to be used by runner build resources (default is no node selector) (string)',
6868
})
6969
.option('set-value', {
7070
describe: 'Set values for templates, example: --set-value LocalVolumesDir=/mnt/disks/ssd0/codefresh-volumes',
@@ -76,7 +76,7 @@ const installRuntimeCmd = new Command({
7676
describe: 'Set to true to simulate installation',
7777
})
7878
.option('in-cluster', {
79-
describe: 'Set flag if venona is been installed from inside a cluster',
79+
describe: 'Set flag if runner is been installed from inside a cluster',
8080
})
8181
.option('runtime-kube-namespace', {
8282
describe: 'Name of the namespace on which runtime should be installed [$CF_ARG_KUBE_NAMESPACE]',
@@ -85,7 +85,7 @@ const installRuntimeCmd = new Command({
8585
describe: 'Set the runner type to kubernetes (alpha feature)',
8686
})
8787
.option('build-annotations', {
88-
describe: 'The kubernetes metadata.annotations as "key=value" to be used by venona build resources (default is no node selector)',
88+
describe: 'The kubernetes metadata.annotations as "key=value" to be used by runner build resources (default is no node selector)',
8989
})
9090
.option('runtime-kube-config-path', {
9191
describe: 'Path to kubeconfig file (default is $HOME/.kube/config)',

0 commit comments

Comments
 (0)