1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | const async = require('async');
|
17 |
|
18 | const { AppOptionsName, DomainTypes, EnvOptionsName, LogLevel, OperationType, OrgOptionsName } = require('./Constants');
|
19 | const FileProcessorHelper = require('./FileProcessorHelper');
|
20 | const { getObjectByPicking, isEmpty, isNullOrUndefined } = require('./Utils');
|
21 |
|
22 | class AppFileProcessor {
|
23 | constructor(options) {
|
24 | this.cliManager = options.cliManager;
|
25 | this.envFileProcessor = options.envFileProcessor;
|
26 | this.serviceFileProcessor = options.serviceFileProcessor;
|
27 | this.applicationsService = options.applicationsService;
|
28 | this.environmentsService = options.environmentsService;
|
29 | this.servicesService = options.servicesService;
|
30 | }
|
31 |
|
32 | process(options, done) {
|
33 | const operationType = options.operation;
|
34 | const configApp = options.parsedData;
|
35 | if (operationType === OperationType.CREATE) {
|
36 | this._createApp(configApp, options, done);
|
37 | } else if (operationType === OperationType.UPDATE) {
|
38 | this._updateApp(configApp, options, done);
|
39 | } else {
|
40 | return setImmediate(() => { done(new Error(`Operation type not supported: ${operationType}`)); });
|
41 | }
|
42 | }
|
43 |
|
44 | _createApp(configApp, options, done) {
|
45 | let app;
|
46 |
|
47 | async.series([
|
48 | (next) => {
|
49 | const data = getObjectByPicking(configApp.settings, ['realtime', 'sessionTimeoutInSeconds']);
|
50 | data.name = options.name;
|
51 | const orgId = options[OrgOptionsName.ORG];
|
52 | if (!isNullOrUndefined(orgId)) {
|
53 | data.organizationId = orgId;
|
54 | }
|
55 |
|
56 | this.cliManager.log(LogLevel.INFO, `Creating app: ${data.name}`);
|
57 | this.applicationsService.create(data, (err, result) => {
|
58 | if (err) {
|
59 | return next(err);
|
60 | }
|
61 |
|
62 | app = result;
|
63 | next();
|
64 | });
|
65 | },
|
66 | (next) => {
|
67 | this._createServices({ services: configApp.services, appId: app.id }, next);
|
68 | },
|
69 | (next) => {
|
70 | this._createInitialEnvs(app, configApp.environments, next);
|
71 | }
|
72 | ], (err) => {
|
73 | if (err) {
|
74 | return done(err);
|
75 | }
|
76 |
|
77 | done(null, { id: app.id });
|
78 | });
|
79 | }
|
80 |
|
81 | |
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 | _createServices(options, done) {
|
90 | if (isNullOrUndefined(options.services) || isEmpty(options.services)) {
|
91 | return setImmediate(done);
|
92 | }
|
93 |
|
94 | const servicesNames = Object.keys(options.services);
|
95 | async.eachSeries(
|
96 | servicesNames,
|
97 | (currName, next) => {
|
98 | this.cliManager.log(LogLevel.INFO, `Creating service: ${currName}`);
|
99 | this.serviceFileProcessor.process(
|
100 | {
|
101 | operation: OperationType.CREATE,
|
102 | parsedData: options.services[currName],
|
103 | name: currName,
|
104 | domainId: options.appId,
|
105 | domainType: DomainTypes.APP
|
106 | },
|
107 | next
|
108 | );
|
109 | },
|
110 | done
|
111 | );
|
112 | }
|
113 |
|
114 | _updateServices(options, done) {
|
115 | const configServices = options.services;
|
116 | if (isEmpty(configServices)) {
|
117 | return setImmediate(done);
|
118 | }
|
119 |
|
120 | const existingServices = options.existingServices;
|
121 | const operation = OperationType.UPDATE;
|
122 |
|
123 | async.eachSeries(
|
124 | configServices,
|
125 | (currService, next) => {
|
126 | const nameIdentifier = Object.keys(currService)[0];
|
127 | const existingService = existingServices.find(x => x.name === nameIdentifier);
|
128 | const updateData = currService[nameIdentifier];
|
129 | updateData.name = updateData.name || nameIdentifier;
|
130 | const processOptions = {
|
131 | operation,
|
132 | parsedData: updateData,
|
133 | serviceId: existingService.id,
|
134 | domainId: options.appId,
|
135 | domainType: DomainTypes.APP
|
136 | };
|
137 | this.cliManager.log(LogLevel.INFO, `Updating service: ${nameIdentifier}`);
|
138 | this.serviceFileProcessor.process(processOptions, next);
|
139 | },
|
140 | done
|
141 | );
|
142 | }
|
143 |
|
144 | |
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 | _createInitialEnvs(app, configEnvs, done) {
|
154 | if (isNullOrUndefined(configEnvs) || isEmpty(configEnvs)) {
|
155 | return setImmediate(done);
|
156 | }
|
157 |
|
158 | const envNames = Object.keys(configEnvs);
|
159 | const defaultEnvName = 'development';
|
160 | const findDefEnv = x => x.name.toLowerCase() === defaultEnvName;
|
161 |
|
162 | let updateDefaultEnv = true;
|
163 | async.eachSeries(
|
164 | envNames,
|
165 | (currentName, next) => {
|
166 |
|
167 |
|
168 | const operation = updateDefaultEnv ? OperationType.UPDATE : OperationType.CREATE;
|
169 | const options = {
|
170 | operation,
|
171 | name: currentName,
|
172 | parsedData: configEnvs[currentName],
|
173 | [AppOptionsName.APP]: app.id
|
174 | };
|
175 |
|
176 | if (updateDefaultEnv) {
|
177 | options.env = app.environments.find(findDefEnv);
|
178 | options.parsedData.name = currentName;
|
179 | updateDefaultEnv = false;
|
180 | }
|
181 |
|
182 | this.envFileProcessor.process(options, next);
|
183 | },
|
184 | done
|
185 | );
|
186 | }
|
187 |
|
188 | _createEnvs(appId, configEnvs, done) {
|
189 | if (isNullOrUndefined(configEnvs) || isEmpty(configEnvs)) {
|
190 | return setImmediate(done);
|
191 | }
|
192 |
|
193 | const envNames = Object.keys(configEnvs);
|
194 |
|
195 | async.eachSeries(
|
196 | envNames,
|
197 | (currentName, next) => {
|
198 | const options = {
|
199 | operation: OperationType.CREATE,
|
200 | name: currentName,
|
201 | parsedData: configEnvs[currentName],
|
202 | [AppOptionsName.APP]: appId
|
203 | };
|
204 | this.envFileProcessor.process(options, next);
|
205 | },
|
206 | done
|
207 | );
|
208 | }
|
209 |
|
210 | |
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 | _modifyEnvs(app, configEnvs, done) {
|
221 | if (isNullOrUndefined(configEnvs) || isEmpty(configEnvs)) {
|
222 | return setImmediate(done);
|
223 | }
|
224 |
|
225 | const existingEnvs = app.environments;
|
226 | const groupedEntities = FileProcessorHelper.groupEntitiesPerOperationType(existingEnvs, configEnvs);
|
227 |
|
228 | async.series([
|
229 | (next) => {
|
230 | this._updateEnvs(existingEnvs, groupedEntities[OperationType.UPDATE], next);
|
231 | },
|
232 | (next) => {
|
233 | this._createEnvs(app.id, groupedEntities[OperationType.CREATE], next);
|
234 | }
|
235 | ], done);
|
236 | }
|
237 |
|
238 | _updateEnvs(existingEnvs, configEnvs, done) {
|
239 | const operation = OperationType.UPDATE;
|
240 |
|
241 | async.eachSeries(
|
242 | configEnvs,
|
243 | (currEnv, next) => {
|
244 | const nameIdentifier = Object.keys(currEnv)[0];
|
245 | const env = existingEnvs.find(x => x.name === nameIdentifier);
|
246 | const options = {
|
247 | operation,
|
248 | parsedData: currEnv[nameIdentifier],
|
249 | [EnvOptionsName.ENV]: env
|
250 | };
|
251 | this.envFileProcessor.process(options, next);
|
252 | },
|
253 | done
|
254 | );
|
255 | }
|
256 |
|
257 | _updateApp(configApp, options, done) {
|
258 | const app = options[AppOptionsName.APP];
|
259 | const appId = app.id;
|
260 | let groupedServices;
|
261 | let existingServices;
|
262 |
|
263 | async.series([
|
264 | (next) => {
|
265 | let data = { name: app.name };
|
266 | data = Object.assign(data, configApp.settings);
|
267 | if (!isNullOrUndefined(app.organizationId)) {
|
268 | data.organizationId = app.organizationId;
|
269 | }
|
270 |
|
271 | this.cliManager.log(LogLevel.INFO, `Updating app: ${data.name}`);
|
272 | this.applicationsService.update(appId, data, next);
|
273 | },
|
274 | (next) => {
|
275 | this.servicesService.getAllOwnedByApp(appId, false, (err, data) => {
|
276 | if (err) {
|
277 | return next(err);
|
278 | }
|
279 |
|
280 | existingServices = data;
|
281 | const configServices = configApp.services || {};
|
282 | groupedServices = FileProcessorHelper.groupEntitiesPerOperationType(existingServices, configServices);
|
283 | next();
|
284 | });
|
285 | },
|
286 | (next) => {
|
287 | this._createServices({ services: groupedServices[OperationType.CREATE], appId }, next);
|
288 | },
|
289 | (next) => {
|
290 | this._updateServices({ services: groupedServices[OperationType.UPDATE], existingServices, appId }, next);
|
291 | },
|
292 | (next) => {
|
293 | this._modifyEnvs(app, configApp.environments, next);
|
294 | }
|
295 | ], (err) => {
|
296 | if (err) {
|
297 | return done(err);
|
298 | }
|
299 |
|
300 | done(null, { id: appId });
|
301 | });
|
302 | }
|
303 | }
|
304 |
|
305 | module.exports = AppFileProcessor;
|