Parcourir la source

Merge pull request #697 from smiclea/refector-plugin

Refactor plugin system static classes
Nashwan Azhari il y a 4 ans
Parent
commit
d1110f5e7a

+ 8 - 47
src/plugins/aws/OptionsSchemaPlugin.ts

@@ -12,30 +12,23 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import type { InstanceScript } from '@src/@types/Instance'
 import { Field } from '@src/@types/Field'
-import type { OptionValues, StorageMap } from '@src/@types/Endpoint'
+import type { OptionValues } from '@src/@types/Endpoint'
 import type { SchemaProperties, SchemaDefinitions } from '@src/@types/Schema'
-import type { NetworkMap } from '@src/@types/Network'
-import { UserScriptData } from '@src/@types/MainItem'
-import DefaultOptionsSchemaPlugin, {
-  defaultGetDestinationEnv,
-  defaultGetMigrationImageMap,
+import OptionsSchemaPluginBase, {
   defaultFillFieldValues,
   defaultFillMigrationImageMapValues,
   removeExportImageFieldValues,
 } from '../default/OptionsSchemaPlugin'
 
-export default class OptionsSchemaParser {
-  static migrationImageMapFieldName = DefaultOptionsSchemaPlugin.migrationImageMapFieldName
-
-  static parseSchemaToFields(opts: {
+export default class OptionsSchemaParser extends OptionsSchemaPluginBase {
+  override parseSchemaToFields(opts: {
     schema: SchemaProperties,
     schemaDefinitions?: SchemaDefinitions | null | undefined,
     dictionaryKey?: string,
     requiresWindowsImage?: boolean,
   }) {
-    const fields: Field[] = DefaultOptionsSchemaPlugin.parseSchemaToFields(opts)
+    const fields: Field[] = super.parseSchemaToFields(opts)
     const exportImage = fields.find(f => f.name === 'export_image')
     if (exportImage) {
       exportImage.required = true
@@ -43,8 +36,8 @@ export default class OptionsSchemaParser {
     return fields
   }
 
-  static sortFields(fields: Field[]) {
-    DefaultOptionsSchemaPlugin.sortFields(fields)
+  override sortFields(fields: Field[]) {
+    super.sortFields(fields)
     fields.sort((f1, f2) => {
       // sort region first
       if (f1.name === 'region') {
@@ -57,7 +50,7 @@ export default class OptionsSchemaParser {
     })
   }
 
-  static fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
+  override fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
     const { field, options, requiresWindowsImage } = opts
     const option = options.find(f => f.name === field.name)
     if (!option) {
@@ -73,36 +66,4 @@ export default class OptionsSchemaParser {
       removeExportImageFieldValues(field)
     }
   }
-
-  static getDestinationEnv(options: { [prop: string]: any } | null, oldOptions?: any) {
-    const env = {
-      ...defaultGetDestinationEnv(options, oldOptions),
-      ...defaultGetMigrationImageMap(
-        options,
-        oldOptions,
-        this.migrationImageMapFieldName,
-      ),
-    }
-    return env
-  }
-
-  static getNetworkMap(networkMappings: NetworkMap[] | null) {
-    return DefaultOptionsSchemaPlugin.getNetworkMap(networkMappings)
-  }
-
-  static getStorageMap(
-    defaultStorage: { value: string | null, busType?: string | null },
-    storageMap: StorageMap[] | null,
-    configDefault?: string | null,
-  ) {
-    return DefaultOptionsSchemaPlugin.getStorageMap(defaultStorage, storageMap, configDefault)
-  }
-
-  static getUserScripts(
-    uploadedUserScripts: InstanceScript[],
-    removedUserScripts: InstanceScript[],
-    userScriptData: UserScriptData | null | undefined,
-  ) {
-    return DefaultOptionsSchemaPlugin.getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
-  }
 }

+ 4 - 9
src/plugins/azure/ConnectionSchemaPlugin.ts

@@ -12,8 +12,7 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import { Endpoint } from '@src/@types/Endpoint'
-import {
+import ConnectionSchemaParserBase, {
   connectionSchemaToFields,
   defaultSchemaToFields,
   fieldsToPayload,
@@ -88,8 +87,8 @@ const azureConnectionParse = (
   return [radioGroup, cloudProfileDropdown]
 }
 
-export default class ConnectionSchemaParser {
-  static parseSchemaToFields(schema: any) {
+export default class ConnectionSchemaParser extends ConnectionSchemaParserBase {
+  override parseSchemaToFields(schema: any) {
     let fields = azureConnectionParse(schema)
 
     fields = [
@@ -100,7 +99,7 @@ export default class ConnectionSchemaParser {
     return fields
   }
 
-  static parseConnectionInfoToPayload(data: any, schema: any) {
+  override parseConnectionInfoToPayload(data: any, schema: any) {
     const connectionInfo: any = fieldsToPayload(data, schema)
     const loginType = data.login_type || 'user_credentials'
     connectionInfo[loginType] = fieldsToPayload(data, schema.properties[loginType])
@@ -132,8 +131,4 @@ export default class ConnectionSchemaParser {
 
     return connectionInfo
   }
-
-  static parseConnectionResponse(endpoint: Endpoint) {
-    return endpoint
-  }
 }

+ 4 - 68
src/plugins/azure/OptionsSchemaPlugin.ts

@@ -12,23 +12,11 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import type { InstanceScript } from '@src/@types/Instance'
-import type { Field } from '@src/@types/Field'
-import type { OptionValues, StorageMap } from '@src/@types/Endpoint'
 import type { SchemaProperties, SchemaDefinitions } from '@src/@types/Schema'
-import type { NetworkMap } from '@src/@types/Network'
-import { UserScriptData } from '@src/@types/MainItem'
-import DefaultOptionsSchemaPlugin, {
-  defaultFillMigrationImageMapValues,
-  defaultFillFieldValues,
-  defaultGetDestinationEnv,
-  defaultGetMigrationImageMap,
-} from '../default/OptionsSchemaPlugin'
+import OptionsSchemaParserBase from '../default/OptionsSchemaPlugin'
 
-export default class OptionsSchemaParser {
-  static migrationImageMapFieldName = DefaultOptionsSchemaPlugin.migrationImageMapFieldName
-
-  static parseSchemaToFields(opts: {
+export default class OptionsSchemaParser extends OptionsSchemaParserBase {
+  override parseSchemaToFields(opts: {
     schema: SchemaProperties,
     schemaDefinitions?: SchemaDefinitions | null | undefined,
     dictionaryKey?: string,
@@ -38,58 +26,6 @@ export default class OptionsSchemaParser {
     if (schemaDefinitions?.azure_image?.required) {
       schemaDefinitions.azure_image.required = []
     }
-    return DefaultOptionsSchemaPlugin.parseSchemaToFields(opts)
-  }
-
-  static sortFields(fields: Field[]) {
-    DefaultOptionsSchemaPlugin.sortFields(fields)
-  }
-
-  static fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
-    const { field, options, requiresWindowsImage } = opts
-    const option = options.find(f => f.name === field.name)
-    if (!option) {
-      return
-    }
-    if (!defaultFillMigrationImageMapValues({
-      field,
-      option,
-      migrationImageMapFieldName: DefaultOptionsSchemaPlugin.migrationImageMapFieldName,
-      requiresWindowsImage,
-    })) {
-      defaultFillFieldValues(field, option)
-    }
-  }
-
-  static getDestinationEnv(options: { [prop: string]: any } | null, oldOptions?: any) {
-    const env = {
-      ...defaultGetDestinationEnv(options, oldOptions),
-      ...defaultGetMigrationImageMap(
-        options,
-        oldOptions,
-        DefaultOptionsSchemaPlugin.migrationImageMapFieldName,
-      ),
-    }
-    return env
-  }
-
-  static getNetworkMap(networkMappings: NetworkMap[] | null | undefined) {
-    return DefaultOptionsSchemaPlugin.getNetworkMap(networkMappings)
-  }
-
-  static getStorageMap(
-    defaultStorage: { value: string | null, busType?: string | null },
-    storageMap: StorageMap[] | null,
-    configDefault?: string | null,
-  ) {
-    return DefaultOptionsSchemaPlugin.getStorageMap(defaultStorage, storageMap, configDefault)
-  }
-
-  static getUserScripts(
-    uploadedUserScripts: InstanceScript[],
-    removedUserScripts: InstanceScript[],
-    userScriptData: UserScriptData | null | undefined,
-  ) {
-    return DefaultOptionsSchemaPlugin.getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
+    return super.parseSchemaToFields(opts)
   }
 }

+ 6 - 4
src/plugins/default/ConnectionSchemaPlugin.ts

@@ -143,8 +143,8 @@ export const fieldsToPayload = (data: { [prop: string]: any }, schema: SchemaPro
   return info
 }
 
-export default class ConnectionSchemaParser {
-  static parseSchemaToFields(schema: Schema): Field[] {
+class ConnectionSchemaParserBase {
+  parseSchemaToFields(schema: Schema): Field[] {
     let fields = connectionSchemaToFields(schema.oneOf[0])
 
     fields = [
@@ -155,7 +155,7 @@ export default class ConnectionSchemaParser {
     return fields
   }
 
-  static parseConnectionInfoToPayload(data: { [prop: string]: any }, schema: any) {
+  parseConnectionInfoToPayload(data: { [prop: string]: any }, schema: any) {
     const schemaRoot = schema.oneOf ? schema.oneOf[0] : schema
     const connectionInfo = fieldsToPayload(data, schemaRoot)
 
@@ -167,7 +167,9 @@ export default class ConnectionSchemaParser {
     return connectionInfo
   }
 
-  static parseConnectionResponse(endpoint: Endpoint) {
+  parseConnectionResponse(endpoint: Endpoint) {
     return endpoint
   }
 }
+
+export default ConnectionSchemaParserBase

+ 2 - 2
src/plugins/default/InstanceInfoPlugin.ts

@@ -14,8 +14,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import type { Instance } from '@src/@types/Instance'
 
-export default class InstanceInfoPlugin {
-  static parseInstance(instance: Instance): Instance {
+export default class InstanceInfoPluginBase {
+  parseInstance(instance: Instance): Instance {
     return instance
   }
 }

+ 4 - 4
src/plugins/default/MinionPoolSchemaPlugin.ts

@@ -1,8 +1,8 @@
 import { Field } from '@src/@types/Field'
 import DomUtils from '@src/utils/DomUtils'
 
-export default class MinionPoolSchemaPlugin {
-  static getMinionPoolToOptionsQuery(envData?: any) {
+export default class MinionPoolSchemaPluginBase {
+  getMinionPoolToOptionsQuery(envData?: any) {
     let envString = ''
     if (envData) {
       envString = `?env=${DomUtils.encodeToBase64Url(envData)}`
@@ -10,11 +10,11 @@ export default class MinionPoolSchemaPlugin {
     return envString
   }
 
-  static minionPoolTransformOptionsFields(fields: Field[]) {
+  minionPoolTransformOptionsFields(fields: Field[]) {
     return fields
   }
 
-  static getMinionPoolEnv(schema: Field[], data: any) {
+  getMinionPoolEnv(schema: Field[], data: any) {
     const payload: any = {}
     schema.forEach(field => {
       if (data[field.name] === null || data[field.name] === undefined || data[field.name] === '') {

+ 9 - 9
src/plugins/default/OptionsSchemaPlugin.ts

@@ -179,10 +179,10 @@ export const defaultGetMigrationImageMap = (
   return env
 }
 
-export default class OptionsSchemaParser {
-  static migrationImageMapFieldName = 'migr_image_map'
+export default class OptionsSchemaParserBase {
+  migrationImageMapFieldName = 'migr_image_map'
 
-  static parseSchemaToFields(opts: {
+  parseSchemaToFields(opts: {
     schema: SchemaProperties,
     schemaDefinitions?: SchemaDefinitions | null,
     dictionaryKey?: string,
@@ -194,7 +194,7 @@ export default class OptionsSchemaParser {
     return defaultSchemaToFields(schema, schemaDefinitions, dictionaryKey)
   }
 
-  static sortFields(fields: Field[]) {
+  sortFields(fields: Field[]) {
     fields.sort((a, b) => {
       if (a.required && !b.required) {
         return -1
@@ -208,7 +208,7 @@ export default class OptionsSchemaParser {
     })
   }
 
-  static fillFieldValues(opts: {
+  fillFieldValues(opts: {
     field: Field,
     options: OptionValues[],
     requiresWindowsImage: boolean,
@@ -232,7 +232,7 @@ export default class OptionsSchemaParser {
     }
   }
 
-  static getDestinationEnv(options?: { [prop: string]: any } | null, oldOptions?: any) {
+  getDestinationEnv(options?: { [prop: string]: any } | null, oldOptions?: any) {
     const env = {
       ...defaultGetDestinationEnv(
         options,
@@ -247,7 +247,7 @@ export default class OptionsSchemaParser {
     return env
   }
 
-  static getNetworkMap(networkMappings: NetworkMap[] | null | undefined) {
+  getNetworkMap(networkMappings: NetworkMap[] | null | undefined) {
     const payload: any = {}
     if (!networkMappings?.length) {
       return payload
@@ -270,7 +270,7 @@ export default class OptionsSchemaParser {
     return payload
   }
 
-  static getStorageMap(
+  getStorageMap(
     defaultStorage: { value: string | null, busType?: string | null } | undefined,
     storageMap?: StorageMap[] | null,
     configDefault?: string | null,
@@ -325,7 +325,7 @@ export default class OptionsSchemaParser {
     return payload
   }
 
-  static getUserScripts(
+  getUserScripts(
     uploadedUserScripts: InstanceScript[],
     removedUserScripts: InstanceScript[],
     userScriptData: UserScriptData | null | undefined,

+ 16 - 16
src/plugins/index.ts

@@ -42,11 +42,11 @@ const hasKey = <O>(obj: O, key: keyof any): key is keyof O => key in obj
 export const ConnectionSchemaPlugin = {
   for: (provider: ProviderTypes) => {
     const map = {
-      default: DefaultConnectionSchemaPlugin,
-      azure: AzureConnectionSchemaPlugin,
-      openstack: OpenstackConnectionSchemaPlugin,
-      oci: OciConnectionSchemaPlugin,
-      kubevirt: KubevirtConnectionSchemaPlugin,
+      default: new DefaultConnectionSchemaPlugin(),
+      azure: new AzureConnectionSchemaPlugin(),
+      openstack: new OpenstackConnectionSchemaPlugin(),
+      oci: new OciConnectionSchemaPlugin(),
+      kubevirt: new KubevirtConnectionSchemaPlugin(),
     }
     if (hasKey(map, provider)) {
       return map[provider]
@@ -58,13 +58,13 @@ export const ConnectionSchemaPlugin = {
 export const OptionsSchemaPlugin = {
   for: (provider: ProviderTypes) => {
     const map = {
-      default: DefaultOptionsSchemaPlugin,
-      aws: AwsOptionsSchemaPlugin,
-      oracle_vm: OvmOptionsSchemaPlugin,
-      openstack: OpenstackOptionsSchemaPlugin,
-      vmware_vsphere: VmwareOptionsSchemaPlugin,
-      ovirt: OvirtOptionsSchemaPlugin,
-      azure: AzureOptionsSchemaPlugin,
+      default: new DefaultOptionsSchemaPlugin(),
+      aws: new AwsOptionsSchemaPlugin(),
+      oracle_vm: new OvmOptionsSchemaPlugin(),
+      openstack: new OpenstackOptionsSchemaPlugin(),
+      vmware_vsphere: new VmwareOptionsSchemaPlugin(),
+      ovirt: new OvirtOptionsSchemaPlugin(),
+      azure: new AzureOptionsSchemaPlugin(),
     }
     if (hasKey(map, provider)) {
       return map[provider]
@@ -90,8 +90,8 @@ export const ContentPlugin = {
 export const InstanceInfoPlugin = {
   for: (provider: ProviderTypes) => {
     const map = {
-      default: DefaultInstanceInfoPlugin,
-      oci: OciInstanceInfoPlugin,
+      default: new DefaultInstanceInfoPlugin(),
+      oci: new OciInstanceInfoPlugin(),
     }
     if (hasKey(map, provider)) {
       return map[provider]
@@ -103,8 +103,8 @@ export const InstanceInfoPlugin = {
 export const MinionPoolSchemaPlugin = {
   for: (provider: ProviderTypes) => {
     const map = {
-      default: DefaultMinionPoolSchemaPlugin,
-      openstack: OpenstackMinionPoolSchemaPlugin,
+      default: new DefaultMinionPoolSchemaPlugin(),
+      openstack: new OpenstackMinionPoolSchemaPlugin(),
     }
     if (hasKey(map, provider)) {
       return map[provider]

+ 4 - 14
src/plugins/kubevirt/ConnectionSchemaPlugin.ts

@@ -15,12 +15,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import type { Schema } from '@src/@types/Schema'
 import type { Field } from '@src/@types/Field'
 
-import DefaultConnectionSchemaParser from '@src/plugins/default/ConnectionSchemaPlugin'
-import { Endpoint } from '@src/@types/Endpoint'
+import ConnectionSchemaParserBase from '@src/plugins/default/ConnectionSchemaPlugin'
 
-export default class ConnectionSchemaParser {
-  static parseSchemaToFields(schema: Schema): Field[] {
-    const fields = DefaultConnectionSchemaParser.parseSchemaToFields(schema)
+export default class ConnectionSchemaParser extends ConnectionSchemaParserBase {
+  override parseSchemaToFields(schema: Schema): Field[] {
+    const fields = super.parseSchemaToFields(schema)
     const kubeConfigField = fields.find(f => f.name === 'kube_config')
     if (kubeConfigField) {
       kubeConfigField.useFile = true
@@ -28,13 +27,4 @@ export default class ConnectionSchemaParser {
 
     return fields
   }
-
-  static parseConnectionInfoToPayload(data: { [prop: string]: any }, schema: Schema) {
-    const payload = DefaultConnectionSchemaParser.parseConnectionInfoToPayload(data, schema)
-    return payload
-  }
-
-  static parseConnectionResponse(endpoint: Endpoint) {
-    return endpoint
-  }
 }

+ 4 - 14
src/plugins/oci/ConnectionSchemaPlugin.ts

@@ -15,12 +15,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import type { Schema } from '@src/@types/Schema'
 import type { Field } from '@src/@types/Field'
 
-import DefaultConnectionSchemaParser from '@src/plugins/default/ConnectionSchemaPlugin'
-import { Endpoint } from '@src/@types/Endpoint'
+import ConnectionSchemaParserBase from '@src/plugins/default/ConnectionSchemaPlugin'
 
-export default class ConnectionSchemaParser {
-  static parseSchemaToFields(schema: Schema): Field[] {
-    const fields = DefaultConnectionSchemaParser.parseSchemaToFields(schema)
+export default class ConnectionSchemaParser extends ConnectionSchemaParserBase {
+  override parseSchemaToFields(schema: Schema): Field[] {
+    const fields = super.parseSchemaToFields(schema)
     const privateKeyField = fields.find(f => f.name === 'private_key_data')
     if (privateKeyField) {
       privateKeyField.useTextArea = true
@@ -28,13 +27,4 @@ export default class ConnectionSchemaParser {
 
     return fields
   }
-
-  static parseConnectionInfoToPayload(data: { [prop: string]: any }, schema: Schema) {
-    const payload = DefaultConnectionSchemaParser.parseConnectionInfoToPayload(data, schema)
-    return payload
-  }
-
-  static parseConnectionResponse(endpoint: Endpoint) {
-    return endpoint
-  }
 }

+ 3 - 2
src/plugins/oci/InstanceInfoPlugin.ts

@@ -13,9 +13,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 import type { Instance } from '@src/@types/Instance'
+import InstanceInfoPluginBase from '@src/plugins/default/InstanceInfoPlugin'
 
-export default class InstanceInfoPlugin {
-  static parseInstance(instance: Instance): Instance {
+export default class InstanceInfoPlugin extends InstanceInfoPluginBase {
+  override parseInstance(instance: Instance): Instance {
     const rootDisk = instance.devices.disks[0]
     if (rootDisk) {
       rootDisk.disabled = {

+ 7 - 8
src/plugins/openstack/ConnectionSchemaPlugin.ts

@@ -15,8 +15,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import type { Schema } from '@src/@types/Schema'
 import type { Field } from '@src/@types/Field'
 import type { Endpoint } from '@src/@types/Endpoint'
-
-import DefaultConnectionSchemaParser from '@src/plugins/default/ConnectionSchemaPlugin'
+import ConnectionSchemaParserBase from '@src/plugins/default/ConnectionSchemaPlugin'
 
 const customSort = (fields: Field[]) => {
   const sortPriority: any = {
@@ -48,9 +47,9 @@ const customSort = (fields: Field[]) => {
   return fields
 }
 
-export default class ConnectionSchemaParser {
-  static parseSchemaToFields(schema: Schema): Field[] {
-    const fields = DefaultConnectionSchemaParser.parseSchemaToFields(schema)
+export default class ConnectionSchemaParser extends ConnectionSchemaParserBase {
+  override parseSchemaToFields(schema: Schema): Field[] {
+    const fields = super.parseSchemaToFields(schema)
     const identityField = fields.find(f => f.name === 'identity_api_version')
     if (identityField && !identityField.default) {
       identityField.default = identityField.minimum
@@ -83,7 +82,7 @@ export default class ConnectionSchemaParser {
     return fields
   }
 
-  static parseConnectionInfoToPayload(data: { [prop: string]: any }, schema: Schema) {
+  override parseConnectionInfoToPayload(data: { [prop: string]: any }, schema: Schema) {
     if (data.openstack_use_current_user) {
       return {}
     }
@@ -91,11 +90,11 @@ export default class ConnectionSchemaParser {
     delete data.project_domain
     // eslint-disable-next-line no-param-reassign
     delete data.user_domain
-    const payload = DefaultConnectionSchemaParser.parseConnectionInfoToPayload(data, schema)
+    const payload = super.parseConnectionInfoToPayload(data, schema)
     return payload
   }
 
-  static parseConnectionResponse(endpoint: Endpoint) {
+  override parseConnectionResponse(endpoint: Endpoint) {
     if (!endpoint.connection_info || Object.keys(endpoint.connection_info).length === 0) {
       return {
         openstack_use_current_user: true,

+ 6 - 6
src/plugins/openstack/MinionPoolSchemaPlugin.ts

@@ -1,20 +1,20 @@
-import DefaultMinionPoolSchemaPlugin from '@src/plugins/default/MinionPoolSchemaPlugin'
+import MinionPoolSchemaPluginBase from '@src/plugins/default/MinionPoolSchemaPlugin'
 import { Field } from '@src/@types/Field'
 import DomUtils from '@src/utils/DomUtils'
 
-export default class MinionPoolSchemaPlugin {
-  static getMinionPoolToOptionsQuery(envData: any) {
+export default class MinionPoolSchemaPlugin extends MinionPoolSchemaPluginBase {
+  override getMinionPoolToOptionsQuery(envData: any) {
     return `?env=${DomUtils.encodeToBase64Url({ ...envData, list_all_destination_networks: true })}`
   }
 
-  static minionPoolTransformOptionsFields(fields: Field[]) {
+  override minionPoolTransformOptionsFields(fields: Field[]) {
     // Remove this field, as all networks are always listed
     fields = fields.filter(f => f.name !== 'list_all_destination_networks')
     return fields
   }
 
-  static getMinionPoolEnv(schema: Field[], data: any) {
-    const payload: any = DefaultMinionPoolSchemaPlugin.getMinionPoolEnv(schema, data)
+  override getMinionPoolEnv(schema: Field[], data: any) {
+    const payload: any = super.getMinionPoolEnv(schema, data)
     return { ...payload, list_all_destination_networks: true }
   }
 }

+ 7 - 51
src/plugins/openstack/OptionsSchemaPlugin.ts

@@ -12,30 +12,23 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import type { InstanceScript } from '@src/@types/Instance'
 import { Field } from '@src/@types/Field'
-import type { OptionValues, StorageMap } from '@src/@types/Endpoint'
+import type { OptionValues } from '@src/@types/Endpoint'
 import type { SchemaProperties, SchemaDefinitions } from '@src/@types/Schema'
-import type { NetworkMap } from '@src/@types/Network'
-import { UserScriptData } from '@src/@types/MainItem'
-import DefaultOptionsSchemaPlugin, {
-  defaultGetDestinationEnv,
-  defaultGetMigrationImageMap,
+import OptionsSchemaPluginBase, {
   defaultFillFieldValues,
   defaultFillMigrationImageMapValues,
   removeExportImageFieldValues,
 } from '../default/OptionsSchemaPlugin'
 
-export default class OptionsSchemaParser {
-  static migrationImageMapFieldName = DefaultOptionsSchemaPlugin.migrationImageMapFieldName
-
-  static parseSchemaToFields(opts: {
+export default class OptionsSchemaParser extends OptionsSchemaPluginBase {
+  override parseSchemaToFields(opts: {
     schema: SchemaProperties,
     schemaDefinitions?: SchemaDefinitions | null | undefined,
     dictionaryKey?: string,
     requiresWindowsImage?: boolean,
   }) {
-    const fields: Field[] = DefaultOptionsSchemaPlugin.parseSchemaToFields(opts)
+    const fields: Field[] = super.parseSchemaToFields(opts)
     const exportImage = fields.find(f => f.name === 'coriolis_backups_options')?.properties?.find(p => p.name === 'export_image')
     if (exportImage) {
       exportImage.required = true
@@ -61,17 +54,13 @@ export default class OptionsSchemaParser {
     return fields
   }
 
-  static sortFields(fields: Field[]) {
-    DefaultOptionsSchemaPlugin.sortFields(fields)
-  }
-
-  static fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
+  override fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
     const { field, options, requiresWindowsImage } = opts
     if (field.name === 'replica_export_mechanism' && field.subFields) {
       field.subFields.forEach(sf => {
         if (sf.properties) {
           sf.properties.forEach(f => {
-            DefaultOptionsSchemaPlugin.fillFieldValues({
+            super.fillFieldValues({
               field: f, options, customFieldName: f.name.split('/')[1], requiresWindowsImage,
             })
             removeExportImageFieldValues(f)
@@ -93,37 +82,4 @@ export default class OptionsSchemaParser {
       }
     }
   }
-
-  static getDestinationEnv(options: { [prop: string]: any } | null, oldOptions?: any) {
-    const env = {
-      ...defaultGetDestinationEnv(options, oldOptions),
-      ...defaultGetMigrationImageMap(
-        options,
-        oldOptions,
-        this.migrationImageMapFieldName,
-      ),
-    }
-    return env
-  }
-
-  static getNetworkMap(networkMappings: NetworkMap[] | null) {
-    return DefaultOptionsSchemaPlugin.getNetworkMap(networkMappings)
-  }
-
-  static getStorageMap(
-    defaultStorage: { value: string | null, busType?: string | null },
-    storageMap: StorageMap[] | null,
-    configDefault?: string | null,
-  ) {
-    return DefaultOptionsSchemaPlugin.getStorageMap(defaultStorage, storageMap, configDefault)
-  }
-
-  static getUserScripts(
-    uploadedUserScripts: InstanceScript[],
-    removedUserScripts: InstanceScript[],
-    userScriptData: UserScriptData | null | undefined,
-  ) {
-    return DefaultOptionsSchemaPlugin
-      .getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
-  }
 }

+ 10 - 35
src/plugins/ovirt/OptionsSchemaPlugin.ts

@@ -12,29 +12,26 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import type { InstanceScript } from '@src/@types/Instance'
 import type { Field } from '@src/@types/Field'
-import type { OptionValues, StorageMap } from '@src/@types/Endpoint'
+import type { OptionValues } from '@src/@types/Endpoint'
 import type { SchemaProperties, SchemaDefinitions } from '@src/@types/Schema'
-import type { NetworkMap } from '@src/@types/Network'
-import { UserScriptData } from '@src/@types/MainItem'
-import DefaultOptionsSchemaPlugin, {
+import OptionsSchemaPluginBase, {
   defaultFillMigrationImageMapValues,
   defaultFillFieldValues,
   defaultGetDestinationEnv,
   defaultGetMigrationImageMap,
 } from '../default/OptionsSchemaPlugin'
 
-export default class OptionsSchemaParser {
-  static migrationImageMapFieldName = 'migr_template_map'
+export default class OptionsSchemaParser extends OptionsSchemaPluginBase {
+  override migrationImageMapFieldName = 'migr_template_map'
 
-  static parseSchemaToFields(opts: {
+  override parseSchemaToFields(opts: {
     schema: SchemaProperties,
     schemaDefinitions?: SchemaDefinitions | null | undefined,
     dictionaryKey?: string,
     requiresWindowsImage?: boolean,
   }) {
-    const fields: Field[] = DefaultOptionsSchemaPlugin.parseSchemaToFields(opts)
+    const fields: Field[] = super.parseSchemaToFields(opts)
     fields.forEach(f => {
       if (
         f.name !== 'migr_template_username_map'
@@ -61,11 +58,8 @@ export default class OptionsSchemaParser {
     return fields
   }
 
-  static sortFields(fields: Field[]) {
-    DefaultOptionsSchemaPlugin.sortFields(fields)
-  }
-
-  static fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
+  // @TODO - check if this override is necessary, aka this.migrationImageMapFieldName is used from this class
+  override fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
     const { field, options, requiresWindowsImage } = opts
 
     const option = options.find(f => f.name === field.name)
@@ -82,7 +76,8 @@ export default class OptionsSchemaParser {
     }
   }
 
-  static getDestinationEnv(options: { [prop: string]: any } | null, oldOptions?: any) {
+  // @TODO - check if this override is necessary, aka this.migrationImageMapFieldName is used from this class
+  override getDestinationEnv(options: { [prop: string]: any } | null, oldOptions?: any) {
     const env = {
       ...defaultGetDestinationEnv(options, oldOptions),
       ...defaultGetMigrationImageMap(
@@ -93,24 +88,4 @@ export default class OptionsSchemaParser {
     }
     return env
   }
-
-  static getNetworkMap(networkMappings: NetworkMap[] | null | undefined) {
-    return DefaultOptionsSchemaPlugin.getNetworkMap(networkMappings)
-  }
-
-  static getStorageMap(
-    defaultStorage: { value: string | null, busType?: string | null },
-    storageMap: StorageMap[] | null,
-    configDefault?: string | null,
-  ) {
-    return DefaultOptionsSchemaPlugin.getStorageMap(defaultStorage, storageMap, configDefault)
-  }
-
-  static getUserScripts(
-    uploadedUserScripts: InstanceScript[],
-    removedUserScripts: InstanceScript[],
-    userScriptData: UserScriptData | null | undefined,
-  ) {
-    return DefaultOptionsSchemaPlugin.getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
-  }
 }

+ 9 - 37
src/plugins/ovm/OptionsSchemaPlugin.ts

@@ -12,29 +12,26 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import type { InstanceScript } from '@src/@types/Instance'
 import type { Field } from '@src/@types/Field'
-import type { OptionValues, StorageMap } from '@src/@types/Endpoint'
+import type { OptionValues } from '@src/@types/Endpoint'
 import type { SchemaProperties, SchemaDefinitions } from '@src/@types/Schema'
-import type { NetworkMap } from '@src/@types/Network'
-import { UserScriptData } from '@src/@types/MainItem'
-import DefaultOptionsSchemaPlugin, {
+import OptionsSchemaPluginBase, {
   defaultFillMigrationImageMapValues,
   defaultFillFieldValues,
   defaultGetDestinationEnv,
   defaultGetMigrationImageMap,
 } from '../default/OptionsSchemaPlugin'
 
-export default class OptionsSchemaParser {
-  static migrationImageMapFieldName = 'migr_template_map'
+export default class OptionsSchemaParser extends OptionsSchemaPluginBase {
+  override migrationImageMapFieldName = 'migr_template_map'
 
-  static parseSchemaToFields(opts: {
+  override parseSchemaToFields(opts: {
     schema: SchemaProperties,
     schemaDefinitions?: SchemaDefinitions | null | undefined,
     dictionaryKey?: string,
     requiresWindowsImage?: boolean,
   }) {
-    const fields: Field[] = DefaultOptionsSchemaPlugin.parseSchemaToFields(opts)
+    const fields: Field[] = super.parseSchemaToFields(opts)
     const makeRequired = (fieldName: string) => {
       const field = fields.find(f => f.name === fieldName)
       if (field) {
@@ -99,18 +96,14 @@ export default class OptionsSchemaParser {
     return fields
   }
 
-  static sortFields(fields: Field[]) {
-    DefaultOptionsSchemaPlugin.sortFields(fields)
-  }
-
-  static fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
+  override fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
     const { field, options, requiresWindowsImage } = opts
 
     if (field.name === 'use_coriolis_exporter') {
       field.subFields?.forEach(sf => {
         if (sf.properties) {
           sf.properties.forEach(f => {
-            DefaultOptionsSchemaPlugin.fillFieldValues({
+            super.fillFieldValues({
               field: f, options, customFieldName: f.name.split('/')[1], requiresWindowsImage,
             })
             if (f.name === 'export_template' && f.enum) {
@@ -141,7 +134,7 @@ export default class OptionsSchemaParser {
     }
   }
 
-  static getDestinationEnv(options: { [prop: string]: any } | null, oldOptions?: any) {
+  override getDestinationEnv(options: { [prop: string]: any } | null, oldOptions?: any) {
     let newOptions: any = { ...options }
     if (newOptions.use_coriolis_exporter != null) {
       newOptions = { use_coriolis_exporter: newOptions.use_coriolis_exporter }
@@ -159,25 +152,4 @@ export default class OptionsSchemaParser {
     }
     return env
   }
-
-  static getNetworkMap(networkMappings: NetworkMap[] | null | undefined) {
-    return DefaultOptionsSchemaPlugin.getNetworkMap(networkMappings)
-  }
-
-  static getStorageMap(
-    defaultStorage: { value: string | null, busType?: string | null },
-    storageMap: StorageMap[] | null,
-    configDefault?: string | null,
-  ) {
-    return DefaultOptionsSchemaPlugin.getStorageMap(defaultStorage, storageMap, configDefault)
-  }
-
-  static getUserScripts(
-    uploadedUserScripts: InstanceScript[],
-    removedUserScripts: InstanceScript[],
-    userScriptData: UserScriptData | null | undefined,
-  ) {
-    return DefaultOptionsSchemaPlugin
-      .getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
-  }
 }

+ 10 - 35
src/plugins/vmware_vsphere/OptionsSchemaPlugin.ts

@@ -12,29 +12,26 @@ You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-import type { InstanceScript } from '@src/@types/Instance'
 import type { Field } from '@src/@types/Field'
-import type { OptionValues, StorageMap } from '@src/@types/Endpoint'
+import type { OptionValues } from '@src/@types/Endpoint'
 import type { SchemaProperties, SchemaDefinitions } from '@src/@types/Schema'
-import type { NetworkMap } from '@src/@types/Network'
-import { UserScriptData } from '@src/@types/MainItem'
-import DefaultOptionsSchemaPlugin, {
+import OptionsSchemaPluginBase, {
   defaultFillMigrationImageMapValues,
   defaultFillFieldValues,
   defaultGetDestinationEnv,
   defaultGetMigrationImageMap,
 } from '../default/OptionsSchemaPlugin'
 
-export default class OptionsSchemaParser {
-  static migrationImageMapFieldName = 'migr_template_map'
+export default class OptionsSchemaParser extends OptionsSchemaPluginBase {
+  override migrationImageMapFieldName = 'migr_template_map'
 
-  static parseSchemaToFields(opts: {
+  override parseSchemaToFields(opts: {
     schema: SchemaProperties,
     schemaDefinitions?: SchemaDefinitions | null | undefined,
     dictionaryKey?: string,
     requiresWindowsImage?: boolean,
   }) {
-    const fields = DefaultOptionsSchemaPlugin.parseSchemaToFields(opts)
+    const fields = super.parseSchemaToFields(opts)
     fields.forEach(f => {
       if (
         f.name !== 'migr_template_username_map'
@@ -64,11 +61,8 @@ export default class OptionsSchemaParser {
     return fields
   }
 
-  static sortFields(fields: Field[]) {
-    DefaultOptionsSchemaPlugin.sortFields(fields)
-  }
-
-  static fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
+  // @TODO - check if this override is necessary, aka this.migrationImageMapFieldName is used from this class
+  override fillFieldValues(opts: { field: Field, options: OptionValues[], requiresWindowsImage: boolean }) {
     const { field, options, requiresWindowsImage } = opts
 
     const option = options.find(f => f.name === field.name)
@@ -85,7 +79,8 @@ export default class OptionsSchemaParser {
     }
   }
 
-  static getDestinationEnv(options?: { [prop: string]: any } | null, oldOptions?: any) {
+  // @TODO - check if this override is necessary, aka this.migrationImageMapFieldName is used from this class
+  override getDestinationEnv(options?: { [prop: string]: any } | null, oldOptions?: any) {
     const env = {
       ...defaultGetDestinationEnv(options, oldOptions),
       ...defaultGetMigrationImageMap(
@@ -96,24 +91,4 @@ export default class OptionsSchemaParser {
     }
     return env
   }
-
-  static getNetworkMap(networkMappings: NetworkMap[] | null | undefined) {
-    return DefaultOptionsSchemaPlugin.getNetworkMap(networkMappings)
-  }
-
-  static getStorageMap(
-    defaultStorage?: { value: string | null, busType?: string | null },
-    storageMap?: StorageMap[] | null,
-    configDefault?: string | null,
-  ) {
-    return DefaultOptionsSchemaPlugin.getStorageMap(defaultStorage, storageMap, configDefault)
-  }
-
-  static getUserScripts(
-    uploadedUserScripts: InstanceScript[],
-    removedUserScripts: InstanceScript[],
-    userScriptData: UserScriptData | null | undefined,
-  ) {
-    return DefaultOptionsSchemaPlugin.getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
-  }
 }

+ 6 - 8
src/sources/MigrationSource.ts

@@ -231,12 +231,11 @@ class MigrationSource {
     }
 
     if (opts.uploadedScripts?.length || opts.removedScripts?.length || migration.user_scripts) {
-      payload.migration.user_scripts = DefaultOptionsSchemaPlugin
-        .getUserScripts(
-          opts.uploadedScripts || [],
-          opts.removedScripts || [],
-          migration.user_scripts,
-        )
+      payload.migration.user_scripts = new DefaultOptionsSchemaPlugin().getUserScripts(
+        opts.uploadedScripts || [],
+        opts.removedScripts || [],
+        migration.user_scripts,
+      )
     }
 
     const response = await Api.send({
@@ -289,8 +288,7 @@ class MigrationSource {
     })
 
     if (uploadedUserScripts.length || removedUserScripts.length || userScriptData) {
-      payload.migration.user_scripts = DefaultOptionsSchemaPlugin
-        .getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
+      payload.migration.user_scripts = new DefaultOptionsSchemaPlugin().getUserScripts(uploadedUserScripts, removedUserScripts, userScriptData)
     }
 
     if (Object.keys(minionPoolMappings).length) {

+ 2 - 2
src/sources/MinionPoolSource.ts

@@ -179,7 +179,7 @@ class MinionPoolSource {
     } = config
     const payload = {
       minion_pool: {
-        ...DefaultMinionPoolSchemaPlugin.getMinionPoolEnv(defaultSchema, data),
+        ...new DefaultMinionPoolSchemaPlugin().getMinionPoolEnv(defaultSchema, data),
         endpoint_id: endpointId,
         environment_options: SchemaParser.getMinionPoolEnv(provider, envSchema, data),
       },
@@ -203,7 +203,7 @@ class MinionPoolSource {
     } = config
     const payload = {
       minion_pool: {
-        ...DefaultMinionPoolSchemaPlugin.getMinionPoolEnv(defaultSchema, data),
+        ...new DefaultMinionPoolSchemaPlugin().getMinionPoolEnv(defaultSchema, data),
         environment_options: SchemaParser.getMinionPoolEnv(provider, envSchema, data),
       },
     }

+ 5 - 6
src/sources/ReplicaSource.ts

@@ -275,12 +275,11 @@ class ReplicaSource {
     }
 
     if (updateData.uploadedScripts?.length || updateData.removedScripts?.length) {
-      payload.replica.user_scripts = DefaultOptionsSchemaPlugin
-        .getUserScripts(
-          updateData.uploadedScripts || [],
-          updateData.removedScripts || [],
-          replica.user_scripts,
-        )
+      payload.replica.user_scripts = new DefaultOptionsSchemaPlugin().getUserScripts(
+        updateData.uploadedScripts || [],
+        updateData.removedScripts || [],
+        replica.user_scripts,
+      )
     }
 
     const response = await Api.send({

+ 2 - 4
src/sources/WizardSource.ts

@@ -36,10 +36,8 @@ class WizardSource {
     const {
       type, data, defaultStorage, storageMap, uploadedUserScripts,
     } = opts
-    const sourceParser = data.source
-      ? OptionsSchemaPlugin.for(data.source.type) : DefaultOptionsSchemaParser
-    const destParser = data.target
-      ? OptionsSchemaPlugin.for(data.target.type) : DefaultOptionsSchemaParser
+    const sourceParser = data.source ? OptionsSchemaPlugin.for(data.source.type) : new DefaultOptionsSchemaParser()
+    const destParser = data.target ? OptionsSchemaPlugin.for(data.target.type) : new DefaultOptionsSchemaParser()
     const payload: any = {}
     payload[type] = {
       origin_endpoint_id: data.source ? data.source.id : 'null',