clever-tools 3.8.3 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/clever.js +178 -427
- package/package.json +10 -3
- package/src/command-options.js +4 -10
- package/src/command-promise-handler.js +5 -7
- package/src/commands/accesslogs.js +9 -13
- package/src/commands/activity.js +10 -14
- package/src/commands/addon.js +68 -38
- package/src/commands/applications.js +9 -16
- package/src/commands/cancel-deploy.js +5 -9
- package/src/commands/config.js +7 -11
- package/src/commands/console.js +5 -9
- package/src/commands/create.js +5 -9
- package/src/commands/curl.js +7 -11
- package/src/commands/database.js +13 -16
- package/src/commands/delete.js +4 -8
- package/src/commands/deploy.js +10 -14
- package/src/commands/diag.js +9 -11
- package/src/commands/domain.js +354 -17
- package/src/commands/drain.js +10 -20
- package/src/commands/env.js +13 -17
- package/src/commands/link.js +3 -7
- package/src/commands/login.js +13 -15
- package/src/commands/logout.js +3 -7
- package/src/commands/logs.js +9 -13
- package/src/commands/makeDefault.js +3 -7
- package/src/commands/notify-email.js +9 -19
- package/src/commands/open.js +5 -9
- package/src/commands/profile.js +21 -12
- package/src/commands/published-config.js +11 -15
- package/src/commands/restart.js +7 -11
- package/src/commands/scale.js +3 -7
- package/src/commands/service.js +8 -18
- package/src/commands/ssh.js +4 -8
- package/src/commands/status.js +7 -11
- package/src/commands/stop.js +5 -9
- package/src/commands/tcp-redirs.js +11 -15
- package/src/commands/unlink.js +4 -8
- package/src/commands/version.js +4 -6
- package/src/commands/webhooks.js +8 -16
- package/src/format-table.js +4 -8
- package/src/initial-setup.js +49 -0
- package/src/load-package-json.cjs +5 -0
- package/src/logger.js +5 -8
- package/src/models/activity.js +3 -7
- package/src/models/addon.js +44 -59
- package/src/models/app_configuration.js +18 -31
- package/src/models/application.js +37 -61
- package/src/models/application_configuration.js +11 -15
- package/src/models/configuration.js +11 -15
- package/src/models/deployments.js +6 -10
- package/src/models/domain.js +6 -10
- package/src/models/drain.js +5 -13
- package/src/models/exit-strategy-option.js +4 -8
- package/src/models/fs-utils.js +3 -7
- package/src/models/git.js +19 -34
- package/src/models/ids-resolver.js +6 -12
- package/src/models/interact.js +2 -6
- package/src/models/isomorphic-http-with-agent.js +3 -9
- package/src/models/json-array.js +1 -3
- package/src/models/log-v4.js +10 -12
- package/src/models/log.js +11 -15
- package/src/models/namespaces.js +7 -13
- package/src/models/node-dns-resolver.js +43 -0
- package/src/models/notification.js +8 -17
- package/src/models/organisation.js +4 -10
- package/src/models/send-to-api.js +17 -13
- package/src/models/user.js +16 -9
- package/src/models/utils.js +2 -6
- package/src/models/variables.js +4 -10
- package/src/parsers.js +31 -70
- package/src/commands/networkgroups/commands.js +0 -7
- package/src/commands/networkgroups/index.js +0 -67
- package/src/commands/networkgroups/members.js +0 -80
- package/src/commands/networkgroups/peers.js +0 -83
- package/src/models/format-ng-table.js +0 -115
- package/src/models/format-string.js +0 -44
- package/src/models/networkgroup.js +0 -64
- package/src/models/wireguard-conf.js +0 -95
- package/src/models/wireguard.js +0 -75
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Resolver } from 'node:dns/promises';
|
|
2
|
+
|
|
3
|
+
export class DnsResolver {
|
|
4
|
+
constructor () {
|
|
5
|
+
this._resolver = new Resolver();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resolves A records for the given hostname.
|
|
10
|
+
*
|
|
11
|
+
* @async
|
|
12
|
+
* @param {string} hostname - The hostname to resolve A records for.
|
|
13
|
+
* @returns {Promise<string[]>} A promise that resolves to an array of IP addresses, or an empty array if not found or an error occurs.
|
|
14
|
+
*/
|
|
15
|
+
resolveA (hostname) {
|
|
16
|
+
return this._resolver.resolve4(hostname).catch((error) => {
|
|
17
|
+
switch (error.code) {
|
|
18
|
+
case 'ENOTFOUND':
|
|
19
|
+
case 'ENODATA':
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`Could not resolve DNS for ${hostname}. Caused by: ${error.message}`);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolves CNAME records for the given hostname.
|
|
28
|
+
*
|
|
29
|
+
* @async
|
|
30
|
+
* @param {string} hostname - The hostname to resolve CNAME records for.
|
|
31
|
+
* @returns {Promise<string|null>} A promise that resolves to the CNAME record if found, or null if not found or an error occurs.
|
|
32
|
+
*/
|
|
33
|
+
resolveCname (hostname) {
|
|
34
|
+
return this._resolver.resolveCname(hostname).catch((error) => {
|
|
35
|
+
switch (error.code) {
|
|
36
|
+
case 'ENOTFOUND':
|
|
37
|
+
case 'ENODATA':
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`Could not resolve DNS for ${hostname}. Caused by: ${error.message}`);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import cliparse from 'cliparse';
|
|
2
|
+
import * as AppConfig from '../models/app_configuration.js';
|
|
3
|
+
import * as Organisation from '../models/organisation.js';
|
|
4
|
+
import * as User from '../models/user.js';
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const AppConfig = require('../models/app_configuration.js');
|
|
6
|
-
const Organisation = require('../models/organisation.js');
|
|
7
|
-
const User = require('../models/user.js');
|
|
8
|
-
|
|
9
|
-
function listMetaEvents () {
|
|
10
|
-
return autocomplete.words([
|
|
6
|
+
export function listMetaEvents () {
|
|
7
|
+
return cliparse.autocomplete.words([
|
|
11
8
|
'META_SERVICE_LIFECYCLE',
|
|
12
9
|
'META_DEPLOYMENT_RESULT',
|
|
13
10
|
'META_SERVICE_MANAGEMENT',
|
|
@@ -15,13 +12,13 @@ function listMetaEvents () {
|
|
|
15
12
|
]);
|
|
16
13
|
}
|
|
17
14
|
|
|
18
|
-
function getOrgaIdOrUserId (orgIdOrName) {
|
|
15
|
+
export function getOrgaIdOrUserId (orgIdOrName) {
|
|
19
16
|
return (orgIdOrName == null)
|
|
20
17
|
? User.getCurrentId()
|
|
21
18
|
: Organisation.getId(orgIdOrName);
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
async function getOwnerAndApp (alias, org, useLinkedApp) {
|
|
21
|
+
export async function getOwnerAndApp (alias, org, useLinkedApp) {
|
|
25
22
|
|
|
26
23
|
if (!useLinkedApp) {
|
|
27
24
|
const ownerId = await getOrgaIdOrUserId(org);
|
|
@@ -30,9 +27,3 @@ async function getOwnerAndApp (alias, org, useLinkedApp) {
|
|
|
30
27
|
|
|
31
28
|
return AppConfig.getAppDetails({ alias });
|
|
32
29
|
}
|
|
33
|
-
|
|
34
|
-
module.exports = {
|
|
35
|
-
listMetaEvents,
|
|
36
|
-
getOrgaIdOrUserId,
|
|
37
|
-
getOwnerAndApp,
|
|
38
|
-
};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import _ from 'lodash';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { getSummary } from '@clevercloud/client/esm/api/v2/user.js';
|
|
4
|
+
import { sendToApi } from '../models/send-to-api.js';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
const { sendToApi } = require('../models/send-to-api.js');
|
|
7
|
-
|
|
8
|
-
async function getId (orgaIdOrName) {
|
|
6
|
+
export async function getId (orgaIdOrName) {
|
|
9
7
|
if (orgaIdOrName == null) {
|
|
10
8
|
return null;
|
|
11
9
|
}
|
|
@@ -32,7 +30,3 @@ async function getByName (name) {
|
|
|
32
30
|
|
|
33
31
|
return filteredOrgs[0];
|
|
34
32
|
}
|
|
35
|
-
|
|
36
|
-
module.exports = {
|
|
37
|
-
getId,
|
|
38
|
-
};
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { Logger } from '../logger.js';
|
|
2
|
+
import { addOauthHeader } from '@clevercloud/client/esm/oauth.js';
|
|
3
|
+
import { conf, loadOAuthConf } from '../models/configuration.js';
|
|
4
|
+
import { execWarpscript } from '@clevercloud/client/esm/request-warp10.superagent.js';
|
|
5
|
+
import { prefixUrl } from '@clevercloud/client/esm/prefix-url.js';
|
|
6
|
+
import { request } from '@clevercloud/client/esm/request.fetch.js';
|
|
7
|
+
import { subtle as cryptoSuble } from 'node:crypto';
|
|
2
8
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
// Required for @clevercloud/client with "old" Node.js
|
|
10
|
+
if (globalThis.crypto == null) {
|
|
11
|
+
globalThis.crypto = {
|
|
12
|
+
subtle: cryptoSuble,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
9
15
|
|
|
10
16
|
async function loadTokens () {
|
|
11
17
|
const tokens = await loadOAuthConf();
|
|
@@ -17,7 +23,7 @@ async function loadTokens () {
|
|
|
17
23
|
};
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
async function sendToApi (requestParams) {
|
|
26
|
+
export async function sendToApi (requestParams) {
|
|
21
27
|
const tokens = await loadTokens();
|
|
22
28
|
return Promise.resolve(requestParams)
|
|
23
29
|
.then(prefixUrl(conf.API_HOST))
|
|
@@ -30,7 +36,7 @@ async function sendToApi (requestParams) {
|
|
|
30
36
|
.catch(processError);
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
function processError (error) {
|
|
39
|
+
export function processError (error) {
|
|
34
40
|
const code = error.code ?? error?.cause?.code;
|
|
35
41
|
if (code === 'EAI_AGAIN') {
|
|
36
42
|
throw new Error('Cannot reach the Clever Cloud API, please check your internet connection.', { cause: error });
|
|
@@ -41,18 +47,16 @@ function processError (error) {
|
|
|
41
47
|
throw error;
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
function sendToWarp10 (requestParams) {
|
|
50
|
+
export function sendToWarp10 (requestParams) {
|
|
45
51
|
return Promise.resolve(requestParams)
|
|
46
52
|
.then(prefixUrl(conf.WARP_10_EXEC_URL))
|
|
47
53
|
.then((requestParams) => execWarpscript(requestParams, { retry: 1 }));
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
async function getHostAndTokens () {
|
|
56
|
+
export async function getHostAndTokens () {
|
|
51
57
|
const tokens = await loadTokens();
|
|
52
58
|
return {
|
|
53
59
|
apiHost: conf.API_HOST,
|
|
54
60
|
tokens,
|
|
55
61
|
};
|
|
56
62
|
}
|
|
57
|
-
|
|
58
|
-
module.exports = { sendToApi, sendToWarp10, getHostAndTokens, processError };
|
package/src/models/user.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import { get } from '@clevercloud/client/esm/api/v2/organisation.js';
|
|
2
|
+
import { sendToApi } from '../models/send-to-api.js';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const { sendToApi } = require('../models/send-to-api.js');
|
|
5
|
-
|
|
6
|
-
function getCurrent () {
|
|
4
|
+
export function getCurrent () {
|
|
7
5
|
return get({}).then(sendToApi);
|
|
8
|
-
}
|
|
6
|
+
}
|
|
9
7
|
|
|
10
|
-
function getCurrentId () {
|
|
8
|
+
export function getCurrentId () {
|
|
11
9
|
return get({}).then(sendToApi)
|
|
12
10
|
.then(({ id }) => id);
|
|
13
|
-
}
|
|
11
|
+
}
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
// TODO move to clever client
|
|
14
|
+
export function getCurrentToken () {
|
|
15
|
+
return Promise.resolve({
|
|
16
|
+
method: 'get',
|
|
17
|
+
url: '/v2/self/tokens/current',
|
|
18
|
+
headers: { Accept: 'application/json' },
|
|
19
|
+
// no query params
|
|
20
|
+
// no body
|
|
21
|
+
}).then(sendToApi);
|
|
22
|
+
}
|
package/src/models/utils.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
// Inspirations:
|
|
4
2
|
// https://github.com/sindresorhus/p-defer/blob/master/index.js
|
|
5
3
|
// https://github.com/ljharb/promise-deferred/blob/master/index.js
|
|
6
4
|
|
|
7
5
|
// When you mix async/await APIs with event emitters callbacks, it's hard to keep a proper error flow without a good old deferred.
|
|
8
|
-
class Deferred {
|
|
6
|
+
export class Deferred {
|
|
9
7
|
|
|
10
8
|
constructor () {
|
|
11
9
|
this.promise = new Promise((resolve, reject) => {
|
|
@@ -15,11 +13,9 @@ class Deferred {
|
|
|
15
13
|
}
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
function truncateWithEllipsis (length, string) {
|
|
16
|
+
export function truncateWithEllipsis (length, string) {
|
|
19
17
|
if (string.length > length - 1) {
|
|
20
18
|
return string.substring(0, length - 1) + '…';
|
|
21
19
|
}
|
|
22
20
|
return string;
|
|
23
21
|
}
|
|
24
|
-
|
|
25
|
-
module.exports = { Deferred, truncateWithEllipsis };
|
package/src/models/variables.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const readline = require('readline');
|
|
5
|
-
const { ERROR_TYPES, parseRaw, toNameValueObject, validateName } = require('@clevercloud/client/cjs/utils/env-vars.js');
|
|
1
|
+
import _countBy from 'lodash/countBy.js';
|
|
2
|
+
import readline from 'node:readline';
|
|
3
|
+
import { ERROR_TYPES, parseRaw, toNameValueObject, validateName } from '@clevercloud/client/esm/utils/env-vars.js';
|
|
6
4
|
|
|
7
5
|
function readStdin () {
|
|
8
6
|
|
|
@@ -105,7 +103,7 @@ function parseFromNameEqualsValue (rawStdin) {
|
|
|
105
103
|
return toNameValueObject(variables);
|
|
106
104
|
}
|
|
107
105
|
|
|
108
|
-
async function readVariablesFromStdin (format) {
|
|
106
|
+
export async function readVariablesFromStdin (format) {
|
|
109
107
|
|
|
110
108
|
const rawStdin = await readStdin();
|
|
111
109
|
|
|
@@ -118,7 +116,3 @@ async function readVariablesFromStdin (format) {
|
|
|
118
116
|
throw new Error('Unrecognized environment input format. Available formats are \'name-equals-value\' and \'json\'');
|
|
119
117
|
}
|
|
120
118
|
}
|
|
121
|
-
|
|
122
|
-
module.exports = {
|
|
123
|
-
readVariablesFromStdin,
|
|
124
|
-
};
|
package/src/parsers.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import cliparse from 'cliparse';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import * as Application from './models/application.js';
|
|
4
|
+
import ISO8601 from 'iso8601-duration';
|
|
5
|
+
import Duration from 'duration-js';
|
|
4
6
|
|
|
5
|
-
const
|
|
6
|
-
const ISO8601 = require('iso8601-duration');
|
|
7
|
-
const Duration = require('duration-js');
|
|
7
|
+
const addonOptionsRegex = /^\w+=.+$/;
|
|
8
8
|
|
|
9
|
-
function
|
|
9
|
+
export function addonOptions (options) {
|
|
10
|
+
for (const option of options) {
|
|
11
|
+
if (!option.match(addonOptionsRegex)) {
|
|
12
|
+
return cliparse.parsers.error('Invalid option: ' + option);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return cliparse.parsers.success(options.join(','));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function flavor (flavor) {
|
|
10
19
|
const flavors = Application.listAvailableFlavors();
|
|
11
20
|
if (flavors.includes(flavor)) {
|
|
12
21
|
return cliparse.parsers.success(flavor);
|
|
@@ -14,14 +23,14 @@ function flavor (flavor) {
|
|
|
14
23
|
return cliparse.parsers.error('Invalid value: ' + flavor);
|
|
15
24
|
}
|
|
16
25
|
|
|
17
|
-
function buildFlavor (flavorOrDisabled) {
|
|
26
|
+
export function buildFlavor (flavorOrDisabled) {
|
|
18
27
|
if (flavorOrDisabled === 'disabled') {
|
|
19
28
|
return cliparse.parsers.success(flavorOrDisabled);
|
|
20
29
|
}
|
|
21
30
|
return flavor(flavorOrDisabled);
|
|
22
31
|
}
|
|
23
32
|
|
|
24
|
-
function instances (instances) {
|
|
33
|
+
export function instances (instances) {
|
|
25
34
|
const parsedInstances = parseInt(instances, 10);
|
|
26
35
|
if (isNaN(parsedInstances)) {
|
|
27
36
|
return cliparse.parsers.error('Invalid number: ' + instances);
|
|
@@ -32,7 +41,7 @@ function instances (instances) {
|
|
|
32
41
|
return cliparse.parsers.success(parsedInstances);
|
|
33
42
|
}
|
|
34
43
|
|
|
35
|
-
function date (dateString) {
|
|
44
|
+
export function date (dateString) {
|
|
36
45
|
const date = new Date(dateString);
|
|
37
46
|
if (isNaN(dateString) && !isNaN(date.getTime())) {
|
|
38
47
|
return cliparse.parsers.success(date);
|
|
@@ -48,7 +57,7 @@ function date (dateString) {
|
|
|
48
57
|
|
|
49
58
|
const appIdRegex = /^app_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
50
59
|
|
|
51
|
-
function appIdOrName (string) {
|
|
60
|
+
export function appIdOrName (string) {
|
|
52
61
|
if (string.match(appIdRegex)) {
|
|
53
62
|
return cliparse.parsers.success({ app_id: string });
|
|
54
63
|
}
|
|
@@ -57,7 +66,7 @@ function appIdOrName (string) {
|
|
|
57
66
|
|
|
58
67
|
const orgaIdRegex = /^(user_|orga_)[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
59
68
|
|
|
60
|
-
function orgaIdOrName (string) {
|
|
69
|
+
export function orgaIdOrName (string) {
|
|
61
70
|
if (string.match(orgaIdRegex)) {
|
|
62
71
|
return cliparse.parsers.success({ orga_id: string });
|
|
63
72
|
}
|
|
@@ -66,27 +75,18 @@ function orgaIdOrName (string) {
|
|
|
66
75
|
|
|
67
76
|
const addonIdRegex = /^addon_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
68
77
|
|
|
69
|
-
function addonIdOrName (string) {
|
|
78
|
+
export function addonIdOrName (string) {
|
|
70
79
|
if (string.match(addonIdRegex)) {
|
|
71
80
|
return cliparse.parsers.success({ addon_id: string });
|
|
72
81
|
}
|
|
73
82
|
return cliparse.parsers.success({ addon_name: string });
|
|
74
83
|
}
|
|
75
84
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
function ngIdOrLabel (string) {
|
|
79
|
-
if (string.match(ngIdRegex)) {
|
|
80
|
-
return cliparse.parsers.success({ ng_id: string });
|
|
81
|
-
}
|
|
82
|
-
return cliparse.parsers.success({ ng_label: string });
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function commaSeparated (string) {
|
|
85
|
+
export function commaSeparated (string) {
|
|
86
86
|
return cliparse.parsers.success(string.split(','));
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
function integer (string) {
|
|
89
|
+
export function integer (string) {
|
|
90
90
|
const integer = parseInt(string);
|
|
91
91
|
if (isNaN(integer)) {
|
|
92
92
|
return cliparse.parsers.error('Invalid number: ' + string);
|
|
@@ -94,7 +94,7 @@ function integer (string) {
|
|
|
94
94
|
return cliparse.parsers.success(integer);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
function nonEmptyString (string) {
|
|
97
|
+
export function nonEmptyString (string) {
|
|
98
98
|
if (typeof string !== 'string' || string === '') {
|
|
99
99
|
return cliparse.parsers.error('Invalid string, it should not be empty');
|
|
100
100
|
}
|
|
@@ -104,14 +104,14 @@ function nonEmptyString (string) {
|
|
|
104
104
|
// /^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/i;
|
|
105
105
|
const tagRegex = /^[^,\s]+$/;
|
|
106
106
|
|
|
107
|
-
function tag (string) {
|
|
107
|
+
export function tag (string) {
|
|
108
108
|
if (string.match(tagRegex)) {
|
|
109
109
|
return cliparse.parsers.success(string);
|
|
110
110
|
}
|
|
111
111
|
return cliparse.parsers.error(`Invalid tag '${string}'. Should match ${tagRegex}`);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function tags (string) {
|
|
114
|
+
export function tags (string) {
|
|
115
115
|
if (String(string).length === 0) {
|
|
116
116
|
return cliparse.parsers.success([]);
|
|
117
117
|
}
|
|
@@ -124,34 +124,18 @@ function tags (string) {
|
|
|
124
124
|
return cliparse.parsers.success(tags);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
const possible = ['application', 'addon', 'external'];
|
|
129
|
-
if (possible.includes(string)) {
|
|
130
|
-
return cliparse.parsers.success(string);
|
|
131
|
-
}
|
|
132
|
-
return cliparse.parsers.error(`Invalid member type '${string}'. Should be in ${JSON.stringify(possible)}`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function ngPeerRole (string) {
|
|
136
|
-
const possible = ['client', 'server'];
|
|
137
|
-
if (possible.includes(string)) {
|
|
138
|
-
return cliparse.parsers.success(string);
|
|
139
|
-
}
|
|
140
|
-
return cliparse.parsers.error(`Invalid peer role '${string}'. Should be in ${JSON.stringify(possible)}`);
|
|
141
|
-
}
|
|
127
|
+
export const ipAddressRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/;
|
|
142
128
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
function ipAddress (string) {
|
|
129
|
+
export function ipAddress (string) {
|
|
146
130
|
if (string.match(ipAddressRegex)) {
|
|
147
131
|
return cliparse.parsers.success(string);
|
|
148
132
|
}
|
|
149
133
|
return cliparse.parsers.error(`Invalid IP address '${string}'. Should match ${ipAddressRegex}`);
|
|
150
134
|
}
|
|
151
135
|
|
|
152
|
-
const portNumberRegex = /^\d{1,5}$/;
|
|
136
|
+
export const portNumberRegex = /^\d{1,5}$/;
|
|
153
137
|
|
|
154
|
-
function portNumber (number) {
|
|
138
|
+
export function portNumber (number) {
|
|
155
139
|
if (String(number).match(portNumberRegex)) {
|
|
156
140
|
return cliparse.parsers.success(number);
|
|
157
141
|
}
|
|
@@ -164,7 +148,7 @@ function portNumber (number) {
|
|
|
164
148
|
* @param {string} durationStr an ISO8601, 1h or a positive number
|
|
165
149
|
* @returns {number} number of seconds
|
|
166
150
|
*/
|
|
167
|
-
function durationInSeconds (durationStr = '') {
|
|
151
|
+
export function durationInSeconds (durationStr = '') {
|
|
168
152
|
const failed = cliparse.parsers.error(`Invalid duration: "${durationStr}", expect (IS0 8601 duration / a "1h, 1m, 30s" like duration / a positive number in seconds)`);
|
|
169
153
|
|
|
170
154
|
if (durationStr.startsWith('P')) {
|
|
@@ -190,26 +174,3 @@ function durationInSeconds (durationStr = '') {
|
|
|
190
174
|
return cliparse.parsers.success(n);
|
|
191
175
|
}
|
|
192
176
|
}
|
|
193
|
-
|
|
194
|
-
module.exports = {
|
|
195
|
-
buildFlavor,
|
|
196
|
-
flavor,
|
|
197
|
-
instances,
|
|
198
|
-
date,
|
|
199
|
-
appIdOrName,
|
|
200
|
-
orgaIdOrName,
|
|
201
|
-
addonIdOrName,
|
|
202
|
-
ngIdOrLabel,
|
|
203
|
-
commaSeparated,
|
|
204
|
-
integer,
|
|
205
|
-
tag,
|
|
206
|
-
tags,
|
|
207
|
-
ngMemberType,
|
|
208
|
-
ngPeerRole,
|
|
209
|
-
ipAddressRegex,
|
|
210
|
-
ipAddress,
|
|
211
|
-
portNumberRegex,
|
|
212
|
-
portNumber,
|
|
213
|
-
durationInSeconds,
|
|
214
|
-
nonEmptyString,
|
|
215
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const ngApi = require('@clevercloud/client/cjs/api/v4/network-group.js');
|
|
4
|
-
|
|
5
|
-
const { sendToApi } = require('../../models/send-to-api.js');
|
|
6
|
-
|
|
7
|
-
const Logger = require('../../logger.js');
|
|
8
|
-
const NetworkGroup = require('../../models/networkgroup.js');
|
|
9
|
-
const Formatter = require('../../models/format-string.js');
|
|
10
|
-
const TableFormatter = require('../../models/format-ng-table.js');
|
|
11
|
-
|
|
12
|
-
async function listNetworkGroups (params) {
|
|
13
|
-
const { org: orgaIdOrName, alias, json } = params.options;
|
|
14
|
-
const ownerId = await NetworkGroup.getOwnerId(orgaIdOrName, alias);
|
|
15
|
-
|
|
16
|
-
Logger.info(`Listing Network Groups from owner ${Formatter.formatString(ownerId)}`);
|
|
17
|
-
const result = await ngApi.listNetworkGroups({ ownerId }).then(sendToApi);
|
|
18
|
-
|
|
19
|
-
if (json) {
|
|
20
|
-
Logger.println(JSON.stringify(result, null, 2));
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
if (result.length === 0) {
|
|
24
|
-
Logger.println(`No Network Group found for ${ownerId}. You can create one with ${Formatter.formatCommand('clever networkgroups create')}.`);
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
TableFormatter.printNetworkGroupsTableHeader();
|
|
28
|
-
result
|
|
29
|
-
.map((ng) => TableFormatter.formatNetworkGroupsLine(ng))
|
|
30
|
-
.forEach((ng) => Logger.println(ng));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function createNg (params) {
|
|
36
|
-
const { org: orgaIdOrName, alias, label, description, tags, json } = params.options;
|
|
37
|
-
const ownerId = await NetworkGroup.getOwnerId(orgaIdOrName, alias);
|
|
38
|
-
|
|
39
|
-
Logger.info(`Creating Network Group from owner ${Formatter.formatString(ownerId)}`);
|
|
40
|
-
const body = { ownerId: ownerId, label, description, tags };
|
|
41
|
-
Logger.debug('Sending body: ' + JSON.stringify(body, null, 2));
|
|
42
|
-
const result = await ngApi.createNetworkGroup({ ownerId }, body).then(sendToApi);
|
|
43
|
-
|
|
44
|
-
if (json) {
|
|
45
|
-
Logger.println(JSON.stringify(result, null, 2));
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
Logger.println(`Network Group ${Formatter.formatString(label)} creation will be performed asynchronously.`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function deleteNg (params) {
|
|
53
|
-
const { org: orgaIdOrName, alias, ng: networkGroupIdOrLabel } = params.options;
|
|
54
|
-
const ownerId = await NetworkGroup.getOwnerId(orgaIdOrName, alias);
|
|
55
|
-
const networkGroupId = await NetworkGroup.getId(ownerId, networkGroupIdOrLabel);
|
|
56
|
-
|
|
57
|
-
Logger.info(`Deleting Network Group ${Formatter.formatString(networkGroupId)} from owner ${Formatter.formatString(ownerId)}`);
|
|
58
|
-
await ngApi.deleteNetworkGroup({ ownerId, networkGroupId }).then(sendToApi);
|
|
59
|
-
|
|
60
|
-
Logger.println(`Network Group ${Formatter.formatString(networkGroupId)} deletion will be performed asynchronously.`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
module.exports = {
|
|
64
|
-
listNetworkGroups,
|
|
65
|
-
createNg,
|
|
66
|
-
deleteNg,
|
|
67
|
-
};
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const ngApi = require('@clevercloud/client/cjs/api/v4/network-group.js');
|
|
4
|
-
|
|
5
|
-
const { sendToApi } = require('../../models/send-to-api.js');
|
|
6
|
-
|
|
7
|
-
const Logger = require('../../logger.js');
|
|
8
|
-
const NetworkGroup = require('../../models/networkgroup.js');
|
|
9
|
-
const Formatter = require('../../models/format-string.js');
|
|
10
|
-
const TableFormatter = require('../../models/format-ng-table.js');
|
|
11
|
-
|
|
12
|
-
async function listMembers (params) {
|
|
13
|
-
const { org: orgaIdOrName, alias, ng: networkGroupIdOrLabel, 'natural-name': naturalName, json } = params.options;
|
|
14
|
-
const ownerId = await NetworkGroup.getOwnerId(orgaIdOrName, alias);
|
|
15
|
-
const networkGroupId = await NetworkGroup.getId(ownerId, networkGroupIdOrLabel);
|
|
16
|
-
|
|
17
|
-
Logger.info(`Listing members from Network Group '${networkGroupId}'`);
|
|
18
|
-
const result = await ngApi.listNetworkGroupMembers({ ownerId, networkGroupId }).then(sendToApi);
|
|
19
|
-
|
|
20
|
-
if (json) {
|
|
21
|
-
Logger.println(JSON.stringify(result, null, 2));
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
if (result.length === 0) {
|
|
25
|
-
Logger.println(`No member found. You can add one with ${Formatter.formatCommand('clever networkgroups members add')}.`);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
await TableFormatter.printMembersTableHeader(naturalName);
|
|
29
|
-
for (const ng of result) {
|
|
30
|
-
Logger.println(await TableFormatter.formatMembersLine(ng, naturalName));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async function getMember (params) {
|
|
37
|
-
const { org: orgaIdOrName, alias, ng: networkGroupIdOrLabel, 'member-id': memberId, 'natural-name': naturalName, json } = params.options;
|
|
38
|
-
const ownerId = await NetworkGroup.getOwnerId(orgaIdOrName, alias);
|
|
39
|
-
const networkGroupId = await NetworkGroup.getId(ownerId, networkGroupIdOrLabel); ;
|
|
40
|
-
|
|
41
|
-
Logger.info(`Getting details for member ${Formatter.formatString(memberId)} in Network Group ${Formatter.formatString(networkGroupId)}`);
|
|
42
|
-
const result = await ngApi.getNetworkGroupMember({ ownerId, networkGroupId, memberId: memberId }).then(sendToApi);
|
|
43
|
-
|
|
44
|
-
if (json) {
|
|
45
|
-
Logger.println(JSON.stringify(result, null, 2));
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
await TableFormatter.printMembersTableHeader(naturalName);
|
|
49
|
-
Logger.println(await TableFormatter.formatMembersLine(result, naturalName));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function addMember (params) {
|
|
54
|
-
const { org: orgaIdOrName, alias, ng: networkGroupIdOrLabel, 'member-id': memberId, type, 'domain-name': domainName, label } = params.options;
|
|
55
|
-
const ownerId = await NetworkGroup.getOwnerId(orgaIdOrName, alias);
|
|
56
|
-
const networkGroupId = await NetworkGroup.getId(ownerId, networkGroupIdOrLabel);
|
|
57
|
-
|
|
58
|
-
const body = { id: memberId, label, domain_name: domainName, type };
|
|
59
|
-
Logger.debug('Sending body: ' + JSON.stringify(body, null, 2));
|
|
60
|
-
await ngApi.createNetworkGroupMember({ ownerId, networkGroupId }, body).then(sendToApi);
|
|
61
|
-
|
|
62
|
-
Logger.println(`Successfully added member ${Formatter.formatString(memberId)} to Network Group ${Formatter.formatString(networkGroupId)}.`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async function removeMember (params) {
|
|
66
|
-
const { org: orgaIdOrName, alias, ng: networkGroupIdOrLabel, 'member-id': memberId } = params.options;
|
|
67
|
-
const ownerId = await NetworkGroup.getOwnerId(orgaIdOrName, alias);
|
|
68
|
-
const networkGroupId = await NetworkGroup.getId(ownerId, networkGroupIdOrLabel);
|
|
69
|
-
|
|
70
|
-
await ngApi.deleteNetworkGroupMember({ ownerId, networkGroupId, memberId }).then(sendToApi);
|
|
71
|
-
|
|
72
|
-
Logger.println(`Successfully removed member ${Formatter.formatString(memberId)} from Network Group ${Formatter.formatString(networkGroupId)}.`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = {
|
|
76
|
-
listMembers,
|
|
77
|
-
getMember,
|
|
78
|
-
addMember,
|
|
79
|
-
removeMember,
|
|
80
|
-
};
|