Merge pull request #485 from backstage/blam/migrate-linkerd

linkerd: Support `linkerd-backend` deployed alongside control plane
This commit is contained in:
Ben Lambert 2024-05-21 17:22:52 +02:00 committed by GitHub
commit 1b90af1f1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 69 additions and 41 deletions

View File

@ -0,0 +1,5 @@
---
'@backstage-community/plugin-linkerd-backend': patch
---
Fix issue with logging errors, and native in cluster API calls to control plane

View File

@ -0,0 +1,6 @@
export interface Config {
linkerd: {
/** If the Linkerd Backend is deployed in the same cluster as the control plane, it will not use the k8s plugin proxy */
deployedWithControlPlane?: boolean;
};
}

View File

@ -54,6 +54,7 @@
"supertest": "^6.2.4"
},
"files": [
"dist"
"dist",
"config.d.ts"
]
}

View File

@ -2,6 +2,7 @@ import {
AuthService,
BackstageCredentials,
DiscoveryService,
RootConfigService,
} from '@backstage/backend-plugin-api';
import { ResponseError } from '@backstage/errors';
import qs from 'qs';
@ -13,16 +14,19 @@ export class LinkerdVizClient {
private constructor(
private readonly discoveryApi: DiscoveryService,
private readonly authApi: AuthService,
private readonly configApi: RootConfigService,
) {}
static fromConfig({
discovery,
auth,
config,
}: {
discovery: DiscoveryService;
auth: AuthService;
config: RootConfigService;
}) {
return new LinkerdVizClient(discovery, auth);
return new LinkerdVizClient(discovery, auth, config);
}
async request<T = any>(
@ -31,7 +35,11 @@ export class LinkerdVizClient {
) {
const k8sBase = await this.discoveryApi.getBaseUrl('kubernetes');
const targetUrl = `${k8sBase}/proxy/api/v1/namespaces/linkerd-viz/services/web:8084/proxy${url}`;
const targetUrl = this.configApi.getOptionalBoolean(
'linkerd.deployedWithControlPlane',
)
? `http://web.linkerd-viz.svc.cluster.local:8084/proxy${url}`
: `${k8sBase}/proxy/api/v1/namespaces/linkerd-viz/services/web:8084/proxy${url}`;
const { token } = await this.authApi.getPluginRequestToken({
onBehalfOf: options.credentials,
@ -45,7 +53,7 @@ export class LinkerdVizClient {
});
if (!response.ok) {
throw ResponseError.fromResponse(response);
throw await ResponseError.fromResponse(response);
}
return response.json() as Promise<T>;

View File

@ -19,14 +19,16 @@ export const linkerdPlugin = createBackendPlugin({
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
discovery: coreServices.discovery,
config: coreServices.rootConfig,
},
async init({ httpRouter, logger, auth, httpAuth, discovery }) {
async init({ httpRouter, logger, auth, httpAuth, discovery, config }) {
httpRouter.use(
await createRouter({
logger,
auth,
httpAuth,
discovery,
config,
}),
);
httpRouter.addAuthPolicy({

View File

@ -4,6 +4,7 @@ import {
DiscoveryService,
HttpAuthService,
LoggerService,
RootConfigService,
} from '@backstage/backend-plugin-api';
import express from 'express';
import Router from 'express-promise-router';
@ -13,17 +14,19 @@ export interface RouterOptions {
logger: LoggerService;
discovery: DiscoveryService;
auth: AuthService;
config: RootConfigService;
httpAuth: HttpAuthService;
}
export async function createRouter(
opts: RouterOptions,
): Promise<express.Router> {
const { discovery, auth, httpAuth } = opts;
const { discovery, auth, httpAuth, config } = opts;
const linkerdVizClient = LinkerdVizClient.fromConfig({
discovery,
auth,
config,
});
const router = Router();
@ -39,45 +42,48 @@ export async function createRouter(
const {
params: { namespace, deployment },
} = request;
try {
const [current] = await linkerdVizClient.stats(
{ resourceType: 'deployment', namespace, resourceName: deployment },
{ credentials: await httpAuth.credentials(request) },
);
const [current] = await linkerdVizClient.stats(
{ resourceType: 'deployment', namespace, resourceName: deployment },
{ credentials: await httpAuth.credentials(request) },
);
const incoming = await linkerdVizClient.stats(
{
allNamespaces: true,
toName: deployment,
toNamespace: namespace,
toType: 'deployment',
resourceType: 'all',
},
{ credentials: await httpAuth.credentials(request) },
);
const incoming = await linkerdVizClient.stats(
{
allNamespaces: true,
toName: deployment,
toNamespace: namespace,
toType: 'deployment',
resourceType: 'all',
},
{ credentials: await httpAuth.credentials(request) },
);
const outgoing = await linkerdVizClient.stats(
{
allNamespaces: true,
fromName: deployment,
fromNamespace: namespace,
fromType: 'deployment',
resourceType: 'all',
},
{ credentials: await httpAuth.credentials(request) },
);
const outgoing = await linkerdVizClient.stats(
{
allNamespaces: true,
fromName: deployment,
fromNamespace: namespace,
fromType: 'deployment',
resourceType: 'all',
},
{ credentials: await httpAuth.credentials(request) },
);
const edges = await linkerdVizClient.edges(
{ namespace, resourceType: 'deployment' },
{ credentials: await httpAuth.credentials(request) },
);
const edges = await linkerdVizClient.edges(
{ namespace, resourceType: 'deployment' },
{ credentials: await httpAuth.credentials(request) },
);
response.send({
current,
incoming,
outgoing,
edges,
});
response.send({
current,
incoming,
outgoing,
edges,
});
} catch (ex) {
console.log(await ex, ex.stack);
}
},
);