1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-20 14:03:36 +03:00

F OpenNebula/One#6386: Remove extra step when creating Image (#3115)

This commit is contained in:
Jorge Miguel Lobo Escalona 2024-06-17 11:53:24 +02:00 committed by GitHub
parent b1c92d811e
commit a64457813d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 19 additions and 437 deletions

View File

@ -10,7 +10,6 @@ resource_name: "IMAGE"
actions:
create_dialog: true
import_dialog: true
dockerfile_dialog: false
clone: true
lock: true
unlock: true

View File

@ -10,7 +10,6 @@ resource_name: "IMAGE"
actions:
create_dialog: true
import_dialog: true
dockerfile_dialog: false
clone: true
lock: true
unlock: true

View File

@ -10,7 +10,6 @@ resource_name: "IMAGE"
actions:
create_dialog: true
import_dialog: true
dockerfile_dialog: false
clone: true
lock: true
unlock: true

View File

@ -34,6 +34,7 @@ import {
MultiplePagesEmpty as ServiceTemplateIcon,
Packages as ServicesIcon,
Box as StorageIcon,
HeadsetHelp as SupportIcon,
Home as SystemIcon,
EmptyPage as TemplateIcon,
Archive as TemplatesIcon,
@ -43,7 +44,6 @@ import {
Folder as VmGroupIcon,
ModernTv as VmsIcons,
MinusPinAlt as ZoneIcon,
HeadsetHelp as SupportIcon,
} from 'iconoir-react'
import loadable from '@loadable/component'
@ -194,12 +194,6 @@ const BackupDetail = loadable(
const CreateImages = loadable(() => import('client/containers/Images/Create'), {
ssr: false,
})
const CreateDockerfile = loadable(
() => import('client/containers/Images/Dockerfile'),
{
ssr: false,
}
)
// Marketplace
const Marketplaces = loadable(() => import('client/containers/Marketplaces'), {
@ -390,7 +384,6 @@ export const PATH = {
LIST: `/${RESOURCE_NAMES.IMAGE}`,
DETAIL: `/${RESOURCE_NAMES.IMAGE}/:id`,
CREATE: `/${RESOURCE_NAMES.IMAGE}/create`,
DOCKERFILE: `/${RESOURCE_NAMES.IMAGE}/dockerfile`,
},
FILES: {
LIST: `/${RESOURCE_NAMES.FILE}`,
@ -691,11 +684,6 @@ const ENDPOINTS = [
path: PATH.STORAGE.FILES.CREATE,
Component: CreateFiles,
},
{
title: T.CreateDockerfile,
path: PATH.STORAGE.IMAGES.DOCKERFILE,
Component: CreateDockerfile,
},
{
title: T.Backups,
path: PATH.STORAGE.BACKUPS.LIST,

View File

@ -1,41 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import FormWithSchema from 'client/components/Forms/FormWithSchema'
import {
SCHEMA,
FIELDS,
} from 'client/components/Forms/Image/CreateDockerfile/Steps/Dockerfile/schema'
import { T } from 'client/constants'
export const STEP_ID = 'dockerfile'
const Content = () => <FormWithSchema id={STEP_ID} fields={FIELDS} />
/**
* Docker file.
*
* @returns {object} Dockerfile step
*/
const DockerFile = () => ({
id: STEP_ID,
label: T.Dockerfile,
resolver: SCHEMA,
optionsValidate: { abortEarly: false },
content: Content,
})
export default DockerFile

View File

@ -1,41 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import { string, object, ObjectSchema } from 'yup'
import { Field, getValidationFromFields, encodeBase64 } from 'client/utils'
import { T, INPUT_TYPES } from 'client/constants'
/** @type {Field} Dockerfile field */
export const DOCKERFILE = {
name: 'PATH',
label: T.Dockerfile,
type: INPUT_TYPES.DOCKERFILE,
cy: 'dockerfile',
validation: string()
.trim()
.required()
.afterSubmit((value) => encodeBase64(value)),
grid: { md: 12 },
}
/**
* @returns {Field[]} Fields
*/
export const FIELDS = [DOCKERFILE]
/**
* @returns {ObjectSchema} Schema
*/
export const SCHEMA = object(getValidationFromFields(FIELDS))

View File

@ -1,42 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import FormWithSchema from 'client/components/Forms/FormWithSchema'
import {
SCHEMA,
FIELDS,
} from 'client/components/Forms/Image/CreateDockerfile/Steps/General/schema'
import { T } from 'client/constants'
export const STEP_ID = 'general'
const Content = () => <FormWithSchema id={STEP_ID} fields={FIELDS} />
/**
* General configuration about VM Template.
*
* @returns {object} General configuration step
*/
const General = () => ({
id: STEP_ID,
label: T.Configuration,
resolver: SCHEMA,
optionsValidate: { abortEarly: false },
content: Content,
})
export default General

View File

@ -1,64 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import { string, boolean, number, object, ObjectSchema } from 'yup'
import { Field, getValidationFromFields } from 'client/utils'
import { T, INPUT_TYPES } from 'client/constants'
export const IMAGE_LOCATION_TYPES = {
PATH: 'path',
UPLOAD: 'upload',
EMPTY: 'empty',
}
/** @type {Field} Name field */
export const NAME = {
name: 'NAME',
label: T.Name,
type: INPUT_TYPES.TEXT,
validation: string().trim().required(),
grid: { xs: 12, md: 6 },
}
/** @type {Field} Context field */
export const CONTEXT = {
name: 'CONTEXT',
label: T.Context,
type: INPUT_TYPES.SWITCH,
validation: boolean().yesOrNo(),
grid: { xs: 12, md: 6 },
}
/** @type {Field} Size field */
export const SIZE = {
name: 'SIZE',
htmlType: 'number',
label: T.Size,
type: INPUT_TYPES.TEXT,
tooltip: T.ImageSize,
validation: number().positive().required(),
grid: { md: 12 },
}
/**
* @returns {Field[]} Fields
*/
export const FIELDS = [NAME, CONTEXT, SIZE]
/**
* @param {object} [stepProps] - Step props
* @returns {ObjectSchema} Schema
*/
export const SCHEMA = object(getValidationFromFields(FIELDS))

View File

@ -1,63 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import Datastore, {
STEP_ID as DATASTORE_ID,
} from 'client/components/Forms/Image/CloneForm/Steps/DatastoresTable'
import General, {
STEP_ID as GENERAL_ID,
} from 'client/components/Forms/Image/CreateForm/Steps/General'
import AdvancedOptions, {
STEP_ID as ADVANCE_ID,
} from 'client/components/Forms/Image/CreateForm/Steps/AdvancedOptions'
import CustomAttributes, {
STEP_ID as CUSTOM_ID,
} from 'client/components/Forms/Image/CreateForm/Steps/CustomAttributes'
import { jsonToXml } from 'client/models/Helper'
import { createSteps, cloneObject, set } from 'client/utils'
const Steps = createSteps(
[General, Datastore, AdvancedOptions, CustomAttributes],
{
transformBeforeSubmit: (formData) => {
const {
[GENERAL_ID]: general = {},
[DATASTORE_ID]: [datastore] = [],
[ADVANCE_ID]: advanced = {},
[CUSTOM_ID]: custom = {},
} = formData ?? {}
const generalData = cloneObject(general)
set(generalData, 'UPLOAD', undefined)
set(generalData, 'IMAGE_LOCATION', undefined)
return {
template: jsonToXml({
...custom,
...advanced,
...generalData,
}),
datastore: datastore?.ID,
file: general?.UPLOAD,
}
},
}
)
export default Steps

View File

@ -1,55 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import Datastore, {
STEP_ID as DATASTORE_ID,
} from 'client/components/Forms/Image/CloneForm/Steps/DatastoresTable'
import General, {
STEP_ID as GENERAL_ID,
} from 'client/components/Forms/Image/CreateDockerfile/Steps/General'
import Dockerfile, {
STEP_ID as DOCKERFILE_ID,
} from 'client/components/Forms/Image/CreateDockerfile/Steps/Dockerfile'
import { jsonToXml } from 'client/models/Helper'
import { createSteps, cloneObject, set } from 'client/utils'
const Steps = createSteps([General, Datastore, Dockerfile], {
transformBeforeSubmit: (formData) => {
const {
[GENERAL_ID]: general = {},
[DATASTORE_ID]: [datastore] = [],
[DOCKERFILE_ID]: dockerfile = {},
} = formData ?? {}
const generalData = cloneObject(general)
set(generalData, 'CONTEXT', undefined)
set(generalData, 'SIZE', undefined)
return {
template: jsonToXml({
...{
PATH: `dockerfile://?fileb64=${dockerfile.PATH}&amp;context=${general.CONTEXT}&amp;size=${general.SIZE}`,
},
...generalData,
}),
datastore: datastore?.ID,
}
},
})
export default Steps

View File

@ -31,11 +31,4 @@ const CloneForm = (configProps) =>
const CreateForm = (configProps) =>
AsyncLoadForm({ formPath: 'Image/CreateForm' }, configProps)
/**
* @param {ConfigurationProps} configProps - Configuration
* @returns {ReactElement|CreateStepsCallback} Asynchronous loaded form
*/
const CreateDockerfileForm = (configProps) =>
AsyncLoadForm({ formPath: 'Image/CreateDockerfile' }, configProps)
export { CloneForm, CreateForm, CreateDockerfileForm }
export { CloneForm, CreateForm }

View File

@ -13,44 +13,41 @@
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import { useMemo } from 'react'
import { useHistory } from 'react-router-dom'
import { Typography, Grid } from '@mui/material'
import { Typography } from '@mui/material'
import {
MoreVert,
AddCircledOutline,
Lock,
Cart,
Group,
Lock,
MoreVert,
Trash,
Code,
PageEdit,
} from 'iconoir-react'
import { useMemo } from 'react'
import { useHistory } from 'react-router-dom'
import { useViews } from 'client/features/Auth'
import {
useLockImageMutation,
useCloneImageMutation,
useUnlockImageMutation,
useEnableImageMutation,
useDisableImageMutation,
usePersistentImageMutation,
useChangeImageOwnershipMutation,
useCloneImageMutation,
useDisableImageMutation,
useEnableImageMutation,
useLockImageMutation,
usePersistentImageMutation,
useRemoveImageMutation,
useUnlockImageMutation,
} from 'client/features/OneApi/image'
import { ChangeUserForm, ChangeGroupForm } from 'client/components/Forms/Vm'
import { CloneForm } from 'client/components/Forms/Image'
import { ChangeGroupForm, ChangeUserForm } from 'client/components/Forms/Vm'
import {
createActions,
GlobalAction,
createActions,
} from 'client/components/Tables/Enhanced/Utils'
import ImageCreateCard from 'client/components/Cards/ImageCreateCard'
import { Tr, Translate } from 'client/components/HOC'
import { PATH } from 'client/apps/sunstone/routesOne'
import { Tr, Translate } from 'client/components/HOC'
import { IMAGE_ACTIONS, RESOURCE_NAMES, T, VM_ACTIONS } from 'client/constants'
import { isAvailableAction } from 'client/models/VirtualMachine'
import { T, IMAGE_ACTIONS, VM_ACTIONS, RESOURCE_NAMES } from 'client/constants'
const isDisabled = (action) => (rows) =>
!isAvailableAction(
@ -109,39 +106,10 @@ const Actions = () => {
actions: [
{
accessor: IMAGE_ACTIONS.CREATE_DIALOG,
tooltip: T.CreateImage,
dataCy: `image_${IMAGE_ACTIONS.CREATE_DIALOG}`,
tooltip: T.Create,
icon: AddCircledOutline,
options: [
{
isConfirmDialog: true,
dialogProps: {
title: T.CreateImage,
children: () => (
<Grid container spacing={3}>
<ImageCreateCard
name={Tr(T.CreateImage)}
Icon={PageEdit}
onClick={() => history.push(PATH.STORAGE.IMAGES.CREATE)}
/>
{resourcesView?.dockerfile_dialog && (
<ImageCreateCard
name={Tr(T.CreateDockerfile)}
Icon={Code}
onClick={() =>
history.push(PATH.STORAGE.IMAGES.DOCKERFILE)
}
/>
)}
</Grid>
),
fixedWidth: true,
fixedHeight: true,
handleAccept: undefined,
dataCy: `modal-${IMAGE_ACTIONS.CREATE_DIALOG}`,
},
},
],
action: () => history.push(PATH.STORAGE.IMAGES.CREATE),
},
{
accessor: VM_ACTIONS.CREATE_APP_DIALOG,

View File

@ -79,7 +79,6 @@ module.exports = {
CopiedToClipboard: 'Copied to clipboard',
Create: 'Create',
CreateDatastore: 'Create Datastore',
CreateDockerfile: 'Create Dockerfile',
CreateFile: 'Create File',
CreateHost: 'Create Host',
CreateImage: 'Create Image',
@ -598,7 +597,6 @@ module.exports = {
CustomBus: 'Custom bus',
Fs: 'Fs',
CustomFormat: 'Custom Format',
Dockerfile: 'Dockerfile',
Running: 'Running',
DoNotRestoreNICAttributes: 'Do not restore NIC attributes',
DoNotRestoreIPAttributes: 'Do not restore IP attributes',

View File

@ -1,56 +0,0 @@
/* ------------------------------------------------------------------------- *
* Copyright 2002-2023, OpenNebula Project, OpenNebula Systems *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may *
* not use this file except in compliance with the License. You may obtain *
* a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import { ReactElement } from 'react'
import { useHistory } from 'react-router'
import { useGeneralApi } from 'client/features/General'
import { useAllocateImageMutation } from 'client/features/OneApi/image'
import { useGetDatastoresQuery } from 'client/features/OneApi/datastore'
import {
DefaultFormStepper,
SkeletonStepsForm,
} from 'client/components/FormStepper'
import { CreateDockerfileForm } from 'client/components/Forms/Image'
import { PATH } from 'client/apps/sunstone/routesOne'
/**
* Displays the creation or modification form to a VM Template.
*
* @returns {ReactElement} VM Template form
*/
function CreateDockerfile() {
const history = useHistory()
const [allocate] = useAllocateImageMutation()
const { enqueueSuccess } = useGeneralApi()
useGetDatastoresQuery(undefined, { refetchOnMountOrArgChange: false })
const onSubmit = async (stepTemplate) => {
try {
const newTemplateId = await allocate(stepTemplate).unwrap()
history.push(PATH.STORAGE.IMAGES.LIST)
enqueueSuccess(`Image created - #${newTemplateId}`)
} catch {}
}
return (
<CreateDockerfileForm onSubmit={onSubmit} fallback={<SkeletonStepsForm />}>
{(config) => <DefaultFormStepper {...config} />}
</CreateDockerfileForm>
)
}
export default CreateDockerfile