Skip to content

Commit aad79c9

Browse files
authored
E2C: Start connecting on-prem to real apis (#85527)
* E2C: Start connecting on-prem to real apis * actually run the migration * show resources * basic dashboards resources * show dashboard title * remove console logs * cleanup 1 * i18n * disconnect * i18n * restore type * use fixed format * fix
1 parent 0ec48cf commit aad79c9

File tree

15 files changed

+402
-73
lines changed

15 files changed

+402
-73
lines changed

pkg/services/cloudmigration/model.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,8 @@ type MigrateDataResponseDTO struct {
175175
}
176176

177177
type MigrateDataResponseItemDTO struct {
178-
RefID string `json:"refId"`
179-
Status ItemStatus `json:"status"`
180-
Error string `json:"error,omitempty"`
178+
Type MigrateDataType `json:"type"`
179+
RefID string `json:"refId"`
180+
Status ItemStatus `json:"status"`
181+
Error string `json:"error,omitempty"`
181182
}

public/api-merged.json

+6
Original file line numberDiff line numberDiff line change
@@ -15963,9 +15963,15 @@
1596315963
},
1596415964
"status": {
1596515965
"$ref": "#/definitions/ItemStatus"
15966+
},
15967+
"type": {
15968+
"$ref": "#/definitions/MigrateDataType"
1596615969
}
1596715970
}
1596815971
},
15972+
"MigrateDataType": {
15973+
"type": "string"
15974+
},
1596915975
"MoveFolderCommand": {
1597015976
"description": "MoveFolderCommand captures the information required by the folder service\nto move a folder.",
1597115977
"type": "object",

public/app/features/migrate-to-cloud/api/baseAPI.ts

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import { BackendSrvRequest, getBackendSrv } from '@grafana/runtime';
66
interface RequestOptions extends BackendSrvRequest {
77
manageError?: (err: unknown) => { error: unknown };
88
showErrorAlert?: boolean;
9+
10+
// rtk codegen sets this
11+
body?: BackendSrvRequest['data'];
912
}
1013

1114
function createBackendSrvBaseQuery({ baseURL }: { baseURL: string }): BaseQueryFn<RequestOptions> {
@@ -16,6 +19,7 @@ function createBackendSrvBaseQuery({ baseURL }: { baseURL: string }): BaseQueryF
1619
...requestOptions,
1720
url: baseURL + requestOptions.url,
1821
showErrorAlert: requestOptions.showErrorAlert,
22+
data: requestOptions.body,
1923
})
2024
);
2125
return { data: responseData, meta };

public/app/features/migrate-to-cloud/api/endpoints.gen.ts

+55-1
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ const injectedRtkApi = api.injectEndpoints({
2525
createCloudMigrationToken: build.mutation<CreateCloudMigrationTokenApiResponse, CreateCloudMigrationTokenApiArg>({
2626
query: () => ({ url: `/cloudmigration/token`, method: 'POST' }),
2727
}),
28+
getDashboardByUid: build.query<GetDashboardByUidApiResponse, GetDashboardByUidApiArg>({
29+
query: (queryArg) => ({ url: `/dashboards/uid/${queryArg.uid}` }),
30+
}),
2831
}),
2932
overrideExisting: false,
3033
});
31-
export { injectedRtkApi as enhancedApi };
34+
export { injectedRtkApi as generatedAPI };
3235
export type GetMigrationListApiResponse = /** status 200 (empty) */ CloudMigrationListResponse;
3336
export type GetMigrationListApiArg = void;
3437
export type CreateMigrationApiResponse = /** status 200 (empty) */ CloudMigrationResponse;
@@ -64,6 +67,10 @@ export type GetCloudMigrationRunApiArg = {
6467
};
6568
export type CreateCloudMigrationTokenApiResponse = /** status 200 (empty) */ CreateAccessTokenResponseDto;
6669
export type CreateCloudMigrationTokenApiArg = void;
70+
export type GetDashboardByUidApiResponse = /** status 200 (empty) */ DashboardFullWithMeta;
71+
export type GetDashboardByUidApiArg = {
72+
uid: string;
73+
};
6774
export type CloudMigrationResponse = {
6875
created?: string;
6976
id?: number;
@@ -87,10 +94,12 @@ export type CloudMigrationRequest = {
8794
authToken?: string;
8895
};
8996
export type ItemStatus = string;
97+
export type MigrateDataType = string;
9098
export type MigrateDataResponseItemDto = {
9199
error?: string;
92100
refId?: string;
93101
status?: ItemStatus;
102+
type?: MigrateDataType;
94103
};
95104
export type MigrateDataResponseDto = {
96105
id?: number;
@@ -102,6 +111,50 @@ export type CloudMigrationRunList = {
102111
export type CreateAccessTokenResponseDto = {
103112
token?: string;
104113
};
114+
export type Json = object;
115+
export type AnnotationActions = {
116+
canAdd?: boolean;
117+
canDelete?: boolean;
118+
canEdit?: boolean;
119+
};
120+
export type AnnotationPermission = {
121+
dashboard?: AnnotationActions;
122+
organization?: AnnotationActions;
123+
};
124+
export type DashboardMeta = {
125+
annotationsPermissions?: AnnotationPermission;
126+
canAdmin?: boolean;
127+
canDelete?: boolean;
128+
canEdit?: boolean;
129+
canSave?: boolean;
130+
canStar?: boolean;
131+
created?: string;
132+
createdBy?: string;
133+
expires?: string;
134+
/** Deprecated: use FolderUID instead */
135+
folderId?: number;
136+
folderTitle?: string;
137+
folderUid?: string;
138+
folderUrl?: string;
139+
hasAcl?: boolean;
140+
isFolder?: boolean;
141+
isSnapshot?: boolean;
142+
isStarred?: boolean;
143+
provisioned?: boolean;
144+
provisionedExternalId?: string;
145+
publicDashboardEnabled?: boolean;
146+
publicDashboardUid?: string;
147+
slug?: string;
148+
type?: string;
149+
updated?: string;
150+
updatedBy?: string;
151+
url?: string;
152+
version?: number;
153+
};
154+
export type DashboardFullWithMeta = {
155+
dashboard?: Json;
156+
meta?: DashboardMeta;
157+
};
105158
export const {
106159
useGetMigrationListQuery,
107160
useCreateMigrationMutation,
@@ -111,4 +164,5 @@ export const {
111164
useRunCloudMigrationMutation,
112165
useGetCloudMigrationRunQuery,
113166
useCreateCloudMigrationTokenMutation,
167+
useGetDashboardByUidQuery,
114168
} = injectedRtkApi;
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,39 @@
11
export * from './endpoints.gen';
2-
export { enhancedApi as cloudMigrationAPI } from './endpoints.gen';
2+
import { generatedAPI } from './endpoints.gen';
3+
4+
export const cloudMigrationAPI = generatedAPI.enhanceEndpoints({
5+
addTagTypes: ['cloud-migration-config', 'cloud-migration-run'],
6+
endpoints: {
7+
// List Cloud Configs
8+
getMigrationList: {
9+
providesTags: ['cloud-migration-config'] /* should this be a -list? */,
10+
},
11+
12+
// Create Cloud Config
13+
createMigration: {
14+
invalidatesTags: ['cloud-migration-config'],
15+
},
16+
17+
// Get one Cloud Config
18+
getCloudMigration: {
19+
providesTags: ['cloud-migration-config'],
20+
},
21+
22+
// Delete one Cloud Config
23+
deleteCloudMigration: {
24+
invalidatesTags: ['cloud-migration-config'],
25+
},
26+
27+
getCloudMigrationRunList: {
28+
providesTags: ['cloud-migration-run'] /* should this be a -list? */,
29+
},
30+
31+
getCloudMigrationRun: {
32+
providesTags: ['cloud-migration-run'],
33+
},
34+
35+
runCloudMigration: {
36+
invalidatesTags: ['cloud-migration-run'],
37+
},
38+
},
39+
});

public/app/features/migrate-to-cloud/mockAPI.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@ export interface ConnectStackDTOMock {
4141
token: string;
4242
}
4343

44-
export interface MigrationResourceDTOMock {
44+
type MigrationResourceStatus = 'not-migrated' | 'migrated' | 'migrating' | 'failed';
45+
46+
export interface MigrationResourceDatasource {
4547
uid: string;
46-
status: 'not-migrated' | 'migrated' | 'migrating' | 'failed';
48+
status: MigrationResourceStatus;
4749
statusMessage?: string;
48-
type: 'datasource' | 'dashboard'; // TODO: in future this would be a discriminated union with the resource details
50+
type: 'datasource';
4951
resource: {
5052
uid: string;
5153
name: string;
@@ -54,6 +56,19 @@ export interface MigrationResourceDTOMock {
5456
};
5557
}
5658

59+
export interface MigrationResourceDashboard {
60+
uid: string;
61+
status: MigrationResourceStatus;
62+
statusMessage?: string;
63+
type: 'dashboard';
64+
resource: {
65+
uid: string;
66+
name: string;
67+
};
68+
}
69+
70+
export type MigrationResourceDTOMock = MigrationResourceDatasource | MigrationResourceDashboard;
71+
5772
const mockApplications = ['auth-service', 'web server', 'backend'];
5873
const mockEnvs = ['DEV', 'PROD'];
5974
const mockRoles = ['db', 'load-balancer', 'server', 'logs'];

public/app/features/migrate-to-cloud/onprem/EmptyState/CallToAction/CallToAction.tsx

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ import React from 'react';
33
import { Box, Button, ModalsController, Text } from '@grafana/ui';
44
import { Trans } from 'app/core/internationalization';
55

6-
import { useConnectStackMutationMock, useGetStatusQueryMock } from '../../../mockAPI';
6+
import { useCreateMigrationMutation } from '../../../api';
77

88
import { ConnectModal } from './ConnectModal';
99

1010
export const CallToAction = () => {
11-
const [connectStack, connectResponse] = useConnectStackMutationMock();
12-
const { isFetching } = useGetStatusQueryMock();
11+
const [createMigration, createMigrationResponse] = useCreateMigrationMutation();
1312

1413
return (
1514
<ModalsController>
@@ -19,11 +18,11 @@ export const CallToAction = () => {
1918
<Trans i18nKey="migrate-to-cloud.cta.header">Let us manage your Grafana stack</Trans>
2019
</Text>
2120
<Button
22-
disabled={isFetching || connectResponse.isLoading}
21+
disabled={createMigrationResponse.isLoading}
2322
onClick={() =>
2423
showModal(ConnectModal, {
2524
hideModal,
26-
onConfirm: connectStack,
25+
onConfirm: createMigration,
2726
})
2827
}
2928
>

public/app/features/migrate-to-cloud/onprem/EmptyState/CallToAction/ConnectModal.tsx

+21-27
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ import { GrafanaTheme2 } from '@grafana/data';
66
import { Modal, Button, Stack, TextLink, Field, Input, Text, useStyles2 } from '@grafana/ui';
77
import { Trans, t } from 'app/core/internationalization';
88

9-
import { ConnectStackDTOMock } from '../../../mockAPI';
9+
import { CreateMigrationApiArg } from '../../../api';
1010

1111
interface Props {
1212
hideModal: () => void;
13-
onConfirm: (connectStackData: ConnectStackDTOMock) => Promise<{ data: void } | { error: unknown }>;
13+
onConfirm: (connectStackData: CreateMigrationApiArg) => Promise<unknown>;
14+
}
15+
16+
interface FormData {
17+
token: string;
1418
}
1519

1620
export const ConnectModal = ({ hideModal, onConfirm }: Props) => {
1721
const [isConnecting, setIsConnecting] = useState(false);
18-
const cloudStackId = useId();
1922
const tokenId = useId();
2023
const styles = useStyles2(getStyles);
2124

@@ -24,19 +27,22 @@ export const ConnectModal = ({ hideModal, onConfirm }: Props) => {
2427
register,
2528
formState: { errors },
2629
watch,
27-
} = useForm<ConnectStackDTOMock>({
30+
} = useForm<FormData>({
2831
defaultValues: {
29-
stackURL: '',
3032
token: '',
3133
},
3234
});
3335

34-
const stackURL = watch('stackURL');
3536
const token = watch('token');
3637

37-
const onConfirmConnect: SubmitHandler<ConnectStackDTOMock> = async (formData) => {
38+
const onConfirmConnect: SubmitHandler<FormData> = async (formData) => {
3839
setIsConnecting(true);
39-
await onConfirm(formData);
40+
// TODO: location of this is kinda weird, making it tricky to handle errors from this.
41+
await onConfirm({
42+
cloudMigrationRequest: {
43+
authToken: formData.token,
44+
},
45+
});
4046
setIsConnecting(false);
4147
hideModal();
4248
};
@@ -49,46 +55,34 @@ export const ConnectModal = ({ hideModal, onConfirm }: Props) => {
4955
<Trans i18nKey="migrate-to-cloud.connect-modal.body-get-started">
5056
To get started, you&apos;ll need a Grafana.com account.
5157
</Trans>
58+
5259
<TextLink href="https://grafana.com/auth/sign-up/create-user?pg=prod-cloud" external>
5360
{t('migrate-to-cloud.connect-modal.body-sign-up', 'Sign up for a Grafana.com account')}
5461
</TextLink>
62+
5563
<Trans i18nKey="migrate-to-cloud.connect-modal.body-cloud-stack">
5664
You&apos;ll also need a cloud stack. If you just signed up, we&apos;ll automatically create your first
5765
stack. If you have an account, you&apos;ll need to select or create a stack.
5866
</Trans>
67+
5968
<TextLink href="https://grafana.com/auth/sign-in/" external>
6069
{t('migrate-to-cloud.connect-modal.body-view-stacks', 'View my cloud stacks')}
6170
</TextLink>
62-
<Trans i18nKey="migrate-to-cloud.connect-modal.body-paste-stack">
63-
Once you&apos;ve decided on a stack, paste the URL below.
64-
</Trans>
65-
<Field
66-
className={styles.field}
67-
invalid={!!errors.stackURL}
68-
error={errors.stackURL?.message}
69-
label={t('migrate-to-cloud.connect-modal.body-url-field', 'Cloud stack URL')}
70-
required
71-
>
72-
<Input
73-
{...register('stackURL', {
74-
required: t('migrate-to-cloud.connect-modal.stack-required-error', 'Stack URL is required'),
75-
})}
76-
id={cloudStackId}
77-
placeholder="https://example.grafana.net/"
78-
/>
79-
</Field>
71+
8072
<span>
8173
<Trans i18nKey="migrate-to-cloud.connect-modal.body-token">
8274
Your self-managed Grafana installation needs special access to securely migrate content. You&apos;ll
8375
need to create a migration token on your chosen cloud stack.
8476
</Trans>
8577
</span>
78+
8679
<span>
8780
<Trans i18nKey="migrate-to-cloud.connect-modal.body-token-instructions">
8881
Log into your cloud stack and navigate to Administration, General, Migrate to Grafana Cloud. Create a
8982
migration token on that screen and paste the token here.
9083
</Trans>
9184
</span>
85+
9286
<Field
9387
className={styles.field}
9488
invalid={!!errors.token}
@@ -110,7 +104,7 @@ export const ConnectModal = ({ hideModal, onConfirm }: Props) => {
110104
<Button variant="secondary" onClick={hideModal}>
111105
<Trans i18nKey="migrate-to-cloud.connect-modal.cancel">Cancel</Trans>
112106
</Button>
113-
<Button type="submit" disabled={isConnecting || !(stackURL && token)}>
107+
<Button type="submit" disabled={isConnecting || !token}>
114108
{isConnecting
115109
? t('migrate-to-cloud.connect-modal.connecting', 'Connecting to this stack...')
116110
: t('migrate-to-cloud.connect-modal.connect', 'Connect to this stack')}

public/app/features/migrate-to-cloud/onprem/EmptyState/EmptyState.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const EmptyState = () => {
1515
<div className={styles.container}>
1616
<Stack direction="column">
1717
<CallToAction />
18+
1819
<Grid
1920
alignItems="flex-start"
2021
gap={1}

0 commit comments

Comments
 (0)