clever-tools 4.2.0 → 4.4.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.
@@ -1,133 +1,29 @@
1
- import cliparse from 'cliparse';
2
-
3
- const DRAIN_TYPES = [
4
- { id: 'TCPSyslog', structuredDataParameters: 'OPTIONAL' },
5
- { id: 'UDPSyslog', structuredDataParameters: 'OPTIONAL' },
6
- { id: 'HTTP', credentials: 'OPTIONAL' },
7
- { id: 'ElasticSearch', credentials: 'MANDATORY', indexPrefix: 'OPTIONAL' },
8
- { id: 'DatadogHTTP' },
9
- { id: 'NewRelicHTTP', apiKey: 'MANDATORY' },
10
- ];
11
-
12
- export function createDrainBody(appId, drainTargetURL, drainTargetType, drainTargetCredentials, drainTargetConfig) {
13
- if (!authorizeDrainCreation(drainTargetType, drainTargetCredentials, drainTargetConfig)) {
14
- throw new Error(
15
- "Credentials are: optional for HTTP, mandatory for ElasticSearch, NewRelicHTTP and TCPSyslog/UDPSyslog don't need them.",
16
- );
17
- }
18
-
19
- const body = {
20
- url: drainTargetURL,
21
- drainType: drainTargetType,
22
- };
23
- if (credentialsExist(drainTargetCredentials)) {
24
- body.credentials = {
25
- username: drainTargetCredentials.username || '',
26
- password: drainTargetCredentials.password || '',
27
- };
28
- }
29
- if (keyExist(drainTargetConfig)) {
30
- body.APIKey = drainTargetConfig.apiKey;
31
- }
32
- if (indexPrefixExist(drainTargetConfig)) {
33
- body.indexPrefix = drainTargetConfig.indexPrefix;
34
- }
35
- if (structuredDataParametersExist(drainTargetConfig)) {
36
- body.structuredDataParameters = drainTargetConfig.structuredDataParameters;
37
- }
38
- return body;
39
- }
40
-
41
- export function authorizeDrainCreation(drainTargetType, drainTargetCredentials, drainTargetConfig) {
42
- if (drainTypeExists(drainTargetType)) {
43
- // retrieve field for drain type ('mandatory', 'optional', undefined)
44
- const credStatus = fieldStatus(drainTargetType).credentials;
45
- const keyStatus = fieldStatus(drainTargetType).apiKey;
46
- const indexPrefixStatus = fieldStatus(drainTargetType).indexPrefix;
47
- const structuredDataParametersStatus = fieldStatus(drainTargetType).structuredDataParameters;
48
-
49
- if (credStatus === 'MANDATORY') {
50
- return credentialsExist(drainTargetCredentials);
51
- }
52
- if (credStatus === 'OPTIONAL') {
53
- return true;
54
- }
55
- if (!credStatus && !keyStatus) {
56
- return credentialsEmpty(drainTargetCredentials);
57
- }
58
-
59
- if (keyStatus === 'MANDATORY') {
60
- return keyExist(drainTargetConfig);
61
- }
62
- if (keyStatus === 'OPTIONAL') {
63
- return true;
64
- }
65
- if (!keyStatus) {
66
- return keyEmpty(drainTargetConfig);
67
- }
68
-
69
- if (indexPrefixStatus === 'MANDATORY') {
70
- return indexPrefixExist(drainTargetConfig);
71
- }
72
- if (indexPrefixStatus === 'OPTIONAL') {
73
- return true;
74
- }
75
- if (!indexPrefixStatus) {
76
- return indexPrefixEmpty(drainTargetConfig);
77
- }
78
-
79
- if (structuredDataParametersStatus === 'MANDATORY') {
80
- return structuredDataParametersExist(drainTargetConfig);
81
- }
82
- if (structuredDataParametersStatus === 'OPTIONAL') {
83
- return true;
84
- }
85
- if (!structuredDataParametersStatus) {
86
- return structuredDataParametersEmpty(drainTargetConfig);
87
- }
88
- }
89
- }
90
-
91
- function fieldStatus(drainTargetType) {
92
- return DRAIN_TYPES.find(({ id }) => id === drainTargetType);
93
- }
94
-
95
- function drainTypeExists(drainTargetType) {
96
- return DRAIN_TYPES.some(({ id }) => id === drainTargetType);
97
- }
98
-
99
- function credentialsExist({ username, password }) {
100
- return username != null && password != null;
101
- }
102
-
103
- function credentialsEmpty({ username, password }) {
104
- return username == null && password == null;
105
- }
106
-
107
- function indexPrefixExist({ indexPrefix }) {
108
- return indexPrefix != null;
109
- }
110
-
111
- function indexPrefixEmpty({ indexPrefix }) {
112
- return indexPrefix == null;
113
- }
114
-
115
- function structuredDataParametersExist({ structuredDataParameters }) {
116
- return structuredDataParameters != null;
117
- }
118
-
119
- function structuredDataParametersEmpty({ structuredDataParameters }) {
120
- return structuredDataParameters == null;
121
- }
122
-
123
- function keyExist({ apiKey }) {
124
- return apiKey != null;
125
- }
126
-
127
- function keyEmpty({ apiKey }) {
128
- return apiKey == null;
129
- }
130
-
131
- export function listDrainTypes() {
132
- return cliparse.autocomplete.words(DRAIN_TYPES.map((type) => type.id));
1
+ export const DRAIN_TYPES = {
2
+ DATADOG: { apiCode: 'DATADOG', cliCode: 'datadog', label: 'Datadog' },
3
+ ELASTICSEARCH: { apiCode: 'ELASTICSEARCH', cliCode: 'elasticsearch', label: 'Elasticsearch' },
4
+ NEWRELIC: { apiCode: 'NEWRELIC', cliCode: 'newrelic', label: 'New Relic' },
5
+ OVH_TCP: { apiCode: 'OVH_TCP', cliCode: 'ovh-tcp', label: 'OVH TCP' },
6
+ RAW_HTTP: { apiCode: 'RAW_HTTP', cliCode: 'raw-http', label: 'Raw HTTP' },
7
+ SYSLOG_TCP: { apiCode: 'SYSLOG_TCP', cliCode: 'syslog-tcp', label: 'Syslog TCP' },
8
+ SYSLOG_UDP: { apiCode: 'SYSLOG_UDP', cliCode: 'syslog-udp', label: 'Syslog UDP' },
9
+ };
10
+
11
+ export const DRAIN_TYPE_CLI_CODES = Object.values(DRAIN_TYPES).map(({ cliCode }) => cliCode);
12
+
13
+ export function formatDrain(rawDrain) {
14
+ const drainType = DRAIN_TYPES[rawDrain.recipient.type];
15
+ const drainDetails = [
16
+ ['ID', rawDrain.id],
17
+ ['Status', rawDrain.status.status],
18
+ ['Execution status', rawDrain.execution.status],
19
+ ['URL', rawDrain.recipient.url],
20
+ ['Type', drainType.label],
21
+ ['Custom index', rawDrain.recipient.index],
22
+ ['SD parameters', rawDrain.recipient.rfc5424StructuredDataParameters],
23
+ ['Message output rate', Math.floor(rawDrain.backlog.msgRateOut * 60) + ' messages/minute'],
24
+ ['Message throughput', Math.floor(rawDrain.backlog.msgRateOut) + ' bytes/second'],
25
+ ['Backlog', rawDrain.backlog.msgBacklog + ' pending messages'],
26
+ ['Last error', rawDrain.execution.lastError],
27
+ ];
28
+ return Object.fromEntries(drainDetails.filter(([_name, value]) => value != null));
133
29
  }
@@ -1,6 +1,8 @@
1
1
  import { getSummary } from '@clevercloud/client/esm/api/v2/user.js';
2
2
  import { Logger } from '../logger.js';
3
+ import * as User from '../models/user.js';
3
4
  import { loadIdsCache, writeIdsCache } from './configuration.js';
5
+ import * as Organisation from './organisation.js';
4
6
  import { sendToApi } from './send-to-api.js';
5
7
 
6
8
  /*
@@ -171,3 +173,12 @@ export async function findAddonsByAddonProvider(provider) {
171
173
 
172
174
  return candidates;
173
175
  }
176
+
177
+ /**
178
+ * Get the owner ID from an Organisation ID or name
179
+ * @param {object} orgIdOrName The Organisation ID or name
180
+ * @returns {Promise<string>} The owner ID
181
+ */
182
+ export async function getOwnerIdFromOrgIdOrName(orgIdOrName) {
183
+ return orgIdOrName != null ? Organisation.getId(orgIdOrName) : User.getCurrentId();
184
+ }
package/src/models/ng.js CHANGED
@@ -9,10 +9,9 @@ import crypto from 'node:crypto';
9
9
  import { searchNetworkGroupOrResource } from '../clever-client/ng.js';
10
10
  import { styleText } from '../lib/style-text.js';
11
11
  import { Logger } from '../logger.js';
12
+ import { getOwnerIdFromOrgIdOrName } from './ids-resolver.js';
12
13
  import { checkMembersToLink } from './ng-resources.js';
13
- import * as Organisation from './organisation.js';
14
14
  import { sendToApi } from './send-to-api.js';
15
- import * as User from './user.js';
16
15
 
17
16
  export const POLLING_TIMEOUT_MS = 30_000;
18
17
  export const POLLING_INTERVAL_MS = 1000;
@@ -38,7 +37,7 @@ export const NG_MEMBER_PREFIXES = {
38
37
  */
39
38
  export async function create(label, description, tags, membersIds, orgaIdOrName) {
40
39
  const id = `ng_${crypto.randomUUID()}`;
41
- const ownerId = await getOwnerIdFromOrgaIdOrName(orgaIdOrName);
40
+ const ownerId = await getOwnerIdFromOrgIdOrName(orgaIdOrName);
42
41
 
43
42
  if (membersIds?.length > 0) {
44
43
  checkMembersToLink(membersIds);
@@ -126,7 +125,7 @@ export async function getPeerConfig(peerIdOrLabel, ngIdOrLabel, orgaIdOrName) {
126
125
  * @returns {Promise<Array<Object>>} The Network Groups
127
126
  */
128
127
  export async function getNG(networkGroupId, orgaIdOrName) {
129
- const ownerId = await getOwnerIdFromOrgaIdOrName(orgaIdOrName);
128
+ const ownerId = await getOwnerIdFromOrgIdOrName(orgaIdOrName);
130
129
 
131
130
  Logger.info(`Get Network Group ${networkGroupId} for owner ${ownerId}`);
132
131
  const result = await getNetworkGroup({ networkGroupId, ownerId }).then(sendToApi);
@@ -141,7 +140,7 @@ export async function getNG(networkGroupId, orgaIdOrName) {
141
140
  * @returns {Promise<Array<Object>>} The Network Groups
142
141
  */
143
142
  export async function getAllNGs(orgaIdOrName) {
144
- const ownerId = await getOwnerIdFromOrgaIdOrName(orgaIdOrName);
143
+ const ownerId = await getOwnerIdFromOrgIdOrName(orgaIdOrName);
145
144
 
146
145
  Logger.info(`Listing Network Groups from owner ${ownerId}`);
147
146
  const result = await listNetworkGroups({ ownerId }).then(sendToApi);
@@ -159,7 +158,7 @@ export async function getAllNGs(orgaIdOrName) {
159
158
  * @returns {Promise<Object>} Found results
160
159
  */
161
160
  export async function searchNgOrResource(idOrLabel, orgaIdOrName, type = 'all', exactMatch = true) {
162
- const ownerId = await getOwnerIdFromOrgaIdOrName(orgaIdOrName);
161
+ const ownerId = await getOwnerIdFromOrgIdOrName(orgaIdOrName);
163
162
 
164
163
  // If idOrLabel is a string we use it, or we look through multiple keys
165
164
  const query =
@@ -265,12 +264,3 @@ async function pollNetworkGroup(ownerId, ngId, { waitForMembers = null, waitForD
265
264
  pollOnce();
266
265
  });
267
266
  }
268
-
269
- /**
270
- * Get the owner ID from an Organisation ID or name
271
- * @param {object} orgaIdOrName The Organisation ID or name
272
- * @returns {Promise<string>} The owner ID
273
- */
274
- async function getOwnerIdFromOrgaIdOrName(orgaIdOrName) {
275
- return orgaIdOrName != null ? Organisation.getId(orgaIdOrName) : User.getCurrentId();
276
- }
package/src/parsers.js CHANGED
@@ -100,12 +100,13 @@ export function orgaIdOrName(string) {
100
100
  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;
101
101
  const operatorIdRegex =
102
102
  /^(keycloak|otoroshi|matomo|metabase)_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
103
+ const ulidRegex = /^(kubernetes)_[0-9A-HJ-NP-TV-Z]{26}$/i;
103
104
 
104
105
  export function addonIdOrName(string) {
105
106
  if (string.match(addonIdRegex)) {
106
107
  return cliparse.parsers.success({ addon_id: string });
107
108
  }
108
- if (string.match(operatorIdRegex)) {
109
+ if (string.match(operatorIdRegex) || string.match(ulidRegex)) {
109
110
  return cliparse.parsers.success({ operator_id: string });
110
111
  }
111
112
  return cliparse.parsers.success({ addon_name: string });