forked from jlandersen/vscode-kafka
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
9 changed files
with
419 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"$schema": "http://json-schema.org/draft-04/schema#", | ||
"title": "Kafka contributions to package.json", | ||
"type": "object", | ||
"properties": { | ||
"contributes": { | ||
"type": "object", | ||
"properties": { | ||
"kafka": { | ||
"type": "object", | ||
"markdownDescription": "Kafka extensions", | ||
"properties": { | ||
"clusterProviders": { | ||
"type": "array", | ||
"markdownDescription": "Cluster providers definitions.", | ||
"items": [ | ||
{ | ||
"type": "object", | ||
"properties": { | ||
"id": { | ||
"type": "string", | ||
"description": "Cluster provider id." | ||
}, | ||
"name": { | ||
"type": "string", | ||
"description": "Cluster provider name." | ||
} | ||
} | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { KafkaConfig } from "kafkajs"; | ||
import { Cluster, ConnectionOptions } from "../client/client"; | ||
import { ClusterSettings } from "../settings/clusters"; | ||
|
||
export interface KafkaExtensionParticipant { | ||
|
||
getClusterProviderParticipant(clusterProviderId: string) : ClusterProviderParticipant; | ||
|
||
} | ||
|
||
/** | ||
* The kafka extension participant. | ||
*/ | ||
export interface ClusterProviderParticipant { | ||
|
||
/** | ||
* Returns the Kafka clusters managed by this participant. | ||
* | ||
* @param clusterSettings the current cluster settings. | ||
*/ | ||
coonfigureClusters(clusterSettings: ClusterSettings): Promise<Cluster[] | undefined>; | ||
|
||
/** | ||
* Create the KafkaJS client configuration from the given connection options. | ||
* When the participant doesn't implement this method, the KafkaJS client | ||
* configuration is created with the default client configuration factory from vscode-kafka. | ||
* | ||
* @param connectionOptions the Kafka connection options. | ||
*/ | ||
createKafkaConfig?(connectionOptions: ConnectionOptions): KafkaConfig; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
import * as vscode from "vscode"; | ||
import { KafkaConfig } from "kafkajs"; | ||
import { Cluster, ConnectionOptions, createDefaultKafkaConfig as createDefaultKafkaConfig } from "../client/client"; | ||
import { ClusterSettings } from "../settings/clusters"; | ||
import { collectDefaultClusters } from "../wizards/clusters"; | ||
import { ClusterProviderParticipant, KafkaExtensionParticipant } from "./api"; | ||
|
||
/** | ||
* Cluster provider is used to: | ||
* | ||
* - collect clusters (eg: create a cluster from a wizard, import clusters from a repository, ...) | ||
* and add thento the Kafka Explorer. | ||
* - create a Kafka client from a complex process (eg : use SSO to connect to the cluster) | ||
* | ||
* Implementing a cluster provider in custom vscode extension is done in 2 steps: | ||
* | ||
* - define the cluster provider (id, name) in the package.json in the contributes/kafka/clusterProviders section. | ||
* - return the cluster provider processor (See ClusterProviderProcessor) to use in the activate() of the extension. | ||
* | ||
*/ | ||
export class ClusterProvider { | ||
|
||
private processor: ClusterProviderParticipant | undefined; | ||
|
||
constructor(private definition: ClusterProviderDefinition, private extensionId: string) { | ||
|
||
} | ||
|
||
/** | ||
* Returns the cluster provider id. | ||
*/ | ||
public get id(): string { | ||
return this.definition.id; | ||
} | ||
|
||
/** | ||
* Returns the cluster provider name. | ||
*/ | ||
public get name(): string { | ||
return this.definition.name || this.definition.id; | ||
} | ||
|
||
/** | ||
* Returns the clusters managed by the provider which must be added to the kafka explorer. | ||
* | ||
* @param clusterSettings the cluster settings. | ||
*/ | ||
async collectClusters(clusterSettings: ClusterSettings): Promise<Cluster[] | undefined> { | ||
const processor = await this.getProcessor(); | ||
return processor.coonfigureClusters(clusterSettings); | ||
} | ||
|
||
/** | ||
* Create the Kafka JS client instance from the given connection options. | ||
* | ||
* @param connectionOptions the connection options. | ||
*/ | ||
async createKafkaConfig(connectionOptions: ConnectionOptions): Promise<KafkaConfig | undefined> { | ||
const processor = await this.getProcessor(); | ||
if (processor.createKafkaConfig) { | ||
return processor.createKafkaConfig(connectionOptions); | ||
} | ||
} | ||
|
||
private async getProcessor(): Promise<ClusterProviderParticipant> { | ||
if (this.processor) { | ||
return this.processor; | ||
} | ||
// The cluster provider processor is not already loaded, try to activate the owner extension. | ||
// The return of the extension activate() method must return the cluster provider processor. | ||
const extension = vscode.extensions.getExtension(this.extensionId); | ||
if (!extension) { | ||
throw new Error(`Error while getting cluster provider processor. Extension ${this.extensionId} is not available.`); | ||
} | ||
|
||
// Wait for extension is activated to get the processor | ||
const result = await extension.activate(); | ||
if (!result) { | ||
throw new Error(`Error while getting cluster provider processor. Extension ${this.extensionId}.activate() should return 'KafkaExtensionParticipant'.`); | ||
} | ||
if ('getClusterProviderParticipant' in result) { | ||
this.processor = (<KafkaExtensionParticipant>result).getClusterProviderParticipant(this.id); | ||
} | ||
if (!this.processor) { | ||
throw new Error(`Error while getting cluster provider processor. Extension ${this.extensionId}.activate() should return 'KafkaExtensionParticipant'.`); | ||
} | ||
return this.processor; | ||
} | ||
} | ||
|
||
const defaultClusterProviderId = 'vscode-kafka.manual'; | ||
|
||
let providers: Map<string, ClusterProvider> = new Map(); | ||
|
||
export function getClusterProvider(clusterProviderId?: string): ClusterProvider | undefined { | ||
intializeIfNeeded(); | ||
return providers.get(clusterProviderId || defaultClusterProviderId); | ||
} | ||
|
||
export function getClusterProviders(): ClusterProvider[] { | ||
intializeIfNeeded(); | ||
// "Configure manually" provider must be the first | ||
const manual = getClusterProvider(defaultClusterProviderId); | ||
// Other providers must be sorted by name ascending | ||
const others = [...providers.values()] | ||
.filter(provider => provider.id !== defaultClusterProviderId) | ||
.sort(sortByNameAscending); | ||
if (manual) { | ||
return [manual, ...others]; | ||
} | ||
return others; | ||
} | ||
|
||
function sortByNameAscending(a: ClusterProvider, b: ClusterProvider): -1 | 0 | 1 { | ||
if (a.name.toLowerCase() < b.name.toLowerCase()) { return -1; } | ||
if (a.name.toLowerCase() > b.name.toLowerCase()) { return 1; } | ||
return 0; | ||
} | ||
|
||
function intializeIfNeeded() { | ||
if (providers.size === 0) { | ||
providers = collectClusterProviderDefinitions(vscode.extensions.all); | ||
} | ||
} | ||
|
||
export interface ClusterProviderDefinition { | ||
id: string; | ||
name?: string; | ||
} | ||
|
||
/** | ||
* Collect cluster providers defined in package.json (see vscode-kafka which implements default cluster provider with 'Manual' wizard.) | ||
* | ||
* ```json | ||
* "contributes": { | ||
* "kafka": { | ||
* "clusterProviders": [ | ||
* { | ||
* "id": "vscode-kafka.manual", | ||
* "name": "Manual" | ||
* } | ||
* ] | ||
* } | ||
* ``` | ||
* | ||
* @param extensions all installed vscode extensions | ||
* | ||
* @returns the map of cluster providers. | ||
*/ | ||
export function collectClusterProviderDefinitions(extensions: readonly vscode.Extension<any>[]): Map<string, ClusterProvider> { | ||
const result: Map<string, ClusterProvider> = new Map(); | ||
if (extensions && extensions.length) { | ||
for (const extension of extensions) { | ||
const contributesSection = extension.packageJSON['contributes']; | ||
if (contributesSection) { | ||
const kafkaExtension = contributesSection['kafka']; | ||
if (kafkaExtension) { | ||
const clusterProviders = kafkaExtension['clusterProviders']; | ||
if (Array.isArray(clusterProviders) && clusterProviders.length) { | ||
for (const item of clusterProviders) { | ||
const definition = item as ClusterProviderDefinition; | ||
result.set(definition.id, new ClusterProvider(definition, extension.id)); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
export function getDefaultKafkaExtensionParticipant(): KafkaExtensionParticipant { | ||
return { | ||
getClusterProviderParticipant(clusterProviderId: string): ClusterProviderParticipant { | ||
return { | ||
coonfigureClusters: (clusterSettings: ClusterSettings): Promise<Cluster[] | undefined> => collectDefaultClusters(clusterSettings), | ||
createKafkaConfig: (connectionOptions: ConnectionOptions): KafkaConfig => createDefaultKafkaConfig(connectionOptions) | ||
} as ClusterProviderParticipant; | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters