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  }