feat(plugin-vault): use fetchApi instead of raw fetch

Signed-off-by: Thomas Cardonne <thomas.cardonne@adevinta.com>
This commit is contained in:
Thomas Cardonne
2023-04-03 17:31:38 +02:00
parent 169aa51364
commit 7c7f8d38a5
5 changed files with 43 additions and 13 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-vault': patch
---
Use `fetchApi` instead of raw `fetch` in order to pass auth header if necessary.
+7 -6
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { setupRequestMockHandlers } from '@backstage/test-utils';
import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { VaultSecret, VaultClient } from './api';
@@ -26,6 +26,7 @@ describe('api', () => {
const mockBaseUrl = 'https://api-vault.com/api/vault';
const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl);
const fetchApi = new MockFetchApi();
const mockSecretsResult: { items: VaultSecret[] } = {
items: [
@@ -65,7 +66,7 @@ describe('api', () => {
it('should return secrets', async () => {
setupHandlers();
const api = new VaultClient({ discoveryApi });
const api = new VaultClient({ discoveryApi, fetchApi });
expect(await api.listSecrets('test/success')).toEqual(
mockSecretsResult.items,
);
@@ -73,19 +74,19 @@ describe('api', () => {
it('should return empty secret list', async () => {
setupHandlers();
const api = new VaultClient({ discoveryApi });
const api = new VaultClient({ discoveryApi, fetchApi });
expect(await api.listSecrets('test/empty')).toEqual([]);
});
it('should return all the secrets if no path defined', async () => {
setupHandlers();
const api = new VaultClient({ discoveryApi });
const api = new VaultClient({ discoveryApi, fetchApi });
expect(await api.listSecrets('')).toEqual(mockSecretsResult.items);
});
it('should throw an error if the Vault API responds with an HTTP 404', async () => {
setupHandlers();
const api = new VaultClient({ discoveryApi });
const api = new VaultClient({ discoveryApi, fetchApi });
await expect(api.listSecrets('test/not-found')).rejects.toThrow(
"No secrets found in path 'v1/secrets/test%2Fnot-found'",
);
@@ -93,7 +94,7 @@ describe('api', () => {
it('should throw an error if the Vault API responds with a non-successful HTTP status code', async () => {
setupHandlers();
const api = new VaultClient({ discoveryApi });
const api = new VaultClient({ discoveryApi, fetchApi });
await expect(api.listSecrets('test/error')).rejects.toThrow(
'Request failed with 400 Error',
);
+15 -3
View File
@@ -13,7 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DiscoveryApi, createApiRef } from '@backstage/core-plugin-api';
import {
DiscoveryApi,
createApiRef,
FetchApi,
} from '@backstage/core-plugin-api';
import { NotFoundError, ResponseError } from '@backstage/errors';
/**
@@ -52,9 +56,17 @@ export interface VaultApi {
*/
export class VaultClient implements VaultApi {
private readonly discoveryApi: DiscoveryApi;
private readonly fetchApi: FetchApi;
constructor({ discoveryApi }: { discoveryApi: DiscoveryApi }) {
constructor({
discoveryApi,
fetchApi,
}: {
discoveryApi: DiscoveryApi;
fetchApi: FetchApi;
}) {
this.discoveryApi = discoveryApi;
this.fetchApi = fetchApi;
}
private async callApi<T>(
@@ -62,7 +74,7 @@ export class VaultClient implements VaultApi {
query: { [key in string]: any },
): Promise<T> {
const apiUrl = `${await this.discoveryApi.getBaseUrl('vault')}`;
const response = await fetch(
const response = await this.fetchApi.fetch(
`${apiUrl}/${path}?${new URLSearchParams(query).toString()}`,
{
headers: {
@@ -17,6 +17,7 @@
import React from 'react';
import { setupServer } from 'msw/node';
import {
MockFetchApi,
setupRequestMockHandlers,
TestApiRegistry,
} from '@backstage/test-utils';
@@ -33,6 +34,8 @@ describe('EntityVaultTable', () => {
let apis: TestApiRegistry;
const mockBaseUrl = 'https://api-vault.com/api/vault';
const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl);
const fetchApi = new MockFetchApi();
const entity = (secretPath: string) => {
return {
apiVersion: 'backstage.io/v1alpha1',
@@ -90,7 +93,7 @@ describe('EntityVaultTable', () => {
beforeEach(() => {
apis = TestApiRegistry.from([
vaultApiRef,
new VaultClient({ discoveryApi }),
new VaultClient({ discoveryApi, fetchApi }),
]);
});
+12 -3
View File
@@ -19,9 +19,11 @@ import {
createPlugin,
DiscoveryApi,
discoveryApiRef,
FetchApi,
fetchApiRef,
} from '@backstage/core-plugin-api';
import { VaultClient, vaultApiRef } from './api';
import { vaultApiRef, VaultClient } from './api';
/**
* The vault plugin.
@@ -32,10 +34,17 @@ export const vaultPlugin = createPlugin({
apis: [
createApiFactory({
api: vaultApiRef,
deps: { discoveryApi: discoveryApiRef },
factory: ({ discoveryApi }: { discoveryApi: DiscoveryApi }) =>
deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },
factory: ({
discoveryApi,
fetchApi,
}: {
discoveryApi: DiscoveryApi;
fetchApi: FetchApi;
}) =>
new VaultClient({
discoveryApi,
fetchApi,
}),
}),
],