1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-19 06:50:07 +03:00

F #3951: Add support to on-premise provisions (#1085)

This commit is contained in:
Sergio Betanzos 2021-04-09 14:47:10 +02:00 committed by GitHub
parent 02736a1d85
commit 85acc4b703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 86 additions and 54 deletions

View File

@ -14,7 +14,7 @@ const FIRST_STEP = 0
const FormStepper = ({ steps, schema, onSubmit }) => {
const isMobile = useMediaQuery(theme => theme.breakpoints.only('xs'))
const { watch, reset, errors, setError } = useFormContext()
const { isLoading } = useGeneral()
const { isLoading, changeLoading } = useGeneral()
const [formData, setFormData] = useState(() => watch())
const [activeStep, setActiveStep] = useState(FIRST_STEP)
@ -37,15 +37,16 @@ const FormStepper = ({ steps, schema, onSubmit }) => {
.then(() => ({ id, data: stepData }))
}
const setErrors = ({ inner: errors, ...rest }) => {
const setErrors = ({ inner: errors = [], ...rest }) => {
changeLoading(false)
const errorsByPath = groupBy(errors, 'path') ?? {}
const totalErrors = Object.keys(errorsByPath).length
totalErrors > 0
? setError(id, {
type: 'manual',
message: `${totalErrors} error(s) occurred`
})
type: 'manual',
message: `${totalErrors} error(s) occurred`
})
: setError(id, rest)
errors?.forEach(({ path, type, message }) =>

View File

@ -42,5 +42,9 @@ export const PROVIDERS_TYPES = [
{
name: 'packet',
color: '#364562'
},
{
name: 'dummy',
color: '#436637'
}
]

View File

@ -1,4 +1,4 @@
import React, { useCallback } from 'react'
import React, { useCallback, useEffect } from 'react'
import { Divider, Select, Breadcrumbs } from '@material-ui/core'
import ArrowIcon from '@material-ui/icons/ArrowForwardIosRounded'
import Marked from 'marked'
@ -22,16 +22,25 @@ const Template = () => ({
resolver: () => STEP_FORM_SCHEMA,
content: useCallback(
({ data, setFormData }) => {
const { provisionsTemplates } = useProvision()
const templateSelected = data?.[0]
const [provisionSelected, setProvision] = React.useState(() => templateSelected?.plain?.provision_type)
const [provisionSelected, setProvision] = React.useState(
() => templateSelected?.plain?.provision_type ?? Object.keys(provisionsTemplates)?.[0]
)
const [providerSelected, setProvider] = React.useState(() => templateSelected?.provider)
const { provisionsTemplates } = useProvision()
const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description
const providersTypes = provisionsTemplates?.[provisionSelected]?.providers ?? []
const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description
const templatesAvailable = providersTypes?.[providerSelected]
useEffect(() => {
// Select the first provider type
setProvider(Object.keys(providersTypes)?.[0])
}, [provisionSelected])
const {
handleSelect,
handleUnselect,
@ -52,26 +61,29 @@ const Template = () => ({
const handleClick = (template, isSelected) => {
const { name, description, plain = {}, connection } = template
const { location_key: locationKey = '' } = plain
const { [locationKey]: _, ...connectionEditable } = connection
const { [locationKey]: _, ...connectionEditable } = connection ?? {}
// reset rest of form when change template
setFormData({ [CONFIGURATION_ID]: { name, description }, [CONNECTION_ID]: connectionEditable })
setFormData({
[CONFIGURATION_ID]: { name, description },
[CONNECTION_ID]: connectionEditable
})
isSelected
? handleUnselect(name, item => item.name === name)
: handleSelect(template)
}
const RenderOptions = ({ options = {} }) => Object.keys(options)?.map(option => (
<option key={option} value={option}>{option}</option>
))
const RenderOptions = ({ options = {} }) => Object.keys(options)?.map(
option => <option key={option} value={option}>{option}</option>
) ?? <option value=''>{T.None}</option>
const RenderDescription = ({ description = '' }) => {
const renderer = new Marked.Renderer()
renderer.link = (href, title, text) => (
`<a class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiTypography-colorSecondary"
target="_blank" rel="nofollow" title='${title}' href='${href}' >${text}</a>`
target="_blank" rel="nofollow" title='${title}' href='${href}'>${text}</a>`
)
const html = Marked(sanitize`${description}`, { renderer })
@ -91,7 +103,6 @@ const Template = () => ({
value={provisionSelected}
variant='outlined'
>
<option value="">{T.None}</option>
<RenderOptions options={provisionsTemplates} />
</Select>
{provisionSelected && <Select
@ -103,7 +114,6 @@ const Template = () => ({
value={providerSelected}
variant='outlined'
>
<option value="">{T.None}</option>
<RenderOptions options={providersTypes} />
</Select>}
</Breadcrumbs>
@ -124,8 +134,8 @@ const Template = () => ({
!provisionSelected
? 'Please choose your provision type'
: !providerSelected
? 'Please choose your provider type'
: 'Your providers templates list is empty'
? 'Please choose your provider type'
: 'Your providers templates list is empty'
} />
}
gridProps={{ 'data-cy': 'providers-templates' }}

View File

@ -54,7 +54,7 @@ function ProviderCreateForm () {
const { inputs, plain, provider } = templateSelected
const { location_key: locationKey } = plain
const { [locationKey]: connectionFixed } = templateSelected.connection
const connectionFixed = templateSelected.connection?.[locationKey]
const formatData = {
connection: { ...connection, [locationKey]: connectionFixed },

View File

@ -26,6 +26,8 @@ const Info = memo(({ data }) => {
registration_time: time
} = TEMPLATE?.PROVISION_BODY
const hasConnection = connection && Object.keys(connection).length > 0
const isChecked = checked =>
checked === '1' ? <CheckBox /> : <CheckBoxOutlineBlank />
@ -71,26 +73,28 @@ const Info = memo(({ data }) => {
</ListItem>
</List>
</Paper>
<Paper variant="outlined">
<List className={clsx(classes.list, 'w-50')}>
<ListItem className={classes.title}>
<Typography>{Tr(T.Credentials)}</Typography>
<span className={classes.alignToRight}>
{!showConnection && <ConnectionButton />}
</span>
</ListItem>
<Divider />
{Object.entries(connection)?.map(([key, value]) =>
typeof value === 'string' && (
<ListItem key={key}>
<Typography>{key}</Typography>
<Typography data-cy={`provider-${key}`}>
{showConnection?.[key] ?? value}
</Typography>
</ListItem>
))}
</List>
</Paper>
{hasConnection && (
<Paper variant="outlined">
<List className={clsx(classes.list, 'w-50')}>
<ListItem className={classes.title}>
<Typography>{Tr(T.Credentials)}</Typography>
<span className={classes.alignToRight}>
{!showConnection && <ConnectionButton />}
</span>
</ListItem>
<Divider />
{Object.entries(connection)?.map(([key, value]) =>
typeof value === 'string' && (
<ListItem key={key}>
<Typography>{key}</Typography>
<Typography data-cy={`provider-${key}`}>
{showConnection?.[key] ?? value}
</Typography>
</ListItem>
))}
</List>
</Paper>
)}
</Grid>
<Grid item xs={12} md={6}>
<Paper variant="outlined" className={classes.marginBottom}>

View File

@ -1,4 +1,4 @@
import React, { useCallback } from 'react'
import React, { useCallback, useEffect } from 'react'
import { Divider, Select, Breadcrumbs } from '@material-ui/core'
import ArrowIcon from '@material-ui/icons/ArrowForwardIosRounded'
import Marked from 'marked'
@ -22,16 +22,25 @@ const Template = () => ({
label: T.ProvisionTemplate,
resolver: () => STEP_FORM_SCHEMA,
content: useCallback(({ data, setFormData }) => {
const { provisionsTemplates, providers } = useProvision()
const templateSelected = data?.[0]
const [provisionSelected, setProvision] = React.useState(templateSelected?.provision_type)
const [providerSelected, setProvider] = React.useState(templateSelected?.provider)
const [provisionSelected, setProvision] = React.useState(
() => templateSelected?.provision_type ?? Object.keys(provisionsTemplates)?.[0]
)
const [providerSelected, setProvider] = React.useState(() => templateSelected?.provider)
const { provisionsTemplates, providers } = useProvision()
const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description
const providersTypes = provisionsTemplates?.[provisionSelected]?.provisions ?? []
const provisionSelectedDescription = provisionsTemplates?.[provisionSelected]?.description
const templatesAvailable = providersTypes?.[providerSelected] ?? []
useEffect(() => {
// Select the first provider type
setProvider(Object.keys(providersTypes)?.[0])
}, [provisionSelected])
const {
handleSelect,
handleUnselect,
@ -76,7 +85,7 @@ const Template = () => ({
renderer.link = (href, title, text) => (
`<a class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiTypography-colorSecondary"
target="_blank" rel="nofollow" title='${title}' href='${href}' >${text}</a>`
target="_blank" rel="nofollow" title='${title}' href='${href}'>${text}</a>`
)
const html = Marked(sanitize`${description}`, { renderer })
@ -96,7 +105,6 @@ const Template = () => ({
value={provisionSelected}
variant='outlined'
>
<option value="">{T.None}</option>
<RenderOptions options={provisionsTemplates} />
</Select>
{provisionSelected && <Select
@ -108,7 +116,6 @@ const Template = () => ({
value={providerSelected}
variant='outlined'
>
<option value="">{T.None}</option>
<RenderOptions options={providersTypes} />
</Select>}
</Breadcrumbs>
@ -129,8 +136,8 @@ const Template = () => ({
!provisionSelected
? 'Please choose your provision type'
: !providerSelected
? 'Please choose your provider type'
: 'Your provisions templates list is empty'
? 'Please choose your provider type'
: 'Your provisions templates list is empty'
} />
}
gridProps={{ 'data-cy': 'provisions-templates' }}

View File

@ -1,7 +1,8 @@
export const isValidProviderTemplate = ({ name, provider, plain = {}, connection }) => {
const { provision_type: provisionType, location_key: locationKey } = plain
const locationKeyConnectionNotExists = connection[locationKey] === undefined
const hasConnection = connection !== undefined
const locationKeyConnectionNotExists = !hasConnection || connection?.[locationKey] === undefined
return (
!(locationKey && locationKeyConnectionNotExists) ||

View File

@ -27,11 +27,16 @@ export const UserInput = PropTypes.shape({
])
})
export const ProviderType = PropTypes.oneOf(['aws', 'packet'])
export const ProviderType = PropTypes.oneOf([
'aws',
'packet',
'dummy'
])
export const ProvisionType = PropTypes.oneOf([
'metal',
'virtual'
'virtual',
'onprem'
])
export const ProvisionHost = PropTypes.shape({

View File

@ -12,7 +12,7 @@
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const providers = ['aws', 'packet']
const providers = ['aws', 'packet', 'dummy']
const provider = {
id: '/Provider',