@webex/webex-core 3.8.0 → 3.8.1-next.10
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/README.md +87 -27
- package/dist/index.js +28 -9
- package/dist/index.js.map +1 -1
- package/dist/interceptors/redirect.js +18 -0
- package/dist/interceptors/redirect.js.map +1 -1
- package/dist/lib/batcher.js +1 -1
- package/dist/lib/constants.js +10 -1
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/credentials/credentials.js +1 -1
- package/dist/lib/credentials/token.js +1 -1
- package/dist/lib/{services/interceptors → interceptors}/server-error.js +1 -1
- package/dist/lib/interceptors/server-error.js.map +1 -0
- package/dist/lib/services/index.js +2 -29
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/service-host.js +1 -1
- package/dist/lib/services/service-host.js.map +1 -1
- package/dist/lib/services/service-registry.js +1 -1
- package/dist/lib/services/service-registry.js.map +1 -1
- package/dist/lib/services/service-state.js +1 -1
- package/dist/lib/services/service-state.js.map +1 -1
- package/dist/lib/services/services.js +3 -3
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/services-v2/index.js +29 -0
- package/dist/lib/services-v2/index.js.map +1 -0
- package/dist/lib/services-v2/metrics.js +12 -0
- package/dist/lib/services-v2/metrics.js.map +1 -0
- package/dist/lib/services-v2/service-catalog.js +347 -0
- package/dist/lib/services-v2/service-catalog.js.map +1 -0
- package/dist/lib/services-v2/service-detail.js +94 -0
- package/dist/lib/services-v2/service-detail.js.map +1 -0
- package/dist/lib/services-v2/service-fed-ramp.js +13 -0
- package/dist/lib/services-v2/service-fed-ramp.js.map +1 -0
- package/dist/lib/services-v2/services-v2.js +974 -0
- package/dist/lib/services-v2/services-v2.js.map +1 -0
- package/dist/lib/services-v2/types.js +7 -0
- package/dist/lib/services-v2/types.js.map +1 -0
- package/dist/plugins/logger.js +1 -1
- package/dist/webex-core.js +3 -3
- package/dist/webex-core.js.map +1 -1
- package/package.json +13 -13
- package/src/index.js +5 -4
- package/src/interceptors/redirect.js +28 -0
- package/src/lib/constants.js +29 -1
- package/src/lib/{services/interceptors → interceptors}/server-error.js +1 -1
- package/src/lib/services/index.js +2 -7
- package/src/lib/services/service-host.js +1 -1
- package/src/lib/services/service-registry.js +1 -1
- package/src/lib/services/service-state.js +1 -1
- package/src/lib/services/services.js +2 -2
- package/src/lib/services-v2/README.md +3 -0
- package/src/lib/services-v2/index.ts +7 -0
- package/src/lib/services-v2/metrics.ts +4 -0
- package/src/lib/services-v2/service-catalog.ts +361 -0
- package/src/lib/services-v2/service-detail.ts +97 -0
- package/src/lib/services-v2/service-fed-ramp.ts +5 -0
- package/src/lib/services-v2/services-v2.ts +1010 -0
- package/src/lib/services-v2/types.ts +73 -0
- package/src/webex-core.js +1 -1
- package/test/fixtures/host-catalog-v2.ts +157 -0
- package/test/integration/spec/services/services.js +23 -10
- package/test/integration/spec/services-v2/service-catalog.js +664 -0
- package/test/integration/spec/services-v2/services-v2.js +1061 -0
- package/test/unit/spec/interceptors/redirect.js +72 -0
- package/test/unit/spec/services-v2/service-catalog.ts +288 -0
- package/test/unit/spec/services-v2/service-detail.ts +147 -0
- package/test/unit/spec/services-v2/services-v2.ts +516 -0
- package/dist/lib/services/constants.js +0 -17
- package/dist/lib/services/constants.js.map +0 -1
- package/dist/lib/services/interceptors/server-error.js.map +0 -1
- package/src/lib/services/constants.js +0 -21
- /package/dist/lib/{services/interceptors → interceptors}/hostmap.js +0 -0
- /package/dist/lib/{services/interceptors → interceptors}/hostmap.js.map +0 -0
- /package/dist/lib/{services/interceptors → interceptors}/service.js +0 -0
- /package/dist/lib/{services/interceptors → interceptors}/service.js.map +0 -0
- /package/dist/lib/{services/metrics.js → metrics.js} +0 -0
- /package/dist/lib/{services/metrics.js.map → metrics.js.map} +0 -0
- /package/src/lib/{services/interceptors → interceptors}/hostmap.js +0 -0
- /package/src/lib/{services/interceptors → interceptors}/service.js +0 -0
- /package/src/lib/{services/metrics.js → metrics.js} +0 -0
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import {registerInternalPlugin} from '../../webex-core';
|
|
5
5
|
|
|
6
|
-
import * as constants from './constants';
|
|
7
6
|
import Services from './services';
|
|
8
|
-
import ServerErrorInterceptor from '
|
|
9
|
-
import ServiceInterceptor from '
|
|
7
|
+
import ServerErrorInterceptor from '../interceptors/server-error';
|
|
8
|
+
import ServiceInterceptor from '../interceptors/service';
|
|
10
9
|
|
|
11
10
|
registerInternalPlugin('services', Services, {
|
|
12
11
|
interceptors: {
|
|
@@ -15,10 +14,6 @@ registerInternalPlugin('services', Services, {
|
|
|
15
14
|
},
|
|
16
15
|
});
|
|
17
16
|
|
|
18
|
-
export {constants};
|
|
19
|
-
export {default as ServiceInterceptor} from './interceptors/service';
|
|
20
|
-
export {default as ServerErrorInterceptor} from './interceptors/server-error';
|
|
21
|
-
export {default as HostMapInterceptor} from './interceptors/hostmap';
|
|
22
17
|
export {default as Services} from './services';
|
|
23
18
|
export {default as ServiceCatalog} from './service-catalog';
|
|
24
19
|
export {default as ServiceRegistry} from './service-registry';
|
|
@@ -3,12 +3,12 @@ import sha256 from 'crypto-js/sha256';
|
|
|
3
3
|
import {union, forEach} from 'lodash';
|
|
4
4
|
import WebexPlugin from '../webex-plugin';
|
|
5
5
|
|
|
6
|
-
import METRICS from '
|
|
6
|
+
import METRICS from '../metrics';
|
|
7
7
|
import ServiceCatalog from './service-catalog';
|
|
8
8
|
import ServiceRegistry from './service-registry';
|
|
9
9
|
import ServiceState from './service-state';
|
|
10
10
|
import fedRampServices from './service-fed-ramp';
|
|
11
|
-
import {COMMERCIAL_ALLOWED_DOMAINS} from '
|
|
11
|
+
import {COMMERCIAL_ALLOWED_DOMAINS} from '../constants';
|
|
12
12
|
|
|
13
13
|
const trailingSlashes = /(?:^\/)|(?:\/$)/;
|
|
14
14
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
[](https://github.com/RichardLitt/standard-readme)
|
|
2
|
+
|
|
3
|
+
> Services plugin update for WG4 DNSSec enabled users, this module is a work in progress. Please use at your own risk! This service will be updated many times to enable this feature. Continue to use /services.
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import AmpState from 'ampersand-state';
|
|
2
|
+
|
|
3
|
+
import {union} from 'lodash';
|
|
4
|
+
import ServiceDetail from './service-detail';
|
|
5
|
+
import {IServiceDetail, ServiceGroup} from './types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @class
|
|
9
|
+
*/
|
|
10
|
+
const ServiceCatalog = AmpState.extend({
|
|
11
|
+
namespace: 'ServiceCatalog',
|
|
12
|
+
|
|
13
|
+
props: {
|
|
14
|
+
serviceGroups: [
|
|
15
|
+
'object',
|
|
16
|
+
true,
|
|
17
|
+
() => ({
|
|
18
|
+
discovery: [],
|
|
19
|
+
override: [],
|
|
20
|
+
preauth: [],
|
|
21
|
+
postauth: [],
|
|
22
|
+
signin: [],
|
|
23
|
+
}),
|
|
24
|
+
],
|
|
25
|
+
status: [
|
|
26
|
+
'object',
|
|
27
|
+
true,
|
|
28
|
+
() => ({
|
|
29
|
+
discovery: {
|
|
30
|
+
ready: false,
|
|
31
|
+
collecting: false,
|
|
32
|
+
},
|
|
33
|
+
override: {
|
|
34
|
+
ready: false,
|
|
35
|
+
collecting: false,
|
|
36
|
+
},
|
|
37
|
+
preauth: {
|
|
38
|
+
ready: false,
|
|
39
|
+
collecting: false,
|
|
40
|
+
},
|
|
41
|
+
postauth: {
|
|
42
|
+
ready: false,
|
|
43
|
+
collecting: false,
|
|
44
|
+
},
|
|
45
|
+
signin: {
|
|
46
|
+
ready: false,
|
|
47
|
+
collecting: false,
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
51
|
+
isReady: ['boolean', false, false],
|
|
52
|
+
allowedDomains: ['array', false, () => []],
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @private
|
|
57
|
+
* Get all service details for a given service group or return all details if no group is specified.
|
|
58
|
+
* @param {ServiceGroup} serviceGroup - The name of the service group to retrieve details for.
|
|
59
|
+
* @returns {Array<IServiceDetail>} - An array of service details.
|
|
60
|
+
*/
|
|
61
|
+
_getAllServiceDetails(serviceGroup?: ServiceGroup): Array<IServiceDetail> {
|
|
62
|
+
const serviceDetails =
|
|
63
|
+
typeof serviceGroup === 'string'
|
|
64
|
+
? this.serviceGroups[serviceGroup] || []
|
|
65
|
+
: [
|
|
66
|
+
...this.serviceGroups.override,
|
|
67
|
+
...this.serviceGroups.postauth,
|
|
68
|
+
...this.serviceGroups.signin,
|
|
69
|
+
...this.serviceGroups.preauth,
|
|
70
|
+
...this.serviceGroups.discovery,
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
return serviceDetails;
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @private
|
|
78
|
+
* Search the service details array to locate a `ServiceDetails`
|
|
79
|
+
* class object based on its id.
|
|
80
|
+
* @param {string} clusterId
|
|
81
|
+
* @param {ServiceGroup} [serviceGroup]
|
|
82
|
+
* @returns {IServiceDetail}
|
|
83
|
+
*/
|
|
84
|
+
_getServiceDetail(clusterId: string, serviceGroup?: ServiceGroup): IServiceDetail | undefined {
|
|
85
|
+
const serviceDetails = this._getAllServiceDetails(serviceGroup);
|
|
86
|
+
|
|
87
|
+
return serviceDetails.find((serviceDetail: IServiceDetail) => serviceDetail.id === clusterId);
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @private
|
|
92
|
+
* Safely load one or more `ServiceDetail`s into this `ServiceCatalog` instance.
|
|
93
|
+
* @param {ServiceGroup} serviceGroup
|
|
94
|
+
* @param {Array<ServiceDetail>} serviceDetails
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
_loadServiceDetails(serviceGroup: ServiceGroup, serviceDetails: Array<IServiceDetail>): void {
|
|
98
|
+
// declare namespaces outside of loop
|
|
99
|
+
let existingService: IServiceDetail | undefined;
|
|
100
|
+
|
|
101
|
+
serviceDetails.forEach((service) => {
|
|
102
|
+
existingService = this._getServiceDetail(service.id, serviceGroup);
|
|
103
|
+
|
|
104
|
+
if (!existingService) {
|
|
105
|
+
this.serviceGroups[serviceGroup].push(service);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @private
|
|
112
|
+
* Safely unload one or more `ServiceDetail`s into this `Services` instance
|
|
113
|
+
* @param {ServiceGroup} serviceGroup
|
|
114
|
+
* @param {Array<ServiceDetail>} serviceDetails
|
|
115
|
+
* @returns {void}
|
|
116
|
+
*/
|
|
117
|
+
_unloadServiceDetails(serviceGroup: ServiceGroup, serviceDetails: Array<IServiceDetail>): void {
|
|
118
|
+
// declare namespaces outside of loop
|
|
119
|
+
let existingService: IServiceDetail | undefined;
|
|
120
|
+
|
|
121
|
+
serviceDetails.forEach((service) => {
|
|
122
|
+
existingService = this._getServiceDetail(service.id, serviceGroup);
|
|
123
|
+
|
|
124
|
+
if (existingService) {
|
|
125
|
+
this.serviceGroups[serviceGroup].splice(
|
|
126
|
+
this.serviceGroups[serviceGroup].indexOf(existingService),
|
|
127
|
+
1
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Clear all collected catalog data and reset catalog status.
|
|
135
|
+
*
|
|
136
|
+
* @returns {void}
|
|
137
|
+
*/
|
|
138
|
+
clean(): void {
|
|
139
|
+
this.serviceGroups.preauth.length = 0;
|
|
140
|
+
this.serviceGroups.signin.length = 0;
|
|
141
|
+
this.serviceGroups.postauth.length = 0;
|
|
142
|
+
this.status.preauth = {ready: false};
|
|
143
|
+
this.status.signin = {ready: false};
|
|
144
|
+
this.status.postauth = {ready: false};
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Search over all service groups to find a cluster id based
|
|
149
|
+
* on a given url.
|
|
150
|
+
* @param {string} url - Must be parsable by `Url`
|
|
151
|
+
* @returns {string | undefined} - ClusterId of a given url
|
|
152
|
+
*/
|
|
153
|
+
findClusterId(url: string): string | undefined {
|
|
154
|
+
try {
|
|
155
|
+
const incomingUrlObj = new URL(url);
|
|
156
|
+
const allServiceDetails = this._getAllServiceDetails();
|
|
157
|
+
|
|
158
|
+
return allServiceDetails.find((serviceDetail: IServiceDetail) =>
|
|
159
|
+
serviceDetail.serviceUrls.find(({host}) => host === incomingUrlObj.host)
|
|
160
|
+
)?.id;
|
|
161
|
+
} catch {
|
|
162
|
+
// If the URL is invalid or can't be found, return undefined
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Search over all service groups and return a service value from a provided
|
|
169
|
+
* clusterId.
|
|
170
|
+
* @param {object} params
|
|
171
|
+
* @param {string} params.clusterId - clusterId of found service
|
|
172
|
+
* @param {ServiceGroup} [params.serviceGroup] - specify service group
|
|
173
|
+
* @returns {object} service
|
|
174
|
+
* @returns {string} service.name
|
|
175
|
+
* @returns {string} service.url
|
|
176
|
+
*/
|
|
177
|
+
findServiceFromClusterId(
|
|
178
|
+
{clusterId, serviceGroup} = {} as {clusterId: string; serviceGroup?: ServiceGroup}
|
|
179
|
+
): {name: string; url: string} | undefined {
|
|
180
|
+
const serviceDetails = this._getServiceDetail(clusterId, serviceGroup);
|
|
181
|
+
|
|
182
|
+
if (serviceDetails) {
|
|
183
|
+
return {
|
|
184
|
+
name: serviceDetails.serviceName,
|
|
185
|
+
url: serviceDetails.get(),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return undefined;
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Find a service based on the provided url.
|
|
194
|
+
* @param {string} url - Must be parsable by `Url`
|
|
195
|
+
* @returns {IServiceDetail} - ServiceDetail assocated with provided url
|
|
196
|
+
*/
|
|
197
|
+
findServiceDetailFromUrl(url: string): IServiceDetail | undefined {
|
|
198
|
+
const serviceDetails = this._getAllServiceDetails();
|
|
199
|
+
|
|
200
|
+
return serviceDetails.find(({serviceUrls}) => {
|
|
201
|
+
for (const serviceUrl of serviceUrls) {
|
|
202
|
+
if (url.startsWith(serviceUrl.baseUrl)) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return false;
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Finds an allowed domain that matches a specific url.
|
|
213
|
+
*
|
|
214
|
+
* @param {string} url - The url to match the allowed domains against.
|
|
215
|
+
* @returns {string} - The matching allowed domain.
|
|
216
|
+
*/
|
|
217
|
+
findAllowedDomain(url: string): string {
|
|
218
|
+
try {
|
|
219
|
+
const urlObj = new URL(url);
|
|
220
|
+
|
|
221
|
+
return this.allowedDomains.find((allowedDomain) => urlObj.host.includes(allowedDomain));
|
|
222
|
+
} catch {
|
|
223
|
+
// If the URL is invalid or can't be found, return undefined
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Get a service url from the current services list by name. Return undefined
|
|
230
|
+
* if the service is not found.
|
|
231
|
+
* @param {string} clusterId
|
|
232
|
+
* @param {ServiceGroup} serviceGroup
|
|
233
|
+
* @returns {string | undefined}
|
|
234
|
+
*/
|
|
235
|
+
get(clusterId: string, serviceGroup?: ServiceGroup): string | undefined {
|
|
236
|
+
const serviceDetail = this._getServiceDetail(clusterId, serviceGroup);
|
|
237
|
+
|
|
238
|
+
return serviceDetail ? serviceDetail.get() : undefined;
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Get the current allowed domains list.
|
|
243
|
+
*
|
|
244
|
+
* @returns {Array<string>} - the current allowed domains list.
|
|
245
|
+
*/
|
|
246
|
+
getAllowedDomains(): Array<string> {
|
|
247
|
+
return [...this.allowedDomains];
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Mark a priority host service url as failed.
|
|
252
|
+
* This will mark the host associated with the
|
|
253
|
+
* `ServiceDetail` to be removed from the its
|
|
254
|
+
* respective host array, and then return the next
|
|
255
|
+
* viable host from the `ServiceDetail` host array,
|
|
256
|
+
* or the `ServiceDetail` default url if no other priority
|
|
257
|
+
* hosts are available, or if `noPriorityHosts` is set to
|
|
258
|
+
* `true`.
|
|
259
|
+
* @param {string} url
|
|
260
|
+
* @returns {string}
|
|
261
|
+
*/
|
|
262
|
+
markFailedServiceUrl(url: string): string | undefined {
|
|
263
|
+
const serviceDetails = this._getAllServiceDetails();
|
|
264
|
+
|
|
265
|
+
const serviceDetailWithFailedHost = serviceDetails.find((serviceDetail: IServiceDetail) =>
|
|
266
|
+
serviceDetail.failHost(url)
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// if we couldn't find the url we wanted to fail, return undefined
|
|
270
|
+
if (!serviceDetailWithFailedHost) {
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return serviceDetailWithFailedHost.get();
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Set the allowed domains for the catalog.
|
|
279
|
+
*
|
|
280
|
+
* @param {Array<string>} allowedDomains - allowed domains to be assigned.
|
|
281
|
+
* @returns {void}
|
|
282
|
+
*/
|
|
283
|
+
setAllowedDomains(allowedDomains: Array<string>): void {
|
|
284
|
+
this.allowedDomains = [...allowedDomains];
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
*
|
|
289
|
+
* @param {Array<string>} newAllowedDomains - new allowed domains to add to existing set of allowed domains
|
|
290
|
+
* @returns {void}
|
|
291
|
+
*/
|
|
292
|
+
addAllowedDomains(newAllowedDomains: Array<string>): void {
|
|
293
|
+
this.allowedDomains = union(this.allowedDomains, newAllowedDomains);
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Update the current list of `ServiceDetail`s against a provided
|
|
298
|
+
* service hostmap.
|
|
299
|
+
* @emits ServiceCatalog#preauthorized
|
|
300
|
+
* @emits ServiceCatalog#postauthorized
|
|
301
|
+
* @param {ServiceGroup} serviceGroup
|
|
302
|
+
* @param {Array<IServiceDetail>} serviceDetails
|
|
303
|
+
* @returns {void}
|
|
304
|
+
*/
|
|
305
|
+
updateServiceGroups(serviceGroup: ServiceGroup, serviceDetails: Array<IServiceDetail>) {
|
|
306
|
+
const currentServiceDetails = this.serviceGroups[serviceGroup];
|
|
307
|
+
|
|
308
|
+
const unusedServicesDetails = currentServiceDetails.filter((serviceDetail) =>
|
|
309
|
+
serviceDetails.every(({id}) => id !== serviceDetail.id)
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
this._unloadServiceDetails(serviceGroup, unusedServicesDetails);
|
|
313
|
+
|
|
314
|
+
serviceDetails.forEach((serviceObj) => {
|
|
315
|
+
const serviceDetail = this._getServiceDetail(serviceObj.id, serviceGroup);
|
|
316
|
+
|
|
317
|
+
if (serviceDetail) {
|
|
318
|
+
serviceDetail.serviceUrls = serviceObj.serviceUrls || [];
|
|
319
|
+
} else {
|
|
320
|
+
this._loadServiceDetails(serviceGroup, [new ServiceDetail(serviceObj)]);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
this.status[serviceGroup].ready = true;
|
|
325
|
+
this.trigger(serviceGroup);
|
|
326
|
+
},
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Wait until the service catalog is available,
|
|
330
|
+
* or reject after a timeout of 60 seconds.
|
|
331
|
+
* @param {ServiceGroup} serviceGroup
|
|
332
|
+
* @param {number} [timeout] - in seconds
|
|
333
|
+
* @returns {Promise<void>}
|
|
334
|
+
*/
|
|
335
|
+
waitForCatalog(serviceGroup: ServiceGroup, timeout?: number): Promise<void> {
|
|
336
|
+
return new Promise<void>((resolve, reject) => {
|
|
337
|
+
if (this.status[serviceGroup].ready) {
|
|
338
|
+
resolve();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const validatedTimeout = typeof timeout === 'number' && timeout >= 0 ? timeout : 60;
|
|
342
|
+
|
|
343
|
+
const timeoutTimer = setTimeout(
|
|
344
|
+
() =>
|
|
345
|
+
reject(
|
|
346
|
+
new Error(
|
|
347
|
+
`services: timeout occured while waiting for '${serviceGroup}' catalog to populate`
|
|
348
|
+
)
|
|
349
|
+
),
|
|
350
|
+
validatedTimeout * 1000
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
this.once(serviceGroup, () => {
|
|
354
|
+
clearTimeout(timeoutTimer);
|
|
355
|
+
resolve();
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
export default ServiceCatalog;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import AmpState from 'ampersand-state';
|
|
2
|
+
import {ServiceUrl} from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @class
|
|
6
|
+
*/
|
|
7
|
+
const ServiceDetail = AmpState.extend({
|
|
8
|
+
namespace: 'ServiceDetail',
|
|
9
|
+
|
|
10
|
+
props: {
|
|
11
|
+
serviceUrls: ['array', false, () => []],
|
|
12
|
+
serviceName: ['string', true, undefined],
|
|
13
|
+
id: ['string', true, undefined],
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate a host url based on the host
|
|
18
|
+
* uri provided.
|
|
19
|
+
* @param {ServiceUrl} serviceUrl
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
_generateHostUrl(serviceUrl: ServiceUrl): string {
|
|
23
|
+
const url = new URL(serviceUrl.baseUrl);
|
|
24
|
+
|
|
25
|
+
// setting url.hostname will not apply during Url.format(), set host via
|
|
26
|
+
// a string literal instead.
|
|
27
|
+
url.host = `${serviceUrl.host}${url.port ? `:${url.port}` : ''}`;
|
|
28
|
+
|
|
29
|
+
return url.href;
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get the current host url with the highest priority. This will only return a URL with a filtered host that has the
|
|
34
|
+
* `homeCluster` value set to `true`.
|
|
35
|
+
* @returns {string} - The priority host url.
|
|
36
|
+
*/
|
|
37
|
+
_getPriorityHostUrl(): string {
|
|
38
|
+
// format of catalog ensures that array is sorted by highest priority
|
|
39
|
+
let priorityServiceUrl = this._searchForValidPriorityHost();
|
|
40
|
+
|
|
41
|
+
if (!priorityServiceUrl) {
|
|
42
|
+
this.serviceUrls = this.serviceUrls.map((serviceUrl) => {
|
|
43
|
+
serviceUrl.failed = false;
|
|
44
|
+
|
|
45
|
+
return serviceUrl;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
priorityServiceUrl = this._searchForValidPriorityHost();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return priorityServiceUrl ? this._generateHostUrl(priorityServiceUrl) : '';
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Searches for a valid service URL with a priority greater than 0 that has not failed.
|
|
56
|
+
* @returns {ServiceUrl | undefined} - The first valid service URL found, or undefined if none exist.
|
|
57
|
+
*/
|
|
58
|
+
_searchForValidPriorityHost(): ServiceUrl | undefined {
|
|
59
|
+
return this.serviceUrls.find((serviceUrl) => serviceUrl.priority > 0 && !serviceUrl.failed);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Attempt to mark a host from this `ServiceDetail` as failed and return true
|
|
64
|
+
* if the provided url has a host that could be successfully marked as failed.
|
|
65
|
+
*
|
|
66
|
+
* @param {string} url
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
failHost(url: string): boolean {
|
|
70
|
+
const failedUrl = new URL(url);
|
|
71
|
+
|
|
72
|
+
const foundHost = this.serviceUrls.find((serviceUrl) => serviceUrl.host === failedUrl.host);
|
|
73
|
+
|
|
74
|
+
if (foundHost) {
|
|
75
|
+
foundHost.failed = true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return foundHost !== undefined;
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Generate a url using the host with the
|
|
83
|
+
* highest priority via host rendering.
|
|
84
|
+
*
|
|
85
|
+
* @returns {string} - The full service url.
|
|
86
|
+
*/
|
|
87
|
+
get(): string {
|
|
88
|
+
// return empty string to indicate that no service url is available
|
|
89
|
+
if (!this.serviceUrls || this.serviceUrls.length === 0) {
|
|
90
|
+
return '';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return this._getPriorityHostUrl();
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export default ServiceDetail;
|