Skip to content

Commit c89f745

Browse files
Auto creation cluster and re (#234)
1 parent 7c4a77e commit c89f745

File tree

9 files changed

+448
-3
lines changed

9 files changed

+448
-3
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
const debug = require('debug')('codefresh:cli:create:context');
2+
const Command = require('../../Command');
3+
const { cluster } = require('../../../../logic').api;
4+
const createRoot = require('../root/create.cmd');
5+
const authManager = require('../../../../logic/auth').manager; // eslint-disable-line
6+
7+
const command = new Command({
8+
command: 'clusters [name]',
9+
aliases: ['cluster'],
10+
parent: createRoot,
11+
description: 'Create a cluster',
12+
webDocs: {
13+
category: 'Clusters',
14+
title: 'Create Cluster',
15+
weight: 100,
16+
},
17+
builder: (yargs) => {
18+
return yargs
19+
.positional('name', {
20+
describe: 'cluster name',
21+
required: true,
22+
})
23+
.example('codefresh create cluster [name]', 'Creating a cluster');
24+
},
25+
handler: async (argv) => {
26+
const context = authManager.getCurrentContext();
27+
const { name } = argv;
28+
await cluster.createCluster({
29+
name,
30+
context,
31+
});
32+
},
33+
});
34+
35+
36+
module.exports = command;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const debug = require('debug')('codefresh:cli:create:context');
2+
const Command = require('../../Command');
3+
const { cluster } = require('../../../../logic').api;
4+
const deleteRoot = require('../root/delete.cmd');
5+
6+
const command = new Command({
7+
command: 'cluster <name>',
8+
aliases: ['clusters'],
9+
description: 'Delete a cluster',
10+
parent: deleteRoot,
11+
webDocs: {
12+
category: 'Clusters',
13+
title: 'Delete Cluster',
14+
},
15+
builder: (yargs) => {
16+
return yargs
17+
.positional('name', {
18+
describe: 'Cluster name',
19+
required: true,
20+
})
21+
.example('codefresh delete cluster NAME', 'Delete cluster NAME');
22+
},
23+
handler: async (argv) => {
24+
await cluster.deleteCluster(argv.name);
25+
console.log(`Cluster: ${argv.name} deleted`);
26+
},
27+
});
28+
29+
module.exports = command;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const debug = require('debug')('codefresh:cli:get:cluster');
2+
const Command = require('../../Command');
3+
const { cluster } = require('../../../../logic').api;
4+
const { specifyOutputForArray } = require('../../helpers/get');
5+
const getRoot = require('../root/get.cmd');
6+
7+
8+
const command = new Command({
9+
command: 'clusters',
10+
aliases: ['cluster'],
11+
category: 'Clusters',
12+
parent: getRoot,
13+
description: 'Get an array of clusters',
14+
webDocs: {
15+
category: 'Clusters',
16+
title: 'Get Clusters',
17+
},
18+
builder: (yargs) => {
19+
return yargs
20+
.example('codefresh get clusters', 'Get all clusters');
21+
},
22+
handler: async (argv) => {
23+
const clusters = await cluster.getAllClusters();
24+
specifyOutputForArray(argv.output, clusters);
25+
},
26+
});
27+
28+
module.exports = command;
29+
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const debug = require('debug')('codefresh:cli:create:context');
2+
const Command = require('../../Command');
3+
const fs = require('fs');
4+
const { spawn } = require('child_process');
5+
const { homedir } = require('os');
6+
const rp = require('request-promise');
7+
const createRoot = require('../root/create.cmd');
8+
const authManager = require('../../../../logic/auth').manager; // eslint-disable-line
9+
10+
const scriptUrl = 'https://raw.githubusercontent.com/codefresh-io/k8s-dind-config/master/codefresh-k8s-configure.sh';
11+
let filePath = `${homedir()}/.Codefresh/runtime/codefresh-k8s-configure.sh`;
12+
const dirPath = `${homedir()}/.Codefresh/runtime`;
13+
14+
15+
const callToScript = (k8sScript) =>{
16+
k8sScript.stdout.pipe(process.stdout);
17+
k8sScript.stderr.pipe(process.stderr);
18+
process.stdin.pipe(k8sScript.stdin);
19+
k8sScript.on('exit', (code) => {
20+
fs.unlink('filePath', (error) => {
21+
if (error) {
22+
throw error;
23+
}
24+
console.log('finish');
25+
});
26+
process.exit(code);
27+
});
28+
};
29+
30+
31+
const command = new Command({
32+
command: 'runtime-environments [cluster]',
33+
aliases: ['re', 'runtime-environment'],
34+
parent: createRoot,
35+
description: 'Create a runtime environment',
36+
webDocs: {
37+
category: 'Runtime-Environments (On Prem)',
38+
title: 'Create Runtime-Environments',
39+
weight: 100,
40+
},
41+
builder: (yargs) => {
42+
return yargs
43+
.positional('cluster', {
44+
describe: 'cluster name',
45+
required: true,
46+
})
47+
.option('namespace', {
48+
describe: 'namespace',
49+
})
50+
.option('local', {
51+
describe: 'set if run the script from local file system',
52+
type: 'boolean',
53+
default: false,
54+
})
55+
.option('context', {
56+
describe: 'set your kubectl context',
57+
default: '',
58+
})
59+
.example('codefresh create re [cluster] --namespace codefresh --context kubeCodefresh', 'Creating a runtime environment');
60+
},
61+
handler: async (argv) => {
62+
const currentContext = authManager.getCurrentContext();
63+
const { local, namespace, cluster, context } = argv;
64+
if (!local) {
65+
if (!fs.existsSync(dirPath)) {
66+
fs.mkdirSync(dirPath);
67+
}
68+
const options = {
69+
url: scriptUrl,
70+
method: 'GET',
71+
};
72+
const response = await rp(options);
73+
fs.writeFile(filePath, response, (err) => {
74+
if (err) {
75+
throw err;
76+
}
77+
fs.chmodSync(filePath, '644');
78+
const k8sScript = spawn('bash', [filePath, '--api-token', currentContext.token, '--api-host', currentContext.url, '--namespace', namespace, '--context', context, cluster]);
79+
callToScript(k8sScript);
80+
});
81+
} else {
82+
filePath = './codefresh-k8s-configure.sh';
83+
const k8sScript = spawn('bash', [filePath, '--api-token', currentContext.token, '--api-host', currentContext.url, '--namespace', namespace, '--local','--context', context, cluster]);
84+
callToScript(k8sScript);
85+
}
86+
},
87+
});
88+
89+
90+
module.exports = command;

lib/logic/api/cluster.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
const _ = require('lodash');
2+
const { sendHttpRequest } = require('./helper');
3+
const Cluster = require('../entities/Cluster');
4+
const rp = require('request-promise');
5+
const fs = require('fs');
6+
const { spawn } = require('child_process');
7+
const { homedir, arch } = require('os');
8+
const request = require('request');
9+
const decompress = require('decompress');
10+
const decompressTargz = require('decompress-targz');
11+
const compareVersions = require('compare-versions');
12+
13+
const _createClusterScript = (info, filePath) => {
14+
const { name, context } = info;
15+
fs.chmodSync(filePath, '755');
16+
const clusterScript = spawn(filePath, ['create', '--c', name, '--token', context.token, '--api-host', `${context.url}/`] );
17+
clusterScript.stdout.pipe(process.stdout);
18+
clusterScript.stderr.pipe(process.stderr);
19+
process.stdin.pipe(clusterScript.stdin);
20+
clusterScript.on('exit', (code) => {
21+
process.exit(code);
22+
});
23+
};
24+
25+
const _extractFieldsForTeamEntity = cluster => ({
26+
id: cluster._id,
27+
name: cluster.selector,
28+
provider: cluster.provider,
29+
providerAgent: cluster.providerAgent,
30+
});
31+
32+
const getAllClusters = async () => {
33+
const userOptions = {
34+
url: '/api/clusters',
35+
method: 'GET',
36+
};
37+
38+
const result = await sendHttpRequest(userOptions);
39+
const clusters = [];
40+
let data = {};
41+
_.forEach(result, (cluster) => {
42+
data = _extractFieldsForTeamEntity(cluster);
43+
clusters.push(new Cluster(data));
44+
});
45+
return clusters;
46+
};
47+
48+
const createCluster = async (info) => {
49+
const dirPath = `${homedir()}/.Codefresh/cluster`;
50+
const filePath = `${homedir()}/.Codefresh/cluster/stevedore`;
51+
const versionPath = `${homedir()}/.Codefresh/cluster/version.txt`;
52+
const versionUrl = 'https://raw.githubusercontent.com/codefresh-io/Stevedore/master/VERSION';
53+
let zipPath = `${homedir()}/.Codefresh/cluster/data`;
54+
let shouldUpdate = true;
55+
const options = {
56+
url: versionUrl,
57+
method: 'GET',
58+
headers: {
59+
'User-Agent': 'codefresh',
60+
},
61+
};
62+
const version = await rp(options);
63+
if (!fs.existsSync(dirPath)) {
64+
fs.mkdirSync(dirPath);
65+
} else if (fs.existsSync(versionPath)) {
66+
const currVersion = fs.readFileSync(versionPath, { encoding: 'UTF8' }).trim();
67+
if (compareVersions(currVersion, version) >= 0) {
68+
shouldUpdate = false;
69+
}
70+
}
71+
if (shouldUpdate) {
72+
let osType;
73+
const { platform } = process;
74+
if (_.isEqual(platform, 'darwin')) {
75+
osType = _.isEqual(arch(), 'x32') ? 'Darwin_i386.tar.gz' : 'Darwin_x86_64.tar.gz';
76+
zipPath = `${zipPath}.tar.gz`;
77+
} else if (_.isEqual(platform, 'linux')) {
78+
osType = _.isEqual(arch(), 'x32') ? 'Linux_i386.tar.gz' : 'Linux_x86_64.tar.gz';
79+
zipPath = `${zipPath}.tar.gz`;
80+
} else if (_.isEqual(platform, 'ein32')) {
81+
osType = _.isEqual(arch(), 'x32') ? 'Windows_i386.zip' : 'Windows_x86_64.zip';
82+
zipPath = `${zipPath}.zip`;
83+
}
84+
const assetUrl = `https://github.com/codefresh-io/Stevedore/releases/download/v${version}/stevedore_${version}_${osType}`;
85+
const req = request(assetUrl);
86+
req.pipe(fs.createWriteStream(zipPath));
87+
req.on('end', () => {
88+
console.log('File written!');
89+
decompress(zipPath, `${homedir()}/.Codefresh/cluster`, {
90+
plugins: [
91+
decompressTargz(),
92+
],
93+
}).then(() => {
94+
console.log('Files decompressed');
95+
fs.writeFile(versionPath, version, (err) => {
96+
if (err) {
97+
throw err;
98+
}
99+
});
100+
_createClusterScript(info, filePath);
101+
});
102+
});
103+
} else {
104+
_createClusterScript(info, filePath);
105+
}
106+
};
107+
108+
const deleteCluster = async (clusterName) => {
109+
const clusters = await getAllClusters();
110+
const cluster = _.find(clusters, (curr) => {
111+
return _.isEqual(curr.info.name, clusterName);
112+
});
113+
const options = {
114+
url: `/api/clusters/${cluster.info.provider}/cluster/${cluster.info.id}`,
115+
method: 'DELETE',
116+
};
117+
118+
return sendHttpRequest(options);
119+
};
120+
121+
module.exports = {
122+
createCluster,
123+
getAllClusters,
124+
deleteCluster,
125+
};

lib/logic/api/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const runtimeEnvironments = require('./runtimeEnvironments');
1313
const team = require('./team');
1414
const board = require('./board');
1515
const section = require('./section');
16+
const cluster = require('./cluster');
1617

1718
module.exports = {
1819
user,
@@ -30,4 +31,5 @@ module.exports = {
3031
team,
3132
board,
3233
section,
34+
cluster,
3335
};

lib/logic/entities/Cluster.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const Entity = require('./Entity');
2+
3+
class Cluster extends Entity {
4+
constructor(data) {
5+
super();
6+
this.entityType = 'cluster';
7+
this.info = data;
8+
this.defaultColumns = ['id', 'name'];
9+
this.wideColumns = this.defaultColumns.concat(['provider', 'providerAgent']);
10+
}
11+
}
12+
13+
module.exports = Cluster;

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@
3232
"cli-progress": "^1.6.1",
3333
"colors": "^1.1.2",
3434
"columnify": "^1.5.4",
35+
"compare-versions": "^3.4.0",
3536
"copy-dir": "^0.3.0",
3637
"debug": "^3.1.0",
38+
"decompress": "^4.2.0",
39+
"decompress-targz": "^4.1.1",
3740
"diff": "^3.5.0",
3841
"draftlog": "^1.0.12",
3942
"filesize": "^3.5.11",
@@ -47,7 +50,7 @@
4750
"mongodb": "^3.0.1",
4851
"prettyjson": "^1.2.1",
4952
"recursive-readdir": "^2.2.1",
50-
"request": "^2.83.0",
53+
"request": "^2.88.0",
5154
"request-promise": "^4.2.2",
5255
"rimraf": "^2.6.2",
5356
"tty-table": "^2.5.5",

0 commit comments

Comments
 (0)