mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-30 22:50:10 +03:00
parent
7259d6a964
commit
53e1148ad4
@ -28,66 +28,3 @@ session_remember_expiration: 3600
|
||||
|
||||
# minimum life expiration time (minutes)
|
||||
minimun_opennebula_expiration: 30
|
||||
|
||||
# Prepend for oneprovision command
|
||||
oneprovision_prepend_command: ''
|
||||
|
||||
# Optional param for oneprovision command create
|
||||
oneprovision_optional_create_command: ''
|
||||
|
||||
# Guacamole: use it if you have the Guacd in other server or port
|
||||
# guacd:
|
||||
# port: 4822
|
||||
# host: '127.0.0.1'
|
||||
|
||||
# Currency formatting
|
||||
# Possible values are the ISO 4217 currency codes
|
||||
# https://www.six-group.com/en/products-services/financial-information/data-standards.html
|
||||
currency: EUR
|
||||
|
||||
# Default language setting
|
||||
# Check that the language exists in client/assets/languages
|
||||
default_lang: en
|
||||
|
||||
# Translations: use it if you want to use certain languages on the client.
|
||||
# Check that the language exists in client/assets/languages
|
||||
# langs:
|
||||
# bg_BG: 'Bulgarian (Bulgaria)'
|
||||
# bg: 'Bulgarian'
|
||||
# ca: 'Catalan'
|
||||
# cs_CZ: 'Czech'
|
||||
# da: 'Danish'
|
||||
# de_CH: 'German (Switzerland)'
|
||||
# de: 'German'
|
||||
# el_GR: 'Greek (Greece)'
|
||||
# en: 'English'
|
||||
# es_ES: 'Spanish'
|
||||
# et_EE: 'Estonian'
|
||||
# fa_IR: 'Persian (Iran)'
|
||||
# fa: 'Persian'
|
||||
# fr_CA: 'French (Canada)'
|
||||
# fr_FR: 'French'
|
||||
# hu_HU: 'Hungary'
|
||||
# it_IT: 'Italian'
|
||||
# ja: 'Japanese'
|
||||
# ka: 'Georgian'
|
||||
# lt_LT: 'Lithuanian'
|
||||
# nl_NL: 'Dutch'
|
||||
# pl: Polish
|
||||
# pt_PT: 'Portuguese'
|
||||
# ro_RO: 'Romanian'
|
||||
# ru_RU: 'Russian'
|
||||
# ru: 'Russian'
|
||||
# si: 'Sinhala'
|
||||
# sk_SK: 'Slavak'
|
||||
# sr_RS: 'Serbian'
|
||||
# sv: 'Swedish'
|
||||
# th_TH: 'Thai (Thailand)'
|
||||
# th: 'Thai'
|
||||
# tr_TR: 'Turkish (Turkey)'
|
||||
# tr: 'Turkish'
|
||||
# uk_UA: 'Ukrainian (Ukraine)'
|
||||
# uk: 'Ukrainian'
|
||||
# vi: 'Vietnamese'
|
||||
# zh_CN: 'Chinese (China)'
|
||||
# zh_TW: 'Chinese (Taiwan)'
|
@ -1,5 +1,67 @@
|
||||
################################################################################
|
||||
# Protected Settings
|
||||
################################################################################
|
||||
|
||||
# Prepend for oneprovision command
|
||||
oneprovision_prepend_command: ''
|
||||
|
||||
# Optional param for oneprovision command create
|
||||
oneprovision_optional_create_command: ''
|
||||
oneprovision_optional_create_command: ''
|
||||
|
||||
################################################################################
|
||||
# UI Settings
|
||||
################################################################################
|
||||
|
||||
# True to display 'Keep me logged in' option
|
||||
keep_me_logged_in: true
|
||||
|
||||
# Currency formatting
|
||||
# Possible values are the ISO 4217 currency codes
|
||||
# https://www.six-group.com/en/products-services/financial-information/data-standards.html
|
||||
currency: EUR
|
||||
|
||||
# Default language setting
|
||||
default_lang: en
|
||||
|
||||
# Translations: use it if you want to use certain languages on the client
|
||||
# Check that the language exists in client/assets/languages
|
||||
langs:
|
||||
bg_BG: 'Bulgarian (Bulgaria)'
|
||||
bg: 'Bulgarian'
|
||||
ca: 'Catalan'
|
||||
cs_CZ: 'Czech'
|
||||
da: 'Danish'
|
||||
de_CH: 'German (Switzerland)'
|
||||
de: 'German'
|
||||
el_GR: 'Greek (Greece)'
|
||||
en: 'English'
|
||||
es_ES: 'Spanish'
|
||||
et_EE: 'Estonian'
|
||||
fa_IR: 'Persian (Iran)'
|
||||
fa: 'Persian'
|
||||
fr_CA: 'French (Canada)'
|
||||
fr_FR: 'French'
|
||||
hu_HU: 'Hungary'
|
||||
it_IT: 'Italian'
|
||||
ja: 'Japanese'
|
||||
ka: 'Georgian'
|
||||
lt_LT: 'Lithuanian'
|
||||
nl_NL: 'Dutch'
|
||||
pl: Polish
|
||||
pt_PT: 'Portuguese'
|
||||
ro_RO: 'Romanian'
|
||||
ru_RU: 'Russian'
|
||||
ru: 'Russian'
|
||||
si: 'Sinhala'
|
||||
sk_SK: 'Slavak'
|
||||
sr_RS: 'Serbian'
|
||||
sv: 'Swedish'
|
||||
th_TH: 'Thai (Thailand)'
|
||||
th: 'Thai'
|
||||
tr_TR: 'Turkish (Turkey)'
|
||||
tr: 'Turkish'
|
||||
uk_UA: 'Ukrainian (Ukraine)'
|
||||
uk: 'Ukrainian'
|
||||
vi: 'Vietnamese'
|
||||
zh_CN: 'Chinese (China)'
|
||||
zh_TW: 'Chinese (Taiwan)'
|
@ -1,12 +1,26 @@
|
||||
# Prepend for oneprovision command
|
||||
################################################################################
|
||||
# Protected Settings
|
||||
################################################################################
|
||||
|
||||
# Official support
|
||||
support_url: 'https://opennebula.zendesk.com/api/v2'
|
||||
support_token: ''
|
||||
|
||||
# Prepend for vcenter command
|
||||
vcenter_prepend_command: ''
|
||||
|
||||
# Prepend for sunstone commands
|
||||
sunstone_prepend: ''
|
||||
|
||||
# Support
|
||||
support_url: 'https://opennebula.zendesk.com/api/v2'
|
||||
support_token: ''
|
||||
# Directory to store temp files when uploading images
|
||||
tmpdir: /var/tmp
|
||||
|
||||
################################################################################
|
||||
# UI Settings
|
||||
################################################################################
|
||||
|
||||
# True to display 'Keep me logged in' option
|
||||
keep_me_logged_in: true
|
||||
|
||||
# This automatically adds scheduling actions
|
||||
#
|
||||
@ -21,7 +35,7 @@ leases:
|
||||
edit: false
|
||||
execute_after_weeks: 2
|
||||
warn_before_days: 1
|
||||
|
||||
|
||||
# Support filesystem
|
||||
# You may want to update SUPPORTED_FS in datastore.conf
|
||||
supported_fs:
|
||||
@ -30,3 +44,53 @@ supported_fs:
|
||||
- ext2
|
||||
- xfs
|
||||
|
||||
# Currency formatting
|
||||
# Possible values are the ISO 4217 currency codes
|
||||
# https://www.six-group.com/en/products-services/financial-information/data-standards.html
|
||||
currency: EUR
|
||||
|
||||
# Default language setting
|
||||
default_lang: en
|
||||
|
||||
# Translations: use it if you want to use certain languages on the client
|
||||
# Check that the language exists in client/assets/languages
|
||||
langs:
|
||||
bg_BG: 'Bulgarian (Bulgaria)'
|
||||
bg: 'Bulgarian'
|
||||
ca: 'Catalan'
|
||||
cs_CZ: 'Czech'
|
||||
da: 'Danish'
|
||||
de_CH: 'German (Switzerland)'
|
||||
de: 'German'
|
||||
el_GR: 'Greek (Greece)'
|
||||
en: 'English'
|
||||
es_ES: 'Spanish'
|
||||
et_EE: 'Estonian'
|
||||
fa_IR: 'Persian (Iran)'
|
||||
fa: 'Persian'
|
||||
fr_CA: 'French (Canada)'
|
||||
fr_FR: 'French'
|
||||
hu_HU: 'Hungary'
|
||||
it_IT: 'Italian'
|
||||
ja: 'Japanese'
|
||||
ka: 'Georgian'
|
||||
lt_LT: 'Lithuanian'
|
||||
nl_NL: 'Dutch'
|
||||
pl: Polish
|
||||
pt_PT: 'Portuguese'
|
||||
ro_RO: 'Romanian'
|
||||
ru_RU: 'Russian'
|
||||
ru: 'Russian'
|
||||
si: 'Sinhala'
|
||||
sk_SK: 'Slavak'
|
||||
sr_RS: 'Serbian'
|
||||
sv: 'Swedish'
|
||||
th_TH: 'Thai (Thailand)'
|
||||
th: 'Thai'
|
||||
tr_TR: 'Turkish (Turkey)'
|
||||
tr: 'Turkish'
|
||||
uk_UA: 'Ukrainian (Ukraine)'
|
||||
uk: 'Ukrainian'
|
||||
vi: 'Vietnamese'
|
||||
zh_CN: 'Chinese (China)'
|
||||
zh_TW: 'Chinese (Taiwan)'
|
@ -66,7 +66,6 @@ const SunstoneApp = () => {
|
||||
<AuthLayout
|
||||
subscriptions={[
|
||||
systemApi.endpoints.getOneConfig,
|
||||
systemApi.endpoints.getSunstoneConfig,
|
||||
systemApi.endpoints.getSunstoneViews,
|
||||
]}
|
||||
>
|
||||
|
@ -15,10 +15,8 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { memo, useMemo, ReactElement } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Trash, Edit, ClockOutline } from 'iconoir-react'
|
||||
|
||||
import { useGetSunstoneConfigQuery } from 'client/features/OneApi/system'
|
||||
import ButtonToTriggerForm from 'client/components/Forms/ButtonToTriggerForm'
|
||||
import {
|
||||
CreateCharterForm,
|
||||
@ -33,6 +31,7 @@ import {
|
||||
T,
|
||||
VM_ACTIONS,
|
||||
VM_ACTIONS_IN_CHARTER,
|
||||
SERVER_CONFIG,
|
||||
ScheduleAction,
|
||||
} from 'client/constants'
|
||||
|
||||
@ -155,15 +154,13 @@ const DeleteSchedButton = memo(({ onSubmit, schedule }) => {
|
||||
* @returns {ReactElement} Button
|
||||
*/
|
||||
const CharterButton = memo(({ relative, onSubmit }) => {
|
||||
const { data: config } = useGetSunstoneConfigQuery()
|
||||
|
||||
const leases = useMemo(
|
||||
() =>
|
||||
// filters if exists in the VM actions for charters
|
||||
Object.entries(config?.leases ?? {}).filter(([action]) =>
|
||||
Object.entries(SERVER_CONFIG?.leases ?? {}).filter(([action]) =>
|
||||
VM_ACTIONS_IN_CHARTER.includes(action)
|
||||
),
|
||||
[config?.leases]
|
||||
[]
|
||||
)
|
||||
|
||||
const formConfig = { stepProps: leases, initialValues: leases }
|
||||
|
@ -15,14 +15,13 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
import { number, string, object, ObjectSchema } from 'yup'
|
||||
|
||||
import { useGetSunstoneConfigQuery } from 'client/features/OneApi/system'
|
||||
import {
|
||||
Field,
|
||||
getValidationFromFields,
|
||||
filterFieldsByHypervisor,
|
||||
arrayToOptions,
|
||||
} from 'client/utils'
|
||||
import { T, INPUT_TYPES, HYPERVISORS } from 'client/constants'
|
||||
import { T, INPUT_TYPES, HYPERVISORS, SERVER_CONFIG } from 'client/constants'
|
||||
|
||||
const { vcenter } = HYPERVISORS
|
||||
|
||||
@ -89,11 +88,7 @@ const FILESYSTEM = {
|
||||
type: INPUT_TYPES.SELECT,
|
||||
dependOf: 'TYPE',
|
||||
htmlType: (type) => type === 'swap' && INPUT_TYPES.HIDDEN,
|
||||
values: () => {
|
||||
const { data: config } = useGetSunstoneConfigQuery()
|
||||
|
||||
return arrayToOptions(config?.supported_fs)
|
||||
},
|
||||
values: () => arrayToOptions(SERVER_CONFIG?.supported_fs),
|
||||
validation: string().trim().notRequired().default(undefined),
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@ import { isDevelopment } from 'client/utils'
|
||||
import { LANGUAGES, LANGUAGES_URL } from 'client/constants'
|
||||
|
||||
const TranslateContext = createContext()
|
||||
let languageScript = root.document?.createElement('script')
|
||||
|
||||
/**
|
||||
* @typedef {
|
||||
@ -102,16 +101,20 @@ const TranslateProvider = ({ children = [] }) => {
|
||||
|
||||
script.src = `${LANGUAGES_URL}/${lang}.js`
|
||||
script.async = true
|
||||
script.onload = () => setHash(root.locale)
|
||||
script.onload = () => {
|
||||
setHash(window.locale)
|
||||
|
||||
root.document.body.appendChild(script)
|
||||
languageScript = script
|
||||
// delete script and variables after load
|
||||
delete window.lang
|
||||
delete window.locale
|
||||
window.document.body.removeChild(script)
|
||||
}
|
||||
|
||||
window.document.body.appendChild(script)
|
||||
} catch (error) {
|
||||
isDevelopment() &&
|
||||
console.error('Error while generating script language', error)
|
||||
}
|
||||
|
||||
return () => root.document.body.removeChild(languageScript)
|
||||
}, [lang])
|
||||
|
||||
return (
|
||||
|
@ -17,7 +17,6 @@ import { ReactElement, useMemo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Stack } from '@mui/material'
|
||||
|
||||
import { useGetSunstoneConfigQuery } from 'client/features/OneApi/system'
|
||||
import {
|
||||
useGetVmQuery,
|
||||
useAddScheduledActionMutation,
|
||||
@ -38,7 +37,7 @@ import {
|
||||
isAvailableAction,
|
||||
} from 'client/models/VirtualMachine'
|
||||
import { getActionsAvailable, jsonToXml } from 'client/models/Helper'
|
||||
import { VM_ACTIONS } from 'client/constants'
|
||||
import { VM_ACTIONS, SERVER_CONFIG } from 'client/constants'
|
||||
|
||||
const {
|
||||
SCHED_ACTION_CREATE,
|
||||
@ -57,7 +56,6 @@ const {
|
||||
* @returns {ReactElement} Schedule actions tab
|
||||
*/
|
||||
const VmSchedulingTab = ({ tabProps: { actions } = {}, id }) => {
|
||||
const { data: config } = useGetSunstoneConfigQuery()
|
||||
const [addScheduledAction] = useAddScheduledActionMutation()
|
||||
const [updateScheduledAction] = useUpdateScheduledActionMutation()
|
||||
const [deleteScheduledAction] = useDeleteScheduledActionMutation()
|
||||
@ -77,7 +75,7 @@ const VmSchedulingTab = ({ tabProps: { actions } = {}, id }) => {
|
||||
const isUpdateEnabled = actionsAvailable?.includes?.(SCHED_ACTION_UPDATE)
|
||||
const isDeleteEnabled = actionsAvailable?.includes?.(SCHED_ACTION_DELETE)
|
||||
const isCharterEnabled =
|
||||
actionsAvailable?.includes?.(CHARTER_CREATE) && config?.leases
|
||||
actionsAvailable?.includes?.(CHARTER_CREATE) && SERVER_CONFIG?.leases
|
||||
|
||||
/**
|
||||
* Add new schedule action to VM.
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
} from 'iconoir-react'
|
||||
|
||||
import { useAuth } from 'client/features/Auth'
|
||||
import { useGetResourceQuery } from 'client/features/OneApi/provision'
|
||||
import { useGetProvisionResourceQuery } from 'client/features/OneApi/provision'
|
||||
|
||||
import {
|
||||
TotalProviders,
|
||||
@ -91,7 +91,7 @@ function ProvisionDashboard() {
|
||||
}
|
||||
|
||||
const ResourceWidget = memo(({ resource, ...props }) => {
|
||||
const { data, isLoading } = useGetResourceQuery({ resource })
|
||||
const { data, isLoading } = useGetProvisionResourceQuery({ resource })
|
||||
const total = `${data?.length ?? 0}`
|
||||
|
||||
return (
|
||||
|
@ -13,22 +13,20 @@
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import * as yup from 'yup'
|
||||
import { string, boolean, object } from 'yup'
|
||||
|
||||
import { useAuth } from 'client/features/Auth'
|
||||
import { getValidationFromFields, arrayToOptions } from 'client/utils'
|
||||
import { Tr } from 'client/components/HOC'
|
||||
import { T, INPUT_TYPES, FILTER_POOL } from 'client/constants'
|
||||
import { T, INPUT_TYPES, FILTER_POOL, SERVER_CONFIG } from 'client/constants'
|
||||
|
||||
export const USERNAME = {
|
||||
const USERNAME = {
|
||||
name: 'user',
|
||||
label: T.Username,
|
||||
type: INPUT_TYPES.TEXT,
|
||||
validation: yup
|
||||
.string()
|
||||
validation: string()
|
||||
.trim()
|
||||
.required('Username is a required field')
|
||||
.required()
|
||||
.default(() => ''),
|
||||
grid: { md: 12 },
|
||||
fieldProps: {
|
||||
@ -39,14 +37,13 @@ export const USERNAME = {
|
||||
},
|
||||
}
|
||||
|
||||
export const PASSWORD = {
|
||||
const PASSWORD = {
|
||||
name: 'token',
|
||||
label: T.Password,
|
||||
type: INPUT_TYPES.PASSWORD,
|
||||
validation: yup
|
||||
.string()
|
||||
validation: string()
|
||||
.trim()
|
||||
.required('Password is a required field')
|
||||
.required()
|
||||
.default(() => ''),
|
||||
grid: { md: 12 },
|
||||
fieldProps: {
|
||||
@ -56,22 +53,21 @@ export const PASSWORD = {
|
||||
},
|
||||
}
|
||||
|
||||
export const REMEMBER = {
|
||||
const REMEMBER = {
|
||||
name: 'remember',
|
||||
label: T.KeepLoggedIn,
|
||||
type: INPUT_TYPES.CHECKBOX,
|
||||
validation: yup.boolean().default(() => false),
|
||||
validation: boolean().default(() => false),
|
||||
grid: { md: 12 },
|
||||
}
|
||||
|
||||
export const TOKEN = {
|
||||
const TOKEN = {
|
||||
name: 'token2fa',
|
||||
label: T.Token2FA,
|
||||
type: INPUT_TYPES.TEXT,
|
||||
validation: yup
|
||||
.string()
|
||||
validation: string()
|
||||
.trim()
|
||||
.required('Authenticator is a required field')
|
||||
.required()
|
||||
.default(() => ''),
|
||||
grid: { md: 12 },
|
||||
fieldProps: {
|
||||
@ -81,46 +77,57 @@ export const TOKEN = {
|
||||
},
|
||||
}
|
||||
|
||||
export const GROUP = {
|
||||
const GROUP = {
|
||||
name: 'group',
|
||||
label: T.SelectYourActiveGroup,
|
||||
type: INPUT_TYPES.SELECT,
|
||||
values: () => {
|
||||
const { user, groups } = useAuth()
|
||||
const primaryText = Tr(T.Primary)
|
||||
|
||||
const sortedGroupsById = groups?.sort((a, b) => a.ID - b.ID)
|
||||
|
||||
const formatGroups = arrayToOptions(sortedGroupsById, {
|
||||
const formatGroups = arrayToOptions(groups, {
|
||||
addEmpty: false,
|
||||
getText: ({ ID, NAME }) => {
|
||||
const isPrimary = user?.GID === ID ? `(${Tr(T.Primary)})` : ''
|
||||
const isPrimary = user?.GID === ID ? `(${primaryText})` : ''
|
||||
|
||||
return `${ID} - ${NAME} ${isPrimary}`
|
||||
},
|
||||
getValue: ({ ID }) => String(ID),
|
||||
sorter: (a, b) => a.ID - b.ID,
|
||||
})
|
||||
|
||||
return [{ text: T.ShowAll, value: FILTER_POOL.ALL_RESOURCES }].concat(
|
||||
formatGroups
|
||||
)
|
||||
},
|
||||
validation: yup.string().trim().nullable().default(FILTER_POOL.ALL_RESOURCES),
|
||||
validation: string().trim().nullable().default(FILTER_POOL.ALL_RESOURCES),
|
||||
grid: { md: 12 },
|
||||
fieldProps: {
|
||||
margin: 'normal',
|
||||
},
|
||||
}
|
||||
|
||||
export const FORM_USER_FIELDS = [USERNAME, PASSWORD, REMEMBER]
|
||||
export const FORM_2FA_FIELDS = [TOKEN]
|
||||
export const FORM_GROUP_FIELDS = [GROUP]
|
||||
const FORM_USER_FIELDS = [
|
||||
USERNAME,
|
||||
PASSWORD,
|
||||
`${SERVER_CONFIG?.keep_me_logged}` === 'true' && REMEMBER,
|
||||
].filter(Boolean)
|
||||
|
||||
export const FORM_USER_SCHEMA = yup.object(
|
||||
getValidationFromFields(FORM_USER_FIELDS)
|
||||
)
|
||||
export const FORM_2FA_SCHEMA = yup.object(
|
||||
getValidationFromFields(FORM_2FA_FIELDS)
|
||||
)
|
||||
export const FORM_GROUP_SCHEMA = yup.object(
|
||||
getValidationFromFields(FORM_GROUP_FIELDS)
|
||||
)
|
||||
const FORM_2FA_FIELDS = [TOKEN]
|
||||
|
||||
const FORM_GROUP_FIELDS = [GROUP]
|
||||
|
||||
const FORM_USER_SCHEMA = object(getValidationFromFields(FORM_USER_FIELDS))
|
||||
|
||||
const FORM_2FA_SCHEMA = object(getValidationFromFields(FORM_2FA_FIELDS))
|
||||
|
||||
const FORM_GROUP_SCHEMA = object(getValidationFromFields(FORM_GROUP_FIELDS))
|
||||
|
||||
export {
|
||||
FORM_USER_FIELDS,
|
||||
FORM_2FA_FIELDS,
|
||||
FORM_GROUP_FIELDS,
|
||||
FORM_USER_SCHEMA,
|
||||
FORM_2FA_SCHEMA,
|
||||
FORM_GROUP_SCHEMA,
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import { Trash as DeleteIcon } from 'iconoir-react'
|
||||
|
||||
import {
|
||||
useGetProvisionQuery,
|
||||
useGetResourceQuery,
|
||||
useGetProvisionResourceQuery,
|
||||
useRemoveResourceMutation,
|
||||
} from 'client/features/OneApi/provision'
|
||||
import { useGeneralApi } from 'client/features/General'
|
||||
@ -48,7 +48,7 @@ const Datastores = memo(
|
||||
disableRowSelect
|
||||
disableGlobalSort
|
||||
useQuery={() =>
|
||||
useGetResourceQuery(
|
||||
useGetProvisionResourceQuery(
|
||||
{ resource: 'datastore' },
|
||||
{
|
||||
selectFromResult: ({ data: result = [], ...rest }) => ({
|
||||
|
@ -29,7 +29,7 @@ import {
|
||||
useAddHostToProvisionMutation,
|
||||
useConfigureHostMutation,
|
||||
useRemoveResourceMutation,
|
||||
useGetResourceQuery,
|
||||
useGetProvisionResourceQuery,
|
||||
} from 'client/features/OneApi/provision'
|
||||
|
||||
import { HostsTable } from 'client/components/Tables'
|
||||
@ -87,7 +87,7 @@ const Hosts = memo(({ id }) => {
|
||||
disableRowSelect
|
||||
disableGlobalSort
|
||||
useQuery={() =>
|
||||
useGetResourceQuery(
|
||||
useGetProvisionResourceQuery(
|
||||
{ resource: 'host' },
|
||||
{
|
||||
selectFromResult: ({ data: result = [], ...rest }) => ({
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
useGetProvisionQuery,
|
||||
useAddIpToProvisionMutation,
|
||||
useRemoveResourceMutation,
|
||||
useGetResourceQuery,
|
||||
useGetProvisionResourceQuery,
|
||||
} from 'client/features/OneApi/provision'
|
||||
|
||||
import { VNetworksTable } from 'client/components/Tables'
|
||||
@ -79,7 +79,7 @@ const Networks = memo(({ id }) => {
|
||||
disableRowSelect
|
||||
disableGlobalSort
|
||||
useQuery={() =>
|
||||
useGetResourceQuery(
|
||||
useGetProvisionResourceQuery(
|
||||
{ resource: 'network' },
|
||||
{
|
||||
selectFromResult: ({ data: result = [], ...rest }) => ({
|
||||
|
@ -119,9 +119,9 @@ const provisionApi = oneApi.injectEndpoints({
|
||||
return { params: { id }, command }
|
||||
},
|
||||
}),
|
||||
getResource: builder.query({
|
||||
getProvisionResource: builder.query({
|
||||
/**
|
||||
* Delete the datastore from the provision.
|
||||
* List all resources from a provision.
|
||||
*
|
||||
* @param {object} params - Request parameters
|
||||
* @param {
|
||||
@ -307,8 +307,8 @@ export const {
|
||||
useLazyGetProvisionTemplatesQuery,
|
||||
useGetProvisionLogQuery,
|
||||
useLazyGetProvisionLogQuery,
|
||||
useGetResourceQuery,
|
||||
useLazyGetResourceQuery,
|
||||
useGetProvisionResourceQuery,
|
||||
useLazyGetProvisionResourceQuery,
|
||||
|
||||
// Mutations
|
||||
useCreateProvisionMutation,
|
||||
|
@ -57,22 +57,6 @@ const systemApi = oneApi.injectEndpoints({
|
||||
providesTags: [{ type: SYSTEM, id: 'config' }],
|
||||
keepUnusedDataFor: 600,
|
||||
}),
|
||||
getSunstoneConfig: builder.query({
|
||||
/**
|
||||
* Returns the Sunstone configuration.
|
||||
*
|
||||
* @returns {object} The loaded sunstone-server.conf file
|
||||
* @throws Fails when response isn't code 200
|
||||
*/
|
||||
query: () => {
|
||||
const name = SunstoneActions.SUNSTONE_CONFIG
|
||||
const command = { name, ...SunstoneCommands[name] }
|
||||
|
||||
return { command }
|
||||
},
|
||||
providesTags: [{ type: SYSTEM, id: 'sunstone-config' }],
|
||||
keepUnusedDataFor: 600,
|
||||
}),
|
||||
getSunstoneViews: builder.query({
|
||||
/**
|
||||
* Returns the Sunstone configuration for resource tabs.
|
||||
@ -106,8 +90,6 @@ export const {
|
||||
useLazyGetOneVersionQuery,
|
||||
useGetOneConfigQuery,
|
||||
useLazyGetOneConfigQuery,
|
||||
useGetSunstoneConfigQuery,
|
||||
useLazyGetSunstoneConfigQuery,
|
||||
useGetSunstoneViewsQuery,
|
||||
useLazyGetSunstoneViewsQuery,
|
||||
} = systemApi
|
||||
|
@ -265,19 +265,13 @@ const getEndpoint = () => {
|
||||
* @param {string} key - key get
|
||||
* @returns {string} value of config item
|
||||
*/
|
||||
const getSpecificConfig = (key = '') => {
|
||||
if (key) {
|
||||
const appConfig = getFireedgeConfig()
|
||||
const provisionConfig = getProvisionConfig()
|
||||
if (Object.hasOwnProperty.call(provisionConfig, key)) {
|
||||
return provisionConfig[key]
|
||||
}
|
||||
if (Object.hasOwnProperty.call(appConfig, key)) {
|
||||
return appConfig[key]
|
||||
}
|
||||
}
|
||||
const getSpecificConfig = (key) => {
|
||||
if (!key) return ''
|
||||
|
||||
return ''
|
||||
const provisionConfig = getProvisionConfig({ includeProtectedConfig: true })
|
||||
if (Object.hasOwnProperty.call(provisionConfig, key)) {
|
||||
return provisionConfig[key]
|
||||
}
|
||||
}
|
||||
|
||||
const functionRoutes = {
|
||||
|
@ -18,7 +18,6 @@ const { parse } = require('yaml')
|
||||
const { getSunstoneConfig } = require('server/utils/yml')
|
||||
const { defaults, httpCodes } = require('server/utils/constants')
|
||||
const { existsFile, httpResponse, getFiles } = require('server/utils/server')
|
||||
const { sensitiveDataRemoverConfig } = require('server/utils/opennebula')
|
||||
const { Actions: ActionsUser } = require('server/utils/constants/commands/user')
|
||||
const {
|
||||
Actions: ActionsGroup,
|
||||
@ -26,7 +25,6 @@ const {
|
||||
|
||||
const { defaultEmptyFunction } = defaults
|
||||
const { ok, internalServerError, notFound } = httpCodes
|
||||
const sensitiveData = ['support_url', 'support_token']
|
||||
const httpInternalError = httpResponse(internalServerError, '', '')
|
||||
|
||||
/**
|
||||
@ -165,15 +163,15 @@ const getConfig = (
|
||||
userData = {}
|
||||
) => {
|
||||
let error
|
||||
const config = getSunstoneConfig((err) => {
|
||||
error = err
|
||||
|
||||
const config = getSunstoneConfig({
|
||||
onError: (err) => (error = err),
|
||||
})
|
||||
|
||||
responseHttp(
|
||||
res,
|
||||
next,
|
||||
error
|
||||
? httpResponse(notFound, error)
|
||||
: httpResponse(ok, sensitiveDataRemoverConfig(config, sensitiveData))
|
||||
error ? httpResponse(notFound, error) : httpResponse(ok, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ const { createStore, compose, applyMiddleware } = require('redux')
|
||||
const thunk = require('redux-thunk').default
|
||||
const { ServerStyleSheets } = require('@mui/styles')
|
||||
|
||||
// server side constants (not all of them are used in client)
|
||||
const { getFireedgeConfig } = require('server/utils/yml')
|
||||
// server
|
||||
const { getSunstoneConfig, getProvisionConfig } = require('server/utils/yml')
|
||||
const { defaultApps } = require('server/utils/constants/defaults')
|
||||
|
||||
// client
|
||||
@ -31,18 +31,12 @@ const rootReducer = require('client/store/reducers')
|
||||
const { upperCaseFirst } = require('client/utils')
|
||||
const { APP_URL, STATIC_FILES_URL } = require('client/constants')
|
||||
|
||||
const ALLOWED_KEYS_FROM_CONFIG = ['currency', 'default_lang', 'langs']
|
||||
const APP_NAMES = Object.keys(defaultApps)
|
||||
|
||||
const ensuredConfig = Object.entries(getFireedgeConfig()).reduce(
|
||||
(config, [key, value]) => {
|
||||
if (ALLOWED_KEYS_FROM_CONFIG.includes(key)) {
|
||||
config[key] = value
|
||||
}
|
||||
|
||||
return config
|
||||
},
|
||||
{}
|
||||
)
|
||||
const APP_CONFIG = {
|
||||
[defaultApps.provision.name]: getProvisionConfig() || {},
|
||||
[defaultApps.sunstone.name]: getSunstoneConfig() || {},
|
||||
}
|
||||
|
||||
const ensuredScriptValue = (value) =>
|
||||
JSON.stringify(value).replace(/</g, '\\u003c')
|
||||
@ -50,11 +44,10 @@ const ensuredScriptValue = (value) =>
|
||||
const router = Router()
|
||||
|
||||
router.get('*', (req, res) => {
|
||||
const apps = Object.keys(defaultApps)
|
||||
const appName = parse(req.url)
|
||||
.pathname.split(/\//gi)
|
||||
.filter((sub) => sub?.length > 0)
|
||||
.find((resource) => apps.includes(resource))
|
||||
.find((resource) => APP_NAMES.includes(resource))
|
||||
|
||||
const sheets = new ServerStyleSheets()
|
||||
const composeEnhancer =
|
||||
@ -66,16 +59,22 @@ router.get('*', (req, res) => {
|
||||
composeEnhancer(applyMiddleware(thunk))
|
||||
)
|
||||
|
||||
const storeRender = `<script id="preloadState">window.__PRELOADED_STATE__ = ${ensuredScriptValue(
|
||||
store.getState()
|
||||
)}</script>`
|
||||
|
||||
const App = require(`../../../client/apps/${appName}/index.js`).default
|
||||
|
||||
const rootComponent = renderToString(
|
||||
sheets.collect(<App location={req.url} store={store} />)
|
||||
)
|
||||
|
||||
const config = `
|
||||
<script id="preload-server-side">
|
||||
window.__PRELOADED_CONFIG__ = ${ensuredScriptValue(APP_CONFIG[appName])}
|
||||
</script>`
|
||||
|
||||
const storeRender = `
|
||||
<script id="preloadState">
|
||||
window.__PRELOADED_STATE__ = ${ensuredScriptValue(store.getState())}
|
||||
</script>`
|
||||
|
||||
const css = `<style id="jss-server-side">${sheets.toString()}</style>`
|
||||
|
||||
const html = `
|
||||
@ -95,9 +94,7 @@ router.get('*', (req, res) => {
|
||||
<body>
|
||||
<div id="root">${rootComponent}</div>
|
||||
${storeRender}
|
||||
<script id="preload-server-side">
|
||||
${`window.__PRELOADED_CONFIG__ = ${ensuredScriptValue(ensuredConfig)}`}
|
||||
</script>
|
||||
${config}
|
||||
<script src='${APP_URL}/client/bundle.${appName}.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -122,11 +122,7 @@ const defaults = {
|
||||
defaultHideCredentials: true,
|
||||
defaultHideCredentialReplacer: '****',
|
||||
defaultOneFlowServer: `${protocol}://${defaultIp}:2474`,
|
||||
defaultConfigFile: `${appName}-server.conf`,
|
||||
defaultSunstonePath: internalSunstonePath,
|
||||
defaultSunstoneViews: `${appNameSunstone}-views.yaml`,
|
||||
defaultSunstoneConfig: `${appNameSunstone}-server.conf`,
|
||||
defaultProvisionConfig: `${appNameProvision}-server.conf`,
|
||||
defaultProvisionPath: internalProvisionPath,
|
||||
defaultProvidersConfigPath: 'providers.d',
|
||||
defaultTypeLog: 'prod',
|
||||
@ -163,6 +159,26 @@ const defaults = {
|
||||
defaultHost: '0.0.0.0',
|
||||
defaultPort: 2616,
|
||||
defaultEvents: ['SIGINT', 'SIGTERM'],
|
||||
|
||||
/** CONFIGURATION FILE */
|
||||
defaultConfigFile: `${appName}-server.conf`,
|
||||
defaultSunstoneViews: `${appNameSunstone}-views.yaml`,
|
||||
defaultSunstoneConfig: `${appNameSunstone}-server.conf`,
|
||||
defaultProvisionConfig: `${appNameProvision}-server.conf`,
|
||||
protectedConfigData: {
|
||||
[appNameSunstone]: [
|
||||
'support_url',
|
||||
'support_token',
|
||||
'vcenter_prepend_command',
|
||||
'sunstone_prepend',
|
||||
'guacd',
|
||||
'tmpdir',
|
||||
],
|
||||
[appNameProvision]: [
|
||||
'oneprovision_prepend_command',
|
||||
'oneprovision_optional_create_command',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = defaults
|
||||
|
@ -511,26 +511,6 @@ const CSVtoArray = (text = '') => {
|
||||
return rtn
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove config sensitive data.
|
||||
*
|
||||
* @param {object} config - config data
|
||||
* @param {Array} keys - key for remove
|
||||
* @returns {object} config without sensitive data
|
||||
*/
|
||||
const sensitiveDataRemoverConfig = (config = {}, keys = []) => {
|
||||
const rtn = config
|
||||
if (Array.isArray(keys)) {
|
||||
keys.forEach((key) => {
|
||||
if (Object.hasOwnProperty.call(config, key)) {
|
||||
delete rtn[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
opennebulaConnect,
|
||||
responseOpennebula,
|
||||
@ -543,5 +523,4 @@ module.exports = {
|
||||
fillResourceforHookConnection,
|
||||
consoleParseToString,
|
||||
consoleParseToJSON,
|
||||
sensitiveDataRemoverConfig,
|
||||
}
|
||||
|
@ -16,12 +16,15 @@
|
||||
|
||||
const { env } = require('process')
|
||||
const { resolve } = require('path')
|
||||
const { parse } = require('yaml')
|
||||
const { parse: yamlToJson } = require('yaml')
|
||||
const {
|
||||
defaultConfigFile,
|
||||
defaultWebpackMode,
|
||||
defaultSunstoneConfig,
|
||||
defaultProvisionConfig,
|
||||
protectedConfigData,
|
||||
defaultAppName,
|
||||
defaultApps,
|
||||
defaultEmptyFunction,
|
||||
} = require('./constants/defaults')
|
||||
const { existsFile, defaultError } = require('server/utils/server')
|
||||
@ -30,81 +33,118 @@ const { global } = require('window-or-global')
|
||||
|
||||
const defaultPath =
|
||||
env && env.NODE_ENV === defaultWebpackMode ? ['../', '../', '../'] : ['../']
|
||||
|
||||
const basePaths = [__dirname, ...defaultPath, 'etc']
|
||||
|
||||
const getConfigPathByApp = (app) =>
|
||||
({
|
||||
[defaultAppName]:
|
||||
global?.paths?.FIREEDGE_CONFIG ||
|
||||
resolve(...basePaths, defaultConfigFile),
|
||||
[defaultApps.sunstone.name]:
|
||||
global?.paths?.SUNSTONE_CONFIG ||
|
||||
resolve(...basePaths, 'sunstone', defaultSunstoneConfig),
|
||||
[defaultApps.provision.name]:
|
||||
global?.paths?.PROVISION_CONFIG ||
|
||||
resolve(...basePaths, 'provision', defaultProvisionConfig),
|
||||
}[app])
|
||||
|
||||
const getProtectedKeysByApp = (app) => protectedConfigData[app] || []
|
||||
|
||||
/**
|
||||
* Get fireedge configurations.
|
||||
*
|
||||
* @param {string} pathfile - path config file
|
||||
* @param {Function} errorFunction - callback error
|
||||
* @param {string} filePath - path config file
|
||||
* @param {Function} onError - callback error
|
||||
* @returns {object} fireedge configurations
|
||||
*/
|
||||
const readYAMLFile = (pathfile = '', errorFunction = defaultEmptyFunction) => {
|
||||
const readYAMLFile = (filePath = '', onError = defaultEmptyFunction) => {
|
||||
let rtn = {}
|
||||
const err = (error) => {
|
||||
|
||||
const errorFunction = (error) => {
|
||||
messageTerminal(defaultError(error))
|
||||
if (typeof errorFunction === 'function') {
|
||||
errorFunction(error)
|
||||
onError === 'function' && onError(error)
|
||||
}
|
||||
|
||||
const successFunction = (data) => {
|
||||
try {
|
||||
rtn = yamlToJson(data)
|
||||
} catch (error) {
|
||||
errorFunction(error?.message)
|
||||
}
|
||||
}
|
||||
if (pathfile) {
|
||||
existsFile(
|
||||
pathfile,
|
||||
(filedata) => {
|
||||
try {
|
||||
rtn = parse(filedata)
|
||||
} catch (error) {
|
||||
err(error && error.message)
|
||||
}
|
||||
},
|
||||
err
|
||||
)
|
||||
}
|
||||
|
||||
filePath && existsFile(filePath, successFunction, errorFunction)
|
||||
|
||||
return rtn
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fireedge configurations.
|
||||
* Filter configuration by list of keys.
|
||||
*
|
||||
* @param {Function} callbackError - callback error
|
||||
* @returns {object} fireedge configurations
|
||||
* @param {object} config - Config to filter
|
||||
* @param {Array} [keys] - List of keys to filter
|
||||
* @returns {object} Filtered object
|
||||
*/
|
||||
const getFireedgeConfig = (callbackError = defaultEmptyFunction) => {
|
||||
const pathfile =
|
||||
(global && global.paths && global.paths.FIREEDGE_CONFIG) ||
|
||||
resolve(...basePaths, defaultConfigFile)
|
||||
const filterByProtectedKeys = (config = {}, keys = []) => {
|
||||
const entries = Object.entries(config)
|
||||
const filteredEntries = entries.filter(([key]) => !keys.includes(key))
|
||||
|
||||
return readYAMLFile(pathfile, callbackError)
|
||||
return Object.fromEntries(filteredEntries)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sunstone configurations.
|
||||
*
|
||||
* @param {Function} callbackError - callback error
|
||||
* @returns {object} sunstone configurations
|
||||
* @typedef GetConfigurationOptions
|
||||
* @property {function(string)} [onError] - Function to be called when an error
|
||||
* @property {boolean} [includeProtectedConfig] - Include protected config
|
||||
*/
|
||||
const getSunstoneConfig = (callbackError = defaultEmptyFunction) => {
|
||||
const pathfile =
|
||||
(global && global.paths && global.paths.SUNSTONE_CONFIG) ||
|
||||
resolve(...basePaths, 'sunstone', defaultSunstoneConfig)
|
||||
|
||||
return readYAMLFile(pathfile, callbackError)
|
||||
/**
|
||||
* Get configuration by app name.
|
||||
*
|
||||
* @param {string} [app] - App name. Default: fireedge
|
||||
* @param {GetConfigurationOptions} options - Options
|
||||
* @returns {object} Configuration
|
||||
*/
|
||||
const getConfiguration = (
|
||||
app = defaultAppName,
|
||||
{ onError = defaultEmptyFunction, includeProtectedConfig = false } = {}
|
||||
) => {
|
||||
const config = readYAMLFile(getConfigPathByApp(app), onError)
|
||||
|
||||
if (config && includeProtectedConfig) {
|
||||
return filterByProtectedKeys(config, getProtectedKeysByApp(app))
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* Get provision configurations.
|
||||
* Get FireEdge configuration.
|
||||
*
|
||||
* @param {Function} callbackError - callback error
|
||||
* @returns {object} provision configurations
|
||||
* @param {GetConfigurationOptions} [options] - Options
|
||||
* @returns {object} FireEdge configuration
|
||||
*/
|
||||
const getProvisionConfig = (callbackError = defaultEmptyFunction) => {
|
||||
const pathfile =
|
||||
(global && global.paths && global.paths.PROVISION_CONFIG) ||
|
||||
resolve(...basePaths, 'provision', defaultProvisionConfig)
|
||||
const getFireedgeConfig = (options) =>
|
||||
getConfiguration(defaultAppName, { includeProtectedConfig: true, ...options })
|
||||
|
||||
return readYAMLFile(pathfile, callbackError)
|
||||
}
|
||||
/**
|
||||
* Get Sunstone configuration.
|
||||
*
|
||||
* @param {GetConfigurationOptions} [options] - Options
|
||||
* @returns {object} Sunstone configuration
|
||||
*/
|
||||
const getSunstoneConfig = (options) =>
|
||||
getConfiguration(defaultApps.sunstone.name, options)
|
||||
|
||||
/**
|
||||
* Get Provision configuration.
|
||||
*
|
||||
* @param {GetConfigurationOptions} [options] - Options
|
||||
* @returns {object} Provision configuration
|
||||
*/
|
||||
const getProvisionConfig = (options) =>
|
||||
getConfiguration(defaultApps.provision.name, options)
|
||||
|
||||
module.exports = {
|
||||
getFireedgeConfig,
|
||||
|
Loading…
x
Reference in New Issue
Block a user