github.com/openshift/installer@v1.4.17/pkg/asset/agent/agentconfig/agenthosts_test.go (about)

     1  package agentconfig
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    10  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  	"k8s.io/utils/pointer"
    12  
    13  	aiv1beta1 "github.com/openshift/assisted-service/api/v1beta1"
    14  	"github.com/openshift/installer/pkg/asset"
    15  	agentAsset "github.com/openshift/installer/pkg/asset/agent"
    16  	"github.com/openshift/installer/pkg/asset/agent/joiner"
    17  	"github.com/openshift/installer/pkg/asset/agent/workflow"
    18  	"github.com/openshift/installer/pkg/asset/installconfig"
    19  	"github.com/openshift/installer/pkg/ipnet"
    20  	"github.com/openshift/installer/pkg/types"
    21  	"github.com/openshift/installer/pkg/types/agent"
    22  	"github.com/openshift/installer/pkg/types/baremetal"
    23  )
    24  
    25  const (
    26  	agentNetworkConfigOne = `interfaces:
    27  - ipv4:
    28      address:
    29      - ip: 192.168.111.80
    30        prefix-length: 24
    31      dhcp: false
    32      enabled: true
    33    mac-address: 28:d2:44:d2:b2:1a
    34    name: eth0
    35    state: up
    36    type: ethernet
    37  `
    38  	agentNetworkConfigTwo = `interfaces:
    39  - ipv4:
    40      address:
    41      - ip: 192.168.111.81
    42        prefix-length: 24
    43      dhcp: false
    44      enabled: true
    45    mac-address: 28:d2:44:d2:b2:1b
    46    name: eth0
    47    state: up
    48    type: ethernet
    49  `
    50  	installNetworkConfigOne = `interfaces:
    51  - ipv4:
    52      address:
    53      - ip: 192.168.111.80
    54        prefix-length: 24
    55      dhcp: false
    56      enabled: true
    57    mac-address: 28:d2:44:b0:bf:01
    58    name: eth0
    59    state: up
    60    type: ethernet
    61  `
    62  	installNetworkConfigTwo = `interfaces:
    63  - ipv4:
    64      address:
    65      - ip: 192.168.111.81
    66        prefix-length: 24
    67      dhcp: false
    68      enabled: true
    69    mac-address: 28:d2:44:b0:bf:02
    70    name: eth0
    71    state: up
    72    type: ethernet
    73  `
    74  )
    75  
    76  func TestAgentHosts_Generate(t *testing.T) {
    77  	cases := []struct {
    78  		name           string
    79  		dependencies   []asset.Asset
    80  		expectedError  string
    81  		expectedConfig *AgentHostsBuilder
    82  	}{
    83  		{
    84  			name: "host-from-add-nodes-config",
    85  			dependencies: []asset.Asset{
    86  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeAddNodes},
    87  				&joiner.AddNodesConfig{
    88  					Config: joiner.Config{
    89  						Hosts: []agent.Host{
    90  							{
    91  								Hostname: "extra-worker-0",
    92  								Role:     "worker",
    93  								Interfaces: []*aiv1beta1.Interface{
    94  									{
    95  										Name:       "enp3s1",
    96  										MacAddress: "28:d2:44:d2:b2:1a",
    97  									},
    98  								},
    99  							},
   100  						},
   101  					},
   102  				},
   103  				getNoHostsInstallConfig(),
   104  				getNoHostsAgentConfig(),
   105  			},
   106  			expectedConfig: agentHosts().hosts(agentHost().name("extra-worker-0").role("worker").interfaces(iface("enp3s1", "28:d2:44:d2:b2:1a"))),
   107  		},
   108  		{
   109  			name: "no-hosts",
   110  			dependencies: []asset.Asset{
   111  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   112  				&joiner.AddNodesConfig{},
   113  				getNoHostsInstallConfig(),
   114  				getNoHostsAgentConfig(),
   115  			},
   116  			expectedConfig: nil,
   117  		},
   118  		{
   119  			name: "host-from-agent-config",
   120  			dependencies: []asset.Asset{
   121  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   122  				&joiner.AddNodesConfig{},
   123  				getInstallConfigSingleHost(),
   124  				getAgentConfigSingleHost(),
   125  			},
   126  			expectedConfig: agentHosts().hosts(agentHost().name("test").role("master").interfaces(iface("enp3s1", "28:d2:44:d2:b2:1a")).deviceHint()),
   127  		},
   128  		{
   129  			name: "host-from-install-config",
   130  			dependencies: []asset.Asset{
   131  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   132  				&joiner.AddNodesConfig{},
   133  				getInstallConfigSingleHost(),
   134  				getNoHostsAgentConfig(),
   135  			},
   136  			expectedConfig: agentHosts().hosts(agentHost().name("test").role("master").interfaces(iface("boot", "28:d2:44:b0:bf:01")).deviceHint()),
   137  		},
   138  		{
   139  			name: "multi-host-from-agent-config",
   140  			dependencies: []asset.Asset{
   141  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   142  				&joiner.AddNodesConfig{},
   143  				getInstallConfigSingleHost(),
   144  				getAgentConfigMultiHost(),
   145  			},
   146  			expectedConfig: agentHosts().hosts(
   147  				agentHost().name("test").role("master").interfaces(iface("enp3s1", "28:d2:44:d2:b2:1a")).deviceHint().networkConfig(agentNetworkConfigOne),
   148  				agentHost().name("test-2").role("worker").interfaces(iface("enp3s1", "28:d2:44:d2:b2:1b")).networkConfig(agentNetworkConfigTwo)),
   149  		},
   150  		{
   151  			name: "multi-host-from-install-config",
   152  			dependencies: []asset.Asset{
   153  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   154  				&joiner.AddNodesConfig{},
   155  				getInstallConfigMultiHost(),
   156  				getNoHostsAgentConfig(),
   157  			},
   158  			expectedConfig: agentHosts().hosts(
   159  				agentHost().name("test").role("master").interfaces(iface("eth0", "28:d2:44:b0:bf:01")).deviceHint().networkConfig(installNetworkConfigOne),
   160  				agentHost().name("test-2").role("worker").interfaces(iface("eth0", "28:d2:44:b0:bf:02")).networkConfig(installNetworkConfigTwo)),
   161  		},
   162  		{
   163  			name: "unsupported-device-name-agent-config",
   164  			dependencies: []asset.Asset{
   165  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   166  				&joiner.AddNodesConfig{},
   167  				getInstallConfigSingleHost(),
   168  				getAgentConfigUnsupportedDeviceName(),
   169  			},
   170  			expectedError:  "invalid Hosts configuration: Hosts[0].rootDeviceHints.deviceName: Invalid value: \"/dev/disk/by-id/wwn-0x600508e000000000ce506dc50ab0ad05\": Device Name of root device hint must be path in /dev/ or /dev/disk/by-path/",
   171  			expectedConfig: nil,
   172  		},
   173  		{
   174  			name: "unsupported-wwn-extension-install-config",
   175  			dependencies: []asset.Asset{
   176  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   177  				&joiner.AddNodesConfig{},
   178  				getInstallConfigUnsupportedWWNExtension(),
   179  				getNoHostsAgentConfig(),
   180  			},
   181  			expectedError:  "invalid Hosts configuration: Hosts[0].rootDeviceHints.wwnWithExtension: Forbidden: WWN extensions are not supported in root device hints",
   182  			expectedConfig: nil,
   183  		},
   184  		{
   185  			name: "unsupported-www-vendor-extension-agent-config",
   186  			dependencies: []asset.Asset{
   187  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   188  				&joiner.AddNodesConfig{},
   189  				getInstallConfigSingleHost(),
   190  				getAgentConfigUnsupportedWWNVendorExtension(),
   191  			},
   192  			expectedError:  "invalid Hosts configuration: Hosts[0].rootDeviceHints.wwnVendorExtension: Forbidden: WWN vendor extensions are not supported in root device hints",
   193  			expectedConfig: nil,
   194  		},
   195  		{
   196  			name: "node-hostname-and-role-are-not-required",
   197  			dependencies: []asset.Asset{
   198  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   199  				&joiner.AddNodesConfig{},
   200  				getInstallConfigNoHostnameOrRole(),
   201  				getNoHostsAgentConfig(),
   202  			},
   203  			expectedConfig: agentHosts().hosts(agentHost().interfaces(iface("boot", "28:d2:44:b0:bf:01")).deviceHint()),
   204  		},
   205  		{
   206  			name: "host-roles-have-incorrect-values",
   207  			dependencies: []asset.Asset{
   208  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   209  				&joiner.AddNodesConfig{},
   210  				getInstallConfigSingleHost(),
   211  				getAgentConfigInvalidHostRole(),
   212  			},
   213  			expectedError:  "invalid Hosts configuration: Hosts[0].Host: Forbidden: host role has incorrect value. Role must either be 'master' or 'worker'",
   214  			expectedConfig: nil,
   215  		},
   216  		{
   217  			name: "different-hosts-cannot-have-same-mac",
   218  			dependencies: []asset.Asset{
   219  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   220  				&joiner.AddNodesConfig{},
   221  				getInstallConfigSameMac(),
   222  				getNoHostsAgentConfig(),
   223  			},
   224  			expectedError:  "invalid Hosts configuration: Hosts[1].Interfaces[0].macAddress: Invalid value: \"28:d2:44:b0:bf:01\": duplicate MAC address found",
   225  			expectedConfig: nil,
   226  		},
   227  		{
   228  			name: "invalid-mac",
   229  			dependencies: []asset.Asset{
   230  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   231  				&joiner.AddNodesConfig{},
   232  				getInstallConfigSingleHost(),
   233  				getAgentConfigInvalidMac(),
   234  			},
   235  			expectedError:  "invalid Hosts configuration: Hosts[0].Interfaces[0].macAddress: Invalid value: \"000000\": address 000000: invalid MAC address",
   236  			expectedConfig: nil,
   237  		},
   238  		{
   239  			name: "duplicate-mac-same-host-agent-config",
   240  			dependencies: []asset.Asset{
   241  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   242  				&joiner.AddNodesConfig{},
   243  				getInstallConfigSingleHost(),
   244  				getAgentConfigInvalidInterfaces(),
   245  			},
   246  			expectedError:  "invalid Hosts configuration: Hosts[0].Interfaces[1].macAddress: Invalid value: \"28:d2:44:d2:b2:1a\": duplicate MAC address found",
   247  			expectedConfig: nil,
   248  		},
   249  		{
   250  			name: "duplicate-mac-same-host-install-config",
   251  			dependencies: []asset.Asset{
   252  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   253  				&joiner.AddNodesConfig{},
   254  				getInstallConfigInvalidInterfaces(),
   255  				getNoHostsAgentConfig(),
   256  			},
   257  			expectedError:  "invalid Hosts configuration: Hosts[0].Interfaces[1].macAddress: Invalid value: \"28:d2:44:b0:bf:01\": duplicate MAC address found",
   258  			expectedConfig: nil,
   259  		},
   260  		{
   261  			name: "invalid-rendezvous-agent-config",
   262  			dependencies: []asset.Asset{
   263  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   264  				&joiner.AddNodesConfig{},
   265  				getInstallConfigSingleHost(),
   266  				getAgentConfigInvalidRendezvousIP(),
   267  			},
   268  			expectedError:  "invalid Hosts configuration: Hosts[1].Host: Forbidden: Host test-2 has role 'worker' and has the rendezvousIP assigned to it. The rendezvousIP must be assigned to a control plane host.",
   269  			expectedConfig: nil,
   270  		},
   271  		{
   272  			name: "invalid-rendezvous-install-config",
   273  			dependencies: []asset.Asset{
   274  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   275  				&joiner.AddNodesConfig{},
   276  				getInstallConfigInvalidRendezvousIP(),
   277  				getNoHostsAgentConfig(),
   278  			},
   279  			expectedError:  "invalid Hosts configuration: Hosts[0].Host: Forbidden: Host test has role 'worker' and has the rendezvousIP assigned to it. The rendezvousIP must be assigned to a control plane host.",
   280  			expectedConfig: nil,
   281  		},
   282  		{
   283  			name: "host-missing-interface-error",
   284  			dependencies: []asset.Asset{
   285  				&workflow.AgentWorkflow{Workflow: workflow.AgentWorkflowTypeInstall},
   286  				&joiner.AddNodesConfig{},
   287  				getInstallConfigSingleHost(),
   288  				getAgentConfigMissingInterfaces(),
   289  			},
   290  			expectedError:  "invalid Hosts configuration: [Hosts[0].Interfaces: Required value: at least one interface must be defined for each node, Hosts[1].Interfaces: Required value: at least one interface must be defined for each node, Hosts[2].Interfaces: Required value: at least one interface must be defined for each node]",
   291  			expectedConfig: nil,
   292  		},
   293  	}
   294  	for _, tc := range cases {
   295  		t.Run(tc.name, func(t *testing.T) {
   296  			parents := asset.Parents{}
   297  			parents.Add(tc.dependencies...)
   298  
   299  			asset := &AgentHosts{}
   300  			err := asset.Generate(context.Background(), parents)
   301  
   302  			if tc.expectedError != "" {
   303  				assert.Equal(t, tc.expectedError, err.Error())
   304  			} else {
   305  				assert.NoError(t, err)
   306  				if tc.expectedConfig != nil {
   307  					assert.Equal(t, tc.expectedConfig.build().Hosts, asset.Hosts, "unexpected Config in AgentHosts")
   308  				} else {
   309  					assert.Nil(t, asset.Hosts)
   310  				}
   311  			}
   312  		})
   313  	}
   314  }
   315  
   316  func getNoHostsInstallConfig() *agentAsset.OptionalInstallConfig {
   317  	_, newCidr, err1 := net.ParseCIDR("192.168.111.0/24")
   318  	_, machineNetCidr, err2 := net.ParseCIDR("10.10.11.0/24")
   319  	if err1 != nil || err2 != nil {
   320  		return nil
   321  	}
   322  
   323  	return &agentAsset.OptionalInstallConfig{
   324  		AssetBase: installconfig.AssetBase{
   325  			Config: &types.InstallConfig{
   326  				ObjectMeta: metav1.ObjectMeta{
   327  					Name: "test-cluster",
   328  				},
   329  				BaseDomain: "test-domain",
   330  				PullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"authorization value\"}}}",
   331  				ControlPlane: &types.MachinePool{
   332  					Name:     "master",
   333  					Replicas: pointer.Int64(3),
   334  					Platform: types.MachinePoolPlatform{},
   335  				},
   336  				Networking: &types.Networking{
   337  					MachineNetwork: []types.MachineNetworkEntry{
   338  						{
   339  							CIDR: ipnet.IPNet{IPNet: *machineNetCidr},
   340  						},
   341  					},
   342  					ClusterNetwork: []types.ClusterNetworkEntry{
   343  						{
   344  							CIDR:       ipnet.IPNet{IPNet: *newCidr},
   345  							HostPrefix: 23,
   346  						},
   347  					},
   348  					ServiceNetwork: []ipnet.IPNet{
   349  						*ipnet.MustParseCIDR("172.30.0.0/16"),
   350  					},
   351  				},
   352  				Platform: types.Platform{
   353  					BareMetal: &baremetal.Platform{
   354  						APIVIPs:     []string{"192.168.122.10"},
   355  						IngressVIPs: []string{"192.168.122.11"},
   356  					},
   357  				},
   358  			},
   359  		},
   360  		Supplied: true,
   361  	}
   362  }
   363  
   364  func getNoHostsAgentConfig() *AgentConfig {
   365  	return &AgentConfig{
   366  		Config: &agent.Config{
   367  			TypeMeta: metav1.TypeMeta{
   368  				Kind:       "AgentConfig",
   369  				APIVersion: "v1alpha1",
   370  			},
   371  			ObjectMeta: metav1.ObjectMeta{
   372  				Name:      "ocp-edge-cluster-0",
   373  				Namespace: "cluster-0",
   374  			},
   375  			RendezvousIP: "192.168.111.80",
   376  		},
   377  	}
   378  }
   379  
   380  func getAgentConfigSingleHost() *AgentConfig {
   381  	a := getNoHostsAgentConfig()
   382  	a.Config.Hosts = []agent.Host{
   383  		{
   384  			Hostname: "test",
   385  			Role:     "master",
   386  			Interfaces: []*aiv1beta1.Interface{
   387  				{
   388  					Name:       "enp3s1",
   389  					MacAddress: "28:d2:44:d2:b2:1a",
   390  				},
   391  			},
   392  			RootDeviceHints: baremetal.RootDeviceHints{
   393  				DeviceName: "/dev/sda",
   394  			},
   395  		},
   396  	}
   397  	return a
   398  }
   399  
   400  func getAgentConfigMultiHost() *AgentConfig {
   401  	a := getAgentConfigSingleHost()
   402  	a.Config.Hosts[0].NetworkConfig.Raw = []byte(agentNetworkConfigOne)
   403  	host := agent.Host{
   404  		Hostname: "test-2",
   405  		Role:     "worker",
   406  		Interfaces: []*aiv1beta1.Interface{
   407  			{
   408  				Name:       "enp3s1",
   409  				MacAddress: "28:d2:44:d2:b2:1b",
   410  			},
   411  		},
   412  		NetworkConfig: aiv1beta1.NetConfig{
   413  			Raw: []byte(agentNetworkConfigTwo),
   414  		},
   415  	}
   416  	a.Config.Hosts = append(a.Config.Hosts, host)
   417  	return a
   418  }
   419  
   420  func getAgentConfigUnsupportedDeviceName() *AgentConfig {
   421  	a := getAgentConfigSingleHost()
   422  	a.Config.Hosts[0].RootDeviceHints = baremetal.RootDeviceHints{
   423  		DeviceName: "/dev/disk/by-id/wwn-0x600508e000000000ce506dc50ab0ad05",
   424  	}
   425  	return a
   426  }
   427  
   428  func getAgentConfigUnsupportedWWNVendorExtension() *AgentConfig {
   429  	a := getAgentConfigSingleHost()
   430  	a.Config.Hosts[0].RootDeviceHints = baremetal.RootDeviceHints{
   431  		WWNVendorExtension: "wwn-with-vendor-extension-value",
   432  	}
   433  	return a
   434  }
   435  
   436  func getAgentConfigInvalidHostRole() *AgentConfig {
   437  	a := getAgentConfigSingleHost()
   438  	a.Config.Hosts[0].Role = "invalid-role"
   439  	return a
   440  }
   441  
   442  func getAgentConfigInvalidMac() *AgentConfig {
   443  	a := getAgentConfigSingleHost()
   444  	a.Config.Hosts[0].Interfaces[0].MacAddress = "000000"
   445  	return a
   446  }
   447  
   448  func getAgentConfigInvalidInterfaces() *AgentConfig {
   449  	a := getNoHostsAgentConfig()
   450  	a.Config.Hosts = []agent.Host{
   451  		{
   452  			Hostname: "test",
   453  			Role:     "master",
   454  			Interfaces: []*aiv1beta1.Interface{
   455  				{
   456  					Name:       "enp3s1",
   457  					MacAddress: "28:d2:44:d2:b2:1a",
   458  				},
   459  				{
   460  					Name:       "enp3s2",
   461  					MacAddress: "28:d2:44:d2:b2:1a",
   462  				},
   463  			},
   464  		},
   465  	}
   466  	return a
   467  }
   468  
   469  func getAgentConfigMissingInterfaces() *AgentConfig {
   470  	a := getNoHostsAgentConfig()
   471  	a.Config.Hosts = []agent.Host{
   472  		{
   473  			Hostname: "control-0.example.org",
   474  			Role:     "master",
   475  		},
   476  		{
   477  			Hostname: "control-1.example.org",
   478  			Role:     "master",
   479  		},
   480  		{
   481  			Hostname: "control-2.example.org",
   482  			Role:     "master",
   483  		},
   484  	}
   485  	return a
   486  }
   487  
   488  func getAgentConfigInvalidRendezvousIP() *AgentConfig {
   489  	a := getAgentConfigMultiHost()
   490  	a.Config.RendezvousIP = "192.168.111.81"
   491  	return a
   492  }
   493  
   494  func getInstallConfigSingleHost() *agentAsset.OptionalInstallConfig {
   495  	a := getNoHostsInstallConfig()
   496  	a.Config.Platform.BareMetal.Hosts = []*baremetal.Host{
   497  		{
   498  			Name:           "test",
   499  			Role:           "master",
   500  			BootMACAddress: "28:d2:44:b0:bf:01",
   501  			RootDeviceHints: &baremetal.RootDeviceHints{
   502  				DeviceName: "/dev/sda",
   503  			},
   504  		},
   505  	}
   506  	return a
   507  }
   508  
   509  func getInstallConfigMultiHost() *agentAsset.OptionalInstallConfig {
   510  	a := getInstallConfigSingleHost()
   511  	a.Config.Platform.BareMetal.Hosts[0].NetworkConfig = &apiextv1.JSON{
   512  		Raw: []byte(installNetworkConfigOne),
   513  	}
   514  	host := &baremetal.Host{
   515  		Name:           "test-2",
   516  		Role:           "worker",
   517  		BootMACAddress: "28:d2:44:b0:bf:02",
   518  		NetworkConfig: &apiextv1.JSON{
   519  			Raw: []byte(installNetworkConfigTwo),
   520  		},
   521  	}
   522  	a.Config.Platform.BareMetal.Hosts = append(a.Config.Platform.BareMetal.Hosts, host)
   523  	return a
   524  }
   525  
   526  func getInstallConfigSameMac() *agentAsset.OptionalInstallConfig {
   527  	var networkConfigSameMac = `interfaces:
   528  - ipv4:
   529      address:
   530      - ip: 192.168.111.81
   531        prefix-length: 24
   532      dhcp: false
   533      enabled: true
   534    mac-address: 28:d2:44:b0:bf:01
   535    name: eth0
   536    state: up
   537    type: ethernet
   538  `
   539  	a := getInstallConfigMultiHost()
   540  	a.Config.Platform.BareMetal.Hosts[1].BootMACAddress = "28:d2:44:b0:bf:01"
   541  	a.Config.Platform.BareMetal.Hosts[1].NetworkConfig = &apiextv1.JSON{
   542  		Raw: []byte(networkConfigSameMac),
   543  	}
   544  	return a
   545  }
   546  
   547  func getInstallConfigInvalidInterfaces() *agentAsset.OptionalInstallConfig {
   548  	var networkConfigSameMacSameHost = `interfaces:
   549  - ipv4:
   550      address:
   551      - ip: 192.168.111.80
   552        prefix-length: 24
   553      dhcp: false
   554      enabled: true
   555    mac-address: 28:d2:44:b0:bf:01
   556    name: eth0
   557    state: up
   558    type: ethernet
   559  - ipv4:
   560      address:
   561      - ip: 192.168.111.81
   562        prefix-length: 24
   563      dhcp: false
   564      enabled: true
   565    mac-address: 28:d2:44:b0:bf:01
   566    name: eth0
   567    state: up
   568    type: ethernet
   569  `
   570  	a := getInstallConfigSingleHost()
   571  	a.Config.Platform.BareMetal.Hosts[0].NetworkConfig = &apiextv1.JSON{
   572  		Raw: []byte(networkConfigSameMacSameHost),
   573  	}
   574  	return a
   575  }
   576  
   577  func getInstallConfigUnsupportedWWNExtension() *agentAsset.OptionalInstallConfig {
   578  	a := getInstallConfigSingleHost()
   579  	a.Config.Platform.BareMetal.Hosts[0].RootDeviceHints = &baremetal.RootDeviceHints{
   580  		WWNWithExtension: "wwn-with-extension-value",
   581  	}
   582  	return a
   583  }
   584  
   585  func getInstallConfigNoHostnameOrRole() *agentAsset.OptionalInstallConfig {
   586  	a := getInstallConfigSingleHost()
   587  	a.Config.Platform.BareMetal.Hosts[0].Name = ""
   588  	a.Config.Platform.BareMetal.Hosts[0].Role = ""
   589  	return a
   590  }
   591  
   592  func getInstallConfigInvalidRendezvousIP() *agentAsset.OptionalInstallConfig {
   593  	a := getInstallConfigSingleHost()
   594  	a.Config.Platform.BareMetal.Hosts[0].NetworkConfig = &apiextv1.JSON{
   595  		Raw: []byte(installNetworkConfigOne),
   596  	}
   597  	a.Config.Platform.BareMetal.Hosts[0].Role = "worker"
   598  	return a
   599  }
   600  
   601  // AgentConfigBuilder it's a builder class to make it easier creating agent.Config instance
   602  // used in the test cases.
   603  type AgentHostsBuilder struct {
   604  	AgentHosts
   605  }
   606  
   607  func agentHosts() *AgentHostsBuilder {
   608  	return &AgentHostsBuilder{
   609  		AgentHosts: AgentHosts{
   610  			Hosts: []agent.Host{{}},
   611  		},
   612  	}
   613  }
   614  
   615  func (ahb *AgentHostsBuilder) build() *AgentHosts {
   616  	return &ahb.AgentHosts
   617  }
   618  
   619  func (ahb *AgentHostsBuilder) hosts(builders ...*HostBuilder) *AgentHostsBuilder {
   620  	hosts := []agent.Host{}
   621  	for _, b := range builders {
   622  		hosts = append(hosts, *b.build())
   623  	}
   624  	ahb.Hosts = hosts
   625  
   626  	return ahb
   627  }
   628  
   629  // HostBuilder it's a builder class to make it easier creating agent.Host instances
   630  // used in the test cases, as part of the AgentHosts type.
   631  type HostBuilder struct {
   632  	agent.Host
   633  }
   634  
   635  func agentHost() *HostBuilder {
   636  	return &HostBuilder{}
   637  }
   638  
   639  func (hb *HostBuilder) build() *agent.Host {
   640  	return &hb.Host
   641  }
   642  
   643  func (hb *HostBuilder) name(name string) *HostBuilder {
   644  	hb.Host.Hostname = name
   645  	return hb
   646  }
   647  
   648  func (hb *HostBuilder) role(role string) *HostBuilder {
   649  	hb.Host.Role = role
   650  	return hb
   651  }
   652  
   653  func (hb *HostBuilder) interfaces(builders ...*InterfacetBuilder) *HostBuilder {
   654  	ifaces := []*aiv1beta1.Interface{}
   655  	for _, b := range builders {
   656  		ifaces = append(ifaces, b.build())
   657  	}
   658  	hb.Host.Interfaces = ifaces
   659  	return hb
   660  }
   661  
   662  func (hb *HostBuilder) networkConfig(raw string) *HostBuilder {
   663  	hb.Host.NetworkConfig = aiv1beta1.NetConfig{
   664  		Raw: unmarshalJSON([]byte(raw)),
   665  	}
   666  	return hb
   667  }
   668  
   669  func (hb *HostBuilder) deviceHint() *HostBuilder {
   670  	hb.Host.RootDeviceHints = baremetal.RootDeviceHints{
   671  		DeviceName: "/dev/sda",
   672  	}
   673  	return hb
   674  }
   675  
   676  // InterfacetBuilder it's a builder class to make it easier creating aiv1beta1.Interface instances
   677  // used in the test cases, as part of the agent.Config type.
   678  type InterfacetBuilder struct {
   679  	aiv1beta1.Interface
   680  }
   681  
   682  func iface(name string, mac string) *InterfacetBuilder {
   683  	return &InterfacetBuilder{
   684  		Interface: aiv1beta1.Interface{
   685  			Name:       name,
   686  			MacAddress: mac,
   687  		},
   688  	}
   689  }
   690  
   691  func (ib *InterfacetBuilder) build() *aiv1beta1.Interface {
   692  	return &ib.Interface
   693  }