github.com/openshift/installer@v1.4.17/pkg/asset/imagebased/image/imagebased_config_test.go (about)

     1  package image
     2  
     3  import (
     4  	"errors"
     5  	"os"
     6  	"os/exec"
     7  	"testing"
     8  
     9  	"github.com/golang/mock/gomock"
    10  	"github.com/stretchr/testify/assert"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  	"sigs.k8s.io/yaml"
    13  
    14  	aiv1beta1 "github.com/openshift/assisted-service/api/v1beta1"
    15  	"github.com/openshift/installer/pkg/asset"
    16  	"github.com/openshift/installer/pkg/asset/mock"
    17  	"github.com/openshift/installer/pkg/types"
    18  	"github.com/openshift/installer/pkg/types/imagebased"
    19  )
    20  
    21  var (
    22  	rawNMStateConfig = `
    23  interfaces:
    24    - name: eth0
    25      type: ethernet
    26      state: up
    27      mac-address: 00:00:00:00:00:00
    28      ipv4:
    29        enabled: true
    30        address:
    31          - ip: 192.168.122.2
    32            prefix-length: 23
    33        dhcp: false`
    34  )
    35  
    36  func TestImageBasedInstallConfig_LoadedFromDisk(t *testing.T) {
    37  	skipTestIfnmstatectlIsMissing(t)
    38  
    39  	cases := []struct {
    40  		name       string
    41  		data       string
    42  		fetchError error
    43  
    44  		expectedError  string
    45  		expectedFound  bool
    46  		expectedConfig *ImageBasedInstallationConfigBuilder
    47  	}{
    48  		{
    49  			name: "valid-config-single-node",
    50  			data: `
    51  apiVersion: v1beta1
    52  metadata:
    53    name: image-based-installation-config
    54  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
    55  seedImage: quay.io/openshift-kni/seed-image:4.16.0
    56  seedVersion: 4.16.0
    57  installationDisk: /dev/vda
    58  networkConfig:
    59    interfaces:
    60      - name: eth0
    61        type: ethernet
    62        state: up
    63        mac-address: 00:00:00:00:00:00
    64        ipv4:
    65          enabled: true
    66          address:
    67            - ip: 192.168.122.2
    68              prefix-length: 23
    69          dhcp: false
    70  `,
    71  
    72  			expectedFound:  true,
    73  			expectedConfig: ibiConfig(),
    74  		},
    75  		{
    76  			name: "not-yaml",
    77  			data: `This is not a yaml file`,
    78  
    79  			expectedFound: false,
    80  			expectedError: "failed to unmarshal image-based-installation-config.yaml: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type imagebased.InstallationConfig",
    81  		},
    82  		{
    83  			name:       "file-not-found",
    84  			fetchError: &os.PathError{Err: os.ErrNotExist},
    85  
    86  			expectedFound: false,
    87  		},
    88  		{
    89  			name:       "error-fetching-file",
    90  			fetchError: errors.New("fetch failed"),
    91  
    92  			expectedFound: false,
    93  			expectedError: "failed to load image-based-installation-config.yaml file: fetch failed",
    94  		},
    95  		{
    96  			name: "unknown-field",
    97  			data: `
    98  apiVersion: v1beta1
    99  metadata:
   100    name: image-based-installation-config
   101  wrongField: wrongValue`,
   102  
   103  			expectedFound: false,
   104  			expectedError: "failed to unmarshal image-based-installation-config.yaml: error unmarshaling JSON: while decoding JSON: json: unknown field \"wrongField\"",
   105  		},
   106  		{
   107  			name: "empty-pullSecret",
   108  			data: `
   109  apiVersion: v1beta1
   110  metadata:
   111    name: image-based-installation-config
   112  seedVersion: 4.16.0
   113  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   114  installationDisk: /dev/vda`,
   115  
   116  			expectedFound: false,
   117  			expectedError: "invalid Image-based Installation ISO Config: pullSecret: Required value: you must specify a pullSecret",
   118  		},
   119  		{
   120  			name: "invalid-pullSecret",
   121  			data: `
   122  apiVersion: v1beta1
   123  metadata:
   124    name: image-based-installation-config
   125  pullSecret: "{\"missing\":\"auths\"}"
   126  seedVersion: 4.16.0
   127  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   128  installationDisk: /dev/vda`,
   129  
   130  			expectedFound: false,
   131  			expectedError: "invalid Image-based Installation ISO Config: pullSecret: Invalid value: \"{\\\"missing\\\":\\\"auths\\\"}\": auths required",
   132  		},
   133  		{
   134  			name: "invalid-sshKey",
   135  			data: `
   136  apiVersion: v1beta1
   137  metadata:
   138    name: image-based-installation-config
   139  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   140  seedVersion: 4.16.0
   141  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   142  installationDisk: /dev/vda
   143  sshKey: invalid_ssh_key`,
   144  
   145  			expectedFound: false,
   146  			expectedError: "invalid Image-based Installation ISO Config: sshKey: Invalid value: \"invalid_ssh_key\": ssh: no key found",
   147  		},
   148  		{
   149  			name: "empty-seedVersion",
   150  			data: `
   151  apiVersion: v1beta1
   152  metadata:
   153    name: image-based-installation-config
   154  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   155  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   156  installationDisk: /dev/vda`,
   157  
   158  			expectedFound: false,
   159  			expectedError: "invalid Image-based Installation ISO Config: seedVersion: Required value: you must specify a seedVersion",
   160  		},
   161  		{
   162  			name: "empty-seedImage",
   163  			data: `
   164  apiVersion: v1beta1
   165  metadata:
   166    name: image-based-installation-config
   167  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   168  seedVersion: 4.16.0
   169  installationDisk: /dev/vda`,
   170  
   171  			expectedFound: false,
   172  			expectedError: "invalid Image-based Installation ISO Config: seedImage: Required value: you must specify a seedImage",
   173  		},
   174  		{
   175  			name: "empty-installationDisk",
   176  			data: `
   177  apiVersion: v1beta1
   178  metadata:
   179    name: image-based-installation-config
   180  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   181  seedImage: "quay.io/openshift-kni/seed-image:4.16.0"
   182  seedVersion: "4.16.0"`,
   183  
   184  			expectedFound: false,
   185  			expectedError: "invalid Image-based Installation ISO Config: installationDisk: Required value: you must specify an installationDisk",
   186  		},
   187  		{
   188  			name: "invalid-additionalTrustBundle",
   189  			data: `
   190  apiVersion: v1beta1
   191  metadata:
   192    name: image-based-installation-config
   193  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   194  seedVersion: 4.16.0
   195  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   196  installationDisk: /dev/vda
   197  additionalTrustBundle: invalid_cert
   198  `,
   199  
   200  			expectedFound: false,
   201  			expectedError: "invalid Image-based Installation ISO Config: additionalTrustBundle: Invalid value: \"invalid_cert\": invalid block",
   202  		},
   203  		{
   204  			name: "invalid-networkConfig",
   205  			data: `
   206  apiVersion: v1beta1
   207  metadata:
   208    name: image-based-installation-config
   209  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   210  seedVersion: 4.16.0
   211  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   212  installationDisk: /dev/vda
   213  networkConfig:
   214    invalid: config
   215  `,
   216  
   217  			expectedFound: false,
   218  			expectedError: "networkConfig: Invalid value: invalid: config\n: failed to execute 'nmstatectl gc', error: InvalidArgument: Invalid YAML string: unknown field `invalid`",
   219  		},
   220  		{
   221  			name: "invalid-imageDigestSources",
   222  			data: `
   223  apiVersion: v1beta1
   224  metadata:
   225    name: image-based-installation-config
   226  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   227  seedVersion: 4.16.0
   228  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   229  installationDisk: /dev/vda
   230  imageDigestSources:
   231  - source: quay.io
   232    mirrors:
   233    - Registry.lab.redhat.com:5000
   234  `,
   235  
   236  			expectedFound: false,
   237  			expectedError: "invalid Image-based Installation ISO Config: imageDigestSources[0].mirrors[0]: Invalid value: \"Registry.lab.redhat.com:5000\": failed to parse: invalid reference format: repository name must be lowercase",
   238  		},
   239  		{
   240  			name: "invalid-proxy-schemes",
   241  			data: `
   242  apiVersion: v1beta1
   243  metadata:
   244    name: image-based-installation-config
   245  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   246  seedVersion: 4.16.0
   247  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   248  installationDisk: /dev/vda
   249  proxy:
   250    httpProxy: ""
   251    httpsProxy: ""
   252    noProxy: ""
   253  `,
   254  
   255  			expectedFound: false,
   256  			expectedError: "invalid Image-based Installation ISO Config: proxy: Required value: must include httpProxy or httpsProxy",
   257  		},
   258  		{
   259  			name: "invalid-proxy-http-uri",
   260  			data: `
   261  apiVersion: v1beta1
   262  metadata:
   263    name: image-based-installation-config
   264  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   265  seedVersion: 4.16.0
   266  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   267  installationDisk: /dev/vda
   268  proxy:
   269    httpProxy: "invalidscheme://"
   270    httpsProxy: ""
   271    noProxy: ""
   272  `,
   273  
   274  			expectedFound: false,
   275  			expectedError: "invalid Image-based Installation ISO Config: proxy.httpProxy: Unsupported value: \"invalidscheme\": supported values: \"http\"",
   276  		},
   277  		{
   278  			name: "invalid-proxy-https-uri",
   279  			data: `
   280  apiVersion: v1beta1
   281  metadata:
   282    name: image-based-installation-config
   283  pullSecret: "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}"
   284  seedVersion: 4.16.0
   285  seedImage: quay.io/openshift-kni/seed-image:4.16.0
   286  installationDisk: /dev/vda
   287  proxy:
   288    httpProxy: ""
   289    httpsProxy: "invalidscheme://"
   290    noProxy: ""
   291  `,
   292  
   293  			expectedFound: false,
   294  			expectedError: "invalid Image-based Installation ISO Config: proxy.httpsProxy: Unsupported value: \"invalidscheme\": supported values: \"http\", \"https\"",
   295  		},
   296  	}
   297  	for _, tc := range cases {
   298  		t.Run(tc.name, func(t *testing.T) {
   299  			mockCtrl := gomock.NewController(t)
   300  			defer mockCtrl.Finish()
   301  
   302  			fileFetcher := mock.NewMockFileFetcher(mockCtrl)
   303  			fileFetcher.EXPECT().FetchByName(configFilename).
   304  				Return(
   305  					&asset.File{
   306  						Filename: configFilename,
   307  						Data:     []byte(tc.data)},
   308  					tc.fetchError,
   309  				)
   310  
   311  			asset := &ImageBasedInstallationConfig{}
   312  			found, err := asset.Load(fileFetcher)
   313  			assert.Equal(t, tc.expectedFound, found)
   314  			if tc.expectedError != "" {
   315  				assert.ErrorContains(t, err, tc.expectedError)
   316  			} else {
   317  				assert.NoError(t, err)
   318  				if tc.expectedConfig != nil {
   319  					assert.Equal(t, tc.expectedConfig.build(), asset.Config, "unexpected Config in ImageBasedInstallConfig")
   320  				}
   321  			}
   322  		})
   323  	}
   324  }
   325  
   326  // ImageBasedInstallationConfigBuilder it's a builder class to make it easier
   327  // creating imagebased.InstallationConfig instance used in the test cases.
   328  type ImageBasedInstallationConfigBuilder struct {
   329  	imagebased.InstallationConfig
   330  }
   331  
   332  func ibiConfig() *ImageBasedInstallationConfigBuilder {
   333  	return &ImageBasedInstallationConfigBuilder{
   334  		InstallationConfig: imagebased.InstallationConfig{
   335  			ObjectMeta: metav1.ObjectMeta{
   336  				Name: "image-based-installation-config",
   337  			},
   338  			TypeMeta: metav1.TypeMeta{
   339  				APIVersion: imagebased.ImageBasedConfigVersion,
   340  			},
   341  			SeedImage:            "quay.io/openshift-kni/seed-image:4.16.0",
   342  			SeedVersion:          "4.16.0",
   343  			InstallationDisk:     "/dev/vda",
   344  			ExtraPartitionStart:  "-40G",
   345  			ExtraPartitionLabel:  "varlibcontainers",
   346  			ExtraPartitionNumber: 5,
   347  			Shutdown:             false,
   348  			SSHKey:               "",
   349  			PullSecret:           "{\"auths\":{\"example.com\":{\"auth\":\"c3VwZXItc2VjcmV0Cg==\"}}}",
   350  			NetworkConfig: aiv1beta1.NetConfig{
   351  				Raw: unmarshalJSON([]byte(rawNMStateConfig)),
   352  			},
   353  		},
   354  	}
   355  }
   356  
   357  func (icb *ImageBasedInstallationConfigBuilder) build() *imagebased.InstallationConfig {
   358  	return &icb.InstallationConfig
   359  }
   360  
   361  func (icb *ImageBasedInstallationConfigBuilder) additionalTrustBundle(atb string) *ImageBasedInstallationConfigBuilder {
   362  	icb.InstallationConfig.AdditionalTrustBundle = atb
   363  	return icb
   364  }
   365  
   366  func (icb *ImageBasedInstallationConfigBuilder) networkConfig(nc aiv1beta1.NetConfig) *ImageBasedInstallationConfigBuilder {
   367  	icb.InstallationConfig.NetworkConfig = nc
   368  	return icb
   369  }
   370  
   371  func (icb *ImageBasedInstallationConfigBuilder) imageDigestSources(ids []types.ImageDigestSource) *ImageBasedInstallationConfigBuilder {
   372  	icb.InstallationConfig.ImageDigestSources = ids
   373  	return icb
   374  }
   375  
   376  func (icb *ImageBasedInstallationConfigBuilder) ignitionConfigOverride(ignitionConfigOverride string) *ImageBasedInstallationConfigBuilder {
   377  	icb.InstallationConfig.IgnitionConfigOverride = ignitionConfigOverride
   378  	return icb
   379  }
   380  
   381  func unmarshalJSON(b []byte) []byte {
   382  	output, err := yaml.JSONToYAML(b)
   383  	if err != nil {
   384  		return nil
   385  	}
   386  	return output
   387  }
   388  
   389  func skipTestIfnmstatectlIsMissing(t *testing.T) {
   390  	t.Helper()
   391  
   392  	_, execErr := exec.LookPath("nmstatectl")
   393  	if execErr != nil {
   394  		t.Skip("No nmstatectl binary available")
   395  	}
   396  }