Skip to content

Commit 12a9431

Browse files
Saas 7579 (#514)
Download components on image to offline
1 parent 0f662de commit 12a9431

File tree

11 files changed

+202
-102
lines changed

11 files changed

+202
-102
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ RUN apk del yarn
3939

4040
RUN ln -s $(pwd)/lib/interface/cli/codefresh /usr/local/bin/codefresh
4141

42+
RUN codefresh components update --location components
4243
ENTRYPOINT ["codefresh"]

lib/binary/downloader.js

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,16 @@ function _ensureDirectory(location) {
2828
}
2929

3030
async function _getRemoteVersion({
31-
name, osType,
31+
name, branch, path, file,
3232
}) {
33-
// get the 10 latest releases
34-
const releasesUrl = `https://api.github.com/repos/codefresh-io/${name}/releases?per_page=10`;
35-
const res = await rp({
36-
uri: releasesUrl,
33+
const final = branch ? `${name}/${branch}/${path}` : `${name}/${path}`;
34+
const url = `https://raw.githubusercontent.com/codefresh-io/${final}/${file}`;
35+
const req = await rp({
36+
url,
3737
method: 'GET',
3838
headers: { 'User-Agent': 'codefresh' },
3939
});
40-
41-
const releases = JSON.parse(res);
42-
for (let i = 0; i < releases.length; i += 1) {
43-
const curRelease = releases[i];
44-
const neededAsset = (curRelease.assets || []).find(asset => {
45-
const assetName = asset.name || '';
46-
return assetName.startsWith(`${name}_`) && assetName.endsWith(osType);
47-
});
48-
if (neededAsset) {
49-
return { remoteVersion: curRelease.name, download_url: neededAsset.browser_download_url };
50-
}
51-
}
52-
return { remoteVersion: '0', download_url: '' };
40+
return req;
5341
}
5442

5543
function _buildDownloadURL({ name, version, binary }) {
@@ -118,19 +106,26 @@ class Downloader {
118106

119107
let localVersion = _getLocalVersion(join(dir, component.local.versionFile));
120108
const {
121-
repo: name,
109+
repo: name, branch, versionPath: path, versionFile: file,
122110
} = component.remote;
123-
let { remoteVersion, download_url } = await _getRemoteVersion({ name, osType });
111+
let remoteVersion = await _getRemoteVersion({
112+
name, branch, path, file,
113+
});
124114
remoteVersion = remoteVersion.trim();
125115
localVersion = localVersion.trim();
126116

127117
if (compareVersions(localVersion, remoteVersion) >= 0) {
118+
// logger.debug(`Download is not required latest-version=${remoteVersion} local-version=${localVersion}`);
128119
return Promise.resolve();
129120
}
130-
logger.debug(`${component.name} component upgrade is required, downloading latest version [${remoteVersion}]`);
121+
logger.debug(`${component.name} component upgrade is required, downloading.`);
131122

132-
const resp = await request(download_url);
133123

124+
const binary = `${name}_${remoteVersion}_${osType}`;
125+
const version = component.version.prefix ? `${component.version.prefix}${remoteVersion}` : remoteVersion;
126+
const url = _buildDownloadURL({ name, version, binary });
127+
const resp = await request(url);
128+
134129
if (this.progress) {
135130
let size = 0;
136131
resp.on('response', (res) => {
@@ -161,11 +156,15 @@ class Downloader {
161156
}
162157
resolveFn();
163158
});
159+
resp.on('error', (err) => {
160+
rejectFn(err);
161+
});
164162
});
165163
}
166164
}
167165

168166
module.exports = {
169167
CommonProgressFormat: 'downloading [{bar}] {percentage}% | {value}/{total}',
170168
Downloader,
169+
CODEFRESH_PATH,
171170
};

lib/binary/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
const components = require('./components');
22
const { Runner } = require('./runner');
3-
const { Downloader, CommonProgressFormat } = require('./downloader');
3+
const { Downloader, CommonProgressFormat, CODEFRESH_PATH } = require('./downloader');
44

55
module.exports = {
66
components,
77
Runner,
88
Downloader,
99
CommonProgressFormat,
10+
CODEFRESH_PATH,
1011
};

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
const getCmd = require('./get.cmd').toCommand();
22
const deleteCmd = require('./delete.cmd').toCommand();
33
const createCmd = require('./create.cmd').toCommand();
4-
const { sdk } = require('../../../../logic');
5-
4+
const { Runner } = require('./../../../../binary');
65
const request = require('requestretry');
76

87
jest.mock('../../../../logic/entities/Cluster');
9-
8+
jest.mock('../hybrid/helper');
9+
jest.mock('./../../../../binary');
1010

1111
const DEFAULT_RESPONSE = request.__defaultResponse();
1212

@@ -29,10 +29,9 @@ describe('cluster commands', () => {
2929

3030
describe('create', () => {
3131
it('should skip', async () => {
32-
jest.spyOn(sdk.clusters, 'create').mockImplementation();
3332
const argv = {};
3433
await createCmd.handler(argv);
35-
expect(sdk.clusters.create).toBeCalled();
34+
expect(Runner.mock.instances[0].run).toBeCalled();
3635
});
3736
});
3837

lib/interface/cli/commands/cluster/create.cmd.js

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
const Command = require('../../Command');
22
const createRoot = require('../root/create.cmd');
33
const { sdk } = require('../../../../logic');
4-
const ProgressEvents = require('../../helpers/progressEvents');
5-
const cliProgress = require('cli-progress');
4+
const { downloadSteveDore } = require('../hybrid/helper');
5+
const { Runner, components } = require('../../../../binary');
66

77
const command = new Command({
88
command: 'clusters [name]',
@@ -53,33 +53,30 @@ const command = new Command({
5353
if (terminateProcess === undefined) {
5454
terminateProcess = true;
5555
}
56-
const events = new ProgressEvents();
57-
const format = 'downloading cluster installer [{bar}] {percentage}% | {value}/{total}';
58-
const progressBar = new cliProgress.SingleBar(
59-
{ stopOnComplete: true, format },
60-
cliProgress.Presets.shades_classic,
61-
);
62-
let clusterTotalSize;
63-
events.onStart((size) => {
64-
progressBar.start(size, 0);
65-
clusterTotalSize = size;
66-
});
67-
events.onProgress((progress) => {
68-
progressBar.update(progress);
69-
if (progress >= clusterTotalSize) {
70-
console.log('\n');
71-
}
72-
});
73-
return sdk.clusters.create({
56+
const binLocation = await downloadSteveDore();
57+
const componentRunner = new Runner(binLocation);
58+
const commands = [
59+
'create',
60+
'--c',
7461
contextName,
75-
context,
62+
'--token',
63+
context.token,
64+
'--api-host',
65+
`${context.url}/`,
66+
'--namespace',
7667
namespace,
68+
'--serviceaccount',
7769
serviceaccount,
78-
behindFirewall,
79-
name,
80-
terminateProcess,
81-
events,
82-
});
70+
];
71+
if (name) {
72+
commands.push('--name-overwrite');
73+
commands.push(name);
74+
}
75+
if (behindFirewall) {
76+
commands.push('--behind-firewall');
77+
}
78+
79+
await componentRunner.run(components.stevedore, commands);
8380
},
8481
});
8582

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const Command = require('../../Command');
2+
const componentsRoot = require('../root/components.cmd');
3+
const helper = require('../hybrid/helper');
4+
5+
const command = new Command({
6+
command: 'update',
7+
parent: componentsRoot,
8+
description: 'Update Codefresh CLI components',
9+
webDocs: {
10+
category: 'Componenets',
11+
title: 'Update',
12+
},
13+
builder: yargs => yargs
14+
.env('CF_ARG_') // this means that every process.env.CF_ARG_* will be passed to argv
15+
.option('location', {
16+
describe: 'Override dowload folder location',
17+
}),
18+
handler: async (argv) => {
19+
console.log('Updating components');
20+
const { location } = argv;
21+
await helper.downloadRelatedComponents(location);
22+
},
23+
});
24+
25+
module.exports = command;

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

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ const { followLogs } = require('../../helpers/logs');
1010
const ProgressEvents = require('../../helpers/progressEvents');
1111
const cliProgress = require('cli-progress');
1212
const figlet = require('figlet');
13+
const path = require('path');
1314
const {
1415
components, Runner, Downloader, CommonProgressFormat,
16+
CODEFRESH_PATH,
1517
} = require('./../../../../binary');
18+
const { pathExists } = require('../../helpers/general');
1619

1720
const INSTALLATION_DEFAULTS = {
1821
NAMESPACE: 'codefresh',
@@ -23,6 +26,7 @@ const INSTALLATION_DEFAULTS = {
2326
CF_CONTEXT_NAME: 'cf-runner',
2427
STORAGE_CLASS_PREFIX: 'dind-local-volumes-runner',
2528
RESUME_OLD_INSTALLATION: true,
29+
COMPONENTS_FOLDER: 'components',
2630
};
2731

2832
const maxRuntimeNameLength = 63;
@@ -308,7 +312,7 @@ async function getRecommendedKubeNamespace(kubeconfigPath, kubeContextName) {
308312
return name;
309313
}
310314

311-
async function _downloadVeonona() {
315+
async function downloadVeonona(location = CODEFRESH_PATH) {
312316
const downloader = new Downloader({
313317
progress: new cliProgress.SingleBar(
314318
{
@@ -317,13 +321,57 @@ async function _downloadVeonona() {
317321
},
318322
cliProgress.Presets.shades_classic,
319323
),
324+
location,
320325
});
321-
await downloader.download(components.venona);
326+
const [error] = await to(downloader.download(components.venona));
327+
if (error) {
328+
const newLocation = path.join(INSTALLATION_DEFAULTS.COMPONENTS_FOLDER, components.venona.local.dir, components.venona.local.binary);
329+
if (await pathExists(newLocation)) {
330+
console.log('Failed to download installer, using binary from components folder');
331+
return path.resolve(process.cwd(), INSTALLATION_DEFAULTS.COMPONENTS_FOLDER);
332+
}
333+
console.log('Failed to download component, aborting');
334+
throw error;
335+
}
336+
return location;
337+
}
338+
async function downloadSteveDore(location = CODEFRESH_PATH) {
339+
const downloader = new Downloader({
340+
progress: new cliProgress.SingleBar(
341+
{
342+
stopOnComplete: true,
343+
format: CommonProgressFormat,
344+
},
345+
cliProgress.Presets.shades_classic,
346+
),
347+
location,
348+
});
349+
const [error] = await to(downloader.download(components.stevedore));
350+
if (error) {
351+
const newLocation = path.join(
352+
INSTALLATION_DEFAULTS.COMPONENTS_FOLDER,
353+
components.stevedore.local.dir, components.stevedore.local.binary,
354+
);
355+
if (await pathExists(newLocation)) {
356+
console.log('Failed to download installer, using binary from components folder');
357+
return path.resolve(process.cwd(), INSTALLATION_DEFAULTS.COMPONENTS_FOLDER);
358+
}
359+
console.log('Failed to download component, aborting');
360+
throw error;
361+
}
362+
return location;
363+
}
364+
365+
async function downloadHybridComponents(location) {
366+
await downloadVeonona(location);
367+
console.log(`Kubernetes components installer downloaded successfully to ${location} `);
368+
await downloadSteveDore(location);
369+
console.log(`Kubernetes registrator installer downloaded successfully ${location}`);
322370
}
323371

324372
async function runClusterAcceptanceTests({ kubeNamespace, kubeConfigPath }) {
325-
await _downloadVeonona();
326-
const componentRunner = new Runner();
373+
const binLocation = await downloadVeonona();
374+
const componentRunner = new Runner(binLocation);
327375
const cmd = ['test', '--log-formtter', DefaultLogFormatter];
328376
if (kubeNamespace) {
329377
cmd.push('--kube-namespace');
@@ -353,8 +401,8 @@ async function installAgent({
353401
verbose, // --verbose
354402
logFormatting = DefaultLogFormatter, // --log-formtter
355403
}) {
356-
await _downloadVeonona();
357-
const componentRunner = new Runner();
404+
const binLocation = await downloadVeonona();
405+
const componentRunner = new Runner(binLocation);
358406
const cmd = [
359407
'install',
360408
'agent',
@@ -422,8 +470,8 @@ async function installRuntime({
422470
storageClassName, // --storage-class
423471
logFormatting = DefaultLogFormatter, // --log-formtter
424472
}) {
425-
await _downloadVeonona();
426-
const componentRunner = new Runner();
473+
const binLocation = await downloadVeonona();
474+
const componentRunner = new Runner(binLocation);
427475
const cmd = [
428476
'install',
429477
'runtime',
@@ -487,8 +535,8 @@ async function attachRuntime({
487535
runtimeName, // --runtimeName
488536
logFormatting = DefaultLogFormatter, // --log-formtter
489537
}) {
490-
await _downloadVeonona();
491-
const componentRunner = new Runner();
538+
const binLocation = await downloadVeonona();
539+
const componentRunner = new Runner(binLocation);
492540
const cmd = [
493541
'attach',
494542
'--kube-context-name',
@@ -615,6 +663,9 @@ module.exports = {
615663
newRuntimeName,
616664
newAgentName,
617665
parseNodeSelector,
666+
downloadRelatedComponents: downloadHybridComponents,
667+
downloadSteveDore,
668+
downloadVeonona,
618669
INSTALLATION_DEFAULTS,
619670
DefaultLogFormatter,
620671
};

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ const initCmd = new Command({
111111
.option('install-monitor', {
112112
describe: 'Install a monitoring component that will help provide valueable data about your cluster to Codefresh',
113113
type: 'boolean',
114-
default: true,
114+
default: true,
115115
})
116116
.option('kube-namespace', {
117117
describe: 'Name of the namespace on which venona should be installed [$CF_ARG_KUBE_NAMESPACE]',
@@ -330,7 +330,6 @@ const initCmd = new Command({
330330
installationPlan.addContext('agent', agent);
331331
const { token: agentToken } = agent;
332332
console.log(`A Codefresh Runner with the name: ${colors.cyan(agentName)} has been created.`);
333-
console.log(agentToken);
334333
installationPlan.addContext('agentToken', agentToken);
335334
},
336335
condition: async () => !installationPlan.getContext('agentToken'),

0 commit comments

Comments
 (0)