Skip to content

Commit 1116d1e

Browse files
authored
Kubevirt cred unmarshal fix (stolostron#3330)
* ACM-10186 Correctly encode kubevirt credential in wizard Signed-off-by: zlayne <zlayne@redhat.com> * fix lint Signed-off-by: zlayne <zlayne@redhat.com> * Update CreateCluster test for kubevirt Signed-off-by: zlayne <zlayne@redhat.com> * Update CreateCluster test for kubevirt Signed-off-by: zlayne <zlayne@redhat.com> * updat cred creation in test Signed-off-by: zlayne <zlayne@redhat.com> * availableMap refresh Signed-off-by: zlayne <zlayne@redhat.com> * unskip tests Signed-off-by: zlayne <zlayne@redhat.com> --------- Signed-off-by: zlayne <zlayne@redhat.com>
1 parent cdebe0e commit 1116d1e

File tree

6 files changed

+253
-57
lines changed

6 files changed

+253
-57
lines changed

frontend/src/routes/Infrastructure/Clusters/ManagedClusters/CreateCluster/CreateCluster.test.tsx

+222-37
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,16 @@
11
/* Copyright Contributors to the Open Cluster Management project */
22

3-
import {
4-
ClusterCurator,
5-
ClusterCuratorApiVersion,
6-
ClusterCuratorKind,
7-
ClusterImageSet,
8-
ClusterImageSetApiVersion,
9-
ClusterImageSetKind,
10-
IResource,
11-
MachinePool,
12-
MachinePoolApiVersion,
13-
MachinePoolKind,
14-
ManagedCluster,
15-
ManagedClusterApiVersion,
16-
ManagedClusterKind,
17-
Project,
18-
ProjectApiVersion,
19-
ProjectKind,
20-
ProjectRequest,
21-
ProjectRequestApiVersion,
22-
ProjectRequestKind,
23-
ProviderConnection,
24-
ProviderConnectionApiVersion,
25-
ProviderConnectionKind,
26-
Secret,
27-
SubscriptionOperator,
28-
SubscriptionOperatorApiVersion,
29-
SubscriptionOperatorKind,
30-
} from '../../../../../resources'
3+
import { ClusterImageSetK8sResource } from '@openshift-assisted/ui-lib/cim'
314
import { render, screen } from '@testing-library/react'
5+
import { Scope } from 'nock/types'
326
import { MemoryRouter, Route } from 'react-router-dom'
337
import { RecoilRoot } from 'recoil'
348
import {
359
clusterCuratorsState,
10+
managedClusterInfosState,
3611
managedClusterSetsState,
3712
managedClustersState,
13+
namespacesState,
3814
secretsState,
3915
settingsState,
4016
subscriptionOperatorsState,
@@ -46,34 +22,65 @@ import {
4622
nockIgnoreRBAC,
4723
nockList,
4824
} from '../../../../../lib/nock-util'
25+
import { PluginContext } from '../../../../../lib/PluginContext'
26+
import { PluginDataContext } from '../../../../../lib/PluginDataContext'
4927
import {
5028
clickByPlaceholderText,
5129
clickByRole,
5230
clickByTestId,
5331
clickByText,
32+
ocpApi,
33+
pasteByTestId,
5434
typeByPlaceholderText,
5535
typeByTestId,
5636
typeByText,
5737
waitForNocks,
5838
waitForNotText,
5939
waitForText,
60-
ocpApi,
61-
pasteByTestId,
6240
} from '../../../../../lib/test-util'
6341
import { NavigationPath } from '../../../../../NavigationPath'
64-
import { Scope } from 'nock/types'
6542
import {
66-
clusterName,
43+
ClusterCurator,
44+
ClusterCuratorApiVersion,
45+
ClusterCuratorKind,
46+
ClusterImageSet,
47+
ClusterImageSetApiVersion,
48+
ClusterImageSetKind,
49+
IResource,
50+
MachinePool,
51+
MachinePoolApiVersion,
52+
MachinePoolKind,
53+
ManagedCluster,
54+
ManagedClusterApiVersion,
55+
ManagedClusterInfoApiVersion,
56+
ManagedClusterInfoKind,
57+
ManagedClusterKind,
58+
NamespaceApiVersion,
59+
NamespaceKind,
60+
Project,
61+
ProjectApiVersion,
62+
ProjectKind,
63+
ProjectRequest,
64+
ProjectRequestApiVersion,
65+
ProjectRequestKind,
66+
ProviderConnection,
67+
ProviderConnectionApiVersion,
68+
ProviderConnectionKind,
69+
Secret,
70+
SubscriptionOperator,
71+
SubscriptionOperatorApiVersion,
72+
SubscriptionOperatorKind,
73+
} from '../../../../../resources'
74+
import { CLUSTER_INFRA_TYPE_PARAM } from '../ClusterInfrastructureType'
75+
import { CreateClusterPage } from '../CreateClusterPage'
76+
import {
6777
baseDomain,
78+
clusterImageSet,
79+
clusterName,
6880
mockAgentClusterInstall,
6981
mockClusterDeploymentAI,
70-
clusterImageSet,
7182
mockClusterImageSet,
7283
} from './CreateCluster.sharedmocks'
73-
import { PluginContext } from '../../../../../lib/PluginContext'
74-
import { CreateClusterPage } from '../CreateClusterPage'
75-
import { PluginDataContext } from '../../../../../lib/PluginDataContext'
76-
import { CLUSTER_INFRA_TYPE_PARAM } from '../ClusterInfrastructureType'
7784

7885
//const awsProjectNamespace = 'test-aws-namespace'
7986

@@ -1061,3 +1068,181 @@ describe('CreateCluster on premise', () => {
10611068
2 * 60 * 1000
10621069
)
10631070
})
1071+
1072+
describe('CreateCluster KubeVirt', () => {
1073+
const Component = () => {
1074+
return (
1075+
<RecoilRoot
1076+
initializeState={(snapshot) => {
1077+
snapshot.set(namespacesState, [
1078+
{
1079+
apiVersion: NamespaceApiVersion,
1080+
kind: NamespaceKind,
1081+
metadata: { name: 'testNs' },
1082+
},
1083+
])
1084+
snapshot.set(managedClustersState, [])
1085+
snapshot.set(managedClusterSetsState, [])
1086+
snapshot.set(managedClusterInfosState, [
1087+
{
1088+
apiVersion: ManagedClusterInfoApiVersion,
1089+
kind: ManagedClusterInfoKind,
1090+
metadata: { name: 'local-cluster', namespace: 'local-cluster' },
1091+
status: {
1092+
consoleURL: 'https://testCluster.com',
1093+
conditions: [
1094+
{
1095+
type: 'ManagedClusterConditionAvailable',
1096+
reason: 'ManagedClusterConditionAvailable',
1097+
status: 'True',
1098+
},
1099+
{ type: 'ManagedClusterJoined', reason: 'ManagedClusterJoined', status: 'True' },
1100+
{ type: 'HubAcceptedManagedCluster', reason: 'HubAcceptedManagedCluster', status: 'True' },
1101+
],
1102+
version: '1.17',
1103+
distributionInfo: {
1104+
type: 'ocp',
1105+
ocp: {
1106+
version: '1.2.3',
1107+
availableUpdates: [],
1108+
desiredVersion: '1.2.3',
1109+
upgradeFailed: false,
1110+
},
1111+
},
1112+
},
1113+
},
1114+
])
1115+
snapshot.set(secretsState, [
1116+
{
1117+
apiVersion: ProviderConnectionApiVersion,
1118+
kind: ProviderConnectionKind,
1119+
metadata: {
1120+
name: 'connectionKubeVirt',
1121+
namespace: clusterName,
1122+
labels: {
1123+
'cluster.open-cluster-management.io/type': 'kubevirt',
1124+
},
1125+
},
1126+
stringData: {
1127+
pullSecret: '{"pullSecret":"secret"}',
1128+
'ssh-publickey': 'ssh-rsa AAAAB1 fake@email.com',
1129+
},
1130+
type: 'kubernetes.io/dockerconfigjson',
1131+
} as Secret,
1132+
])
1133+
snapshot.set(clusterCuratorsState, mockClusterCurators)
1134+
}}
1135+
>
1136+
<MemoryRouter initialEntries={[`${NavigationPath.createCluster}?${CLUSTER_INFRA_TYPE_PARAM}=kubevirt`]}>
1137+
<Route path={NavigationPath.createCluster}>
1138+
<CreateClusterPage />
1139+
</Route>
1140+
</MemoryRouter>
1141+
</RecoilRoot>
1142+
)
1143+
}
1144+
1145+
beforeEach(() => {
1146+
nockIgnoreRBAC()
1147+
nockIgnoreApiPaths()
1148+
nockIgnoreOperatorCheck()
1149+
})
1150+
1151+
test('can create KubeVirt cluster', async () => {
1152+
const clusterImageSet415: ClusterImageSetK8sResource = {
1153+
apiVersion: ClusterImageSetApiVersion,
1154+
kind: ClusterImageSetKind,
1155+
metadata: {
1156+
name: 'ocp-release415',
1157+
},
1158+
spec: {
1159+
releaseImage: 'quay.io/openshift-release-dev/ocp-release:4.15.0-x86_64',
1160+
},
1161+
}
1162+
const storageClass = {
1163+
kind: 'StorageClass',
1164+
apiVersion: 'storage.k8s.io/v1',
1165+
metadata: {
1166+
name: 'gp3-csi',
1167+
annotations: {
1168+
'storageclass.kubernetes.io/is-default-class': 'true',
1169+
},
1170+
},
1171+
provisioner: 'ebs.csi.aws.com',
1172+
parameters: {
1173+
encrypted: 'true',
1174+
type: 'gp3',
1175+
},
1176+
reclaimPolicy: 'Delete',
1177+
allowVolumeExpansion: true,
1178+
volumeBindingMode: 'WaitForFirstConsumer',
1179+
}
1180+
const initialNocks: Scope[] = [
1181+
nockList(clusterImageSet415 as IResource, [clusterImageSet415] as IResource[]),
1182+
nockList(storageClass as IResource, [storageClass] as IResource[]),
1183+
]
1184+
render(<Component />)
1185+
1186+
// wait for tables/combos to fill in
1187+
await waitForNocks(initialNocks)
1188+
await waitForText('Cluster details', true)
1189+
await waitForText('Node pools')
1190+
await waitForText('Review and create')
1191+
1192+
// fill-in Cluster details
1193+
await typeByTestId('clusterName', clusterName)
1194+
1195+
await clickByPlaceholderText('Select or enter a release image')
1196+
await clickByText('OpenShift 4.15.0')
1197+
1198+
await typeByTestId('additionalLabels', 'myLabelKey=myValue')
1199+
1200+
await clickByPlaceholderText('Select a credential')
1201+
await clickByText('Add credential')
1202+
await clickByTestId('credentialsName')
1203+
await typeByTestId('credentialsName', 'testpullsecret')
1204+
await clickByTestId('namespaceName-input-toggle-select-typeahead')
1205+
await clickByText('testNs')
1206+
await clickByText('Next', 1)
1207+
await pasteByTestId('pullSecret', pullSecretAI)
1208+
await clickByText('Next', 1)
1209+
await clickByText('Add')
1210+
1211+
// wait for cred creation
1212+
await waitForNocks([
1213+
nockCreate({
1214+
apiVersion: 'v1',
1215+
kind: 'Secret',
1216+
type: 'Opaque',
1217+
metadata: {
1218+
name: 'testpullsecret',
1219+
namespace: 'testNs',
1220+
labels: {
1221+
'cluster.open-cluster-management.io/type': 'kubevirt',
1222+
'cluster.open-cluster-management.io/credentials': '',
1223+
},
1224+
},
1225+
stringData: {
1226+
pullSecret: '{"auths":{"cloud.openshift.com":{"auth":"b3BlbSKIPPED","email":"my@email.somewhere.com"}}}\n',
1227+
'ssh-publickey': '',
1228+
},
1229+
} as Secret),
1230+
])
1231+
1232+
await clickByPlaceholderText('Select a credential')
1233+
await clickByText('connectionKubeVirt')
1234+
1235+
// transition to NodePools
1236+
await new Promise((resolve) => setTimeout(resolve, 500))
1237+
1238+
await clickByText('Next')
1239+
// The test is flaky here?
1240+
await new Promise((resolve) => setTimeout(resolve, 500))
1241+
await clickByTestId('nodePoolName')
1242+
await typeByTestId('nodePoolName', 'testPool')
1243+
1244+
// Review and Save step
1245+
await clickByText('Next')
1246+
await waitForText('Infrastructure provider credential')
1247+
})
1248+
})

frontend/src/routes/Infrastructure/Clusters/ManagedClusters/CreateCluster/CreateCluster.tsx

+16-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import getControlDataAZR from './controlData/ControlDataAZR'
5959
import getControlDataCIM from './controlData/ControlDataCIM'
6060
import getControlDataGCP from './controlData/ControlDataGCP'
6161
import getControlDataHypershift from './controlData/ControlDataHypershift'
62-
import { getControlDataKubeVirt } from './controlData/ControlDataKubeVirt'
62+
import { getControlDataKubeVirt, setKubeVirtSecrets } from './controlData/ControlDataKubeVirt'
6363
import getControlDataOST from './controlData/ControlDataOST'
6464
import getControlDataRHV from './controlData/ControlDataRHV'
6565
import getControlDataVMW from './controlData/ControlDataVMW'
@@ -148,9 +148,23 @@ export default function CreateCluster(props: { infrastructureType: ClusterInfras
148148
(control: any) => {
149149
if (control.id === 'connection') {
150150
if (newSecret && control.setActive) {
151-
control.setActive(newSecret.metadata.name)
151+
const secretName = newSecret?.metadata.name ?? ''
152+
if (control.providerId === 'kubevirt') {
153+
// preset replacement fields to get around delayed control state from setAvailableConnections
154+
control.availableMap[secretName] = {
155+
replacements: {
156+
pullSecret: newSecret.data?.pullSecret ?? '',
157+
'ssh-publickey': newSecret.data?.['ssh-publickey'] ?? '',
158+
encoded: true,
159+
},
160+
}
161+
}
162+
control.setActive(secretName)
152163
setNewSecret(undefined) // override with the new secret once
153164
}
165+
if (!newSecret && control.providerId === 'kubevirt') {
166+
setKubeVirtSecrets(control)
167+
}
154168
setSelectedConnection(providerConnections.find((provider) => control.active === provider.metadata.name))
155169
} else if (control.id === 'kubevirt-operator-alert') {
156170
control.hidden = isKubevirtEnabled

frontend/src/routes/Infrastructure/Clusters/ManagedClusters/CreateCluster/controlData/ControlDataKubeVirt.js

+6-15
Original file line numberDiff line numberDiff line change
@@ -45,30 +45,20 @@ const operatorAlert = (localCluster, t) => {
4545
}
4646

4747
export const setKubeVirtSecrets = (control) => {
48-
const { active, availableMap = {}, available } = control
48+
const { active, availableMap = {} } = control
4949
const replacements = get(availableMap[active], 'replacements')
5050
const activePullSecret = replacements?.pullSecret ?? ''
5151
const activeSSHKey = replacements?.['ssh-publickey'] ?? ''
52+
const isEncoded = replacements?.encoded && replacements?.encoded === true
5253

53-
if (active) {
54+
if (active && !isEncoded && activePullSecret !== '') {
5455
control.availableMap[active] = {
5556
replacements: {
5657
pullSecret: Buffer.from(activePullSecret, 'ascii').toString('base64'),
57-
'ssh-publickey': activeSSHKey,
58+
'ssh-publickey': Buffer.from(activeSSHKey, 'ascii').toString('base64'),
59+
encoded: true,
5860
},
5961
}
60-
} else {
61-
// No Credential active -> reset availableMaps to reset the encodings
62-
available.forEach((cred) => {
63-
const encodedPullSecret = control.availableMap[cred].replacements.pullSecret
64-
const publicKey = control.availableMap[cred].replacements['ssh-publickey']
65-
control.availableMap[cred] = {
66-
replacements: {
67-
pullSecret: Buffer.from(encodedPullSecret, 'base64').toString('ascii'),
68-
'ssh-publickey': publicKey,
69-
},
70-
}
71-
})
7262
}
7363
}
7464

@@ -120,6 +110,7 @@ export const getControlDataKubeVirt = (
120110
available: [],
121111
footer: <CreateCredentialModal handleModalToggle={handleModalToggle} />,
122112
onSelect: setKubeVirtSecrets,
113+
hasReplacements: true,
123114
},
124115
{
125116
name: t('creation.ocp.name'),

frontend/src/routes/Infrastructure/Clusters/ManagedClusters/CreateCluster/controlData/ControlDataKubeVirt.test.js

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ describe('Cluster creation control data for KubeVirt', () => {
6161
replacements: {
6262
pullSecret: 'pullSecretData',
6363
'ssh-publickey': 'ssh-publickey TESTING johndoe@email.com',
64+
encoded: false,
6465
},
6566
},
6667
},
@@ -76,6 +77,7 @@ describe('Cluster creation control data for KubeVirt', () => {
7677
replacements: {
7778
pullSecret: 'cHVsbFNlY3JldERhdGE=',
7879
'ssh-publickey': 'ssh-publickey TESTING johndoe@email.com',
80+
encoded: true,
7981
},
8082
},
8183
},

0 commit comments

Comments
 (0)