@red-hat-developer-hub/backstage-plugin-orchestrator-backend 4.1.1

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +740 -0
  2. package/README.md +5 -0
  3. package/app-config.yaml +3 -0
  4. package/dist/helpers/errorBuilder.cjs.js +36 -0
  5. package/dist/helpers/errorBuilder.cjs.js.map +1 -0
  6. package/dist/helpers/filterBuilder.cjs.js +197 -0
  7. package/dist/helpers/filterBuilder.cjs.js.map +1 -0
  8. package/dist/helpers/queryBuilder.cjs.js +40 -0
  9. package/dist/helpers/queryBuilder.cjs.js.map +1 -0
  10. package/dist/index.cjs.js +10 -0
  11. package/dist/index.cjs.js.map +1 -0
  12. package/dist/index.d.ts +9 -0
  13. package/dist/package.json.cjs.js +6 -0
  14. package/dist/package.json.cjs.js.map +1 -0
  15. package/dist/plugin.cjs.js +45 -0
  16. package/dist/plugin.cjs.js.map +1 -0
  17. package/dist/routerWrapper/index.cjs.js +31 -0
  18. package/dist/routerWrapper/index.cjs.js.map +1 -0
  19. package/dist/service/DataIndexService.cjs.js +405 -0
  20. package/dist/service/DataIndexService.cjs.js.map +1 -0
  21. package/dist/service/DataInputSchemaService.cjs.js +12 -0
  22. package/dist/service/DataInputSchemaService.cjs.js.map +1 -0
  23. package/dist/service/DevModeService.cjs.js +144 -0
  24. package/dist/service/DevModeService.cjs.js.map +1 -0
  25. package/dist/service/GitService.cjs.js +72 -0
  26. package/dist/service/GitService.cjs.js.map +1 -0
  27. package/dist/service/GitWrapper/git.cjs.js +219 -0
  28. package/dist/service/GitWrapper/git.cjs.js.map +1 -0
  29. package/dist/service/Helper.cjs.js +66 -0
  30. package/dist/service/Helper.cjs.js.map +1 -0
  31. package/dist/service/OrchestratorService.cjs.js +119 -0
  32. package/dist/service/OrchestratorService.cjs.js.map +1 -0
  33. package/dist/service/ScaffolderService.cjs.js +94 -0
  34. package/dist/service/ScaffolderService.cjs.js.map +1 -0
  35. package/dist/service/SonataFlowService.cjs.js +188 -0
  36. package/dist/service/SonataFlowService.cjs.js.map +1 -0
  37. package/dist/service/WorkflowCacheService.cjs.js +91 -0
  38. package/dist/service/WorkflowCacheService.cjs.js.map +1 -0
  39. package/dist/service/api/mapping/V2Mappings.cjs.js +150 -0
  40. package/dist/service/api/mapping/V2Mappings.cjs.js.map +1 -0
  41. package/dist/service/api/v2.cjs.js +187 -0
  42. package/dist/service/api/v2.cjs.js.map +1 -0
  43. package/dist/service/constants.cjs.js +10 -0
  44. package/dist/service/constants.cjs.js.map +1 -0
  45. package/dist/service/router.cjs.js +626 -0
  46. package/dist/service/router.cjs.js.map +1 -0
  47. package/dist/types/pagination.cjs.js +30 -0
  48. package/dist/types/pagination.cjs.js.map +1 -0
  49. package/package.json +110 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScaffolderService.cjs.js","sources":["../../src/service/ScaffolderService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { loggerToWinstonLogger } from '@backstage/backend-common';\nimport type {\n LoggerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport type { Config } from '@backstage/config';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createBuiltinActions,\n TemplateActionRegistry,\n} from '@backstage/plugin-scaffolder-backend';\nimport {\n ActionContext,\n TemplateAction,\n} from '@backstage/plugin-scaffolder-node';\nimport type { JsonObject, JsonValue } from '@backstage/types';\n\nimport fs from 'fs-extra';\n\nimport { randomUUID } from 'crypto';\nimport path from 'path';\nimport { PassThrough } from 'stream';\n\nimport { getWorkingDirectory } from './Helper';\n\nexport interface ActionExecutionContext {\n actionId: string;\n instanceId: string | undefined;\n input: JsonObject;\n}\n\nexport class ScaffolderService {\n private actionRegistry: TemplateActionRegistry;\n private streamLogger = new PassThrough();\n\n constructor(\n private readonly logger: LoggerService,\n private readonly config: Config,\n private readonly catalogApi: CatalogApi,\n private readonly urlReader: UrlReaderService,\n ) {\n this.actionRegistry = new TemplateActionRegistry();\n }\n\n public loadActions(): void {\n const actions = [\n ...createBuiltinActions({\n integrations: ScmIntegrations.fromConfig(this.config),\n catalogClient: this.catalogApi,\n reader: this.urlReader,\n config: this.config,\n }),\n ];\n actions.forEach(a => this.actionRegistry.register(a));\n }\n\n public getAction(id: string): TemplateAction {\n return this.actionRegistry.get(id);\n }\n\n public async executeAction(\n actionExecutionContext: ActionExecutionContext,\n ): Promise<JsonValue> {\n if (this.actionRegistry.list().length === 0) {\n this.loadActions();\n }\n\n const action: TemplateAction = this.getAction(\n actionExecutionContext.actionId,\n );\n const stepOutput: { [outputName: string]: JsonValue } = {};\n\n let workspacePath: string;\n try {\n const workingDirectory = await getWorkingDirectory(\n this.config,\n this.logger,\n );\n workspacePath = path.join(\n workingDirectory,\n actionExecutionContext.instanceId ?? randomUUID(),\n );\n } catch (err: unknown) {\n this.logger.error(\n `Error getting working directory to execute action ${actionExecutionContext.actionId}`,\n err as Error,\n );\n throw err;\n }\n const actionContext: ActionContext<JsonObject> = {\n input: actionExecutionContext.input,\n workspacePath: workspacePath,\n // TODO: Move this to LoggerService after scaffolder-node moves to LoggerService\n // https://github.com/backstage/backstage/issues/26933\n logger: loggerToWinstonLogger(this.logger),\n logStream: this.streamLogger,\n createTemporaryDirectory: async () =>\n await fs.mkdtemp(`${workspacePath}_step-${0}-`),\n output(name: string, value: JsonValue) {\n stepOutput[name] = value;\n },\n getInitiatorCredentials: async () => {\n return {\n $$type: '@backstage/BackstageCredentials',\n principal: 'mock-principal',\n };\n },\n checkpoint: async (key, fn) => {\n this.logger.info(`Orchestrator ScaffolderService checkpoint ${key}`);\n return fn();\n },\n };\n await action.handler(actionContext);\n\n return stepOutput;\n }\n}\n"],"names":["TemplateActionRegistry","PassThrough","createBuiltinActions","ScmIntegrations","getWorkingDirectory","path","randomUUID","loggerToWinstonLogger","fs"],"mappings":"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"}
@@ -0,0 +1,188 @@
1
+ 'use strict';
2
+
3
+ var backstagePluginOrchestratorCommon = require('@red-hat-developer-hub/backstage-plugin-orchestrator-common');
4
+
5
+ class SonataFlowService {
6
+ constructor(dataIndexService, logger) {
7
+ this.dataIndexService = dataIndexService;
8
+ this.logger = logger;
9
+ }
10
+ async fetchWorkflowInfoOnService(args) {
11
+ const urlToFetch = `${args.serviceUrl}/management/processes/${args.definitionId}`;
12
+ const response = await fetch(urlToFetch);
13
+ if (response.ok) {
14
+ const json = await response.json();
15
+ this.logger.debug(`Fetch workflow info result: ${JSON.stringify(json)}`);
16
+ return json;
17
+ }
18
+ throw new Error(
19
+ await this.createPrefixFetchErrorMessage(urlToFetch, response)
20
+ );
21
+ }
22
+ async fetchWorkflowDefinition(definitionId) {
23
+ const source = await this.dataIndexService.fetchWorkflowSource(
24
+ definitionId
25
+ );
26
+ if (source) {
27
+ return backstagePluginOrchestratorCommon.fromWorkflowSource(source);
28
+ }
29
+ return void 0;
30
+ }
31
+ async fetchWorkflowOverviews(args) {
32
+ const { definitionIds, pagination, filter } = args;
33
+ const workflowInfos = await this.dataIndexService.fetchWorkflowInfos({
34
+ definitionIds,
35
+ pagination,
36
+ filter
37
+ });
38
+ if (!workflowInfos?.length) {
39
+ return [];
40
+ }
41
+ const items = await Promise.all(
42
+ workflowInfos.filter((info) => info.source).map((info) => this.fetchWorkflowOverviewBySource(info.source))
43
+ );
44
+ return items.filter((item) => !!item);
45
+ }
46
+ async executeWorkflow(args) {
47
+ const urlToFetch = args.businessKey ? `${args.serviceUrl}/${args.definitionId}?businessKey=${args.businessKey}` : `${args.serviceUrl}/${args.definitionId}`;
48
+ const response = await fetch(urlToFetch, {
49
+ method: "POST",
50
+ body: JSON.stringify(args.inputData),
51
+ headers: { "content-type": "application/json" }
52
+ });
53
+ const json = await response.json();
54
+ if (json.id) {
55
+ this.logger.debug(
56
+ `Execute workflow successful. Response: ${JSON.stringify(json)}`
57
+ );
58
+ return json;
59
+ } else if (!response.ok) {
60
+ const errorMessage = await this.createPrefixFetchErrorMessage(
61
+ urlToFetch,
62
+ response,
63
+ "POST"
64
+ );
65
+ this.logger.error(
66
+ `Execute workflow failed. Response: ${JSON.stringify(json)}`
67
+ );
68
+ throw new Error(errorMessage);
69
+ } else {
70
+ this.logger.error(
71
+ `Execute workflow did not return a workflow instance ID. Response: ${JSON.stringify(
72
+ json
73
+ )}`
74
+ );
75
+ throw new Error("Execute workflow did not return a workflow instance ID");
76
+ }
77
+ }
78
+ async retriggerInstance(args) {
79
+ const urlToFetch = `${args.serviceUrl}/management/processes/${args.definitionId}/instances/${args.instanceId}/retrigger`;
80
+ const response = await fetch(urlToFetch, {
81
+ method: "POST"
82
+ });
83
+ if (!response.ok) {
84
+ throw new Error(
85
+ `${await this.createPrefixFetchErrorMessage(
86
+ urlToFetch,
87
+ response,
88
+ "POST"
89
+ )}`
90
+ );
91
+ }
92
+ return true;
93
+ }
94
+ async fetchWorkflowOverview(definitionId) {
95
+ const source = await this.dataIndexService.fetchWorkflowSource(
96
+ definitionId
97
+ );
98
+ if (!source) {
99
+ this.logger.debug(`Workflow source not found: ${definitionId}`);
100
+ return void 0;
101
+ }
102
+ return await this.fetchWorkflowOverviewBySource(source);
103
+ }
104
+ async fetchWorkflowOverviewBySource(source) {
105
+ let processInstances = [];
106
+ const limit = 10;
107
+ let offset = 0;
108
+ let lastTriggered = /* @__PURE__ */ new Date(0);
109
+ let lastRunStatus;
110
+ let lastRunId;
111
+ let counter = 0;
112
+ let totalDuration = 0;
113
+ const definition = backstagePluginOrchestratorCommon.fromWorkflowSource(source);
114
+ do {
115
+ processInstances = await this.dataIndexService.fetchInstancesByDefinitionId({
116
+ definitionId: definition.id,
117
+ limit,
118
+ offset
119
+ });
120
+ for (const pInstance of processInstances) {
121
+ if (!pInstance.start) {
122
+ continue;
123
+ }
124
+ if (new Date(pInstance.start) > lastTriggered) {
125
+ lastRunId = pInstance.id;
126
+ lastTriggered = new Date(pInstance.start);
127
+ lastRunStatus = pInstance.state;
128
+ }
129
+ if (pInstance.end) {
130
+ const start = new Date(pInstance.start);
131
+ const end = new Date(pInstance.end);
132
+ totalDuration += end.valueOf() - start.valueOf();
133
+ counter++;
134
+ }
135
+ }
136
+ offset += limit;
137
+ } while (processInstances.length > 0);
138
+ return {
139
+ workflowId: definition.id,
140
+ name: definition.name,
141
+ format: backstagePluginOrchestratorCommon.extractWorkflowFormat(source),
142
+ lastRunId,
143
+ lastTriggeredMs: lastTriggered.getTime(),
144
+ lastRunStatus,
145
+ category: backstagePluginOrchestratorCommon.getWorkflowCategory(definition),
146
+ avgDurationMs: counter ? totalDuration / counter : void 0,
147
+ description: definition.description
148
+ };
149
+ }
150
+ async pingWorkflowService(args) {
151
+ const urlToFetch = `${args.serviceUrl}/management/processes/${args.definitionId}`;
152
+ const response = await fetch(urlToFetch);
153
+ return response.ok;
154
+ }
155
+ async updateInstanceInputData(args) {
156
+ const { definitionId, serviceUrl, instanceId, inputData } = args;
157
+ const urlToFetch = `${serviceUrl}/${definitionId}/${instanceId}`;
158
+ const response = await fetch(urlToFetch, {
159
+ method: "PATCH",
160
+ body: JSON.stringify(inputData),
161
+ headers: { "content-type": "application/json" }
162
+ });
163
+ return response.ok;
164
+ }
165
+ async createPrefixFetchErrorMessage(urlToFetch, response, httpMethod = "GET") {
166
+ const res = await response.json();
167
+ const errorInfo = [];
168
+ let errorMsg = `Request ${httpMethod} ${urlToFetch} failed with: StatusCode: ${response.status}`;
169
+ if (response.statusText) {
170
+ errorInfo.push(`StatusText: ${response.statusText}`);
171
+ }
172
+ if (res?.details) {
173
+ errorInfo.push(`Details: ${res?.details}`);
174
+ }
175
+ if (res?.stack) {
176
+ errorInfo.push(`Stack: ${res?.stack}`);
177
+ }
178
+ if (errorInfo.length > 0) {
179
+ errorMsg += ` ${errorInfo.join(", ")}`;
180
+ } else {
181
+ errorMsg += " Unexpected error";
182
+ }
183
+ return errorMsg;
184
+ }
185
+ }
186
+
187
+ exports.SonataFlowService = SonataFlowService;
188
+ //# sourceMappingURL=SonataFlowService.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SonataFlowService.cjs.js","sources":["../../src/service/SonataFlowService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nimport {\n extractWorkflowFormat,\n Filter,\n fromWorkflowSource,\n getWorkflowCategory,\n ProcessInstance,\n ProcessInstanceStateValues,\n ProcessInstanceVariables,\n WorkflowDefinition,\n WorkflowExecutionResponse,\n WorkflowInfo,\n WorkflowOverview,\n} from '@red-hat-developer-hub/backstage-plugin-orchestrator-common';\n\nimport { Pagination } from '../types/pagination';\nimport { DataIndexService } from './DataIndexService';\n\nexport class SonataFlowService {\n constructor(\n private readonly dataIndexService: DataIndexService,\n private readonly logger: LoggerService,\n ) {}\n\n public async fetchWorkflowInfoOnService(args: {\n definitionId: string;\n serviceUrl: string;\n }): Promise<WorkflowInfo | undefined> {\n const urlToFetch = `${args.serviceUrl}/management/processes/${args.definitionId}`;\n const response = await fetch(urlToFetch);\n\n if (response.ok) {\n const json = await response.json();\n this.logger.debug(`Fetch workflow info result: ${JSON.stringify(json)}`);\n return json;\n }\n throw new Error(\n await this.createPrefixFetchErrorMessage(urlToFetch, response),\n );\n }\n\n public async fetchWorkflowDefinition(\n definitionId: string,\n ): Promise<WorkflowDefinition | undefined> {\n const source = await this.dataIndexService.fetchWorkflowSource(\n definitionId,\n );\n if (source) {\n return fromWorkflowSource(source);\n }\n return undefined;\n }\n\n public async fetchWorkflowOverviews(args: {\n definitionIds?: string[];\n pagination?: Pagination;\n filter?: Filter;\n }): Promise<WorkflowOverview[] | undefined> {\n const { definitionIds, pagination, filter } = args;\n const workflowInfos = await this.dataIndexService.fetchWorkflowInfos({\n definitionIds,\n pagination,\n filter,\n });\n if (!workflowInfos?.length) {\n return [];\n }\n const items = await Promise.all(\n workflowInfos\n .filter(info => info.source)\n .map(info => this.fetchWorkflowOverviewBySource(info.source!)),\n );\n return items.filter((item): item is WorkflowOverview => !!item);\n }\n\n public async executeWorkflow(args: {\n definitionId: string;\n serviceUrl: string;\n inputData: ProcessInstanceVariables;\n businessKey?: string;\n }): Promise<WorkflowExecutionResponse | undefined> {\n const urlToFetch = args.businessKey\n ? `${args.serviceUrl}/${args.definitionId}?businessKey=${args.businessKey}`\n : `${args.serviceUrl}/${args.definitionId}`;\n\n const response = await fetch(urlToFetch, {\n method: 'POST',\n body: JSON.stringify(args.inputData),\n headers: { 'content-type': 'application/json' },\n });\n\n const json = await response.json();\n if (json.id) {\n this.logger.debug(\n `Execute workflow successful. Response: ${JSON.stringify(json)}`,\n );\n return json;\n } else if (!response.ok) {\n const errorMessage = await this.createPrefixFetchErrorMessage(\n urlToFetch,\n response,\n 'POST',\n );\n this.logger.error(\n `Execute workflow failed. Response: ${JSON.stringify(json)}`,\n );\n throw new Error(errorMessage);\n } else {\n this.logger.error(\n `Execute workflow did not return a workflow instance ID. Response: ${JSON.stringify(\n json,\n )}`,\n );\n throw new Error('Execute workflow did not return a workflow instance ID');\n }\n }\n\n public async retriggerInstance(args: {\n definitionId: string;\n instanceId: string;\n serviceUrl: string;\n }): Promise<boolean> {\n const urlToFetch = `${args.serviceUrl}/management/processes/${args.definitionId}/instances/${args.instanceId}/retrigger`;\n\n const response = await fetch(urlToFetch, {\n method: 'POST',\n });\n\n if (!response.ok) {\n throw new Error(\n `${await this.createPrefixFetchErrorMessage(\n urlToFetch,\n response,\n 'POST',\n )}`,\n );\n }\n\n return true;\n }\n\n public async fetchWorkflowOverview(\n definitionId: string,\n ): Promise<WorkflowOverview | undefined> {\n const source = await this.dataIndexService.fetchWorkflowSource(\n definitionId,\n );\n if (!source) {\n this.logger.debug(`Workflow source not found: ${definitionId}`);\n return undefined;\n }\n return await this.fetchWorkflowOverviewBySource(source);\n }\n\n private async fetchWorkflowOverviewBySource(\n source: string,\n ): Promise<WorkflowOverview | undefined> {\n let processInstances: ProcessInstance[] = [];\n const limit = 10;\n let offset: number = 0;\n\n let lastTriggered: Date = new Date(0);\n let lastRunStatus: ProcessInstanceStateValues | undefined;\n let lastRunId: string | undefined;\n let counter = 0;\n let totalDuration = 0;\n const definition = fromWorkflowSource(source);\n\n do {\n processInstances =\n await this.dataIndexService.fetchInstancesByDefinitionId({\n definitionId: definition.id,\n limit,\n offset,\n });\n\n for (const pInstance of processInstances) {\n if (!pInstance.start) {\n continue;\n }\n if (new Date(pInstance.start) > lastTriggered) {\n lastRunId = pInstance.id;\n lastTriggered = new Date(pInstance.start);\n lastRunStatus = pInstance.state;\n }\n if (pInstance.end) {\n const start: Date = new Date(pInstance.start);\n const end: Date = new Date(pInstance.end);\n totalDuration += end.valueOf() - start.valueOf();\n counter++;\n }\n }\n offset += limit;\n } while (processInstances.length > 0);\n\n return {\n workflowId: definition.id,\n name: definition.name,\n format: extractWorkflowFormat(source),\n lastRunId,\n lastTriggeredMs: lastTriggered.getTime(),\n lastRunStatus,\n category: getWorkflowCategory(definition),\n avgDurationMs: counter ? totalDuration / counter : undefined,\n description: definition.description,\n };\n }\n\n public async pingWorkflowService(args: {\n definitionId: string;\n serviceUrl: string;\n }): Promise<boolean> {\n const urlToFetch = `${args.serviceUrl}/management/processes/${args.definitionId}`;\n const response = await fetch(urlToFetch);\n return response.ok;\n }\n\n public async updateInstanceInputData(args: {\n definitionId: string;\n serviceUrl: string;\n instanceId: string;\n inputData: ProcessInstanceVariables;\n }): Promise<boolean> {\n const { definitionId, serviceUrl, instanceId, inputData } = args;\n const urlToFetch = `${serviceUrl}/${definitionId}/${instanceId}`;\n const response = await fetch(urlToFetch, {\n method: 'PATCH',\n body: JSON.stringify(inputData),\n headers: { 'content-type': 'application/json' },\n });\n return response.ok;\n }\n\n public async createPrefixFetchErrorMessage(\n urlToFetch: string,\n response: Response,\n httpMethod = 'GET',\n ): Promise<string> {\n const res = await response.json();\n const errorInfo = [];\n let errorMsg = `Request ${httpMethod} ${urlToFetch} failed with: StatusCode: ${response.status}`;\n\n if (response.statusText) {\n errorInfo.push(`StatusText: ${response.statusText}`);\n }\n if (res?.details) {\n errorInfo.push(`Details: ${res?.details}`);\n }\n if (res?.stack) {\n errorInfo.push(`Stack: ${res?.stack}`);\n }\n if (errorInfo.length > 0) {\n errorMsg += ` ${errorInfo.join(', ')}`;\n } else {\n errorMsg += ' Unexpected error';\n }\n\n return errorMsg;\n }\n}\n"],"names":["fromWorkflowSource","extractWorkflowFormat","getWorkflowCategory"],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ class WorkflowCacheService {
4
+ constructor(logger, dataIndexService, sonataFlowService) {
5
+ this.logger = logger;
6
+ this.dataIndexService = dataIndexService;
7
+ this.sonataFlowService = sonataFlowService;
8
+ }
9
+ TASK_ID = "task__Orchestrator__WorkflowCacheService";
10
+ DEFAULT_FREQUENCY_IN_SECONDS = 5;
11
+ DEFAULT_TIMEOUT_IN_MINUTES = 10;
12
+ definitionIdCache = /* @__PURE__ */ new Set();
13
+ get definitionIds() {
14
+ return Array.from(this.definitionIdCache);
15
+ }
16
+ isEmpty() {
17
+ return this.definitionIdCache.size === 0;
18
+ }
19
+ isAvailable(definitionId, cacheHandler = "skip") {
20
+ if (!definitionId) {
21
+ return false;
22
+ }
23
+ const isAvailable = this.definitionIdCache.has(definitionId);
24
+ if (!isAvailable && cacheHandler === "throw") {
25
+ throw new Error(
26
+ `Workflow service "${definitionId}" not available at the moment`
27
+ );
28
+ }
29
+ return isAvailable;
30
+ }
31
+ schedule(args) {
32
+ const {
33
+ scheduler,
34
+ frequencyInSeconds = this.DEFAULT_FREQUENCY_IN_SECONDS,
35
+ timeoutInMinutes = this.DEFAULT_TIMEOUT_IN_MINUTES
36
+ } = args;
37
+ scheduler.scheduleTask({
38
+ id: this.TASK_ID,
39
+ frequency: { seconds: frequencyInSeconds },
40
+ timeout: { minutes: timeoutInMinutes },
41
+ fn: async () => {
42
+ await this.runTask();
43
+ }
44
+ });
45
+ }
46
+ async runTask() {
47
+ try {
48
+ const idUrlMap = await this.dataIndexService.fetchWorkflowServiceUrls();
49
+ this.definitionIdCache.forEach((definitionId) => {
50
+ if (!idUrlMap[definitionId]) {
51
+ this.definitionIdCache.delete(definitionId);
52
+ }
53
+ });
54
+ await Promise.all(
55
+ Object.entries(idUrlMap).map(async ([definitionId, serviceUrl]) => {
56
+ let isServiceUp = false;
57
+ try {
58
+ isServiceUp = await this.sonataFlowService.pingWorkflowService({
59
+ definitionId,
60
+ serviceUrl
61
+ });
62
+ } catch (err) {
63
+ this.logger.error(
64
+ `Ping workflow ${definitionId} service threw error: ${err}`
65
+ );
66
+ }
67
+ if (isServiceUp) {
68
+ this.definitionIdCache.add(definitionId);
69
+ } else {
70
+ this.logger.error(
71
+ `Failed to ping service for workflow ${definitionId} at ${serviceUrl}`
72
+ );
73
+ if (this.definitionIdCache.has(definitionId)) {
74
+ this.definitionIdCache.delete(definitionId);
75
+ }
76
+ }
77
+ })
78
+ );
79
+ const workflowDefinitionIds = this.isEmpty() ? "empty cache" : Array.from(this.definitionIdCache).join(", ");
80
+ this.logger.debug(
81
+ `${this.TASK_ID} updated the workflow definition ID cache to: ${workflowDefinitionIds}`
82
+ );
83
+ } catch (error) {
84
+ this.logger.error(`Error running ${this.TASK_ID}: ${error}`);
85
+ return;
86
+ }
87
+ }
88
+ }
89
+
90
+ exports.WorkflowCacheService = WorkflowCacheService;
91
+ //# sourceMappingURL=WorkflowCacheService.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowCacheService.cjs.js","sources":["../../src/service/WorkflowCacheService.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { PluginTaskScheduler } from '@backstage/backend-tasks';\n\nimport { DataIndexService } from './DataIndexService';\nimport { SonataFlowService } from './SonataFlowService';\n\nexport type CacheHandler = 'skip' | 'throw';\n\nexport class WorkflowCacheService {\n private readonly TASK_ID = 'task__Orchestrator__WorkflowCacheService';\n private readonly DEFAULT_FREQUENCY_IN_SECONDS = 5;\n private readonly DEFAULT_TIMEOUT_IN_MINUTES = 10;\n private readonly definitionIdCache = new Set<string>();\n\n constructor(\n private readonly logger: LoggerService,\n private readonly dataIndexService: DataIndexService,\n private readonly sonataFlowService: SonataFlowService,\n ) {}\n\n public get definitionIds(): string[] {\n return Array.from(this.definitionIdCache);\n }\n\n public isEmpty(): boolean {\n return this.definitionIdCache.size === 0;\n }\n\n public isAvailable(\n definitionId?: string,\n cacheHandler: CacheHandler = 'skip',\n ): boolean {\n if (!definitionId) {\n return false;\n }\n const isAvailable = this.definitionIdCache.has(definitionId);\n if (!isAvailable && cacheHandler === 'throw') {\n throw new Error(\n `Workflow service \"${definitionId}\" not available at the moment`,\n );\n }\n return isAvailable;\n }\n\n public schedule(args: {\n scheduler: PluginTaskScheduler;\n frequencyInSeconds?: number;\n timeoutInMinutes?: number;\n }): void {\n const {\n scheduler,\n frequencyInSeconds = this.DEFAULT_FREQUENCY_IN_SECONDS,\n timeoutInMinutes = this.DEFAULT_TIMEOUT_IN_MINUTES,\n } = args;\n\n scheduler.scheduleTask({\n id: this.TASK_ID,\n frequency: { seconds: frequencyInSeconds },\n timeout: { minutes: timeoutInMinutes },\n fn: async () => {\n await this.runTask();\n },\n });\n }\n\n private async runTask() {\n try {\n const idUrlMap = await this.dataIndexService.fetchWorkflowServiceUrls();\n this.definitionIdCache.forEach(definitionId => {\n if (!idUrlMap[definitionId]) {\n this.definitionIdCache.delete(definitionId);\n }\n });\n await Promise.all(\n Object.entries(idUrlMap).map(async ([definitionId, serviceUrl]) => {\n let isServiceUp = false;\n try {\n isServiceUp = await this.sonataFlowService.pingWorkflowService({\n definitionId,\n serviceUrl,\n });\n } catch (err) {\n this.logger.error(\n `Ping workflow ${definitionId} service threw error: ${err}`,\n );\n }\n if (isServiceUp) {\n this.definitionIdCache.add(definitionId);\n } else {\n this.logger.error(\n `Failed to ping service for workflow ${definitionId} at ${serviceUrl}`,\n );\n if (this.definitionIdCache.has(definitionId)) {\n this.definitionIdCache.delete(definitionId);\n }\n }\n }),\n );\n\n const workflowDefinitionIds = this.isEmpty()\n ? 'empty cache'\n : Array.from(this.definitionIdCache).join(', ');\n\n this.logger.debug(\n `${this.TASK_ID} updated the workflow definition ID cache to: ${workflowDefinitionIds}`,\n );\n } catch (error) {\n this.logger.error(`Error running ${this.TASK_ID}: ${error}`);\n return;\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ 'use strict';
2
+
3
+ var moment = require('moment');
4
+ var backstagePluginOrchestratorCommon = require('@red-hat-developer-hub/backstage-plugin-orchestrator-common');
5
+
6
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
+
8
+ var moment__default = /*#__PURE__*/_interopDefaultCompat(moment);
9
+
10
+ function mapToWorkflowOverviewDTO(overview) {
11
+ return {
12
+ name: overview.name,
13
+ format: overview.format,
14
+ workflowId: overview.workflowId,
15
+ avgDurationMs: overview.avgDurationMs,
16
+ description: overview.description,
17
+ lastRunId: overview.lastRunId,
18
+ lastRunStatus: overview.lastRunStatus ? getProcessInstancesStatusDTOFromString(overview.lastRunStatus) : void 0,
19
+ lastTriggeredMs: overview.lastTriggeredMs,
20
+ category: mapWorkflowCategoryDTOFromString(overview.category)
21
+ };
22
+ }
23
+ function mapWorkflowCategoryDTOFromString(category) {
24
+ return category?.toLocaleLowerCase() === "assessment" ? "assessment" : "infrastructure";
25
+ }
26
+ function getWorkflowCategoryDTO(definition) {
27
+ return backstagePluginOrchestratorCommon.getWorkflowCategory(definition);
28
+ }
29
+ function getWorkflowFormatDTO(source) {
30
+ return backstagePluginOrchestratorCommon.extractWorkflowFormat(source);
31
+ }
32
+ function mapToWorkflowDTO(source) {
33
+ const definition = backstagePluginOrchestratorCommon.fromWorkflowSource(source);
34
+ return {
35
+ annotations: definition.annotations,
36
+ category: getWorkflowCategoryDTO(definition),
37
+ description: definition.description,
38
+ name: definition.name,
39
+ format: getWorkflowFormatDTO(source),
40
+ id: definition.id
41
+ };
42
+ }
43
+ function mapWorkflowCategoryDTO(category) {
44
+ if (category === backstagePluginOrchestratorCommon.WorkflowCategory.ASSESSMENT) {
45
+ return "assessment";
46
+ }
47
+ return "infrastructure";
48
+ }
49
+ function getProcessInstancesStatusDTOFromString(state) {
50
+ switch (state) {
51
+ case backstagePluginOrchestratorCommon.ProcessInstanceState.Active.valueOf():
52
+ return "Active";
53
+ case backstagePluginOrchestratorCommon.ProcessInstanceState.Error.valueOf():
54
+ return "Error";
55
+ case backstagePluginOrchestratorCommon.ProcessInstanceState.Completed.valueOf():
56
+ return "Completed";
57
+ case backstagePluginOrchestratorCommon.ProcessInstanceState.Aborted.valueOf():
58
+ return "Aborted";
59
+ case backstagePluginOrchestratorCommon.ProcessInstanceState.Suspended.valueOf():
60
+ return "Suspended";
61
+ case backstagePluginOrchestratorCommon.ProcessInstanceState.Pending.valueOf():
62
+ return "Pending";
63
+ default:
64
+ throw new Error(
65
+ `state ${state} is not one of the values of type ProcessInstanceStatusDTO`
66
+ );
67
+ }
68
+ }
69
+ function getProcessInstanceStateFromStatusDTOString(status) {
70
+ switch (status) {
71
+ case "Active":
72
+ return backstagePluginOrchestratorCommon.ProcessInstanceState.Active.valueOf();
73
+ case "Error":
74
+ return backstagePluginOrchestratorCommon.ProcessInstanceState.Error.valueOf();
75
+ case "Completed":
76
+ return backstagePluginOrchestratorCommon.ProcessInstanceState.Completed.valueOf();
77
+ case "Aborted":
78
+ return backstagePluginOrchestratorCommon.ProcessInstanceState.Aborted.valueOf();
79
+ case "Suspended":
80
+ return backstagePluginOrchestratorCommon.ProcessInstanceState.Suspended.valueOf();
81
+ case "Pending":
82
+ return backstagePluginOrchestratorCommon.ProcessInstanceState.Pending.valueOf();
83
+ default:
84
+ throw new Error(
85
+ `status ${status} is not one of the values of type ProcessInstanceState`
86
+ );
87
+ }
88
+ }
89
+ function mapToProcessInstanceDTO(processInstance) {
90
+ const start = moment__default.default(processInstance.start);
91
+ const end = moment__default.default(processInstance.end);
92
+ const duration = processInstance.end ? moment__default.default.duration(start.diff(end)).humanize() : void 0;
93
+ let variables;
94
+ if (typeof processInstance?.variables === "string") {
95
+ variables = JSON.parse(processInstance?.variables);
96
+ } else {
97
+ variables = processInstance?.variables;
98
+ }
99
+ return {
100
+ id: processInstance.id,
101
+ processId: processInstance.processId,
102
+ processName: processInstance.processName,
103
+ description: processInstance.description,
104
+ serviceUrl: processInstance.serviceUrl,
105
+ businessKey: processInstance.businessKey,
106
+ endpoint: processInstance.endpoint,
107
+ error: processInstance.error,
108
+ category: mapWorkflowCategoryDTO(processInstance.category),
109
+ start: processInstance.start,
110
+ end: processInstance.end,
111
+ duration,
112
+ // @ts-ignore
113
+ workflowdata: variables?.workflowdata,
114
+ status: getProcessInstancesStatusDTOFromString(processInstance.state),
115
+ nodes: processInstance.nodes.map(mapToNodeInstanceDTO)
116
+ };
117
+ }
118
+ function mapToNodeInstanceDTO(nodeInstance) {
119
+ return { ...nodeInstance, __typename: "NodeInstance" };
120
+ }
121
+ function mapToExecuteWorkflowResponseDTO(workflowId, workflowExecutionResponse) {
122
+ if (!workflowExecutionResponse?.id) {
123
+ throw new Error(
124
+ `Error while mapping ExecuteWorkflowResponse to ExecuteWorkflowResponseDTO for workflow with id ${workflowId}`
125
+ );
126
+ }
127
+ return {
128
+ id: workflowExecutionResponse.id
129
+ };
130
+ }
131
+ function mapToWorkflowRunStatusDTO(status) {
132
+ return {
133
+ key: backstagePluginOrchestratorCommon.capitalize(status),
134
+ value: status
135
+ };
136
+ }
137
+
138
+ exports.getProcessInstanceStateFromStatusDTOString = getProcessInstanceStateFromStatusDTOString;
139
+ exports.getProcessInstancesStatusDTOFromString = getProcessInstancesStatusDTOFromString;
140
+ exports.getWorkflowCategoryDTO = getWorkflowCategoryDTO;
141
+ exports.getWorkflowFormatDTO = getWorkflowFormatDTO;
142
+ exports.mapToExecuteWorkflowResponseDTO = mapToExecuteWorkflowResponseDTO;
143
+ exports.mapToNodeInstanceDTO = mapToNodeInstanceDTO;
144
+ exports.mapToProcessInstanceDTO = mapToProcessInstanceDTO;
145
+ exports.mapToWorkflowDTO = mapToWorkflowDTO;
146
+ exports.mapToWorkflowOverviewDTO = mapToWorkflowOverviewDTO;
147
+ exports.mapToWorkflowRunStatusDTO = mapToWorkflowRunStatusDTO;
148
+ exports.mapWorkflowCategoryDTO = mapWorkflowCategoryDTO;
149
+ exports.mapWorkflowCategoryDTOFromString = mapWorkflowCategoryDTOFromString;
150
+ //# sourceMappingURL=V2Mappings.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"V2Mappings.cjs.js","sources":["../../../../src/service/api/mapping/V2Mappings.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport moment from 'moment';\n\nimport {\n capitalize,\n ExecuteWorkflowResponseDTO,\n extractWorkflowFormat,\n fromWorkflowSource,\n getWorkflowCategory,\n NodeInstance,\n NodeInstanceDTO,\n ProcessInstance,\n ProcessInstanceDTO,\n ProcessInstanceState,\n ProcessInstanceStatusDTO,\n WorkflowCategory,\n WorkflowCategoryDTO,\n WorkflowDefinition,\n WorkflowDTO,\n WorkflowExecutionResponse,\n WorkflowFormatDTO,\n WorkflowOverview,\n WorkflowOverviewDTO,\n WorkflowRunStatusDTO,\n} from '@red-hat-developer-hub/backstage-plugin-orchestrator-common';\n\n// Mapping functions\nexport function mapToWorkflowOverviewDTO(\n overview: WorkflowOverview,\n): WorkflowOverviewDTO {\n return {\n name: overview.name,\n format: overview.format,\n workflowId: overview.workflowId,\n avgDurationMs: overview.avgDurationMs,\n description: overview.description,\n lastRunId: overview.lastRunId,\n lastRunStatus: overview.lastRunStatus\n ? getProcessInstancesStatusDTOFromString(overview.lastRunStatus)\n : undefined,\n lastTriggeredMs: overview.lastTriggeredMs,\n category: mapWorkflowCategoryDTOFromString(overview.category),\n };\n}\n\nexport function mapWorkflowCategoryDTOFromString(\n category?: string,\n): WorkflowCategoryDTO {\n return category?.toLocaleLowerCase() === 'assessment'\n ? 'assessment'\n : 'infrastructure';\n}\n\nexport function getWorkflowCategoryDTO(\n definition: WorkflowDefinition | undefined,\n): WorkflowCategoryDTO {\n return getWorkflowCategory(definition);\n}\n\nexport function getWorkflowFormatDTO(source: string): WorkflowFormatDTO {\n return extractWorkflowFormat(source);\n}\n\nexport function mapToWorkflowDTO(source: string): WorkflowDTO {\n const definition = fromWorkflowSource(source);\n return {\n annotations: definition.annotations,\n category: getWorkflowCategoryDTO(definition),\n description: definition.description,\n name: definition.name,\n format: getWorkflowFormatDTO(source),\n id: definition.id,\n };\n}\n\nexport function mapWorkflowCategoryDTO(\n category?: WorkflowCategory,\n): WorkflowCategoryDTO {\n if (category === WorkflowCategory.ASSESSMENT) {\n return 'assessment';\n }\n return 'infrastructure';\n}\n\nexport function getProcessInstancesStatusDTOFromString(\n state?: string,\n): ProcessInstanceStatusDTO {\n switch (state) {\n case ProcessInstanceState.Active.valueOf():\n return 'Active';\n case ProcessInstanceState.Error.valueOf():\n return 'Error';\n case ProcessInstanceState.Completed.valueOf():\n return 'Completed';\n case ProcessInstanceState.Aborted.valueOf():\n return 'Aborted';\n case ProcessInstanceState.Suspended.valueOf():\n return 'Suspended';\n case ProcessInstanceState.Pending.valueOf():\n return 'Pending';\n default:\n throw new Error(\n `state ${state} is not one of the values of type ProcessInstanceStatusDTO`,\n );\n }\n}\n\nexport function getProcessInstanceStateFromStatusDTOString(\n status?: ProcessInstanceStatusDTO,\n): string {\n switch (status) {\n case 'Active':\n return ProcessInstanceState.Active.valueOf();\n case 'Error':\n return ProcessInstanceState.Error.valueOf();\n case 'Completed':\n return ProcessInstanceState.Completed.valueOf();\n case 'Aborted':\n return ProcessInstanceState.Aborted.valueOf();\n case 'Suspended':\n return ProcessInstanceState.Suspended.valueOf();\n case 'Pending':\n return ProcessInstanceState.Pending.valueOf();\n default:\n throw new Error(\n `status ${status} is not one of the values of type ProcessInstanceState`,\n );\n }\n}\n\nexport function mapToProcessInstanceDTO(\n processInstance: ProcessInstance,\n): ProcessInstanceDTO {\n const start = moment(processInstance.start);\n const end = moment(processInstance.end);\n const duration = processInstance.end\n ? moment.duration(start.diff(end)).humanize()\n : undefined;\n\n let variables: Record<string, unknown> | undefined;\n if (typeof processInstance?.variables === 'string') {\n variables = JSON.parse(processInstance?.variables);\n } else {\n variables = processInstance?.variables;\n }\n\n return {\n id: processInstance.id,\n processId: processInstance.processId,\n processName: processInstance.processName,\n description: processInstance.description,\n serviceUrl: processInstance.serviceUrl,\n businessKey: processInstance.businessKey,\n endpoint: processInstance.endpoint,\n error: processInstance.error,\n category: mapWorkflowCategoryDTO(processInstance.category),\n start: processInstance.start,\n end: processInstance.end,\n duration: duration,\n // @ts-ignore\n workflowdata: variables?.workflowdata,\n status: getProcessInstancesStatusDTOFromString(processInstance.state),\n nodes: processInstance.nodes.map(mapToNodeInstanceDTO),\n };\n}\n\nexport function mapToNodeInstanceDTO(\n nodeInstance: NodeInstance,\n): NodeInstanceDTO {\n return { ...nodeInstance, __typename: 'NodeInstance' };\n}\n\nexport function mapToExecuteWorkflowResponseDTO(\n workflowId: string,\n workflowExecutionResponse: WorkflowExecutionResponse,\n): ExecuteWorkflowResponseDTO {\n if (!workflowExecutionResponse?.id) {\n throw new Error(\n `Error while mapping ExecuteWorkflowResponse to ExecuteWorkflowResponseDTO for workflow with id ${workflowId}`,\n );\n }\n\n return {\n id: workflowExecutionResponse.id,\n };\n}\n\nexport function mapToWorkflowRunStatusDTO(\n status: ProcessInstanceState,\n): WorkflowRunStatusDTO {\n return {\n key: capitalize(status),\n value: status,\n };\n}\n"],"names":["getWorkflowCategory","extractWorkflowFormat","fromWorkflowSource","WorkflowCategory","ProcessInstanceState","moment","capitalize"],"mappings":"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"}