@backstage-community/plugin-kafka-backend 0.3.16
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/CHANGELOG.md +1316 -0
- package/README.md +55 -0
- package/alpha/package.json +6 -0
- package/config.d.ts +52 -0
- package/dist/alpha.cjs.js +30 -0
- package/dist/alpha.cjs.js.map +1 -0
- package/dist/alpha.d.ts +10 -0
- package/dist/cjs/router-Cun3PwJD.cjs.js +132 -0
- package/dist/cjs/router-Cun3PwJD.cjs.js.map +1 -0
- package/dist/index.cjs.js +13 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/package.json +71 -0
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Kafka Backend
|
|
2
|
+
|
|
3
|
+
This is the backend part of the Kafka plugin. It responds to Kafka requests
|
|
4
|
+
from the frontend.
|
|
5
|
+
|
|
6
|
+
## Configuration
|
|
7
|
+
|
|
8
|
+
This configures how to connect to the brokers in your Kafka cluster.
|
|
9
|
+
|
|
10
|
+
### `clientId`
|
|
11
|
+
|
|
12
|
+
The name of the client to use when connecting to the cluster.
|
|
13
|
+
|
|
14
|
+
### `brokers`
|
|
15
|
+
|
|
16
|
+
A list of the brokers' host names and ports to connect to.
|
|
17
|
+
|
|
18
|
+
### `ssl` (optional)
|
|
19
|
+
|
|
20
|
+
Configure TLS connection to the Kafka cluster. The options are passed directly
|
|
21
|
+
to [tls.connect] and used to create the TLS secure context. Normally these
|
|
22
|
+
would include `key` and `cert`.
|
|
23
|
+
|
|
24
|
+
Example:
|
|
25
|
+
|
|
26
|
+
```yaml
|
|
27
|
+
kafka:
|
|
28
|
+
clientId: backstage
|
|
29
|
+
clusters:
|
|
30
|
+
- name: prod
|
|
31
|
+
brokers:
|
|
32
|
+
- localhost:9092
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### `sasl` (optional)
|
|
36
|
+
|
|
37
|
+
Configure SASL authentication for the Kafka client.
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
kafka:
|
|
41
|
+
clientId: backstage
|
|
42
|
+
clusters:
|
|
43
|
+
- name: prod
|
|
44
|
+
brokers:
|
|
45
|
+
- my-cluster:9092
|
|
46
|
+
ssl: true
|
|
47
|
+
sasl:
|
|
48
|
+
mechanism: plain # or 'scram-sha-256' or 'scram-sha-512'
|
|
49
|
+
username: my-username
|
|
50
|
+
password: my-password
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### ACLs
|
|
54
|
+
|
|
55
|
+
If you are using ACLs on Kafka, you will need to have the `DESCRIBE` ACL on both consumer groups and topics.
|
package/config.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2020 The Backstage Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export interface Config {
|
|
17
|
+
kafka?: {
|
|
18
|
+
/**
|
|
19
|
+
* Client ID used to Backstage uses to identify when connecting to the Kafka cluster.
|
|
20
|
+
*/
|
|
21
|
+
clientId: string;
|
|
22
|
+
clusters: Array<{
|
|
23
|
+
name: string;
|
|
24
|
+
/**
|
|
25
|
+
* List of brokers in the Kafka cluster to connect to.
|
|
26
|
+
*/
|
|
27
|
+
brokers: string[];
|
|
28
|
+
/**
|
|
29
|
+
* Optional SSL connection parameters to connect to the cluster. Passed directly to Node tls.connect.
|
|
30
|
+
* See https://nodejs.org/dist/latest-v8.x/docs/api/tls.html#tls_tls_createsecurecontext_options
|
|
31
|
+
*/
|
|
32
|
+
ssl?:
|
|
33
|
+
| {
|
|
34
|
+
ca?: string[];
|
|
35
|
+
/** @visibility secret */
|
|
36
|
+
key?: string;
|
|
37
|
+
cert?: string;
|
|
38
|
+
rejectUnauthorized?: boolean;
|
|
39
|
+
}
|
|
40
|
+
| boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Optional SASL connection parameters.
|
|
43
|
+
*/
|
|
44
|
+
sasl?: {
|
|
45
|
+
mechanism: 'plain' | 'scram-sha-256' | 'scram-sha-512';
|
|
46
|
+
username: string;
|
|
47
|
+
/** @visibility secret */
|
|
48
|
+
password: string;
|
|
49
|
+
};
|
|
50
|
+
}>;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
6
|
+
var router = require('./cjs/router-Cun3PwJD.cjs.js');
|
|
7
|
+
require('express');
|
|
8
|
+
require('express-promise-router');
|
|
9
|
+
require('@backstage/errors');
|
|
10
|
+
require('kafkajs');
|
|
11
|
+
require('lodash');
|
|
12
|
+
|
|
13
|
+
var alpha = backendPluginApi.createBackendPlugin({
|
|
14
|
+
pluginId: "kafka",
|
|
15
|
+
register(env) {
|
|
16
|
+
env.registerInit({
|
|
17
|
+
deps: {
|
|
18
|
+
config: backendPluginApi.coreServices.rootConfig,
|
|
19
|
+
logger: backendPluginApi.coreServices.logger,
|
|
20
|
+
httpRouter: backendPluginApi.coreServices.httpRouter
|
|
21
|
+
},
|
|
22
|
+
async init({ config, logger, httpRouter }) {
|
|
23
|
+
httpRouter.use(await router.createRouter({ config, logger }));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
exports.default = alpha;
|
|
30
|
+
//# sourceMappingURL=alpha.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpha.cjs.js","sources":["../src/alpha.ts"],"sourcesContent":["/*\n * Copyright 2023 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 */\n\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\n\n/**\n * The Kafka backend plugin.\n *\n * @alpha\n */\nexport default createBackendPlugin({\n pluginId: 'kafka',\n register(env) {\n env.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n httpRouter: coreServices.httpRouter,\n },\n async init({ config, logger, httpRouter }) {\n httpRouter.use(await createRouter({ config, logger }));\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","createRouter"],"mappings":";;;;;;;;;;;;AA2BA,YAAeA,oCAAoB,CAAA;AAAA,EACjC,QAAU,EAAA,OAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,UAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,MAAA;AAAA,QACrB,YAAYA,6BAAa,CAAA,UAAA;AAAA,OAC3B;AAAA,MACA,MAAM,IAAK,CAAA,EAAE,MAAQ,EAAA,MAAA,EAAQ,YAAc,EAAA;AACzC,QAAA,UAAA,CAAW,IAAI,MAAMC,mBAAA,CAAa,EAAE,MAAQ,EAAA,MAAA,EAAQ,CAAC,CAAA,CAAA;AAAA,OACvD;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACF,CAAC,CAAA;;;;"}
|
package/dist/alpha.d.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var express = require('express');
|
|
4
|
+
var Router = require('express-promise-router');
|
|
5
|
+
var errors = require('@backstage/errors');
|
|
6
|
+
var kafkajs = require('kafkajs');
|
|
7
|
+
var _ = require('lodash');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
12
|
+
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
13
|
+
var ___default = /*#__PURE__*/_interopDefaultCompat(_);
|
|
14
|
+
|
|
15
|
+
var __defProp = Object.defineProperty;
|
|
16
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
17
|
+
var __publicField = (obj, key, value) => {
|
|
18
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
21
|
+
class KafkaJsApiImpl {
|
|
22
|
+
constructor(options) {
|
|
23
|
+
__publicField(this, "kafka");
|
|
24
|
+
__publicField(this, "logger");
|
|
25
|
+
options.logger.debug(
|
|
26
|
+
`creating kafka client with clientId=${options.clientId} and brokers=${options.brokers}`
|
|
27
|
+
);
|
|
28
|
+
this.kafka = new kafkajs.Kafka(options);
|
|
29
|
+
this.logger = options.logger;
|
|
30
|
+
}
|
|
31
|
+
async fetchTopicOffsets(topic) {
|
|
32
|
+
this.logger.debug(`fetching topic offsets for ${topic}`);
|
|
33
|
+
const admin = this.kafka.admin();
|
|
34
|
+
await admin.connect();
|
|
35
|
+
try {
|
|
36
|
+
return KafkaJsApiImpl.toPartitionOffsets(
|
|
37
|
+
await admin.fetchTopicOffsets(topic)
|
|
38
|
+
);
|
|
39
|
+
} finally {
|
|
40
|
+
await admin.disconnect();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async fetchGroupOffsets(groupId) {
|
|
44
|
+
this.logger.debug(`fetching consumer group offsets for ${groupId}`);
|
|
45
|
+
const admin = this.kafka.admin();
|
|
46
|
+
await admin.connect();
|
|
47
|
+
try {
|
|
48
|
+
const groupOffsets = await admin.fetchOffsets({ groupId });
|
|
49
|
+
return groupOffsets.map((topicOffset) => ({
|
|
50
|
+
topic: topicOffset.topic,
|
|
51
|
+
partitions: KafkaJsApiImpl.toPartitionOffsets(topicOffset.partitions)
|
|
52
|
+
}));
|
|
53
|
+
} finally {
|
|
54
|
+
await admin.disconnect();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
static toPartitionOffsets(result) {
|
|
58
|
+
return result.map((seekEntry) => ({
|
|
59
|
+
id: seekEntry.partition,
|
|
60
|
+
offset: seekEntry.offset
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getClusterDetails(config) {
|
|
66
|
+
return config.map((clusterConfig) => {
|
|
67
|
+
const clusterDetails = {
|
|
68
|
+
name: clusterConfig.getString("name"),
|
|
69
|
+
brokers: clusterConfig.getStringArray("brokers")
|
|
70
|
+
};
|
|
71
|
+
const ssl = clusterConfig.getOptional("ssl");
|
|
72
|
+
const sasl = clusterConfig.getOptional("sasl");
|
|
73
|
+
return {
|
|
74
|
+
...clusterDetails,
|
|
75
|
+
...ssl ? { ssl } : {},
|
|
76
|
+
...sasl ? { sasl } : {}
|
|
77
|
+
};
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const makeRouter = (logger, kafkaApis) => {
|
|
82
|
+
const router = Router__default.default();
|
|
83
|
+
router.use(express__default.default.json());
|
|
84
|
+
const kafkaApiByClusterName = ___default.default.keyBy(kafkaApis, (item) => item.name);
|
|
85
|
+
router.get("/consumers/:clusterId/:consumerId/offsets", async (req, res) => {
|
|
86
|
+
const clusterId = req.params.clusterId;
|
|
87
|
+
const consumerId = req.params.consumerId;
|
|
88
|
+
const kafkaApi = kafkaApiByClusterName[clusterId];
|
|
89
|
+
if (!kafkaApi) {
|
|
90
|
+
const candidates = Object.keys(kafkaApiByClusterName).map((n) => `"${n}"`).join(", ");
|
|
91
|
+
throw new errors.NotFoundError(
|
|
92
|
+
`Found no configured cluster "${clusterId}", candidates are ${candidates}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
logger.info(
|
|
96
|
+
`Fetch consumer group ${consumerId} offsets from cluster ${clusterId}`
|
|
97
|
+
);
|
|
98
|
+
const groupOffsets = await kafkaApi.api.fetchGroupOffsets(consumerId);
|
|
99
|
+
const groupWithTopicOffsets = await Promise.all(
|
|
100
|
+
groupOffsets.map(async ({ topic, partitions }) => {
|
|
101
|
+
const topicOffsets = ___default.default.keyBy(
|
|
102
|
+
await kafkaApi.api.fetchTopicOffsets(topic),
|
|
103
|
+
(partition) => partition.id
|
|
104
|
+
);
|
|
105
|
+
return partitions.map((partition) => ({
|
|
106
|
+
topic,
|
|
107
|
+
partitionId: partition.id,
|
|
108
|
+
groupOffset: partition.offset,
|
|
109
|
+
topicOffset: topicOffsets[partition.id].offset
|
|
110
|
+
}));
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
res.json({ consumerId, offsets: groupWithTopicOffsets.flat() });
|
|
114
|
+
});
|
|
115
|
+
return router;
|
|
116
|
+
};
|
|
117
|
+
async function createRouter(options) {
|
|
118
|
+
const logger = options.logger;
|
|
119
|
+
logger.info("Initializing Kafka backend");
|
|
120
|
+
const clientId = options.config.getString("kafka.clientId");
|
|
121
|
+
const clusters = getClusterDetails(
|
|
122
|
+
options.config.getConfigArray("kafka.clusters")
|
|
123
|
+
);
|
|
124
|
+
const kafkaApis = clusters.map((cluster) => ({
|
|
125
|
+
name: cluster.name,
|
|
126
|
+
api: new KafkaJsApiImpl({ clientId, logger, ...cluster })
|
|
127
|
+
}));
|
|
128
|
+
return makeRouter(logger, kafkaApis);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
exports.createRouter = createRouter;
|
|
132
|
+
//# sourceMappingURL=router-Cun3PwJD.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router-Cun3PwJD.cjs.js","sources":["../../src/service/KafkaApi.ts","../../src/config/ClusterReader.ts","../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 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 */\n\nimport { Kafka, SeekEntry } from 'kafkajs';\nimport { SaslConfig, SslConfig } from '../types/types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport type PartitionOffset = {\n id: number;\n offset: string;\n};\n\nexport type TopicOffset = {\n topic: string;\n partitions: PartitionOffset[];\n};\n\nexport type Options = {\n clientId: string;\n brokers: string[];\n ssl?: SslConfig;\n sasl?: SaslConfig;\n logger: LoggerService;\n};\n\nexport interface KafkaApi {\n fetchTopicOffsets(topic: string): Promise<Array<PartitionOffset>>;\n fetchGroupOffsets(groupId: string): Promise<Array<TopicOffset>>;\n}\n\nexport class KafkaJsApiImpl implements KafkaApi {\n private readonly kafka: Kafka;\n private readonly logger: LoggerService;\n\n constructor(options: Options) {\n options.logger.debug(\n `creating kafka client with clientId=${options.clientId} and brokers=${options.brokers}`,\n );\n\n this.kafka = new Kafka(options);\n this.logger = options.logger;\n }\n\n async fetchTopicOffsets(topic: string): Promise<Array<PartitionOffset>> {\n this.logger.debug(`fetching topic offsets for ${topic}`);\n\n const admin = this.kafka.admin();\n await admin.connect();\n\n try {\n return KafkaJsApiImpl.toPartitionOffsets(\n await admin.fetchTopicOffsets(topic),\n );\n } finally {\n await admin.disconnect();\n }\n }\n\n async fetchGroupOffsets(groupId: string): Promise<Array<TopicOffset>> {\n this.logger.debug(`fetching consumer group offsets for ${groupId}`);\n\n const admin = this.kafka.admin();\n await admin.connect();\n\n try {\n const groupOffsets = await admin.fetchOffsets({ groupId });\n\n return groupOffsets.map(topicOffset => ({\n topic: topicOffset.topic,\n partitions: KafkaJsApiImpl.toPartitionOffsets(topicOffset.partitions),\n }));\n } finally {\n await admin.disconnect();\n }\n }\n\n private static toPartitionOffsets(\n result: Array<SeekEntry>,\n ): Array<PartitionOffset> {\n return result.map(seekEntry => ({\n id: seekEntry.partition,\n offset: seekEntry.offset,\n }));\n }\n}\n","/*\n * Copyright 2020 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 */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, SslConfig, SaslConfig } from '../types/types';\n\nexport function getClusterDetails(config: Config[]): ClusterDetails[] {\n return config.map(clusterConfig => {\n const clusterDetails = {\n name: clusterConfig.getString('name'),\n brokers: clusterConfig.getStringArray('brokers'),\n };\n const ssl = clusterConfig.getOptional('ssl') as SslConfig;\n const sasl = clusterConfig.getOptional('sasl') as SaslConfig;\n\n return {\n ...clusterDetails,\n ...(ssl ? { ssl } : {}),\n ...(sasl ? { sasl } : {}),\n };\n });\n}\n","/*\n * Copyright 2020 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 */\n\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Config } from '@backstage/config';\nimport { NotFoundError } from '@backstage/errors';\nimport { KafkaApi, KafkaJsApiImpl } from './KafkaApi';\nimport _ from 'lodash';\nimport { getClusterDetails } from '../config/ClusterReader';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\n/** @public */\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n}\n\nexport interface ClusterApi {\n name: string;\n api: KafkaApi;\n}\n\nexport const makeRouter = (\n logger: LoggerService,\n kafkaApis: ClusterApi[],\n): express.Router => {\n const router = Router();\n router.use(express.json());\n\n const kafkaApiByClusterName = _.keyBy(kafkaApis, item => item.name);\n\n router.get('/consumers/:clusterId/:consumerId/offsets', async (req, res) => {\n const clusterId = req.params.clusterId;\n const consumerId = req.params.consumerId;\n\n const kafkaApi = kafkaApiByClusterName[clusterId];\n if (!kafkaApi) {\n const candidates = Object.keys(kafkaApiByClusterName)\n .map(n => `\"${n}\"`)\n .join(', ');\n throw new NotFoundError(\n `Found no configured cluster \"${clusterId}\", candidates are ${candidates}`,\n );\n }\n\n logger.info(\n `Fetch consumer group ${consumerId} offsets from cluster ${clusterId}`,\n );\n\n const groupOffsets = await kafkaApi.api.fetchGroupOffsets(consumerId);\n\n const groupWithTopicOffsets = await Promise.all(\n groupOffsets.map(async ({ topic, partitions }) => {\n const topicOffsets = _.keyBy(\n await kafkaApi.api.fetchTopicOffsets(topic),\n partition => partition.id,\n );\n\n return partitions.map(partition => ({\n topic: topic,\n partitionId: partition.id,\n groupOffset: partition.offset,\n topicOffset: topicOffsets[partition.id].offset,\n }));\n }),\n );\n\n res.json({ consumerId, offsets: groupWithTopicOffsets.flat() });\n });\n\n return router;\n};\n\n/** @public */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const logger = options.logger;\n\n logger.info('Initializing Kafka backend');\n\n const clientId = options.config.getString('kafka.clientId');\n\n const clusters = getClusterDetails(\n options.config.getConfigArray('kafka.clusters'),\n );\n\n const kafkaApis = clusters.map(cluster => ({\n name: cluster.name,\n api: new KafkaJsApiImpl({ clientId, logger, ...cluster }),\n }));\n\n return makeRouter(logger, kafkaApis);\n}\n"],"names":["Kafka","Router","express","_","NotFoundError"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var router = require('./cjs/router-Cun3PwJD.cjs.js');
|
|
4
|
+
require('express');
|
|
5
|
+
require('express-promise-router');
|
|
6
|
+
require('@backstage/errors');
|
|
7
|
+
require('kafkajs');
|
|
8
|
+
require('lodash');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
exports.createRouter = router.createRouter;
|
|
13
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { Config } from '@backstage/config';
|
|
3
|
+
import { LoggerService } from '@backstage/backend-plugin-api';
|
|
4
|
+
|
|
5
|
+
/** @public */
|
|
6
|
+
interface RouterOptions {
|
|
7
|
+
logger: LoggerService;
|
|
8
|
+
config: Config;
|
|
9
|
+
}
|
|
10
|
+
/** @public */
|
|
11
|
+
declare function createRouter(options: RouterOptions): Promise<express.Router>;
|
|
12
|
+
|
|
13
|
+
export { type RouterOptions, createRouter };
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@backstage-community/plugin-kafka-backend",
|
|
3
|
+
"version": "0.3.16",
|
|
4
|
+
"description": "A Backstage backend plugin that integrates towards Kafka",
|
|
5
|
+
"backstage": {
|
|
6
|
+
"role": "backend-plugin"
|
|
7
|
+
},
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"backstage",
|
|
13
|
+
"kafka"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://backstage.io",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/backstage/community-plugins",
|
|
19
|
+
"directory": "workspaces/kafka/plugins/kafka-backend"
|
|
20
|
+
},
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"require": "./dist/index.cjs.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.cjs.js"
|
|
27
|
+
},
|
|
28
|
+
"./alpha": {
|
|
29
|
+
"require": "./dist/alpha.cjs.js",
|
|
30
|
+
"types": "./dist/alpha.d.ts",
|
|
31
|
+
"default": "./dist/alpha.cjs.js"
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"main": "./dist/index.cjs.js",
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"config.d.ts",
|
|
40
|
+
"alpha"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "backstage-cli package build",
|
|
44
|
+
"clean": "backstage-cli package clean",
|
|
45
|
+
"lint": "backstage-cli package lint",
|
|
46
|
+
"prepack": "backstage-cli package prepack",
|
|
47
|
+
"postpack": "backstage-cli package postpack",
|
|
48
|
+
"start": "backstage-cli package start",
|
|
49
|
+
"test": "backstage-cli package test"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@backstage/backend-common": "^0.21.7",
|
|
53
|
+
"@backstage/backend-plugin-api": "^0.6.17",
|
|
54
|
+
"@backstage/config": "^1.2.0",
|
|
55
|
+
"@backstage/errors": "^1.2.4",
|
|
56
|
+
"@types/express": "^4.17.6",
|
|
57
|
+
"express": "^4.17.1",
|
|
58
|
+
"express-promise-router": "^4.1.0",
|
|
59
|
+
"kafkajs": "^2.0.0",
|
|
60
|
+
"lodash": "^4.17.21"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@backstage/cli": "^0.26.3",
|
|
64
|
+
"@types/jest-when": "^3.5.0",
|
|
65
|
+
"@types/lodash": "^4.14.151",
|
|
66
|
+
"@types/supertest": "^2.0.8",
|
|
67
|
+
"jest-when": "^3.1.0",
|
|
68
|
+
"supertest": "^6.1.3"
|
|
69
|
+
},
|
|
70
|
+
"configSchema": "config.d.ts"
|
|
71
|
+
}
|