Merge pull request #6116 from goober/feature/extract-ldap-processor

Extract LdapOrgReaderProcessor into a separate package
This commit is contained in:
Fredrik Adelöw
2021-06-28 13:17:43 +02:00
committed by GitHub
30 changed files with 652 additions and 229 deletions
@@ -0,0 +1,3 @@
module.exports = {
extends: [require.resolve('@backstage/cli/config/eslint.backend')],
};
@@ -0,0 +1,10 @@
# Catalog Backend Module for LDAP
This is an extension module to the plugin-catalog-backend plugin, providing an LdapOrgReaderProcessor that can be
used to ingest organization data from an LDAP server. This processor is useful if you want to import users and
groups from your Active Directory or another LDAP compatible server.
## Getting started
See [Backstage documentation](https://backstage.io/docs/integrations/ldap/org) for details on how to install
and configure the plugin.
@@ -0,0 +1,72 @@
## API Report File for "@backstage/plugin-catalog-backend-module-ldap"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { CatalogProcessor } from '@backstage/plugin-catalog-backend';
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend';
import { Client } from 'ldapjs';
import { Config } from '@backstage/config';
import { GroupEntity } from '@backstage/catalog-model';
import { JsonValue } from '@backstage/config';
import { LocationSpec } from '@backstage/catalog-model';
import { Logger } from 'winston';
import { SearchEntry } from 'ldapjs';
import { SearchOptions } from 'ldapjs';
import { UserEntity } from '@backstage/catalog-model';
// @public
export const LDAP_DN_ANNOTATION = "backstage.io/ldap-dn";
// @public
export const LDAP_RDN_ANNOTATION = "backstage.io/ldap-rdn";
// @public
export const LDAP_UUID_ANNOTATION = "backstage.io/ldap-uuid";
// @public
export class LdapClient {
constructor(client: Client);
// (undocumented)
static create(logger: Logger, target: string, bind?: BindConfig): Promise<LdapClient>;
getRootDSE(): Promise<SearchEntry | undefined>;
getVendor(): Promise<LdapVendor>;
search(dn: string, options: SearchOptions): Promise<SearchEntry[]>;
}
// @public
export class LdapOrgReaderProcessor implements CatalogProcessor {
constructor(options: {
providers: LdapProviderConfig[];
logger: Logger;
});
// (undocumented)
static fromConfig(config: Config, options: {
logger: Logger;
}): LdapOrgReaderProcessor;
// (undocumented)
readLocation(location: LocationSpec, _optional: boolean, emit: CatalogProcessorEmit): Promise<boolean>;
}
// @public
export type LdapProviderConfig = {
target: string;
bind?: BindConfig;
users: UserConfig;
groups: GroupConfig;
};
// @public
export function readLdapConfig(config: Config): LdapProviderConfig[];
// @public
export function readLdapOrg(client: LdapClient, userConfig: UserConfig, groupConfig: GroupConfig): Promise<{
users: UserEntity[];
groups: GroupEntity[];
}>;
// (No @packageDocumentation comment for this package)
```
+234
View File
@@ -0,0 +1,234 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { JsonValue } from '@backstage/config';
export interface Config {
/**
* Configuration options for the catalog plugin.
*/
catalog?: {
/**
* List of processor-specific options and attributes
*/
processors?: {
/**
* LdapOrgReaderProcessor configuration
*/
ldapOrg?: {
/**
* The configuration parameters for each single LDAP provider.
*/
providers: Array<{
/**
* The prefix of the target that this matches on, e.g.
* "ldaps://ds.example.net", with no trailing slash.
*/
target: string;
/**
* The settings to use for the bind command. If none are specified,
* the bind command is not issued.
*/
bind?: {
/**
* The DN of the user to auth as.
*
* E.g. "uid=ldap-robot,ou=robots,ou=example,dc=example,dc=net"
*/
dn: string;
/**
* The secret of the user to auth as (its password).
*
* @visibility secret
*/
secret: string;
};
/**
* The settings that govern the reading and interpretation of users.
*/
users: {
/**
* The DN under which users are stored.
*
* E.g. "ou=people,ou=example,dc=example,dc=net"
*/
dn: string;
/**
* The search options to use. The default is scope "one" and
* attributes "*" and "+".
*
* It is common to want to specify a filter, to narrow down the set
* of matching items.
*/
options: {
scope?: 'base' | 'one' | 'sub';
filter?: string;
attributes?: string | string[];
paged?:
| boolean
| {
pageSize?: number;
pagePause?: boolean;
};
};
/**
* JSON paths (on a.b.c form) and hard coded values to set on those
* paths.
*
* This can be useful for example if you want to hard code a
* namespace or similar on the generated entities.
*/
set?: { [key: string]: JsonValue };
/**
* Mappings from well known entity fields, to LDAP attribute names
*/
map?: {
/**
* The name of the attribute that holds the relative
* distinguished name of each entry. Defaults to "uid".
*/
rdn?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.name field of the entity. Defaults to "uid".
*/
name?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.description field of the entity.
*/
description?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.displayName field of the entity. Defaults to
* "cn".
*/
displayName?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.email field of the entity. Defaults to
* "mail".
*/
email?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.picture field of the entity.
*/
picture?: string;
/**
* The name of the attribute that shall be used for the values of
* the spec.memberOf field of the entity. Defaults to "memberOf".
*/
memberOf?: string;
};
};
/**
* The settings that govern the reading and interpretation of groups.
*/
groups: {
/**
* The DN under which groups are stored.
*
* E.g. "ou=people,ou=example,dc=example,dc=net"
*/
dn: string;
/**
* The search options to use. The default is scope "one" and
* attributes "*" and "+".
*
* It is common to want to specify a filter, to narrow down the set
* of matching items.
*/
options: {
scope?: 'base' | 'one' | 'sub';
filter?: string;
attributes?: string | string[];
paged?:
| boolean
| {
pageSize?: number;
pagePause?: boolean;
};
};
/**
* JSON paths (on a.b.c form) and hard coded values to set on those
* paths.
*
* This can be useful for example if you want to hard code a
* namespace or similar on the generated entities.
*/
set?: { [key: string]: JsonValue };
/**
* Mappings from well known entity fields, to LDAP attribute names
*/
map?: {
/**
* The name of the attribute that holds the relative
* distinguished name of each entry. Defaults to "cn".
*/
rdn?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.name field of the entity. Defaults to "cn".
*/
name?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.description field of the entity. Defaults to
* "description".
*/
description?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.type field of the entity. Defaults to "groupType".
*/
type?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.displayName field of the entity. Defaults to
* "cn".
*/
displayName?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.email field of the entity.
*/
email?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.picture field of the entity.
*/
picture?: string;
/**
* The name of the attribute that shall be used for the values of
* the spec.parent field of the entity. Defaults to "memberOf".
*/
memberOf?: string;
/**
* The name of the attribute that shall be used for the values of
* the spec.children field of the entity. Defaults to "member".
*/
members?: string;
};
};
}>;
};
};
};
}
@@ -0,0 +1,50 @@
{
"name": "@backstage/plugin-catalog-backend-module-ldap",
"version": "0.1.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
"homepage": "https://backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "plugins/catalog-backend-module-ldap"
},
"keywords": [
"backstage"
],
"scripts": {
"build": "backstage-cli backend:build",
"lint": "backstage-cli lint",
"test": "backstage-cli test",
"prepack": "backstage-cli prepack",
"postpack": "backstage-cli postpack",
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/catalog-model": "^0.8.3",
"@backstage/config": "^0.1.5",
"@backstage/plugin-catalog-backend": "^0.10.2",
"@types/ldapjs": "^1.0.10",
"ldapjs": "^2.2.0",
"lodash": "^4.17.15",
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.7.1",
"@backstage/test-utils": "^0.1.13",
"@types/lodash": "^4.14.151",
"msw": "^0.21.2"
},
"files": [
"dist",
"config.d.ts"
],
"configSchema": "config.d.ts"
}
@@ -0,0 +1,18 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './processors';
export * from './ldap';
@@ -17,7 +17,7 @@
import { Config, JsonValue } from '@backstage/config';
import { SearchOptions } from 'ldapjs';
import mergeWith from 'lodash/mergeWith';
import { RecursivePartial } from '../../../util';
import { RecursivePartial } from '@backstage/plugin-catalog-backend';
/**
* The configuration parameters for a single LDAP provider.
@@ -0,0 +1,94 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
import { buildMemberOf, buildOrgHierarchy } from './org';
function g(
name: string,
parent: string | undefined,
children: string[],
): GroupEntity {
return {
apiVersion: 'backstage.io/v1alpha1',
kind: 'Group',
metadata: { name },
spec: { type: 'team', parent, children },
};
}
describe('buildOrgHierarchy', () => {
it('adds groups to their parent.children', () => {
const a = g('a', undefined, []);
const b = g('b', 'a', []);
const c = g('c', 'b', []);
const d = g('d', 'a', []);
buildOrgHierarchy([a, b, c, d]);
expect(a.spec.children).toEqual(expect.arrayContaining(['b', 'd']));
expect(b.spec.children).toEqual(expect.arrayContaining(['c']));
expect(c.spec.children).toEqual([]);
expect(d.spec.children).toEqual([]);
});
it('sets parent of groups children', () => {
const a = g('a', undefined, ['b', 'd']);
const b = g('b', undefined, ['c']);
const c = g('c', undefined, []);
const d = g('d', undefined, []);
buildOrgHierarchy([a, b, c, d]);
expect(a.spec.parent).toBeUndefined();
expect(b.spec.parent).toBe('a');
expect(c.spec.parent).toBe('b');
expect(d.spec.parent).toBe('a');
});
});
describe('buildMemberOf', () => {
it('fills indirect member of groups', () => {
const a = g('a', undefined, []);
const b = g('b', 'a', []);
const c = g('c', 'b', []);
const u: UserEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: { name: 'n' },
spec: { profile: {}, memberOf: ['c'] },
};
const groups = [a, b, c];
buildOrgHierarchy(groups);
buildMemberOf(groups, [u]);
expect(u.spec.memberOf).toEqual(expect.arrayContaining(['a', 'b', 'c']));
});
it('takes group spec.members into account', () => {
const a = g('a', undefined, []);
const b = g('b', 'a', []);
const c = g('c', 'b', []);
c.spec.members = ['n'];
const u: UserEntity = {
apiVersion: 'backstage.io/v1alpha1',
kind: 'User',
metadata: { name: 'n' },
spec: { profile: {}, memberOf: [] },
};
const groups = [a, b, c];
buildOrgHierarchy(groups);
buildMemberOf(groups, [u]);
expect(u.spec.memberOf).toEqual(expect.arrayContaining(['a', 'b', 'c']));
});
});
@@ -0,0 +1,87 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
// TODO: Copied from plugin-catalog-backend, but we could also export them from
// there. Or move them to catalog-model.
export function buildOrgHierarchy(groups: GroupEntity[]) {
const groupsByName = new Map(groups.map(g => [g.metadata.name, g]));
//
// Make sure that g.parent.children contain g
//
for (const group of groups) {
const selfName = group.metadata.name;
const parentName = group.spec.parent;
if (parentName) {
const parent = groupsByName.get(parentName);
if (parent && !parent.spec.children.includes(selfName)) {
parent.spec.children.push(selfName);
}
}
}
//
// Make sure that g.children.parent is g
//
for (const group of groups) {
const selfName = group.metadata.name;
for (const childName of group.spec.children) {
const child = groupsByName.get(childName);
if (child && !child.spec.parent) {
child.spec.parent = selfName;
}
}
}
}
// Ensure that users have their transitive group memberships. Requires that
// the groups were previously processed with buildOrgHierarchy()
export function buildMemberOf(groups: GroupEntity[], users: UserEntity[]) {
const groupsByName = new Map(groups.map(g => [g.metadata.name, g]));
users.forEach(user => {
const transitiveMemberOf = new Set<string>();
const todo = [
...user.spec.memberOf,
...groups
.filter(g => g.spec.members?.includes(user.metadata.name))
.map(g => g.metadata.name),
];
for (;;) {
const current = todo.pop();
if (!current) {
break;
}
if (!transitiveMemberOf.has(current)) {
transitiveMemberOf.add(current);
const group = groupsByName.get(current);
if (group?.spec.parent) {
todo.push(group.spec.parent);
}
}
}
user.spec.memberOf = [...transitiveMemberOf];
});
}
@@ -17,7 +17,7 @@
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
import { SearchEntry } from 'ldapjs';
import merge from 'lodash/merge';
import { RecursivePartial } from '../../../util';
import { RecursivePartial } from '@backstage/plugin-catalog-backend';
import { LdapClient } from './client';
import { GroupConfig, UserConfig } from './config';
import {
@@ -17,7 +17,7 @@
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
import { SearchEntry } from 'ldapjs';
import lodashSet from 'lodash/set';
import { buildOrgHierarchy } from '../util/org';
import { buildOrgHierarchy } from './org';
import { LdapClient } from './client';
import { GroupConfig, UserConfig } from './config';
import {
@@ -22,9 +22,12 @@ import {
LdapProviderConfig,
readLdapConfig,
readLdapOrg,
} from './ldap';
import * as results from './results';
import { CatalogProcessor, CatalogProcessorEmit } from './types';
} from '../ldap';
import {
CatalogProcessor,
CatalogProcessorEmit,
results,
} from '@backstage/plugin-catalog-backend';
/**
* Extracts teams and users out of an LDAP server.
@@ -0,0 +1,16 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { LdapOrgReaderProcessor } from './LdapOrgReaderProcessor';
@@ -0,0 +1,17 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export {};
-205
View File
@@ -145,211 +145,6 @@ export interface Config {
}>;
};
/**
* LdapOrgReaderProcessor configuration
*/
ldapOrg?: {
/**
* The configuration parameters for each single LDAP provider.
*/
providers: Array<{
/**
* The prefix of the target that this matches on, e.g.
* "ldaps://ds.example.net", with no trailing slash.
*/
target: string;
/**
* The settings to use for the bind command. If none are specified,
* the bind command is not issued.
*/
bind?: {
/**
* The DN of the user to auth as.
*
* E.g. "uid=ldap-robot,ou=robots,ou=example,dc=example,dc=net"
*/
dn: string;
/**
* The secret of the user to auth as (its password).
*
* @visibility secret
*/
secret: string;
};
/**
* The settings that govern the reading and interpretation of users.
*/
users: {
/**
* The DN under which users are stored.
*
* E.g. "ou=people,ou=example,dc=example,dc=net"
*/
dn: string;
/**
* The search options to use. The default is scope "one" and
* attributes "*" and "+".
*
* It is common to want to specify a filter, to narrow down the set
* of matching items.
*/
options: {
scope?: 'base' | 'one' | 'sub';
filter?: string;
attributes?: string | string[];
paged?:
| boolean
| {
pageSize?: number;
pagePause?: boolean;
};
};
/**
* JSON paths (on a.b.c form) and hard coded values to set on those
* paths.
*
* This can be useful for example if you want to hard code a
* namespace or similar on the generated entities.
*/
set?: { [key: string]: JsonValue };
/**
* Mappings from well known entity fields, to LDAP attribute names
*/
map?: {
/**
* The name of the attribute that holds the relative
* distinguished name of each entry. Defaults to "uid".
*/
rdn?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.name field of the entity. Defaults to "uid".
*/
name?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.description field of the entity.
*/
description?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.displayName field of the entity. Defaults to
* "cn".
*/
displayName?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.email field of the entity. Defaults to
* "mail".
*/
email?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.picture field of the entity.
*/
picture?: string;
/**
* The name of the attribute that shall be used for the values of
* the spec.memberOf field of the entity. Defaults to "memberOf".
*/
memberOf?: string;
};
};
/**
* The settings that govern the reading and interpretation of groups.
*/
groups: {
/**
* The DN under which groups are stored.
*
* E.g. "ou=people,ou=example,dc=example,dc=net"
*/
dn: string;
/**
* The search options to use. The default is scope "one" and
* attributes "*" and "+".
*
* It is common to want to specify a filter, to narrow down the set
* of matching items.
*/
options: {
scope?: 'base' | 'one' | 'sub';
filter?: string;
attributes?: string | string[];
paged?:
| boolean
| {
pageSize?: number;
pagePause?: boolean;
};
};
/**
* JSON paths (on a.b.c form) and hard coded values to set on those
* paths.
*
* This can be useful for example if you want to hard code a
* namespace or similar on the generated entities.
*/
set?: { [key: string]: JsonValue };
/**
* Mappings from well known entity fields, to LDAP attribute names
*/
map?: {
/**
* The name of the attribute that holds the relative
* distinguished name of each entry. Defaults to "cn".
*/
rdn?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.name field of the entity. Defaults to "cn".
*/
name?: string;
/**
* The name of the attribute that shall be used for the value of
* the metadata.description field of the entity. Defaults to
* "description".
*/
description?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.type field of the entity. Defaults to "groupType".
*/
type?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.displayName field of the entity. Defaults to
* "cn".
*/
displayName?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.email field of the entity.
*/
email?: string;
/**
* The name of the attribute that shall be used for the value of
* the spec.profile.picture field of the entity.
*/
picture?: string;
/**
* The name of the attribute that shall be used for the values of
* the spec.parent field of the entity. Defaults to "memberOf".
*/
memberOf?: string;
/**
* The name of the attribute that shall be used for the values of
* the spec.children field of the entity. Defaults to "member".
*/
members?: string;
};
};
}>;
};
/**
* AwsOrganizationCloudAccountProcessor configuration
*/
-2
View File
@@ -39,7 +39,6 @@
"@backstage/search-common": "^0.1.2",
"@octokit/graphql": "^4.5.8",
"@types/express": "^4.17.6",
"@types/ldapjs": "^1.0.9",
"aws-sdk": "^2.840.0",
"codeowners-utils": "^1.0.2",
"core-js": "^3.6.5",
@@ -51,7 +50,6 @@
"git-url-parse": "^11.4.4",
"glob": "^7.1.6",
"knex": "^0.95.1",
"ldapjs": "^2.2.0",
"lodash": "^4.17.15",
"morgan": "^1.10.0",
"p-limit": "^3.0.2",
@@ -25,7 +25,6 @@ export { CodeOwnersProcessor } from './CodeOwnersProcessor';
export { FileReaderProcessor } from './FileReaderProcessor';
export { GithubDiscoveryProcessor } from './GithubDiscoveryProcessor';
export { GithubOrgReaderProcessor } from './GithubOrgReaderProcessor';
export { LdapOrgReaderProcessor } from './LdapOrgReaderProcessor';
export { LocationEntityProcessor } from './LocationEntityProcessor';
export { PlaceholderProcessor } from './PlaceholderProcessor';
export type { PlaceholderResolver } from './PlaceholderProcessor';
@@ -49,7 +49,6 @@ import {
FileReaderProcessor,
GithubDiscoveryProcessor,
GithubOrgReaderProcessor,
LdapOrgReaderProcessor,
PlaceholderProcessor,
PlaceholderResolver,
UrlReaderProcessor,
@@ -371,7 +370,6 @@ export class NextCatalogBuilder {
BitbucketDiscoveryProcessor.fromConfig(config, { logger }),
GithubDiscoveryProcessor.fromConfig(config, { logger }),
GithubOrgReaderProcessor.fromConfig(config, { logger }),
LdapOrgReaderProcessor.fromConfig(config, { logger }),
new UrlReaderProcessor({ reader, logger }),
CodeOwnersProcessor.fromConfig(config, { logger, reader }),
new AnnotateLocationEntityProcessor({ integrations }),
@@ -48,7 +48,6 @@ import {
GithubOrgReaderProcessor,
HigherOrderOperation,
HigherOrderOperations,
LdapOrgReaderProcessor,
LocationEntityProcessor,
LocationReaders,
PlaceholderProcessor,
@@ -317,7 +316,6 @@ export class CatalogBuilder {
BitbucketDiscoveryProcessor.fromConfig(config, { logger }),
GithubDiscoveryProcessor.fromConfig(config, { logger }),
GithubOrgReaderProcessor.fromConfig(config, { logger }),
LdapOrgReaderProcessor.fromConfig(config, { logger }),
new UrlReaderProcessor({ reader, logger }),
CodeOwnersProcessor.fromConfig(config, { logger, reader }),
new LocationEntityProcessor({ integrations }),