diff --git a/src/renderer/components/stages/Networking.tsx b/src/renderer/components/stages/Networking.tsx index 8de699c..07f3003 100644 --- a/src/renderer/components/stages/Networking.tsx +++ b/src/renderer/components/stages/Networking.tsx @@ -8,531 +8,88 @@ * Copyright Contributors to the Zowe Project. */ -import { useState, useEffect, useRef } from "react"; -import { Box, Button, Checkbox, FormControlLabel, IconButton, SvgIcon, SvgIconProps, TextField } from '@mui/material'; +import { useState, useEffect, useRef, Fragment } from "react"; +import { Accordion, AccordionDetails, AccordionSummary, Box, Button, Checkbox, FormControlLabel, IconButton, TextField, Typography } from '@mui/material'; +import { ExpandMore, Add, DeleteForever} from '@mui/icons-material'; import { useAppSelector, useAppDispatch } from '../../hooks'; -import { selectYaml, setNextStepEnabled, setYaml } from '../configuration-wizard/wizardSlice'; +import { selectYaml, setNextStepEnabled, setYaml, selectSchema } from '../configuration-wizard/wizardSlice'; import ContainerCard from '../common/ContainerCard'; import EditorDialog from "../common/EditorDialog"; import { createTheme } from '@mui/material/styles'; import { getStageDetails, getSubStageDetails } from "../../../services/StageDetails"; import { stages } from "../configuration-wizard/Wizard"; -import { selectInitializationStatus, setInitializationStatus, setNetworkingStatus } from "./progress/progressSlice"; +import { setInitializationStatus, setNetworkingStatus } from "./progress/progressSlice"; import { setActiveStep } from "./progress/activeStepSlice"; -import { TYPE_YAML, TYPE_JCL, TYPE_OUTPUT, ajv } from "../common/Utils"; +import { TYPE_YAML, TYPE_OUTPUT } from "../common/Utils"; import { IResponse } from "../../../types/interfaces"; import { selectConnectionArgs } from "./connection/connectionSlice"; import { getInstallationArguments, getProgress, isInitializationStageComplete, updateSubStepSkipStatus } from "./progress/StageProgressStatus"; import { alertEmitter } from "../Header"; +import JsonForm from '../common/JsonForms'; -// const schema = useAppSelector(selectSchema); -const schema: any = { - "$id": "https://zowe.org/schemas/v2/server-base", - "title": "Zowe configuration file", - "description": "Configuration file for Zowe (zowe.org) version 2.", +// FIXME: Hardcoded altered network schema for render purpose as JsonForms can't work with complete schema syntax like ("attls": {"const": true, ...}) +const networkSchema = { "type": "object", - "additionalProperties": true, + "additionalProperties": false, + "description": "Optional, advanced network configuration parameters", "properties": { - "zowe": { + "server": { "type": "object", - "additionalProperties": true, + "description": "Optional, advanced network configuration parameters for Zowe servers", "properties": { - "externalDomains": { - "type": "array", - "description": "List of domain names of how you access Zowe from your local computer.", - "minItems": 1, - "uniqueItems": true, - "items": { - "type": ["string"] - } - }, - "externalPort": { - "type": "integer", - "minimum": 0, - "maximum": 65535, - "description": "Port number of how you access Zowe APIML Gateway from your local computer." - } - } - }, - "components": { - "type": "object", - "patternProperties": { - "^.*$": { + "tls": { "type": "object", + "additionalProperties": false, + "required": ["maxTls", "minTls"], "properties": { - "enabled": { - "type": "boolean", - "description": "Whether to enable or disable this component", - "default": false - }, - "port": { - "type": "integer", - "description": "Optional, port number for component if applicable.", - }, - "debug": { + "attls": { + "description": "Enables AT-TLS for server operations. AT-TLS should only be enabled in a z/OS host environment. Servers will be switched into HTTP mode to accomodate z/OS the specific AT-TLS feature which wraps network calls in TLS.", "type": "boolean", - "description": "Whether to enable or disable debug tracing for this component", "default": false }, - "certificate": { - "$ref": "#/$defs/certificate", - "description": "Certificate for current component." - }, - "launcher": { - "type": "object", - "description": "Set behavior of how the Zowe launcher will handle this particular component", - "additionalProperties": true, - "properties": { - "restartIntervals": { - "type": "array", - "description": "Intervals of seconds to wait before restarting a component if it fails before the minUptime value.", - "items": { - "type": "integer" - } - }, - "minUptime": { - "type": "integer", - "default": 90, - "description": "The minimum amount of seconds before a component is considered running and the restart counter is reset." - }, - "shareAs": { - "type": "string", - "description": "Determines which SHAREAS mode should be used when starting a component", - "enum": ["no", "yes", "must", ""], - "default": "yes" - } - } - }, - "zowe": { - "type": "object", - "description": "Component level overrides for top level Zowe network configuration.", - "additionalProperties": false, - "properties": { - "network": { - "$ref": "#/$defs/networkSettings" - }, - "job": { - "$ref": "#/$defs/componentJobSettings" - } - } - } - } - } - } - }, - "haInstances": { - "type": "object", - "patternProperties": { - "^.*$": { - "type": "object", - "description": "Configuration of Zowe high availability instance.", - "required": ["hostname", "sysname"], - "properties": { - "hostname": { - "type": "string", - "description": "Host name of the Zowe high availability instance. This is hostname for internal communications." - }, - "sysname": { - "type": "string", - "description": "z/OS system name of the Zowe high availability instance. Some JES command will be routed to this system name." - }, - "components": { - "type": "object", - "patternProperties": { - "^.*$": { - "$ref": "#/$defs/component" - } - } - } - } - } - } - } - }, - "$defs": { - "port": { - "type": "integer", - "minimum": 0, - "maximum": 65535 - }, - "scheme": { - "type": "string", - "enum": [ - "http", - "https" - ], - "default": "https" - }, - "certificate": { - "oneOf": [ - { "$ref": "#/$defs/pkcs12-certificate" }, - { "$ref": "#/$defs/keyring-certificate" } - ] - }, - "pkcs12-certificate": { - "type": "object", - "additionalProperties": false, - "required": ["keystore", "truststore", "pem"], - "properties": { - "keystore": { - "type": "object", - "additionalProperties": false, - "description": "Certificate keystore.", - "required": ["type", "file", "alias"], - "properties": { - "type": { - "type": "string", - "description": "Keystore type.", - "const": "PKCS12" - }, - "file": { - "type": "string", - "pattern": "^([^\\0]){1,1024}$", - "minLength": 1, - "maxLength": 1024, - "description": "Path to your PKCS#12 keystore." - }, - "password": { - "type": "string", - "description": "Password of your PKCS#12 keystore." - }, - "alias": { - "type": "string", - "description": "Certificate alias name of defined in your PKCS#12 keystore" - } - } - }, - "truststore": { - "type": "object", - "additionalProperties": false, - "description": "Certificate truststore.", - "required": ["type", "file"], - "properties": { - "type": { - "type": "string", - "description": "Truststore type.", - "const": "PKCS12" - }, - "file": { - "type": "string", - "pattern": "^([^\\0]){1,1024}$", - "minLength": 1, - "maxLength": 1024, - "description": "Path to your PKCS#12 keystore." - }, - "password": { - "type": "string", - "description": "Password of your PKCS#12 keystore." - } - } - }, - "pem": { - "type": "object", - "additionalProperties": false, - "description": "Certificate in PEM format.", - "required": ["key", "certificate"], - "properties": { - "key": { - "type": "string", - "pattern": "^([^\\0]){1,1024}$", - "minLength": 1, - "maxLength": 1024, - "description": "Path to the certificate private key stored in PEM format." - }, - "certificate": { - "type": "string", - "pattern": "^([^\\0]){1,1024}$", - "minLength": 1, - "maxLength": 1024, - "description": "Path to the certificate stored in PEM format." - }, - "certificateAuthorities": { - "description": "List of paths to the certificate authorities stored in PEM format.", - "oneOf": [{ - "type": "string", - "pattern": "^([^\\0]){1,1024}$", - "minLength": 1, - "maxLength": 1024, - "description": "Paths to the certificate authorities stored in PEM format. You can separate multiple certificate authorities by comma." - }, - { - "type": "array", - "description": "Path to the certificate authority stored in PEM format.", - "items": { - "type": "string", - "pattern": "^([^\\0]){1,1024}$", - "minLength": 1, - "maxLength": 1024, - } - } - ] - } - } - } - } - }, - "keyring-certificate": { - "type": "object", - "additionalProperties": false, - "required": ["keystore", "truststore"], - "properties": { - "keystore": { - "type": "object", - "additionalProperties": false, - "description": "Certificate keystore.", - "required": ["type", "file", "alias"], - "properties": { - "type": { - "type": "string", - "description": "Keystore type.", - "enum": ["JCEKS", "JCECCAKS", "JCERACFKS", "JCECCARACFKS", "JCEHYBRIDRACFKS"] - }, - "file": { - "type": "string", - "description": "Path of your z/OS keyring, including ring owner and ring name. Case sensitivity and spaces matter.", - "pattern": "^safkeyring:\/\/.*" - }, - "password": { - "type": "string", - "description": "Literally 'password' may be needed when using keyrings for compatibility with java servers.", - "enum": ["", "password"] - }, - "alias": { - "type": "string", - "description": "Certificate label of z/OS keyring. Case sensitivity and spaces matter." - } - } - }, - "truststore": { - "type": "object", - "additionalProperties": false, - "description": "Certificate truststore.", - "required": ["type", "file"], - "properties": { - "type": { - "type": "string", - "description": "Truststore type.", - "enum": ["JCEKS", "JCECCAKS", "JCERACFKS", "JCECCARACFKS", "JCEHYBRIDRACFKS"] - }, - "file": { - "type": "string", - "description": "Path of your z/OS keyring, including ring owner and ring name. Case sensitivity and spaces matter.", - "pattern": "^safkeyring:\/\/.*" - }, - "password": { - "type": "string", - "description": "Literally 'password' may be needed when using keyrings for compatibility with java servers.", - "enum": ["", "password"] - } - } - }, - "pem": { - "type": "object", - "additionalProperties": false, - "description": "Certificate in PEM format.", - "properties": { - "key": { - "type": "string", - "description": "Path to the certificate private key stored in PEM format." - }, - "certificate": { - "type": "string", - "description": "Path to the certificate stored in PEM format." - }, - "certificateAuthorities": { - "description": "List of paths to the certificate authorities stored in PEM format.", - "oneOf": [{ - "type": "string", - "description": "Paths to the certificate authorities stored in PEM format. You can separate multiple certificate authorities by comma." - }, - { - "type": "array", - "description": "Path to the certificate authority stored in PEM format.", - "items": { - "type": "string" - } - } - ] - } - } - } - } - }, - "component": { - "$anchor": "zoweComponent", - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Whether to enable or disable this component", - "default": false - }, - "certificate": { - "$ref": "#/$defs/certificate", - "description": "Certificate for current component." - }, - "launcher": { - "type": "object", - "description": "Set behavior of how the Zowe launcher will handle this particular component", - "additionalProperties": true, - "properties": { - "restartIntervals": { - "type": "array", - "description": "Intervals of seconds to wait before restarting a component if it fails before the minUptime value.", - "items": { - "type": "integer" - } - }, - "minUptime": { - "type": "integer", - "default": 90, - "description": "The minimum amount of seconds before a component is considered running and the restart counter is reset." - }, - "shareAs": { - "type": "string", - "description": "Determines which SHAREAS mode should be used when starting a component", - "enum": ["no", "yes", "must", ""], - "default": "yes" - } - } - }, - "zowe": { - "type": "object", - "description": "Component level overrides for top level Zowe network configuration.", - "additionalProperties": false, - "properties": { - "network": { - "$ref": "#/$defs/networkSettings" + "maxTls": { + "type": "string", + "enum": [ + "TLSv1.2", + "TLSv1.3" + ], + "default": "TLSv1.3", + "description": "Maximum TLS version allowed for network connections if AT-TLS is not used" }, - "job": { - "$ref": "#/$defs/componentJobSettings" - } - } - } - } - }, - "componentJobSettings": { - "$anchor": "componentJobSettings", - "type": "object", - "description": "Component level overrides for job execution behavior", - "properties": { - "suffix": { - "type": "string", - "description": "Can be used by components to declare a jobname suffix to append to their job. This is not currently used by Zowe itself, it is up to components to use this value if desired. Zowe may use this value in the future." - } - } - }, - "tlsSettings": { - "$anchor": "tlsSettings", - "type": "object", - "properties": { - "ciphers": { - "type": "array", - "description": "Acceptable TLS cipher suites for network connections, in IANA format.", - "items": { - "type": "string" - } - }, - "curves": { - "type": "array", - "description": "Acceptable key exchange elliptic curves for network connections.", - "items": { - "type": "string" + "minTls": { + "type": "string", + "enum": [ + "TLSv1.2", + "TLSv1.3" + ], + "default": "TLSv1.2", + "description": "Minimum TLS version allowed for network connections if AT-TLS is not used, and less than or equal to network.maxTls." + } } - }, - "maxTls": { - "type": "string", - "enum": ["TLSv1.2", "TLSv1.3"], - "default": "TLSv1.3", - "description": "Maximum TLS version allowed for network connections." - }, - "minTls": { - "type": "string", - "enum": ["TLSv1.2", "TLSv1.3"], - "default": "TLSv1.2", - "description": "Minimum TLS version allowed for network connections, and less than or equal to network.maxTls." } } }, - "networkSettings": { + "client": { "type": "object", - "$anchor": "networkSettings", "additionalProperties": false, - "description": "Optional, advanced network configuration parameters", + "description": "Optional, advanced network configuration parameters for Zowe servers when sending requests as clients.", "properties": { - "server": { + "tls": { "type": "object", "additionalProperties": false, - "description": "Optional, advanced network configuration parameters for Zowe servers", "properties": { - "tls": { - "$ref": "#/$defs/tlsSettings" - }, - "listenAddresses": { - "type": "array", - "description": "The IP addresses which all of the Zowe servers will be binding on and listening to. Some servers may only support listening on the first element.", - "items": { - "type": "string", - "pattern": "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" - } - }, - "vipaIp": { - "type": "string", - "description": "The IP address which all of the Zowe servers will be binding to. If you are using multiple DIPVA addresses, do not use this option." - }, - "validatePortFree": { + "attls": { + "description": "Enables AT-TLS for client operations. AT-TLS should only be enabled in a z/OS host environment. Servers will be switched into HTTP mode to accomodate z/OS the specific AT-TLS feature which wraps network calls in TLS.", "type": "boolean", - "default": true, - "description": "Whether or not to ensure that the port a server is about to use is available. Usually, servers will know this when they attempt to bind to a port, so this option allows you to disable the additional verification step." - } - } - }, - "client": { - "type": "object", - "additionalProperties": false, - "description": "Optional, advanced network configuration parameters for Zowe servers when sending requests as clients.", - "properties": { - "tls": { - "$ref": "#/$defs/tlsSettings" + "default": false } } } } - }, - "registryHandler": { - "$anchor": "registryHandler", - "type": "object", - "required": ["registry", "path"], - "properties": { - "registry": { - "type": "string", - "description": "The location of the default registry for this handler. It could be a URL, path, dataset, whatever this handler supports" - }, - "path": { - "$ref": "/schemas/v2/server-common#zowePath", - "description": "Unix file path to the configmgr-compatible JS file which implements the handler API" - } - } } } } -function AddIcon(props: SvgIconProps) { - return ( - - - - ); -} - -function DeleteIcon(props: SvgIconProps) { - return ( - - - - ); -} - const Networking = () => { const theme = createTheme(); @@ -545,21 +102,21 @@ const Networking = () => { const SUB_STAGE_ID = SUB_STAGES ? getSubStageDetails(STAGE_ID, subStageLabel).id : 0; const dispatch = useAppDispatch(); - const [yaml, setLocalYaml] = useState(useAppSelector(selectYaml)); + const yaml = useAppSelector(selectYaml); + const schema = useAppSelector(selectSchema); const [editorVisible, setEditorVisible] = useState(false); const [isFormValid, setIsFormValid] = useState(false); const [formError, setFormError] = useState(''); const [contentType, setContentType] = useState(''); - const [installationArgs, setInstArgs] = useState(getInstallationArguments()); + + const installationArgs = getInstallationArguments(); const connectionArgs = useAppSelector(selectConnectionArgs); - const [validate] = useState(() => ajv.getSchema("https://zowe.org/schemas/v2/server-base") || ajv.compile(schema)); - const [LOOP_LIMIT] = useState(1024); + // const validate = ajv.compile(schema); // REVIEW: Does not work with current schema. "reference "https://zowe.org/schemas/v2/server-base#zowePath" resolves to more than one schema" - const [stateUpdated, setStateUpdated] = useState(false); const [stageStatus, setStageStatus] = useState(stages[STAGE_ID].subStages[SUB_STAGE_ID].isSkipped); const stageStatusRef = useRef(stageStatus); - const isInitializationSkipped = !useAppSelector(selectInitializationStatus); + // const isInitializationSkipped = !useAppSelector(selectInitializationStatus); // Not used useEffect(() => { stageStatusRef.current = stageStatus; @@ -568,7 +125,9 @@ const Networking = () => { useEffect(() => { const nextPosition = document.getElementById('container-box-id'); if(nextPosition) nextPosition.scrollIntoView({behavior: 'smooth'}); - + if (yaml.zowe?.externalDomains?.length === 1 && yaml.zowe.externalDomains[0] === 'sample-domain.com') { + dispatch(setYaml({...yaml, zowe: {...yaml.zowe, externalDomains: [connectionArgs.host]}})); + } dispatch(setNextStepEnabled(getProgress('networkingStatus'))); dispatch(setInitializationStatus(isInitializationStageComplete())); @@ -585,7 +144,6 @@ const Networking = () => { } const updateProgress = (status: boolean) => { - setStateUpdated(!setStateUpdated); dispatch(setNetworkingStatus(status)); dispatch(setNextStepEnabled(status)); setStageSkipStatus(!status); @@ -595,37 +153,38 @@ const Networking = () => { setContentType(type); setEditorVisible(!editorVisible); }; - - const handleFormChange = async (data: any, isYamlUpdated?: boolean) => { - if(validate) { - validate(data); - if(validate.errors) { - const errPath = validate.errors[0].schemaPath; - const errMsg = validate.errors[0].message; - setStageConfig(false, errPath+' '+errMsg, data.zowe); - - } - } - let newYaml; - if (data.zowe && data.zowe.externalDomains && data.zowe.externalPort) { - newYaml = {...yaml, zowe: {...yaml.zowe, externalDomains: data.zowe.externalDomains, externalPort: data.zowe.externalPort}}; - } - if(data.components){ - newYaml = {...newYaml, components: data.components}; - } - window.electron.ipcRenderer.setConfig(newYaml) - setStageConfig(true, '', newYaml); - }; const setStageConfig = (isValid: boolean, errorMsg: string, data: any) => { setIsFormValid(isValid); setFormError(errorMsg); - setLocalYaml(data); + dispatch(setYaml(data)); + } + + const handleFormChange = async (data: any) => { + window.electron.ipcRenderer.setConfig(data) + dispatch(setYaml(data)); + dispatch(setNetworkingStatus(false)); + }; + + const handleNetworkTLSChange = async (data: any, section: string) => { + const newYaml = {...yaml, zowe: {...yaml.zowe, network: {...yaml.zowe.network, [section]: {...yaml.zowe.network[section], tls: data}}}}; + handleFormChange(newYaml); } const onSaveYaml = (e: any) => { e.preventDefault(); updateProgress(false); + + // Check for duplicated ports in components + const ports = Object.keys(yaml.components) + .filter((c: any) => yaml.components[c].enabled && yaml.components[c].port) + .map(c => Number(yaml.components[c].port)); + const duplicatedPorts = ports.filter((p, ind) => ports.indexOf(p) !== ind); + if (duplicatedPorts.length) { + alertEmitter.emit('showAlert', `Port ${duplicatedPorts[0]} is assigned to a multiple enabled components`, 'error'); + return; + } + alertEmitter.emit('showAlert', 'Uploading yaml...', 'info'); if(!installationArgs.dryRunMode){ window.electron.ipcRenderer.uploadLatestYaml(connectionArgs, installationArgs).then((res: IResponse) => { @@ -662,127 +221,115 @@ const Networking = () => { if(data.components){ newYaml = {...newYaml, components: data.components}; } + if(data.zowe && data.zowe.network){ + newYaml = {...yaml, zowe: {...yaml.zowe, network: data.zowe.network}}; + } setStageConfig(true, '', newYaml); }}/>} - dispatch(setYaml((await window.electron.ipcRenderer.getConfig()).details ?? yaml))}> + dispatch(setYaml((await window.electron.ipcRenderer.getConfig()).details ?? yaml))} // REVIEW: Why? + > {!isFormValid &&
{formError}
} -

External Domains { - let domains = [...yaml.zowe?.externalDomains || [], ""]; - const newYaml = {...yaml, zowe: {...yaml.zowe, externalDomains: domains}}; - window.electron.ipcRenderer.setConfig(newYaml ) - dispatch(setYaml(newYaml)) - dispatch(setNetworkingStatus(false)); - setLocalYaml(newYaml); - }}>

- {yaml.zowe.externalDomains != undefined && yaml.zowe.externalDomains.map((domain: string, index: number) => { - let domains = [...yaml.zowe?.externalDomains]; - domains[index] = e.target.value; - const newYaml = {...yaml, zowe: {...yaml.zowe, externalDomains: domains}}; - // console.log(domains); - window.electron.ipcRenderer.setConfig(newYaml ) - dispatch(setYaml(newYaml)) - dispatch(setNetworkingStatus(false)); - setLocalYaml(newYaml); - }} - /> { - let domains = [...yaml.zowe?.externalDomains]; - domains.splice(index, 1); - const newYaml = {...yaml, zowe: {...yaml.zowe, externalDomains: domains}}; - window.electron.ipcRenderer.setConfig(newYaml ) - dispatch(setYaml(newYaml)) - dispatch(setNetworkingStatus(false)); - setLocalYaml(newYaml); - }}>)} + External Domains + You can list your external domains on how you want to access Zowe.

+ This should be the domain list you would like to put into your web browser's address bar.
+ {Array.isArray(yaml.zowe?.externalDomains) && yaml.zowe.externalDomains.map((domain: string, index: number) => + { + const newYaml = {...yaml, zowe: {...yaml.zowe, externalDomains: yaml.zowe.externalDomains.with(index, e.target.value)}}; + handleFormChange(newYaml); + }} + /> + { + const newYaml = {...yaml, zowe: {...yaml.zowe, externalDomains: [...yaml.zowe.externalDomains, ""]}}; + handleFormChange(newYaml); + }}> + + + {yaml.zowe?.externalDomains.length > 1 && { + const domains = [...yaml.zowe.externalDomains.slice(0, index), ...yaml.zowe.externalDomains.slice(index + 1)]; + const newYaml = {...yaml, zowe: {...yaml.zowe, externalDomains: domains}}; + handleFormChange(newYaml); + }}> + + } + )}
{ const newYaml = {...yaml, zowe: {...yaml.zowe, externalPort: Number(e.target.value)}}; - window.electron.ipcRenderer.setConfig(newYaml) - dispatch(setYaml(newYaml)) - setLocalYaml(newYaml); - // // props.setYaml(newYaml); - // await window.electron.ipcRenderer.setConfigByKeyAndValidate(`${keys[i]}.${toMatch[k]}.${matchedProps[l]}`, Number(e.target.value)) - // // dispatch(setYaml(newYaml)); + handleFormChange(newYaml); }} /> -
- {Object.keys(schema.properties).map((schemaKey, index) => { - if(index < LOOP_LIMIT){ - if (schema.properties[schemaKey].patternProperties != undefined) { //only for rendering patternProperties - if(typeof yaml[schemaKey] === "object" && Object.keys(yaml[schemaKey]).length > 0) { - return
-

{schemaKey}

- {Object.keys(schema.properties[schemaKey].patternProperties).map((regexPattern, rIndex) => { - const pattern = new RegExp(regexPattern); - if(rIndex < LOOP_LIMIT && yaml[schemaKey]) { - return Object.keys(yaml[schemaKey]).map((matchedPattern, mIndex) => { - if(mIndex < LOOP_LIMIT && pattern.test(matchedPattern)){ - return
-
- - {matchedPattern} -
-
- {Object.keys(yaml[schemaKey][matchedPattern]).map((schemaProperty, sIndex) => { - - if(sIndex < LOOP_LIMIT && schemaProperty.length > 0){ - return
- - {typeof yaml[schemaKey][matchedPattern][schemaProperty] === "boolean" && { - // console.log('new yaml:', JSON.stringify({...yaml, [keys[i]]: {...yaml[keys[i]], [toMatch[k]]: {...yaml[keys[i]][toMatch[k]], [matchedProps[l]]: !yaml[keys[i]][toMatch[k]][matchedProps[l]]}}})); - const newYaml = {...yaml, [schemaKey]: {...yaml[schemaKey], [matchedPattern]: {...yaml[schemaKey][matchedPattern], [schemaProperty]: !yaml[schemaKey][matchedPattern][schemaProperty]}}}; - setLocalYaml(newYaml); - await window.electron.ipcRenderer.setConfigByKeyAndValidate(`${schemaKey}.${matchedPattern}.${schemaProperty}`, !yaml[schemaKey][matchedPattern][schemaProperty]) - dispatch(setYaml(newYaml)); - dispatch(setNetworkingStatus(false)); - }}/>} - />} - {typeof yaml[schemaKey][matchedPattern][schemaProperty] === "number" && { - if(!Number.isNaN(Number(e.target.value))){ - const newYaml = {...yaml, [schemaKey]: {...yaml[schemaKey], [matchedPattern]: {...yaml[schemaKey][matchedPattern], [schemaProperty]: Number(e.target.value)}}}; - setLocalYaml(newYaml); - await window.electron.ipcRenderer.setConfigByKeyAndValidate(`${schemaKey}.${matchedPattern}.${schemaProperty}`, Number(e.target.value)) - dispatch(setYaml(newYaml)); - dispatch(setNetworkingStatus(false)); - } - }} - />} -
- } - return null; - })}
- } - return null; - }) - } - return null; - }) + You can configure which port will be used by every component.

+ Note that the gateway port should match the External Port in most cases. + In some use cases, like containerization, this port could be different.
+

+ + } + aria-controls="components-content" + id="components-header" + > + Component ports configuration + + + {Object.keys(yaml.components).filter(component => Object.prototype.hasOwnProperty.call(yaml.components[component], "port")).map(component => { + return
+ { + const newYaml = {...yaml, components: {...yaml.components, [component]: {...yaml.components[component], enabled: !yaml.components[component].enabled}}}; + handleFormChange(newYaml); + }}/>} + /> + 65535} + variant="standard" + size="small" + required={yaml.components[component].enabled} + key={`port-input-${component}`} + value={yaml.components[component].port} + InputProps={{ + style: {minWidth: '100px', width: '100px'} + }} + onChange={async (e) => { + if (!Number.isNaN(Number(e.target.value))) { + const newYaml = {...yaml, components: {...yaml.components, [component]: {...yaml.components[component], port: Number(e.target.value)}}}; + handleFormChange(newYaml); } -
- } - } - } - return null; - })} -
- + }} + /> +
+ })} + + + {(networkSchema && yaml.zowe?.network) ? + + Server TLS configuration + handleNetworkTLSChange(data, 'server')} formData={yaml.zowe?.network.server.tls}/> + Client TLS configuration + handleNetworkTLSChange(data, 'client')} formData={yaml.zowe?.network.client.tls}/> + : null + } +
diff --git a/src/renderer/components/stages/Planning.tsx b/src/renderer/components/stages/Planning.tsx index 3c519e3..f41035e 100644 --- a/src/renderer/components/stages/Planning.tsx +++ b/src/renderer/components/stages/Planning.tsx @@ -248,7 +248,7 @@ const Planning = () => { if (localYaml?.zowe?.logDirectory.startsWith(localYaml?.zowe?.runtimeDirectory) || localYaml?.zowe?.workspaceDirectory.startsWith(localYaml?.zowe?.runtimeDirectory) || localYaml?.zowe?.extensionDirectory.startsWith(localYaml?.zowe?.runtimeDirectory)) { - alertEmitter.emit('showAlert', `Some instance locations (workspace, logs or extensions) are defined inside the runtime directory ${localYaml?.zowe?.runtimeDirectory}. It is not recommended as the runtime directory ment to be read-only.`, 'warning', 20000); + alertEmitter.emit('showAlert', `Some instance locations (workspace, logs or extensions) are defined inside the runtime directory ${localYaml?.zowe?.runtimeDirectory}. It is not recommended as the runtime directory is meant to be read-only.`, 'warning', 20000); } }) }