From 977b1dfbea410912f3482c88707028cd2cf75a19 Mon Sep 17 00:00:00 2001 From: Gregory Yogan Date: Wed, 25 Aug 2021 13:12:00 -0700 Subject: [PATCH 1/4] Re-adding user namespacing Signed-off-by: Gregory Yogan --- .changeset/good-papayas-fetch.md | 5 ++++ plugins/catalog-backend/config.d.ts | 7 +++++ .../GithubMultiOrgReaderProcessor.ts | 1 + .../processors/github/config.test.ts | 30 ++++++++++++++----- .../src/ingestion/processors/github/config.ts | 5 ++++ .../src/ingestion/processors/github/github.ts | 2 ++ 6 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 .changeset/good-papayas-fetch.md diff --git a/.changeset/good-papayas-fetch.md b/.changeset/good-papayas-fetch.md new file mode 100644 index 0000000000..4261d4e24b --- /dev/null +++ b/.changeset/good-papayas-fetch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Adds optional namespacing for users in the GitHub Multi Org Plugin diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 7da9cad139..5701c9df48 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -163,6 +163,13 @@ export interface Config { * Defaults to org name if omitted. */ groupNamespace?: string; + + /** + * The namespace of the users created from this org. + * + * Defaults to empty string if omitted. + */ + userNamespace?: string; }>; }; diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts index ebfcaf5b5d..dfe48939bc 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts @@ -111,6 +111,7 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { client, orgConfig.name, tokenType, + orgConfig.userNamespace, ); const { groups, groupMemberUsers } = await getOrganizationTeams( client, diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts index 7bdc28e6dd..9aa6ee41d7 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts @@ -78,32 +78,48 @@ describe('config', () => { }); describe('readGithubMultiOrgConfig', () => { - function config(orgs: { name: string; groupNamespace?: string }[]) { + function config( + orgs: { name: string; groupNamespace?: string; userNamespace?: string }[], + ) { return new ConfigReader({ orgs }); } it('reads org configs', () => { const output = readGithubMultiOrgConfig( config([ - { name: 'foo', groupNamespace: 'apple' }, - { name: 'bar', groupNamespace: 'Orange' }, + { name: 'foo', groupNamespace: 'apple', userNamespace: 'red' }, + { name: 'bar', groupNamespace: 'Orange', userNamespace: 'blue' }, ]), ); expect(output).toEqual([ - { name: 'foo', groupNamespace: 'apple' }, - { name: 'bar', groupNamespace: 'orange' }, + { name: 'foo', groupNamespace: 'apple', userNamespace: 'red' }, + { name: 'bar', groupNamespace: 'orange', userNamespace: 'blue' }, ]); }); it('defaults groupNamespace to org name if undefined', () => { + const output = readGithubMultiOrgConfig( + config([ + { name: 'foo', userNamespace: 'red' }, + { name: 'bar', userNamespace: 'blue' }, + ]), + ); + + expect(output).toEqual([ + { name: 'foo', groupNamespace: 'foo', userNamespace: 'red' }, + { name: 'bar', groupNamespace: 'bar', userNamespace: 'blue' }, + ]); + }); + + it('defaults userNamespace to empty string if undefined', () => { const output = readGithubMultiOrgConfig( config([{ name: 'foo' }, { name: 'bar' }]), ); expect(output).toEqual([ - { name: 'foo', groupNamespace: 'foo' }, - { name: 'bar', groupNamespace: 'bar' }, + { name: 'foo', groupNamespace: 'foo', userNamespace: '' }, + { name: 'bar', groupNamespace: 'bar', userNamespace: '' }, ]); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.ts index 40305ff1f2..440b0d7801 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.ts @@ -95,6 +95,10 @@ export type GithubMultiOrgConfig = Array<{ * The namespace of the group created for this org. */ groupNamespace: string; + /** + * The namespace of the users created for this org. + */ + userNamespace: string; }>; export function readGithubMultiOrgConfig(config: Config): GithubMultiOrgConfig { @@ -104,5 +108,6 @@ export function readGithubMultiOrgConfig(config: Config): GithubMultiOrgConfig { groupNamespace: ( c.getOptionalString('groupNamespace') ?? c.getString('name') ).toLowerCase(), + userNamespace: c.getOptionalString('userNamespace') ?? '', })); } diff --git a/plugins/catalog-backend/src/ingestion/processors/github/github.ts b/plugins/catalog-backend/src/ingestion/processors/github/github.ts index 9eb5073710..91a0abc992 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/github.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/github.ts @@ -82,6 +82,7 @@ export async function getOrganizationUsers( client: typeof graphql, org: string, tokenType: GithubCredentialType, + userNamespace?: string, ): Promise<{ users: UserEntity[] }> { const query = ` query users($org: String!, $email: Boolean!, $cursor: String) { @@ -117,6 +118,7 @@ export async function getOrganizationUsers( }, }; + if (userNamespace) entity.metadata.namespace = userNamespace; if (user.bio) entity.metadata.description = user.bio; if (user.name) entity.spec.profile!.displayName = user.name; if (user.email) entity.spec.profile!.email = user.email; From 810c114644f02f9505061f4daa1b433ea07d715e Mon Sep 17 00:00:00 2001 From: Gregory Yogan Date: Wed, 25 Aug 2021 15:58:49 -0700 Subject: [PATCH 2/4] Changing changeset to patch Signed-off-by: Gregory Yogan --- .changeset/good-papayas-fetch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/good-papayas-fetch.md b/.changeset/good-papayas-fetch.md index 4261d4e24b..6cd74ce064 100644 --- a/.changeset/good-papayas-fetch.md +++ b/.changeset/good-papayas-fetch.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-backend': minor +'@backstage/plugin-catalog-backend': patch --- Adds optional namespacing for users in the GitHub Multi Org Plugin From 19727d19b1c6959b87dbdb35923aae18c8f77c3d Mon Sep 17 00:00:00 2001 From: Gregory Yogan Date: Fri, 27 Aug 2021 09:11:15 -0700 Subject: [PATCH 3/4] Adding undefined handling of usernamespace and namespaced user deduplicaiton Signed-off-by: Gregory Yogan --- .../processors/GithubMultiOrgReaderProcessor.ts | 9 ++++++--- .../src/ingestion/processors/github/config.test.ts | 7 +++---- .../src/ingestion/processors/github/config.ts | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts index dfe48939bc..e09cff2f1e 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts @@ -124,15 +124,18 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { `Read ${users.length} GitHub users and ${groups.length} GitHub teams from ${orgConfig.name} in ${duration} seconds`, ); + var prefix:string = orgConfig.userNamespace ?? ''; + if (prefix.length > 0) prefix += '/'; + users.forEach(u => { - if (!allUsersMap.has(u.metadata.name)) { - allUsersMap.set(u.metadata.name, u); + if (!allUsersMap.has(prefix + u.metadata.name)) { + allUsersMap.set(prefix + u.metadata.name, u); } }); for (const [groupName, userNames] of groupMemberUsers.entries()) { for (const userName of userNames) { - const user = allUsersMap.get(userName); + const user = allUsersMap.get(prefix + userName); if (user && !user.spec.memberOf.includes(groupName)) { user.spec.memberOf.push(groupName); } diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts index 9aa6ee41d7..4b834938a6 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts @@ -112,14 +112,13 @@ describe('config', () => { ]); }); - it('defaults userNamespace to empty string if undefined', () => { - const output = readGithubMultiOrgConfig( + it('defaults userNamespace to undefined if unspecified', () => { const output = readGithubMultiOrgConfig( config([{ name: 'foo' }, { name: 'bar' }]), ); expect(output).toEqual([ - { name: 'foo', groupNamespace: 'foo', userNamespace: '' }, - { name: 'bar', groupNamespace: 'bar', userNamespace: '' }, + { name: 'foo', groupNamespace: 'foo', userNamespace: undefined }, + { name: 'bar', groupNamespace: 'bar', userNamespace: undefined }, ]); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.ts index 440b0d7801..df9e19ff10 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.ts @@ -96,9 +96,9 @@ export type GithubMultiOrgConfig = Array<{ */ groupNamespace: string; /** - * The namespace of the users created for this org. + * The namespace of the users created for this org. If not specified defaults to undefined. */ - userNamespace: string; + userNamespace: string | undefined; }>; export function readGithubMultiOrgConfig(config: Config): GithubMultiOrgConfig { @@ -108,6 +108,6 @@ export function readGithubMultiOrgConfig(config: Config): GithubMultiOrgConfig { groupNamespace: ( c.getOptionalString('groupNamespace') ?? c.getString('name') ).toLowerCase(), - userNamespace: c.getOptionalString('userNamespace') ?? '', + userNamespace: c.getOptionalString('userNamespace') ?? undefined, })); } From 1a446f014576f42243f1001d132ce1455d8afe2e Mon Sep 17 00:00:00 2001 From: Gregory Yogan Date: Fri, 27 Aug 2021 11:42:02 -0700 Subject: [PATCH 4/4] Formatting and Linting Signed-off-by: Gregory Yogan --- .../src/ingestion/processors/GithubMultiOrgReaderProcessor.ts | 2 +- .../src/ingestion/processors/github/config.test.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts index e09cff2f1e..00b173777d 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts @@ -124,7 +124,7 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { `Read ${users.length} GitHub users and ${groups.length} GitHub teams from ${orgConfig.name} in ${duration} seconds`, ); - var prefix:string = orgConfig.userNamespace ?? ''; + let prefix: string = orgConfig.userNamespace ?? ''; if (prefix.length > 0) prefix += '/'; users.forEach(u => { diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts index 4b834938a6..a67d2378d0 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts @@ -112,7 +112,8 @@ describe('config', () => { ]); }); - it('defaults userNamespace to undefined if unspecified', () => { const output = readGithubMultiOrgConfig( + it('defaults userNamespace to undefined if unspecified', () => { + const output = readGithubMultiOrgConfig( config([{ name: 'foo' }, { name: 'bar' }]), );