Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions libs/locales/lib/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@
"ai:Bare metal host not found": "Bare metal host not found",
"ai:Bare Metal Host related": "Bare Metal Host related",
"ai:Base domain": "Base domain",
"ai:Base domain can only contain letters, digits, hyphens, and dots. Example: example.com": "Base domain can only contain letters, digits, hyphens, and dots. Example: example.com",
"ai:Baseboard Management Controller (BMC)": "Baseboard Management Controller (BMC)",
"ai:Baseboard Management Controller Address": "Baseboard Management Controller Address",
"ai:Belongs to machine CIDR": "Belongs to machine CIDR",
Expand Down Expand Up @@ -192,7 +191,6 @@
"ai:Cluster installation is still in-progress.": "Cluster installation is still in-progress.",
"ai:Cluster installation process": "Cluster installation process",
"ai:Cluster installation was cancelled": "Cluster installation was cancelled.",
"ai:Cluster must be created before configuring infrastructure environment": "Cluster must be created before configuring infrastructure environment",
"ai:Cluster must have at least 3 hosts.": "Cluster must have at least 3 hosts.",
"ai:Cluster name": "Cluster name",
"ai:cluster network": "cluster network",
Expand Down Expand Up @@ -225,7 +223,6 @@
"ai:Configure environment": "Configure environment",
"ai:Configure host inventory settings": "Configure host inventory settings",
"ai:Configure load balancer on Amazon Web Services for me.": "Configure load balancer on Amazon Web Services for me.",
"ai:Configure proxy settings": "Configure proxy settings",
"ai:Configure the SSH key and proxy settings after the modal appears (optional).": "Configure the SSH key and proxy settings after the modal appears (optional).",
"ai:Configure your own NTP sources to sychronize the time between the hosts that will be added to this infrastructure environment.": "Configure your own NTP sources to sychronize the time between the hosts that will be added to this infrastructure environment.",
"ai:Configure your own NTP sources to synchronize the time between the hosts that will be added to this infrastructure environment.": "Configure your own NTP sources to synchronize the time between the hosts that will be added to this infrastructure environment.",
Expand Down Expand Up @@ -363,11 +360,9 @@
"ai:Failed to add hosts to the cluster": "Failed to add hosts to the cluster",
"ai:Failed to configure provisioning to enable registering hosts via BMC.": "Failed to configure provisioning to enable registering hosts via BMC.",
"ai:Failed to create AgentServiceConfig": "Failed to create AgentServiceConfig",
"ai:Failed to create infrastructure environment": "Failed to create infrastructure environment",
"ai:Failed to create IngressController": "Failed to create IngressController",
"ai:Failed to delete host": "Failed to delete host",
"ai:Failed to download the discovery Image": "Failed to download the discovery Image",
"ai:Failed to fetch cluster": "Failed to fetch cluster",
"ai:Failed to fetch cluster credentials.": "Failed to fetch cluster credentials.",
"ai:Failed to get Provisioning Configuration": "Failed to get Provisioning Configuration",
"ai:Failed to load Credentials Download step": "Failed to load Credentials Download step",
Expand All @@ -377,7 +372,6 @@
"ai:Failed to save configuration": "Failed to save configuration",
"ai:Failed to save host selection.": "Failed to save host selection.",
"ai:Failed to update host": "Failed to update host",
"ai:Failed to update infrastructure environment": "Failed to update infrastructure environment",
"ai:Failed validations:": "Failed validations:",
"ai:Failing infrastructure environment": "Failing infrastructure environment",
"ai:Fence Agents Remediation requirements": "Fence Agents Remediation requirements",
Expand Down Expand Up @@ -599,7 +593,6 @@
"ai:Minimum Memory": "Minimum Memory",
"ai:Minimum memory for selected role": "Minimum memory for selected role",
"ai:Minimum number of hosts": "Minimum number of hosts",
"ai:Missing cluster": "Missing cluster",
"ai:Model": "Model",
"ai:Modify your platform configuration to access your platform's features directly in OpenShift.": "Modify your platform configuration to access your platform's features directly in OpenShift.",
"ai:More info for configure storage sizes": "More information for configure storage sizes",
Expand Down Expand Up @@ -710,7 +703,6 @@
"ai:Operators": "Operators",
"ai:Option 1: Add the following records to your DNS server (recommended)": "Option 1: Add the following records to your DNS server (recommended)",
"ai:Option 2: Update your local /etc/hosts or /etc/resolv.conf files": "Option 2: Update your local /etc/hosts or /etc/resolv.conf files",
"ai:Optional configurations": "Optional configurations",
"ai:Otherwise, the VMs will not be able to reboot during the installation process.": "Otherwise, the VMs will not be able to reboot during the installation process.",
"ai:OVN separates the physical network topology from the logical one and is recommended if you're using new or telco features.": "OVN separates the physical network topology from the logical one and is recommended if you are using new or telco features.",
"ai:Packet loss": "Packet loss",
Expand Down Expand Up @@ -784,7 +776,6 @@
"ai:Removing {{name}} will remove the association with {{count}} host. These hosts will become available for other nodepools._plural": "Removing {{name}} will remove the association with {{count}} hosts. These hosts will become available for other nodepools.",
"ai:Removing from cluster": "Removing from cluster",
"ai:Rename hostnames using the custom template:": "Rename hostnames using the custom template:",
"ai:Rendezvous IP": "Rendezvous IP",
"ai:Report a bug": "Report a bug",
"ai:Required field": "Required field",
"ai:Requirements for Two Node control plane OpenShift": "Requirements for Two Node control plane OpenShift",
Expand Down Expand Up @@ -886,7 +877,6 @@
"ai:The following fields are invalid or missing": "The following fields are invalid or missing",
"ai:The following requirement must be met:": "The following requirement must be met:",
"ai:The following requirement must be met:_plural": "The following requirements must be met:",
"ai:The full cluster address [Cluster name].[Base domain] must be a valid DNS name (e.g. mycluster.example.com).": "The full cluster address [Cluster name].[Base domain] must be a valid DNS name (e.g. mycluster.example.com).",
"ai:The generated discovery ISO will contain everything needed to boot.": "The generated discovery ISO will contain everything that is needed to boot.",
"ai:The host has been discovered and needs to be approved to before further use.": "The host has been discovered and needs to be approved to before further use.",
"ai:The host machine is powered on": "The host machine is powered on",
Expand All @@ -898,7 +888,6 @@
"ai:The IP address cannot be a network or broadcast address": "The IP address cannot be a network or broadcast address",
"ai:The IP address pool to use for service IP addresses. You can enter only one IP address pool. If you need to access the services from an external network, configure load balancers and routers to manage the traffic.": "The IP address pool to use for service IP addresses. You can enter only one IP address pool. If you need to access the services from an external network, configure load balancers and routers to manage the traffic.",
"ai:The IP address pool used for service IP addresses.": "The IP address pool used for service IP addresses.",
"ai:The IP address that hosts will use to communicate with the bootstrap node during installation.": "The IP address that hosts will use to communicate with the bootstrap node during installation.",
"ai:The MAC address of the host's network connected NIC that will be used to provision the host.": "The MAC address of the host's network connected NIC that will be used to provision the host.",
"ai:The output displays the following:": "The output displays the following:",
"ai:The primary Ingress and API IP addresses cannot be the same.": "The primary Ingress and API IP addresses cannot be the same.",
Expand Down
6 changes: 1 addition & 5 deletions libs/types/assisted-installer-service.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1806,7 +1806,7 @@ export interface ImageInfo {
staticNetworkConfig?: string;
type?: ImageType;
}
export type ImageType = 'full-iso' | 'minimal-iso' | 'disconnected-iso';
export type ImageType = 'full-iso' | 'minimal-iso';
export interface ImportClusterParams {
/**
* OpenShift cluster name.
Expand Down Expand Up @@ -1913,10 +1913,6 @@ export interface InfraEnv {
* certificates in this bundle.
*/
additionalTrustBundle?: string;
/**
* The pull secret obtained from Red Hat OpenShift Cluster Manager at console.redhat.com/openshift/install/pull-secret.
*/
pullSecret?: string;
}
export interface InfraEnvCreateParams {
/**
Expand Down
6 changes: 0 additions & 6 deletions libs/ui-lib/lib/common/api/assisted-service/ClustersAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,6 @@ const ClustersAPI = {
headers: { 'Content-Type': 'application/json' },
});
},
registerDisconnected(params: { name: string; openshiftVersion: string }) {
return client.post<Cluster, AxiosResponse<Cluster>, { name: string; openshiftVersion: string }>(
`${ClustersAPI.makeBaseURI()}disconnected`,
params,
);
},
};

export default ClustersAPI;
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,12 @@ import { TangServer } from '../clusterConfiguration/DiskEncryptionFields/DiskEnc
import { getDefaultOpenShiftVersion } from '../ui';
import {
baseDomainValidationSchema,
isValidFullClusterAddress,
dnsNameValidationSchema,
nameValidationSchema,
pullSecretValidationSchema,
} from '../../validationSchemas';
import { ClusterDetailsValues } from './types';

const fullClusterAddressTest = (t: TFunction) => ({
name: 'full-cluster-address',
message: t(
'ai:The full cluster address [Cluster name].[Base domain] must be a valid DNS name (e.g. mycluster.example.com).',
),
test: (values: { name?: string; baseDnsDomain?: string } | undefined) => {
const name = values?.name?.trim() ?? '';
const base = values?.baseDnsDomain?.trim() ?? '';
if (!name || !base) return true;
return isValidFullClusterAddress(`${name}.${base}`);
},
});

const emptyTangServers = (): TangServer[] => {
return [
{
Expand Down Expand Up @@ -111,7 +98,6 @@ export const getClusterDetailsValidationSchema = ({
t: TFunction;
}) =>
Yup.lazy((values: { baseDnsDomain: string; isSNODevPreview: boolean }) => {
const fullAddressTest = fullClusterAddressTest(t);
if (pullSecretSet) {
return Yup.object({
name: nameValidationSchema(
Expand All @@ -121,8 +107,10 @@ export const getClusterDetailsValidationSchema = ({
validateUniqueName,
isOcm,
),
baseDnsDomain: baseDomainValidationSchema(t).required(t('ai:Required field')),
}).test(fullAddressTest.name, fullAddressTest.message, fullAddressTest.test);
baseDnsDomain: isOcm
? baseDomainValidationSchema(t).required(t('ai:Required field'))
: dnsNameValidationSchema(t).required(t('ai:Required field')),
});
}
return Yup.object({
name: nameValidationSchema(
Expand All @@ -132,7 +120,9 @@ export const getClusterDetailsValidationSchema = ({
validateUniqueName,
isOcm,
),
baseDnsDomain: baseDomainValidationSchema(t).required(t('ai:Required field')),
baseDnsDomain: isOcm
? baseDomainValidationSchema(t).required(t('ai:Required field'))
: dnsNameValidationSchema(t).required(t('ai:Required field')),
pullSecret: pullSecretValidationSchema(t).required(t('ai:Required field')),
diskEncryptionTangServers: Yup.array().when('diskEncryptionMode', {
is: (diskEncryptionMode: DiskEncryption['mode']) => {
Expand All @@ -150,5 +140,5 @@ export const getClusterDetailsValidationSchema = ({
}),
),
}),
}).test(fullAddressTest.name, fullAddressTest.message, fullAddressTest.test);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ export const OpenShiftVersionModal = ({
key="select-custom-ocp"
variant={ButtonVariant.primary}
onClick={() => {
if (values.customOpenshiftSelect !== null) {
setFieldValue('openshiftVersion', values.customOpenshiftSelect);
}
setFieldValue('openshiftVersion', values.customOpenshiftSelect);
onClose();
}}
>
Expand Down
2 changes: 1 addition & 1 deletion libs/ui-lib/lib/common/components/ui/WizardFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const WizardFooter: React.FC<WizardFooterProps> = ({
variant={ButtonVariant.primary}
name="next"
onClick={onNext}
isDisabled={isNextDisabled || isSubmitting}
isDisabled={isNextDisabled}
isLoading={isNextButtonLoading}
>
{nextButtonText || t('ai:Next')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ const GetPullSecretHelperText: React.FC<{ isOcm: boolean }> = ({ isOcm }) => {

const PullSecretField: React.FC<{ isOcm: boolean }> = ({ isOcm }) => {
const { t } = useTranslation();

return (
<TextAreaField
name="pullSecret"
Expand Down
5 changes: 0 additions & 5 deletions libs/ui-lib/lib/common/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ export const clusterFieldLabels = (t: TFunction): { [key in string]: string } =>
machineNetworks: t('ai:Machine networks'),
clusterNetworks: t('ai:Cluster networks'),
serviceNetworks: t('ai:Service networks'),
rendezvousIp: t('ai:Rendezvous IP'),
});

export const hostValidationGroupLabels = (
Expand Down Expand Up @@ -394,7 +393,6 @@ export const OPERATOR_NAME_METALLB = 'metallb';

export const singleClusterOperators = [
OPERATOR_NAME_CNV,
OPERATOR_NAME_LSO,
OPERATOR_NAME_MTV,
OPERATOR_NAME_NMSTATE,
OPERATOR_NAME_NODE_HEALTHCHECK,
Expand All @@ -404,9 +402,6 @@ export const singleClusterOperators = [
OPERATOR_NAME_CLUSTER_OBSERVABILITY,
OPERATOR_NAME_LOKI,
OPERATOR_NAME_OPENSHIFT_LOGGING,
OPERATOR_NAME_NUMA_RESOURCES,
OPERATOR_NAME_OADP,
OPERATOR_NAME_METALLB,
];

export const singleClusterBundles = ['virtualization'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ export const ipNoSuffixValidationSchema = (t: TFunction) =>

export const macAddressValidationSchema = (t: TFunction) =>
Yup.string().matches(MAC_REGEX, {
message: (params: { value?: unknown }) =>
t('ai:Value "{{value}}" is not valid MAC address.', {
value: params?.value !== undefined ? String(params.value) : '',
}),
message: (value) => t('ai:Value "{{value}}" is not valid MAC address.', { value }),
excludeEmptyString: true,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,55 +123,23 @@ export const dnsNameValidationSchema = (t: TFunction) =>
excludeEmptyString: true,
});

const MAX_DNS_NAME_LENGTH = 253;
/** Only letters, digits, hyphen, and dot (valid DNS/hostname characters). */
const DNS_CHARS_REGEX = /^[a-z0-9.-]+$/i;

/**
* Validates the full cluster address [clusterName].[baseDomain] as a single DNS/hostname
* (e.g. "doma.ca" is valid even though "ca" alone might not pass standalone base-domain rules).
*/
export const isValidFullClusterAddress = (full: string): boolean => {
if (!full || full === '.' || /\s/.test(full)) {
return false;
}
if (full.length > MAX_DNS_NAME_LENGTH) {
return false;
}
if (!DNS_CHARS_REGEX.test(full)) {
return false;
}
const labels = full.split('.');
if (labels.some((label) => label.length === 0 || label.length > 63)) {
return false;
}
return HOST_NAME_REGEX.test(full);
};

export const baseDomainValidationSchema = (t: TFunction) =>
Yup.string()
.test(
'dns-name-label-length',
t(
'ai:Every single host component in the base domain name cannot contain more than 63 characters and must not contain spaces.',
),
(value?: string) => {
// Check if the value contains any spaces
if (/\s/.test(value as string)) {
return false; // Value contains spaces, validation fails
}
Yup.string().test(
'dns-name-label-length',
t(
'ai:Every single host component in the base domain name cannot contain more than 63 characters and must not contain spaces.',
),
(value?: string) => {
// Check if the value contains any spaces
if (/\s/.test(value as string)) {
return false; // Value contains spaces, validation fails
}

// Check the label lengths
const labels = (value || '').split('.');
return labels.every((label: string) => label.length <= 63);
},
)
.matches(NAME_CHARS_REGEX, {
message: t(
'ai:Base domain can only contain letters, digits, hyphens, and dots. Example: example.com',
),
excludeEmptyString: true,
});
// Check the label lengths
const labels = (value || '').split('.');
return labels.every((label: string) => label.length <= 63);
},
);

export const locationValidationSchema = (t: TFunction) =>
Yup.string()
Expand Down
4 changes: 1 addition & 3 deletions libs/ui-lib/lib/ocm/components/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ export const UILibRoutes = ({
<>
<Routes>
<Route path="assisted-installer/clusters" element={<Outlet />}>
<Route path="~new" element={<NewClusterPage />}>
<Route path=":clusterId" element={<NewClusterPage />} />
</Route>
<Route path="~new" element={<NewClusterPage />} />
<Route path=":clusterId" element={<ClusterPage />} />
<Route index element={<Clusters />} />
</Route>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export const discoveryImageTypes: Record<DiscoveryImageType, string> = {
'minimal-iso': 'Minimal image file - Download an ISO that fetches content on boot',
'full-iso': 'Full image file - Download a self-contained ISO',
'discovery-image-ipxe': 'iPXE - Provision from your network server',
'disconnected-iso': 'Disconnected ISO - Provision from a local file',
};

type DiscoveryImageTypeDropdownProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Formik, FormikHelpers } from 'formik';
import { TFunction } from 'i18next';
import {
HostStaticNetworkConfig,
ImageType,
InfraEnv,
Proxy,
} from '@openshift-assisted/types/assisted-installer-service';
Expand Down Expand Up @@ -71,7 +72,7 @@ type OcmDiscoveryImageConfigFormProps = Proxy & {
formikActions: FormikHelpers<OcmDiscoveryImageFormValues>,
) => Promise<void>;
sshPublicKey?: string;
imageType?: DiscoveryImageType;
imageType?: ImageType;
isIpxeSelected?: boolean;
enableCertificate?: boolean;
trustBundle?: InfraEnv['additionalTrustBundle'];
Expand Down Expand Up @@ -105,7 +106,7 @@ export const OcmDiscoveryImageConfigForm = ({
httpsProxy: httpsProxy || '',
noProxy: noProxy || '',
enableProxy: !!(httpProxy || httpsProxy || noProxy),
imageType: imageType,
imageType: imageTypeValue as ImageType,
enableCertificate: enableCertificate || false,
trustBundle: trustBundle || '',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,11 @@ export const getIpAddressValidationSchema = (protocolVersion: ProtocolVersion) =
const protocolVersionLabel = protocolVersion === ProtocolVersion.ipv4 ? 'IPv4' : 'IPv6';
return Yup.string().test(
protocolVersion,
(params: { value?: unknown }) =>
`Value "${
params?.value !== undefined ? String(params.value) : ''
}" is not a valid ${protocolVersionLabel} address`,
`Value \${value} is not a valid ${protocolVersionLabel} address`,
(value?: string) => {
if (value === undefined || value === '') {
if (!value) {
return true;
}
if (typeof value !== 'string') {
return false;
}
return isValidAddress(value, protocolVersion);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ const getExpandedHostComponent = (protocolType: StaticProtocolType) => {
label={`IP address (${getProtocolVersionLabel(protocolVersion)})`}
fieldId={getFieldId(`${fieldName}.ips.${protocolVersion}`, 'input')}
key={protocolVersion}
isRequired
>
<OcmInputField
name={`${fieldName}.ips.${protocolVersion}`}
Expand Down
Loading
Loading