clever-tools 3.8.2 → 3.9.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 +177 -426
- package/package.json +11 -5
- 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 +82 -36
- 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 +348 -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 +52 -54
- 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 +21 -71
- 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,10 @@
|
|
|
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
|
-
|
|
6
|
-
const ISO8601 = require('iso8601-duration');
|
|
7
|
-
const Duration = require('duration-js');
|
|
8
|
-
|
|
9
|
-
function flavor (flavor) {
|
|
7
|
+
export function flavor (flavor) {
|
|
10
8
|
const flavors = Application.listAvailableFlavors();
|
|
11
9
|
if (flavors.includes(flavor)) {
|
|
12
10
|
return cliparse.parsers.success(flavor);
|
|
@@ -14,14 +12,14 @@ function flavor (flavor) {
|
|
|
14
12
|
return cliparse.parsers.error('Invalid value: ' + flavor);
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
function buildFlavor (flavorOrDisabled) {
|
|
15
|
+
export function buildFlavor (flavorOrDisabled) {
|
|
18
16
|
if (flavorOrDisabled === 'disabled') {
|
|
19
17
|
return cliparse.parsers.success(flavorOrDisabled);
|
|
20
18
|
}
|
|
21
19
|
return flavor(flavorOrDisabled);
|
|
22
20
|
}
|
|
23
21
|
|
|
24
|
-
function instances (instances) {
|
|
22
|
+
export function instances (instances) {
|
|
25
23
|
const parsedInstances = parseInt(instances, 10);
|
|
26
24
|
if (isNaN(parsedInstances)) {
|
|
27
25
|
return cliparse.parsers.error('Invalid number: ' + instances);
|
|
@@ -32,7 +30,7 @@ function instances (instances) {
|
|
|
32
30
|
return cliparse.parsers.success(parsedInstances);
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
function date (dateString) {
|
|
33
|
+
export function date (dateString) {
|
|
36
34
|
const date = new Date(dateString);
|
|
37
35
|
if (isNaN(dateString) && !isNaN(date.getTime())) {
|
|
38
36
|
return cliparse.parsers.success(date);
|
|
@@ -48,7 +46,7 @@ function date (dateString) {
|
|
|
48
46
|
|
|
49
47
|
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
48
|
|
|
51
|
-
function appIdOrName (string) {
|
|
49
|
+
export function appIdOrName (string) {
|
|
52
50
|
if (string.match(appIdRegex)) {
|
|
53
51
|
return cliparse.parsers.success({ app_id: string });
|
|
54
52
|
}
|
|
@@ -57,7 +55,7 @@ function appIdOrName (string) {
|
|
|
57
55
|
|
|
58
56
|
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
57
|
|
|
60
|
-
function orgaIdOrName (string) {
|
|
58
|
+
export function orgaIdOrName (string) {
|
|
61
59
|
if (string.match(orgaIdRegex)) {
|
|
62
60
|
return cliparse.parsers.success({ orga_id: string });
|
|
63
61
|
}
|
|
@@ -66,27 +64,18 @@ function orgaIdOrName (string) {
|
|
|
66
64
|
|
|
67
65
|
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
66
|
|
|
69
|
-
function addonIdOrName (string) {
|
|
67
|
+
export function addonIdOrName (string) {
|
|
70
68
|
if (string.match(addonIdRegex)) {
|
|
71
69
|
return cliparse.parsers.success({ addon_id: string });
|
|
72
70
|
}
|
|
73
71
|
return cliparse.parsers.success({ addon_name: string });
|
|
74
72
|
}
|
|
75
73
|
|
|
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) {
|
|
74
|
+
export function commaSeparated (string) {
|
|
86
75
|
return cliparse.parsers.success(string.split(','));
|
|
87
76
|
}
|
|
88
77
|
|
|
89
|
-
function integer (string) {
|
|
78
|
+
export function integer (string) {
|
|
90
79
|
const integer = parseInt(string);
|
|
91
80
|
if (isNaN(integer)) {
|
|
92
81
|
return cliparse.parsers.error('Invalid number: ' + string);
|
|
@@ -94,7 +83,7 @@ function integer (string) {
|
|
|
94
83
|
return cliparse.parsers.success(integer);
|
|
95
84
|
}
|
|
96
85
|
|
|
97
|
-
function nonEmptyString (string) {
|
|
86
|
+
export function nonEmptyString (string) {
|
|
98
87
|
if (typeof string !== 'string' || string === '') {
|
|
99
88
|
return cliparse.parsers.error('Invalid string, it should not be empty');
|
|
100
89
|
}
|
|
@@ -104,14 +93,14 @@ function nonEmptyString (string) {
|
|
|
104
93
|
// /^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/i;
|
|
105
94
|
const tagRegex = /^[^,\s]+$/;
|
|
106
95
|
|
|
107
|
-
function tag (string) {
|
|
96
|
+
export function tag (string) {
|
|
108
97
|
if (string.match(tagRegex)) {
|
|
109
98
|
return cliparse.parsers.success(string);
|
|
110
99
|
}
|
|
111
100
|
return cliparse.parsers.error(`Invalid tag '${string}'. Should match ${tagRegex}`);
|
|
112
101
|
}
|
|
113
102
|
|
|
114
|
-
function tags (string) {
|
|
103
|
+
export function tags (string) {
|
|
115
104
|
if (String(string).length === 0) {
|
|
116
105
|
return cliparse.parsers.success([]);
|
|
117
106
|
}
|
|
@@ -124,34 +113,18 @@ function tags (string) {
|
|
|
124
113
|
return cliparse.parsers.success(tags);
|
|
125
114
|
}
|
|
126
115
|
|
|
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
|
-
}
|
|
142
|
-
|
|
143
|
-
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])$/;
|
|
116
|
+
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])$/;
|
|
144
117
|
|
|
145
|
-
function ipAddress (string) {
|
|
118
|
+
export function ipAddress (string) {
|
|
146
119
|
if (string.match(ipAddressRegex)) {
|
|
147
120
|
return cliparse.parsers.success(string);
|
|
148
121
|
}
|
|
149
122
|
return cliparse.parsers.error(`Invalid IP address '${string}'. Should match ${ipAddressRegex}`);
|
|
150
123
|
}
|
|
151
124
|
|
|
152
|
-
const portNumberRegex = /^\d{1,5}$/;
|
|
125
|
+
export const portNumberRegex = /^\d{1,5}$/;
|
|
153
126
|
|
|
154
|
-
function portNumber (number) {
|
|
127
|
+
export function portNumber (number) {
|
|
155
128
|
if (String(number).match(portNumberRegex)) {
|
|
156
129
|
return cliparse.parsers.success(number);
|
|
157
130
|
}
|
|
@@ -164,7 +137,7 @@ function portNumber (number) {
|
|
|
164
137
|
* @param {string} durationStr an ISO8601, 1h or a positive number
|
|
165
138
|
* @returns {number} number of seconds
|
|
166
139
|
*/
|
|
167
|
-
function durationInSeconds (durationStr = '') {
|
|
140
|
+
export function durationInSeconds (durationStr = '') {
|
|
168
141
|
const failed = cliparse.parsers.error(`Invalid duration: "${durationStr}", expect (IS0 8601 duration / a "1h, 1m, 30s" like duration / a positive number in seconds)`);
|
|
169
142
|
|
|
170
143
|
if (durationStr.startsWith('P')) {
|
|
@@ -190,26 +163,3 @@ function durationInSeconds (durationStr = '') {
|
|
|
190
163
|
return cliparse.parsers.success(n);
|
|
191
164
|
}
|
|
192
165
|
}
|
|
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
|
-
};
|