github.com/openshift/installer@v1.4.17/pkg/asset/agent/joiner/clusterinfo_test.go (about) 1 package joiner 2 3 import ( 4 "context" 5 "encoding/json" 6 "testing" 7 8 "github.com/coreos/stream-metadata-go/stream" 9 "github.com/stretchr/testify/assert" 10 corev1 "k8s.io/api/core/v1" 11 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 "k8s.io/apimachinery/pkg/runtime" 13 "k8s.io/client-go/kubernetes/fake" 14 "k8s.io/utils/ptr" 15 "sigs.k8s.io/yaml" 16 17 configv1 "github.com/openshift/api/config/v1" 18 "github.com/openshift/assisted-service/api/hiveextension/v1beta1" 19 "github.com/openshift/assisted-service/models" 20 fakeclientconfig "github.com/openshift/client-go/config/clientset/versioned/fake" 21 "github.com/openshift/installer/pkg/asset" 22 "github.com/openshift/installer/pkg/asset/agent/workflow" 23 "github.com/openshift/installer/pkg/types" 24 "github.com/openshift/installer/pkg/types/baremetal" 25 ) 26 27 func TestClusterInfo_Generate(t *testing.T) { 28 cases := []struct { 29 name string 30 workflow workflow.AgentWorkflowType 31 nodesConfig AddNodesConfig 32 objs func(t *testing.T) ([]runtime.Object, []runtime.Object) 33 expectedClusterInfo ClusterInfo 34 expectedError string 35 }{ 36 { 37 name: "skip if not add-nodes workflow", 38 workflow: workflow.AgentWorkflowTypeInstall, 39 expectedClusterInfo: ClusterInfo{}, 40 }, 41 { 42 name: "default", 43 workflow: workflow.AgentWorkflowTypeAddNodes, 44 objs: defaultObjects(), 45 expectedClusterInfo: ClusterInfo{ 46 ClusterID: "1b5ba46b-7e56-47b1-a326-a9eebddfb38c", 47 ClusterName: "ostest", 48 ReleaseImage: "registry.ci.openshift.org/ocp/release@sha256:65d9b652d0d23084bc45cb66001c22e796d43f5e9e005c2bc2702f94397d596e", 49 Version: "4.15.0", 50 APIDNSName: "api.ostest.test.metalkube.org", 51 Namespace: "cluster0", 52 PullSecret: "c3VwZXJzZWNyZXQK", // notsecret 53 UserCaBundle: "--- bundle ---", 54 Architecture: "amd64", 55 Proxy: &types.Proxy{ 56 HTTPProxy: "http://proxy", 57 HTTPSProxy: "https://proxy", 58 NoProxy: "localhost", 59 }, 60 ImageDigestSources: []types.ImageDigestSource{ 61 { 62 Source: "quay.io/openshift-release-dev/ocp-v4.0-art-dev", 63 Mirrors: []string{ 64 "registry.example.com:5000/ocp4/openshift4", 65 }, 66 }, 67 }, 68 PlatformType: v1beta1.BareMetalPlatformType, 69 SSHKey: "my-ssh-key", 70 OSImage: buildStreamData(), 71 OSImageLocation: "http://my-coreosimage-url/416.94.202402130130-0", 72 IgnitionEndpointWorker: &models.IgnitionEndpoint{ 73 URL: ptr.To("https://192.168.111.5:22623/config/worker"), 74 CaCertificate: ptr.To("LS0tL_FakeCertificate_LS0tCg=="), 75 }, 76 FIPS: true, 77 }, 78 }, 79 { 80 name: "architecture specified in nodesConfig as arm64 and target cluster is amd64", 81 workflow: workflow.AgentWorkflowTypeAddNodes, 82 nodesConfig: AddNodesConfig{ 83 Config: Config{ 84 CPUArchitecture: "arm64", 85 }, 86 }, 87 objs: func(t *testing.T) ([]runtime.Object, []runtime.Object) { 88 t.Helper() 89 objs, ocObjs := defaultObjects()(t) 90 for i, o := range objs { 91 if node, ok := o.(*corev1.Node); ok { 92 node.Status.NodeInfo.Architecture = "amd64" 93 objs[i] = node 94 break 95 } 96 } 97 return objs, ocObjs 98 }, 99 expectedClusterInfo: ClusterInfo{ 100 ClusterID: "1b5ba46b-7e56-47b1-a326-a9eebddfb38c", 101 ClusterName: "ostest", 102 ReleaseImage: "registry.ci.openshift.org/ocp/release@sha256:65d9b652d0d23084bc45cb66001c22e796d43f5e9e005c2bc2702f94397d596e", 103 Version: "4.15.0", 104 APIDNSName: "api.ostest.test.metalkube.org", 105 Namespace: "cluster0", 106 PullSecret: "c3VwZXJzZWNyZXQK", // notsecret 107 UserCaBundle: "--- bundle ---", 108 Architecture: "arm64", 109 Proxy: &types.Proxy{ 110 HTTPProxy: "http://proxy", 111 HTTPSProxy: "https://proxy", 112 NoProxy: "localhost", 113 }, 114 ImageDigestSources: []types.ImageDigestSource{ 115 { 116 Source: "quay.io/openshift-release-dev/ocp-v4.0-art-dev", 117 Mirrors: []string{ 118 "registry.example.com:5000/ocp4/openshift4", 119 }, 120 }, 121 }, 122 PlatformType: v1beta1.BareMetalPlatformType, 123 SSHKey: "my-ssh-key", 124 OSImage: buildStreamData(), 125 OSImageLocation: "http://my-coreosimage-url/416.94.202402130130-1", 126 FIPS: true, 127 IgnitionEndpointWorker: &models.IgnitionEndpoint{ 128 URL: ptr.To("https://192.168.111.5:22623/config/worker"), 129 CaCertificate: ptr.To("LS0tL_FakeCertificate_LS0tCg=="), 130 }, 131 }, 132 }, 133 { 134 name: "not supported platform", 135 workflow: workflow.AgentWorkflowTypeAddNodes, 136 objs: func(t *testing.T) ([]runtime.Object, []runtime.Object) { 137 t.Helper() 138 objs, ocObjs := defaultObjects()(t) 139 for i, o := range ocObjs { 140 if infra, ok := o.(*configv1.Infrastructure); ok { 141 infra.Spec.PlatformSpec.Type = configv1.AWSPlatformType 142 ocObjs[i] = infra 143 break 144 } 145 } 146 return objs, ocObjs 147 }, 148 expectedError: "Platform: Unsupported value: \"aws\": supported values: \"baremetal\", \"vsphere\", \"none\", \"external\"", 149 }, 150 { 151 name: "sshKey from nodes-config.yaml", 152 workflow: workflow.AgentWorkflowTypeAddNodes, 153 objs: defaultObjects(), 154 nodesConfig: AddNodesConfig{ 155 Config: Config{ 156 SSHKey: "ssh-key-from-config", 157 }, 158 }, 159 expectedClusterInfo: ClusterInfo{ 160 ClusterID: "1b5ba46b-7e56-47b1-a326-a9eebddfb38c", 161 ClusterName: "ostest", 162 ReleaseImage: "registry.ci.openshift.org/ocp/release@sha256:65d9b652d0d23084bc45cb66001c22e796d43f5e9e005c2bc2702f94397d596e", 163 Version: "4.15.0", 164 APIDNSName: "api.ostest.test.metalkube.org", 165 Namespace: "cluster0", 166 PullSecret: "c3VwZXJzZWNyZXQK", // notsecret 167 UserCaBundle: "--- bundle ---", 168 Architecture: "amd64", 169 Proxy: &types.Proxy{ 170 HTTPProxy: "http://proxy", 171 HTTPSProxy: "https://proxy", 172 NoProxy: "localhost", 173 }, 174 ImageDigestSources: []types.ImageDigestSource{ 175 { 176 Source: "quay.io/openshift-release-dev/ocp-v4.0-art-dev", 177 Mirrors: []string{ 178 "registry.example.com:5000/ocp4/openshift4", 179 }, 180 }, 181 }, 182 PlatformType: v1beta1.BareMetalPlatformType, 183 SSHKey: "ssh-key-from-config", 184 OSImage: buildStreamData(), 185 OSImageLocation: "http://my-coreosimage-url/416.94.202402130130-0", 186 IgnitionEndpointWorker: &models.IgnitionEndpoint{ 187 URL: ptr.To("https://192.168.111.5:22623/config/worker"), 188 CaCertificate: ptr.To("LS0tL_FakeCertificate_LS0tCg=="), 189 }, 190 FIPS: true, 191 }, 192 }, 193 } 194 for _, tc := range cases { 195 t.Run(tc.name, func(t *testing.T) { 196 agentWorkflow := &workflow.AgentWorkflow{Workflow: tc.workflow} 197 addNodesConfig := &tc.nodesConfig 198 parents := asset.Parents{} 199 parents.Add(agentWorkflow) 200 parents.Add(addNodesConfig) 201 202 var objects, openshiftObjects []runtime.Object 203 if tc.objs != nil { 204 objects, openshiftObjects = tc.objs(t) 205 } 206 fakeClient := fake.NewSimpleClientset(objects...) 207 fakeOCClient := fakeclientconfig.NewSimpleClientset(openshiftObjects...) 208 209 clusterInfo := &ClusterInfo{ 210 Client: fakeClient, 211 OpenshiftClient: fakeOCClient, 212 } 213 err := clusterInfo.Generate(context.Background(), parents) 214 if tc.expectedError == "" { 215 assert.NoError(t, err) 216 assert.Equal(t, tc.expectedClusterInfo.ClusterID, clusterInfo.ClusterID) 217 assert.Equal(t, tc.expectedClusterInfo.ClusterName, clusterInfo.ClusterName) 218 assert.Equal(t, tc.expectedClusterInfo.Version, clusterInfo.Version) 219 assert.Equal(t, tc.expectedClusterInfo.ReleaseImage, clusterInfo.ReleaseImage) 220 assert.Equal(t, tc.expectedClusterInfo.APIDNSName, clusterInfo.APIDNSName) 221 assert.Equal(t, tc.expectedClusterInfo.PullSecret, clusterInfo.PullSecret) 222 assert.Equal(t, tc.expectedClusterInfo.Namespace, clusterInfo.Namespace) 223 assert.Equal(t, tc.expectedClusterInfo.UserCaBundle, clusterInfo.UserCaBundle) 224 assert.Equal(t, tc.expectedClusterInfo.Proxy, clusterInfo.Proxy) 225 assert.Equal(t, tc.expectedClusterInfo.Architecture, clusterInfo.Architecture) 226 assert.Equal(t, tc.expectedClusterInfo.ImageDigestSources, clusterInfo.ImageDigestSources) 227 assert.Equal(t, tc.expectedClusterInfo.DeprecatedImageContentSources, clusterInfo.DeprecatedImageContentSources) 228 assert.Equal(t, tc.expectedClusterInfo.PlatformType, clusterInfo.PlatformType) 229 assert.Equal(t, tc.expectedClusterInfo.SSHKey, clusterInfo.SSHKey) 230 assert.Equal(t, tc.expectedClusterInfo.OSImageLocation, clusterInfo.OSImageLocation) 231 assert.Equal(t, tc.expectedClusterInfo.OSImage, clusterInfo.OSImage) 232 assert.Equal(t, tc.expectedClusterInfo.IgnitionEndpointWorker, clusterInfo.IgnitionEndpointWorker) 233 assert.Equal(t, tc.expectedClusterInfo.FIPS, clusterInfo.FIPS) 234 } else { 235 assert.Regexp(t, tc.expectedError, err.Error()) 236 } 237 }) 238 } 239 } 240 241 func buildStreamData() *stream.Stream { 242 return &stream.Stream{ 243 Architectures: map[string]stream.Arch{ 244 "x86_64": { 245 Artifacts: map[string]stream.PlatformArtifacts{ 246 "metal": { 247 Release: "416.94.202402130130-0", 248 Formats: map[string]stream.ImageFormat{ 249 "iso": { 250 Disk: &stream.Artifact{ 251 Location: "http://my-coreosimage-url/416.94.202402130130-0", 252 }, 253 }, 254 }, 255 }, 256 }, 257 }, 258 "aarch64": { 259 Artifacts: map[string]stream.PlatformArtifacts{ 260 "metal": { 261 Release: "416.94.202402130130-0", 262 Formats: map[string]stream.ImageFormat{ 263 "iso": { 264 Disk: &stream.Artifact{ 265 Location: "http://my-coreosimage-url/416.94.202402130130-1", 266 }, 267 }, 268 }, 269 }, 270 }, 271 }, 272 }, 273 } 274 } 275 276 func makeCoreOsBootImages(t *testing.T, st *stream.Stream) string { 277 t.Helper() 278 data, err := json.Marshal(st) 279 if err != nil { 280 t.Error(err) 281 } 282 283 return string(data) 284 } 285 286 func makeInstallConfig(t *testing.T) string { 287 t.Helper() 288 ic := &types.InstallConfig{ 289 ObjectMeta: v1.ObjectMeta{ 290 Name: "ostest", 291 }, 292 BaseDomain: "test.metalkube.org", 293 ImageDigestSources: []types.ImageDigestSource{ 294 { 295 Source: "quay.io/openshift-release-dev/ocp-v4.0-art-dev", 296 Mirrors: []string{ 297 "registry.example.com:5000/ocp4/openshift4", 298 }, 299 }, 300 }, 301 Platform: types.Platform{ 302 BareMetal: &baremetal.Platform{}, 303 }, 304 SSHKey: "my-ssh-key", 305 FIPS: true, 306 } 307 data, err := yaml.Marshal(ic) 308 if err != nil { 309 t.Error(err) 310 } 311 312 return string(data) 313 } 314 315 func defaultObjects() func(t *testing.T) ([]runtime.Object, []runtime.Object) { 316 return func(t *testing.T) ([]runtime.Object, []runtime.Object) { 317 t.Helper() 318 objects := []runtime.Object{ 319 &corev1.Secret{ 320 ObjectMeta: v1.ObjectMeta{ 321 Name: "pull-secret", 322 Namespace: "openshift-config", 323 }, 324 Data: map[string][]byte{ 325 ".dockerconfigjson": []byte("c3VwZXJzZWNyZXQK"), 326 }, 327 }, 328 &corev1.ConfigMap{ 329 ObjectMeta: v1.ObjectMeta{ 330 Name: "user-ca-bundle", 331 Namespace: "openshift-config", 332 }, 333 Data: map[string]string{ 334 "ca-bundle.crt": "--- bundle ---", 335 }, 336 }, 337 &corev1.Node{ 338 ObjectMeta: v1.ObjectMeta{ 339 Labels: map[string]string{ 340 "node-role.kubernetes.io/master": "", 341 }, 342 }, 343 Status: corev1.NodeStatus{ 344 NodeInfo: corev1.NodeSystemInfo{ 345 Architecture: "amd64", 346 }, 347 }, 348 }, 349 &corev1.ConfigMap{ 350 ObjectMeta: v1.ObjectMeta{ 351 Name: "cluster-config-v1", 352 Namespace: "kube-system", 353 }, 354 Data: map[string]string{ 355 "install-config": makeInstallConfig(t), 356 }, 357 }, 358 &corev1.ConfigMap{ 359 ObjectMeta: v1.ObjectMeta{ 360 Name: "coreos-bootimages", 361 Namespace: "openshift-machine-config-operator", 362 }, 363 Data: map[string]string{ 364 "stream": makeCoreOsBootImages(t, buildStreamData()), 365 }, 366 }, 367 &corev1.Secret{ 368 ObjectMeta: v1.ObjectMeta{ 369 Name: "worker-user-data-managed", 370 Namespace: "openshift-machine-api", 371 }, 372 Data: map[string][]byte{ 373 "userData": []byte(`{"ignition":{"config":{"merge":[{"source":"https://192.168.111.5:22623/config/worker","verification":{}}], 374 "replace":{"verification":{}}},"proxy":{},"security":{"tls":{"certificateAuthorities":[{"source":"data:text/plain;charset=utf-8;base64,LS0tL_FakeCertificate_LS0tCg==", 375 "verification":{}}]}},"timeouts":{},"version":"3.4.0"},"kernelArguments":{},"passwd":{},"storage":{},"systemd":{}}`), 376 }, 377 }, 378 } 379 380 openshiftObjects := []runtime.Object{ 381 &configv1.ClusterVersion{ 382 ObjectMeta: v1.ObjectMeta{ 383 Name: "version", 384 }, 385 Spec: configv1.ClusterVersionSpec{ 386 ClusterID: "1b5ba46b-7e56-47b1-a326-a9eebddfb38c", 387 }, 388 Status: configv1.ClusterVersionStatus{ 389 History: []configv1.UpdateHistory{ 390 { 391 Image: "registry.ci.openshift.org/ocp/release@sha256:65d9b652d0d23084bc45cb66001c22e796d43f5e9e005c2bc2702f94397d596e", 392 Version: "4.15.0", 393 }, 394 }, 395 }, 396 }, 397 &configv1.Proxy{ 398 ObjectMeta: v1.ObjectMeta{ 399 Name: "cluster", 400 }, 401 Spec: configv1.ProxySpec{ 402 HTTPProxy: "http://proxy", 403 HTTPSProxy: "https://proxy", 404 NoProxy: "localhost", 405 }, 406 }, 407 &configv1.Infrastructure{ 408 ObjectMeta: v1.ObjectMeta{ 409 Name: "cluster", 410 }, 411 Spec: configv1.InfrastructureSpec{ 412 PlatformSpec: configv1.PlatformSpec{ 413 Type: configv1.BareMetalPlatformType, 414 }, 415 }, 416 }, 417 } 418 419 return objects, openshiftObjects 420 } 421 }