Skip to content

Commit dfe61c8

Browse files
committed
Merge branch 'simple-install-dle-ui' into 'master'
feat(ui): simple install for dle (https://gitlab.com/postgres-ai/platform/-/issues/222) See merge request postgres-ai/database-lab!816
2 parents 4097da3 + e4aa4c4 commit dfe61c8

File tree

22 files changed

+7671
-3854
lines changed

22 files changed

+7671
-3854
lines changed

ui/packages/ce/cypress/e2e/tabs.cy.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ describe('Instance page should have "Configuration" tab with content', () => {
99
})
1010
})
1111
it('should have "Configuration" tab with content', () => {
12-
cy.visit('/')
13-
cy.get('.MuiTabs-flexContainer').contains('Configuration')
14-
cy.get('.MuiBox-root').contains('p').should('have.length.greaterThan', 0)
12+
cy.visit('/', {
13+
retryOnStatusCodeFailure: true,
14+
onLoad: () => {
15+
cy.get('.MuiTabs-flexContainer').contains('Configuration')
16+
cy.get('.MuiBox-root')
17+
.contains('p')
18+
.should('have.length.greaterThan', 0)
19+
},
20+
})
1521
})
1622
})

ui/packages/platform/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"formik": "^2.2.9",
4848
"get-user-locale": "^1.4.0",
4949
"jwt-decode": "^3.1.2",
50+
"jwt-encode": "^1.0.1",
5051
"lodash": "^4.17.15",
5152
"md5": "^2.2.1",
5253
"mobx": "^6.3.2",
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { simpleInstallRequest } from 'helpers/simpleInstallRequest'
2+
3+
export const getTaskState = async (req: { taskID: string; userID?: number }) => {
4+
const response = await simpleInstallRequest(
5+
`/state/${req.taskID}`,
6+
{
7+
method: 'GET',
8+
},
9+
req?.userID,
10+
)
11+
12+
return {
13+
response: response.ok ? await response.json() : null,
14+
error: response.ok ? null : await response.json(),
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { SI_API_SERVER } from 'helpers/simpleInstallRequest'
2+
3+
export const initStreamLogs = (taskId: string, otCode: string): WebSocket => {
4+
let url = new URL(
5+
`${SI_API_SERVER.replace(
6+
'https',
7+
'wss',
8+
)}/stream-logs/${taskId}?otCode=${otCode}`,
9+
)
10+
return new WebSocket(url)
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { simpleInstallRequest } from 'helpers/simpleInstallRequest'
2+
import { initialState } from 'components/DbLabInstanceForm/reducer'
3+
import { DEBUG_API_SERVER } from 'components/DbLabInstanceForm/utils'
4+
5+
const API_SERVER = process.env.REACT_APP_API_SERVER
6+
7+
const formatExtraEnvs = (extraEnvs: { [key: string]: string }) => {
8+
return Object.entries(extraEnvs)
9+
.filter(([key, value]) => value)
10+
.map(([key, value]) => {
11+
if (key === 'GCP_SERVICE_ACCOUNT_CONTENTS') {
12+
return `${key}=${value.replace(/\n\s+/g, '')}`
13+
}
14+
return `${key}=${value}`
15+
})
16+
}
17+
18+
export const launchDeploy = async ({
19+
state,
20+
userID,
21+
orgKey,
22+
extraEnvs,
23+
cloudImage,
24+
}: {
25+
state: typeof initialState
26+
orgKey: string
27+
userID?: number
28+
extraEnvs: {
29+
[key: string]: string
30+
}
31+
cloudImage: string
32+
}) => {
33+
const response = await simpleInstallRequest(
34+
'/launch',
35+
{
36+
method: 'POST',
37+
body: JSON.stringify({
38+
playbook: 'deploy_dle.yml',
39+
provision: state.provider,
40+
server: {
41+
name: state.name,
42+
serverType: state.instanceType.native_name,
43+
image: cloudImage,
44+
location: state.location.native_code,
45+
},
46+
image: 'postgresai/dle-se-ansible:v1.0-rc.8',
47+
extraVars: [
48+
`provision=${state.provider}`,
49+
`server_name=${state.name}`,
50+
`dle_platform_project_name=${state.name}`,
51+
`server_type=${state.instanceType.native_name}`,
52+
`server_image=${cloudImage}`,
53+
`server_location=${state.location.native_code}`,
54+
`volume_size=${state.storage}`,
55+
`dle_version=${state.tag}`,
56+
`zpool_datasets_number=${state.snapshots}`,
57+
`dle_verification_token=${state.verificationToken}`,
58+
`dle_platform_org_key=${orgKey}`,
59+
...(state.publicKeys
60+
? // eslint-disable-next-line no-useless-escape
61+
[`ssh_public_keys=\"${state.publicKeys}\"`]
62+
: []),
63+
...(API_SERVER === DEBUG_API_SERVER
64+
? [`dle_platform_url=https://v2.postgres.ai/api/general`]
65+
: []),
66+
],
67+
extraEnvs: formatExtraEnvs(extraEnvs),
68+
}),
69+
},
70+
userID,
71+
)
72+
73+
return {
74+
response: response.ok ? await response.json() : null,
75+
error: response.ok ? null : await response.json(),
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { simpleInstallRequest } from 'helpers/simpleInstallRequest'
2+
3+
export const regenerateCode = async (req: {
4+
taskID: string
5+
userID?: number
6+
}) => {
7+
const response = await simpleInstallRequest(
8+
'/regenerate-code',
9+
{
10+
method: 'POST',
11+
body: JSON.stringify({
12+
taskID: req.taskID,
13+
}),
14+
},
15+
req?.userID,
16+
)
17+
18+
return {
19+
response: response.ok ? await response.json() : null,
20+
error: response.ok ? null : await response.json(),
21+
}
22+
}

ui/packages/platform/src/components/DbLabInstanceForm/DbLabFormSteps/AnsibleInstance.tsx

+28-9
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,42 @@ import { initialState } from '../reducer'
2424

2525
export const formStyles = makeStyles({
2626
marginTop: {
27-
marginTop: '20px',
27+
marginTop: '20px !important',
2828
},
2929
marginBottom: {
3030
marginBottom: '20px',
3131
display: 'block',
3232
},
33+
maxContentWidth: {
34+
maxWidth: '800px',
35+
},
3336
spinner: {
3437
display: 'flex',
3538
justifyContent: 'center',
3639
alignItems: 'center',
3740
height: '100%',
3841
},
42+
buttonSpinner: {
43+
marginRight: '8px',
44+
color: '#fff',
45+
},
3946
title: {
4047
fontWeight: 600,
4148
fontSize: '15px',
4249
margin: '10px 0',
4350
},
51+
mainTitle: {
52+
fontWeight: 600,
53+
fontSize: '20px',
54+
borderBottom: '1px solid #eee',
55+
margin: '0 0 10px 0',
56+
paddingBottom: '10px',
57+
},
58+
note: {
59+
fontSize: '12px',
60+
margin: '0 0 10px 0',
61+
color: '#777',
62+
},
4463
code: {
4564
backgroundColor: '#eee',
4665
borderRadius: '3px',
@@ -59,26 +78,26 @@ export const formStyles = makeStyles({
5978
},
6079
smallMarginTop: {
6180
marginBottom: '10px',
62-
}
81+
},
6382
})
6483

6584
export const InstanceDocumentation = ({
66-
fistStep,
85+
firstStep,
6786
firsStepDescription,
6887
documentation,
6988
secondStep,
7089
snippetContent,
7190
classes,
7291
}: {
73-
fistStep: string
92+
firstStep: string
7493
firsStepDescription?: React.ReactNode
7594
documentation: string
7695
secondStep: React.ReactNode
7796
snippetContent: string
7897
classes: ReturnType<typeof formStyles>
7998
}) => (
8099
<>
81-
<p className={classes.title}>1. {fistStep}</p>
100+
<p className={classes.title}>1. {firstStep}</p>
82101
{firsStepDescription && <p>{firsStepDescription}</p>}
83102
<p className={classes.marginBottom}>
84103
Documentation:{' '}
@@ -182,7 +201,7 @@ export const AnsibleInstance = ({
182201
/>
183202
) : state.provider === 'digitalocean' ? (
184203
<InstanceDocumentation
185-
fistStep="Create Personal Access Token"
204+
firstStep="Create Personal Access Token"
186205
documentation="https://docs.digitalocean.com/reference/api/create-personal-access-token"
187206
secondStep={
188207
<>
@@ -194,7 +213,7 @@ export const AnsibleInstance = ({
194213
/>
195214
) : state.provider === 'hetzner' ? (
196215
<InstanceDocumentation
197-
fistStep="Create API Token"
216+
firstStep="Create API Token"
198217
documentation="https://docs.hetzner.com/cloud/api/getting-started/generating-api-token"
199218
secondStep={
200219
<code className={classes.code}>HCLOUD_API_TOKEN</code>
@@ -204,7 +223,7 @@ export const AnsibleInstance = ({
204223
/>
205224
) : state.provider === 'aws' ? (
206225
<InstanceDocumentation
207-
fistStep="Create access key"
226+
firstStep="Create access key"
208227
documentation="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html"
209228
secondStep={
210229
<>
@@ -217,7 +236,7 @@ export const AnsibleInstance = ({
217236
/>
218237
) : state.provider === 'gcp' ? (
219238
<InstanceDocumentation
220-
fistStep="Create a service account"
239+
firstStep="Create a service account"
221240
documentation="https://developers.google.com/identity/protocols/oauth2/service-account#creatinganaccount"
222241
secondStep={
223242
<code className={classes.code}>

ui/packages/platform/src/components/DbLabInstanceForm/DbLabFormSteps/DockerInstance.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ export const DockerInstance = ({
8484
<ErrorStub title="Error 404" message="orgKey not found" />
8585
) : state.provider === 'digitalocean' ? (
8686
<InstanceDocumentation
87-
fistStep="Create Personal Access Token"
87+
firstStep="Create Personal Access Token"
8888
documentation="https://docs.digitalocean.com/reference/api/create-personal-access-token"
8989
secondStep={<code className={classes.code}>DO_API_TOKEN</code>}
9090
snippetContent="export DO_API_TOKEN=XXXXXX"
9191
classes={classes}
9292
/>
9393
) : state.provider === 'hetzner' ? (
9494
<InstanceDocumentation
95-
fistStep="Create API Token"
95+
firstStep="Create API Token"
9696
documentation="https://docs.hetzner.com/cloud/api/getting-started/generating-api-token"
9797
secondStep={
9898
<code className={classes.code}>HCLOUD_API_TOKEN</code>
@@ -102,7 +102,7 @@ export const DockerInstance = ({
102102
/>
103103
) : state.provider === 'aws' ? (
104104
<InstanceDocumentation
105-
fistStep="Create access key"
105+
firstStep="Create access key"
106106
documentation="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html"
107107
secondStep={
108108
<>
@@ -116,7 +116,7 @@ export const DockerInstance = ({
116116
) : state.provider === 'gcp' ? (
117117
<>
118118
<InstanceDocumentation
119-
fistStep="Create a service account"
119+
firstStep="Create a service account"
120120
firsStepDescription={
121121
<>
122122
Create and save the JSON key for the service account and

ui/packages/platform/src/components/DbLabInstanceForm/DbLabFormSteps/InstanceFormCreation.tsx

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import classNames from 'classnames'
12
import { makeStyles } from '@material-ui/core'
23

34
const useStyles = makeStyles((theme) => ({
@@ -18,6 +19,14 @@ const useStyles = makeStyles((theme) => ({
1819
marginTop: '0',
1920
},
2021
},
22+
fullWidth: {
23+
width: '100%',
24+
maxWidth: '100%',
25+
26+
'& .MuiTextField-root': {
27+
maxWidth: '800px',
28+
}
29+
},
2130
navigation: {
2231
display: 'flex',
2332
flexDirection: 'column',
@@ -60,16 +69,39 @@ export const InstanceFormCreation = ({
6069
formStep,
6170
setFormStep,
6271
children,
72+
install,
73+
fullWidth,
6374
}: {
6475
formStep: string
6576
setFormStep: (step: string) => void
6677
children: React.ReactNode
78+
install?: boolean
79+
fullWidth?: boolean
6780
}) => {
6881
const classes = useStyles()
6982

7083
return (
71-
<div className={classes.snippetContainer}>
84+
<div
85+
className={classNames(
86+
fullWidth && classes.fullWidth,
87+
classes.snippetContainer,
88+
)}
89+
>
7290
<div className={classes.navigation}>
91+
{!install && (
92+
<span
93+
className={formStep === 'simple' ? classes.active : ''}
94+
onClick={() => setFormStep('simple')}
95+
>
96+
<img
97+
src={`/images/simple.svg`}
98+
width={30}
99+
height="auto"
100+
alt={'simple install setup'}
101+
/>
102+
Simple setup
103+
</span>
104+
)}
73105
<span
74106
className={formStep === 'docker' ? classes.active : ''}
75107
onClick={() => setFormStep('docker')}

0 commit comments

Comments
 (0)