Merge pull request #10668 from nodify-at/master

feature: provide access token in JenkinsInstanceConfig.
This commit is contained in:
Fredrik Adelöw
2022-04-07 17:02:07 +02:00
committed by GitHub
5 changed files with 45 additions and 9 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-jenkins-backend': patch
---
feature: provide access token to JenkinsInstanceConfig. It can be passed to other backend calls if authentication enabled. DefaultJenkinsInfoProvider sends always this token to catalog api if access token exists.
+2
View File
@@ -28,6 +28,7 @@ export class DefaultJenkinsInfoProvider implements JenkinsInfoProvider {
getInstance(opt: {
entityRef: CompoundEntityRef;
jobFullName?: string;
backstageToken?: string;
}): Promise<JenkinsInfo>;
// (undocumented)
static readonly NEW_JENKINS_ANNOTATION = 'jenkins.io/job-full-name';
@@ -68,6 +69,7 @@ export interface JenkinsInfoProvider {
getInstance(options: {
entityRef: CompoundEntityRef;
jobFullName?: string;
backstageToken?: string;
}): Promise<JenkinsInfo>;
}
@@ -185,7 +185,9 @@ describe('DefaultJenkinsInfoProvider', () => {
const provider = configureProvider({ jenkins: {} }, undefined);
await expect(provider.getInstance({ entityRef })).rejects.toThrowError();
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
});
it('Reads simple config and annotation', async () => {
@@ -207,7 +209,9 @@ describe('DefaultJenkinsInfoProvider', () => {
);
const info: JenkinsInfo = await provider.getInstance({ entityRef });
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
expect(info).toStrictEqual({
baseUrl: 'https://jenkins.example.com',
crumbIssuer: undefined,
@@ -243,7 +247,9 @@ describe('DefaultJenkinsInfoProvider', () => {
);
const info: JenkinsInfo = await provider.getInstance({ entityRef });
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
expect(info).toMatchObject({
baseUrl: 'https://jenkins.example.com',
jobFullName: 'teamA/artistLookup-build',
@@ -280,7 +286,9 @@ describe('DefaultJenkinsInfoProvider', () => {
);
const info: JenkinsInfo = await provider.getInstance({ entityRef });
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
expect(info).toMatchObject({
baseUrl: 'https://jenkins.example.com',
jobFullName: 'teamA/artistLookup-build',
@@ -317,7 +325,9 @@ describe('DefaultJenkinsInfoProvider', () => {
);
const info: JenkinsInfo = await provider.getInstance({ entityRef });
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
expect(info).toMatchObject({
baseUrl: 'https://jenkins-other.example.com',
jobFullName: 'teamA/artistLookup-build',
@@ -343,7 +353,9 @@ describe('DefaultJenkinsInfoProvider', () => {
);
const info: JenkinsInfo = await provider.getInstance({ entityRef });
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
expect(info).toMatchObject({
baseUrl: 'https://jenkins.example.com',
jobFullName: 'teamA/artistLookup-build',
@@ -369,7 +381,9 @@ describe('DefaultJenkinsInfoProvider', () => {
);
const info: JenkinsInfo = await provider.getInstance({ entityRef });
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
expect(info).toMatchObject({
baseUrl: 'https://jenkins.example.com',
jobFullName: 'teamA/artistLookup-build',
@@ -400,7 +414,9 @@ describe('DefaultJenkinsInfoProvider', () => {
);
const info: JenkinsInfo = await provider.getInstance({ entityRef });
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef);
expect(mockCatalog.getEntityByRef).toBeCalledWith(entityRef, {
backstageToken: undefined,
});
expect(info).toMatchObject({
baseUrl: 'https://jenkins-other.example.com',
jobFullName: 'teamA/artistLookup-build',
@@ -32,6 +32,8 @@ export interface JenkinsInfoProvider {
* A specific job to get. This is only passed in when we know about a job name we are interested in.
*/
jobFullName?: string;
backstageToken?: string;
}): Promise<JenkinsInfo>;
}
@@ -184,9 +186,12 @@ export class DefaultJenkinsInfoProvider implements JenkinsInfoProvider {
async getInstance(opt: {
entityRef: CompoundEntityRef;
jobFullName?: string;
backstageToken?: string;
}): Promise<JenkinsInfo> {
// load entity
const entity = await this.catalog.getEntityByRef(opt.entityRef);
const entity = await this.catalog.getEntityByRef(opt.entityRef, {
token: opt.backstageToken,
});
if (!entity) {
throw new Error(
`Couldn't find entity with name: ${stringifyEntityRef(opt.entityRef)}`,
@@ -44,6 +44,9 @@ export async function createRouter(
'/v1/entity/:namespace/:kind/:name/projects',
async (request, response) => {
const { namespace, kind, name } = request.params;
const token = getBearerTokenFromAuthorizationHeader(
request.header('authorization'),
);
const branch = request.query.branch;
let branchStr: string | undefined;
@@ -67,6 +70,7 @@ export async function createRouter(
namespace,
name,
},
backstageToken: token,
});
const projects = await jenkinsApi.getProjects(jenkinsInfo, branchStr);
@@ -79,6 +83,9 @@ export async function createRouter(
router.get(
'/v1/entity/:namespace/:kind/:name/job/:jobFullName/:buildNumber',
async (request, response) => {
const token = getBearerTokenFromAuthorizationHeader(
request.header('authorization'),
);
const { namespace, kind, name, jobFullName, buildNumber } =
request.params;
@@ -89,6 +96,7 @@ export async function createRouter(
name,
},
jobFullName,
backstageToken: token,
});
const build = await jenkinsApi.getBuild(