grafana/public/app/features/migrate-to-cloud/api.ts
Josh Hunt 648f5ff1ab
E2C: Migration summary (#84890)
* E2C: Migration summary

* remove polling

* stack -> box, box -> stack

* justify

* one less stack
2024-03-21 18:49:21 +02:00

215 lines
6.5 KiB
TypeScript

import { BaseQueryFn, createApi } from '@reduxjs/toolkit/query/react';
import { lastValueFrom } from 'rxjs';
import { BackendSrvRequest, getBackendSrv } from '@grafana/runtime';
interface RequestOptions extends BackendSrvRequest {
manageError?: (err: unknown) => { error: unknown };
showErrorAlert?: boolean;
}
function createBackendSrvBaseQuery({ baseURL }: { baseURL: string }): BaseQueryFn<RequestOptions> {
async function backendSrvBaseQuery(requestOptions: RequestOptions) {
try {
const { data: responseData, ...meta } = await lastValueFrom(
getBackendSrv().fetch({
...requestOptions,
url: baseURL + requestOptions.url,
showErrorAlert: requestOptions.showErrorAlert,
})
);
return { data: responseData, meta };
} catch (error) {
return requestOptions.manageError ? requestOptions.manageError(error) : { error };
}
}
return backendSrvBaseQuery;
}
interface MigrateToCloudStatusDTO {
enabled: boolean;
stackURL?: string;
}
interface CreateMigrationTokenResponseDTO {
token: string;
}
export interface ConnectStackDTO {
stackURL: string;
token: string;
}
export interface MigrationResourceDTO {
uid: string;
status: 'not-migrated' | 'migrated' | 'migrating' | 'failed';
statusMessage?: string;
type: 'datasource' | 'dashboard'; // TODO: in future this would be a discriminated union with the resource details
resource: {
uid: string;
name: string;
type: string;
icon?: string;
};
}
const mockApplications = ['auth-service', 'web server', 'backend'];
const mockEnvs = ['DEV', 'PROD'];
const mockRoles = ['db', 'load-balancer', 'server', 'logs'];
const mockDataSources = ['Prometheus', 'Loki', 'AWS Athena', 'AWS Cloudwatch', 'InfluxDB', 'Elasticsearch'];
const mockDataSourceMetadata: Record<string, { image: string }> = {
Prometheus: {
image: 'https://grafana.com/api/plugins/prometheus/versions/5.0.0/logos/small',
},
Loki: {
image: 'https://grafana.com/api/plugins/loki/versions/5.0.0/logos/small',
},
'AWS Athena': {
image: 'https://grafana.com/api/plugins/grafana-athena-datasource/versions/2.13.5/logos/small',
},
'AWS Cloudwatch': {
image: 'https://grafana.com/api/plugins/computest-cloudwatchalarm-datasource/versions/2.0.0/logos/small',
},
InfluxDB: {
image: 'https://grafana.com/api/plugins/influxdb/versions/5.0.0/logos/small',
},
Elasticsearch: {
image: 'https://grafana.com/api/plugins/elasticsearch/versions/5.0.0/logos/small',
},
};
const mockMigrationResources: MigrationResourceDTO[] = Array.from({ length: 500 }).map((_, index) => {
const dataSource = mockDataSources[index % mockDataSources.length];
const environment = mockEnvs[index % mockEnvs.length];
const application = mockApplications[index % mockApplications.length];
const role = mockRoles[index % mockRoles.length];
return {
status: 'not-migrated',
type: 'datasource',
uid: index.toString(16),
resource: {
uid: `${application}-${environment}-${role}-${index}`,
name: `${application} ${environment} ${role}`,
icon: mockDataSourceMetadata[dataSource]?.image,
type: dataSource,
},
};
});
mockMigrationResources[0].status = 'migrated';
mockMigrationResources[1].status = 'failed';
mockMigrationResources[1].statusMessage = `Source map error: Error: request failed with status 404
Resource URL: http://localhost:3000/public/build/app.f4d0c6a0daa6a5b14892.js
Source Map URL: app.f4d0c6a0daa6a5b14892.js.map`;
mockMigrationResources[2].status = 'migrated';
mockMigrationResources[3].status = 'migrated';
mockMigrationResources[4].status = 'migrating';
mockMigrationResources[5].status = 'migrating';
// TODO remove these mock properties/functions
const queryParams = new URLSearchParams(window.location.search);
const MOCK_DELAY_MS = 1000;
const MOCK_TOKEN = 'TODO_thisWillBeABigLongToken';
let HAS_MIGRATION_TOKEN = false;
let HAS_STACK_DETAILS = !!queryParams.get('mockStackURL');
let STACK_URL: string | undefined = queryParams.get('mockStackURL') || undefined;
function dataWithMockDelay<T>(data: T): Promise<{ data: T }> {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ data });
}, MOCK_DELAY_MS);
});
}
export const migrateToCloudAPI = createApi({
tagTypes: ['migrationToken', 'stackDetails', 'resource'],
reducerPath: 'migrateToCloudAPI',
baseQuery: createBackendSrvBaseQuery({ baseURL: '/api' }),
endpoints: (builder) => ({
// TODO :)
getStatus: builder.query<MigrateToCloudStatusDTO, void>({
providesTags: ['stackDetails'],
queryFn: () => {
const responseData: MigrateToCloudStatusDTO = { enabled: HAS_STACK_DETAILS };
if (STACK_URL) {
responseData.stackURL = STACK_URL;
}
return dataWithMockDelay(responseData);
},
}),
connectStack: builder.mutation<void, ConnectStackDTO>({
invalidatesTags: ['stackDetails'],
queryFn: async ({ stackURL }) => {
HAS_STACK_DETAILS = true;
STACK_URL = stackURL;
return dataWithMockDelay(undefined);
},
}),
disconnectStack: builder.mutation<void, void>({
invalidatesTags: ['stackDetails'],
queryFn: async () => {
HAS_STACK_DETAILS = false;
return dataWithMockDelay(undefined);
},
}),
createMigrationToken: builder.mutation<CreateMigrationTokenResponseDTO, void>({
invalidatesTags: ['migrationToken'],
queryFn: async () => {
HAS_MIGRATION_TOKEN = true;
return dataWithMockDelay({ token: MOCK_TOKEN });
},
}),
deleteMigrationToken: builder.mutation<void, void>({
invalidatesTags: ['migrationToken'],
queryFn: async () => {
HAS_MIGRATION_TOKEN = false;
return dataWithMockDelay(undefined);
},
}),
hasMigrationToken: builder.query<boolean, void>({
providesTags: ['migrationToken'],
queryFn: async () => {
return dataWithMockDelay(HAS_MIGRATION_TOKEN);
},
}),
startMigration: builder.mutation<void, void>({
queryFn: async () => {
return dataWithMockDelay(undefined);
},
}),
listResources: builder.query<MigrationResourceDTO[], void>({
providesTags: ['resource'],
queryFn: async () => {
return dataWithMockDelay(mockMigrationResources);
},
}),
}),
});
export const {
useGetStatusQuery,
useConnectStackMutation,
useDisconnectStackMutation,
useCreateMigrationTokenMutation,
useDeleteMigrationTokenMutation,
useHasMigrationTokenQuery,
useListResourcesQuery,
useStartMigrationMutation,
} = migrateToCloudAPI;