Repository: openshift/assisted-service (language: python)

Issue:
MGMT-18579, MGMT-19018: Add feature flag for minimal OCP version for nmstate service flow
Since version 4.18 includes an updated nmstate, it was decided to enable the nmstate service flow for static networking starting from ocp version 4.18 and above. To provide flexibility, this is implemented as a feature flag, with the default set to 4.18. The version can be adjusted if needed, primarily for testing purposes.

<!--
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

You can refer to [Kubernetes community documentation] on writing good commit messages, which provides good tips and ideas.

Some PRs address specific issues. Please, refer to the [CONTRIBUTING] documentation for more
information on how to link a PR to an existing issue.

It's recommended to take a few extra minutes to provide more information about
how this code was tested. Here are some questions that may be worth answering:

- Should this PR be tested by the reviewer?
- Is this PR relying on CI for an e2e test run?
- Should this PR be tested in a specific environment?
- Any logs, screenshots, etc that can help with the review process?

-->

## List all the issues related to this PR

- [ ] New Feature <!-- new functionality -->
- [X] Enhancement <!-- refactor, code changes, improvement, that won't add new features -->
- [ ] Bug fix
- [ ] Tests
- [ ] Documentation
- [ ] CI/CD <!-- Notice that changes for Dockerfiles/Jenkinsfiles aren't tested in CI due to a known bug. -->

## What environments does this code impact?

- [ ] Automation (CI, tools, etc)
- [ ] Cloud
- [ ] Operator Managed Deployments
- [x] None

## How was this code tested?

<!-- Please, select one or more if needed: -->

- [X] assisted-test-infra environment
- [ ] dev-scripts environment
- [ ] Reviewer's test appreciated
- [ ] Waiting for CI to do a full test run
- [ ] Manual (Elaborate on how it was tested)
- [ ] No tests needed

## Checklist

- [X] Title and description added to both, commit and PR.
- [ ] Relevant issues have been associated (see [CONTRIBUTING] guide)
- [ ] This change does not require a documentation update (docstring, `docs`, README, etc)
- [ ] Does this change include unit-tests (note that code changes require unit-tests)

## Reviewers Checklist

- Are the title and description (in both PR and commit) meaningful and clear?
- Is there a bug required (and linked) for this change?
- Should this PR be backported?

[Kubernetes community documentation]: https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#commit-message-guidelines
[CONTRIBUTING]: https://github.com/openshift/assisted-service/blob/master/CONTRIBUTING.md



Discussion / hints:

Fix patch:
diff --git a/cmd/main.go b/cmd/main.go
index cca03cc5537..1bb2724a9e4 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -118,6 +118,7 @@ var Options struct {
 	OperatorsConfig                      operators.Options
 	GCConfig                             garbagecollector.Config
 	ReleaseSourcesConfig                 releasesources.Config
+	StaticNetworkConfig                  staticnetworkconfig.Config
 	IgnoredOpenshiftVersions             string        `envconfig:"IGNORED_OPENSHIFT_VERSIONS" default:""`
 	ClusterStateMonitorInterval          time.Duration `envconfig:"CLUSTER_MONITOR_INTERVAL" default:"10s"`
 	ClusterEventsUploaderInterval        time.Duration `envconfig:"CLUSTER_EVENTS_UPLOADER_INTERVAL" default:"15m"`
@@ -319,7 +320,7 @@ func main() {
 	)
 	failOnError(err, "failed to create Versions handlers")
 	domainHandler := domains.NewHandler(Options.BMConfig.BaseDNSDomains)
-	staticNetworkConfig := staticnetworkconfig.New(log.WithField("pkg", "static_network_config"))
+	staticNetworkConfig := staticnetworkconfig.New(log.WithField("pkg", "static_network_config"), Options.StaticNetworkConfig)
 	ignitionBuilder, err := ignition.NewBuilder(log.WithField("pkg", "ignition"), staticNetworkConfig, mirrorRegistriesBuilder, releaseHandler, versionHandler)
 	failOnError(err, "failed to create ignition builder")
 	installConfigBuilder := installcfg.NewInstallConfigBuilder(log.WithField("pkg", "installcfg"), mirrorRegistriesBuilder, providerRegistry)
diff --git a/internal/bminventory/inventory.go b/internal/bminventory/inventory.go
index 53457711fae..54c72389ab0 100644
--- a/internal/bminventory/inventory.go
+++ b/internal/bminventory/inventory.go
@@ -3708,7 +3708,7 @@ func (b *bareMetalInventory) DownloadMinimalInitrd(ctx context.Context, params i
 	if infraEnv.StaticNetworkConfig != "" {
 		// backward compatibility - nmstate.service has been available on RHCOS since version 4.14+, therefore, we should maintain both flows
 		var ok bool
-		ok, err = staticnetworkconfig.NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture)
+		ok, err = b.staticNetworkConfig.NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture)
 		if err != nil {
 			return common.GenerateErrorResponder(err)
 		}
@@ -5915,7 +5915,7 @@ func (b *bareMetalInventory) V2DownloadInfraEnvFiles(ctx context.Context, params
 		if infraEnv.StaticNetworkConfig != "" {
 			// backward compatibility - nmstate.service has been available on RHCOS since version 4.14+, therefore, we should maintain both flows
 			var ok bool
-			ok, err = staticnetworkconfig.NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture)
+			ok, err = b.staticNetworkConfig.NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture)
 			if err != nil {
 				return common.GenerateErrorResponder(err)
 			}
diff --git a/internal/ignition/discovery.go b/internal/ignition/discovery.go
index d63210b9782..72cc2614c8f 100644
--- a/internal/ignition/discovery.go
+++ b/internal/ignition/discovery.go
@@ -302,7 +302,7 @@ func (ib *ignitionBuilder) FormatDiscoveryIgnitionFile(ctx context.Context, infr
 
 		// backward compatibility - nmstate.service has been available on RHCOS since version 4.14+, therefore, we should maintain both flows
 		var ok bool
-		ok, err = staticnetworkconfig.NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture)
+		ok, err = ib.staticNetworkConfig.NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture)
 		if err != nil {
 			return "", err
 		}
diff --git a/openshift/template.yaml b/openshift/template.yaml
index 57ee5d7cb28..0f432c4fcf1 100644
--- a/openshift/template.yaml
+++ b/openshift/template.yaml
@@ -2,6 +2,9 @@
 parameters:
 - name: ASSISTED_SERVICE_IMAGE
   value: quay.io/app-sre/assisted-service
+- name: MIN_VERSION_FOR_NMSTATE_SERVICE
+  value: '4.18'
+  required: false
 - name: IMAGE_TAG
   value: ''
   required: true
@@ -330,6 +333,8 @@ objects:
                 value: ${ENABLE_SKIP_MCO_REBOOT}
               - name: ENABLE_SOFT_TIMEOUTS
                 value: ${ENABLE_SOFT_TIMEOUTS}
+              - name: MIN_VERSION_FOR_NMSTATE_SERVICE
+                value: ${MIN_VERSION_FOR_NMSTATE_SERVICE}
               - name: DB_HOST
                 valueFrom:
                   secretKeyRef:
diff --git a/pkg/staticnetworkconfig/backward_compatibility.go b/pkg/staticnetworkconfig/backward_compatibility.go
index b22e9b8c902..75e5e8ec45f 100644
--- a/pkg/staticnetworkconfig/backward_compatibility.go
+++ b/pkg/staticnetworkconfig/backward_compatibility.go
@@ -5,16 +5,19 @@ import (
 	log "github.com/sirupsen/logrus"
 )
 
-const MinimalVersionForNmstatectl = "4.14"
+type Config struct {
+	// MinVersionForNmstateService is a flag that enables the static networking flow using the nmstate service for specific OCP versions.
+	MinVersionForNmstateService string `envconfig:"MIN_VERSION_FOR_NMSTATE_SERVICE" default:"4.18"`
+}
 
-func NMStatectlServiceSupported(version, arch string) (bool, error) {
+func (s *StaticNetworkConfigGenerator) NMStatectlServiceSupported(version, arch string) (bool, error) {
 	// When a cluster is imported, the OpenshiftVersion isn't stored in the database.
 	// Consequently, a bound InfraEnv with static networking uses the Cluster's OpenshiftVersion, which is empty.
 	if version == "" {
 		log.Info("ocp version is empty")
 		return false, nil
 	}
-	versionOK, err := common.VersionGreaterOrEqual(version, MinimalVersionForNmstatectl)
+	versionOK, err := common.VersionGreaterOrEqual(version, s.config.MinVersionForNmstateService)
 	if err != nil {
 		return false, err
 	}
diff --git a/pkg/staticnetworkconfig/generator.go b/pkg/staticnetworkconfig/generator.go
index 872e1bfeb2a..1dabaeb2f16 100644
--- a/pkg/staticnetworkconfig/generator.go
+++ b/pkg/staticnetworkconfig/generator.go
@@ -47,17 +47,20 @@ type StaticNetworkConfig interface {
 	GenerateStaticNetworkConfigDataYAML(staticNetworkConfigStr string) ([]StaticNetworkConfigData, error)
 	FormatStaticNetworkConfigForDB(staticNetworkConfig []*models.HostStaticNetworkConfig) (string, error)
 	ValidateStaticConfigParamsYAML(staticNetworkConfig []*models.HostStaticNetworkConfig, ocpVersion, arch, installerInvoker string) error
+	NMStatectlServiceSupported(version, arch string) (bool, error)
 }
 
 type StaticNetworkConfigGenerator struct {
 	log     logrus.FieldLogger
 	nmstate *nmstate.Nmstate
+	config  Config
 }
 
-func New(log logrus.FieldLogger) StaticNetworkConfig {
+func New(log logrus.FieldLogger, config Config) StaticNetworkConfig {
 	return &StaticNetworkConfigGenerator{
 		log:     log,
 		nmstate: nmstate.New(),
+		config:  config,
 	}
 }
 
@@ -65,7 +68,7 @@ func New(log logrus.FieldLogger) StaticNetworkConfig {
 func (s *StaticNetworkConfigGenerator) injectIPV4V6FieldsIfNeeded(networkYaml string) (string, error) {
 	var config map[string]interface{}
 
-	// Unmarshal the JSON string into the config struct
+	// Unmarshal the YAML string into the config struct
 	err := yaml.Unmarshal([]byte(networkYaml), &config)
 	if err != nil {
 		s.log.WithError(err).Errorf("Error unmarshalling yaml")
@@ -110,7 +113,7 @@ func (s *StaticNetworkConfigGenerator) injectNMPolicyCaptures(hostConfig *models
 
 	err := yaml.Unmarshal([]byte(interfacesWithCaptures), &config)
 	if err != nil {
-		s.log.WithError(err).Errorf("error unmarshalling JSON: %v", err)
+		s.log.WithError(err).Errorf("error unmarshalling YAML: %v", err)
 		return "", err
 	}
 
@@ -323,7 +326,7 @@ func (s *StaticNetworkConfigGenerator) validateInterfaceNamesExistenceYAML(macIn
 
 	var config map[string]interface{}
 
-	// Unmarshal the JSON string into the config struct
+	// Unmarshal the YAML string into the config struct
 	err := yaml.Unmarshal([]byte(networksYaml), &config)
 	if err != nil {
 		s.log.WithError(err).Errorf("Error unmarshalling yaml")
@@ -364,7 +367,7 @@ func (s *StaticNetworkConfigGenerator) validateInterfaceNamesExistenceYAML(macIn
 
 		identifier, exists := nic["identifier"]
 		isMacAddressIdentifier := exists && identifier == "mac-address"
-		isVersionOK, err := NMStatectlServiceSupported(ocpVersion, arch)
+		isVersionOK, err := s.NMStatectlServiceSupported(ocpVersion, arch)
 		if err != nil {
 			return err
 		}
diff --git a/pkg/staticnetworkconfig/mock_generator.go b/pkg/staticnetworkconfig/mock_generator.go
index 0532bd9ad8c..a810b67b7e0 100644
--- a/pkg/staticnetworkconfig/mock_generator.go
+++ b/pkg/staticnetworkconfig/mock_generator.go
@@ -80,6 +80,21 @@ func (mr *MockStaticNetworkConfigMockRecorder) GenerateStaticNetworkConfigDataYA
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenerateStaticNetworkConfigDataYAML", reflect.TypeOf((*MockStaticNetworkConfig)(nil).GenerateStaticNetworkConfigDataYAML), staticNetworkConfigStr)
 }
 
+// NMStatectlServiceSupported mocks base method.
+func (m *MockStaticNetworkConfig) NMStatectlServiceSupported(version, arch string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "NMStatectlServiceSupported", version, arch)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// NMStatectlServiceSupported indicates an expected call of NMStatectlServiceSupported.
+func (mr *MockStaticNetworkConfigMockRecorder) NMStatectlServiceSupported(version, arch interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NMStatectlServiceSupported", reflect.TypeOf((*MockStaticNetworkConfig)(nil).NMStatectlServiceSupported), version, arch)
+}
+
 // ValidateStaticConfigParamsYAML mocks base method.
 func (m *MockStaticNetworkConfig) ValidateStaticConfigParamsYAML(staticNetworkConfig []*models.HostStaticNetworkConfig, ocpVersion, arch, installerInvoker string) error {
 	m.ctrl.T.Helper()


Test patch:
diff --git a/internal/common/test_configuration.go b/internal/common/test_configuration.go
index 3c5ba0876ff..8cfa058cce9 100644
--- a/internal/common/test_configuration.go
+++ b/internal/common/test_configuration.go
@@ -49,6 +49,7 @@ type TestConfiguration struct {
 
 const TestDiskId = "/dev/disk/by-id/test-disk-id"
 const TestDiskPath = "/dev/test-disk"
+const MinimalVersionForNmstatectl = "4.18"
 
 var (
 	OpenShiftVersion string = "4.6"
diff --git a/internal/ignition/discovery_test.go b/internal/ignition/discovery_test.go
index c69bc548528..2ca800b0ac9 100644
--- a/internal/ignition/discovery_test.go
+++ b/internal/ignition/discovery_test.go
@@ -91,7 +91,6 @@ var _ = Describe("IgnitionBuilder", func() {
 		mockVersionHandler                  *versions.MockHandler
 		ignitionConfig                      IgnitionConfig
 		ocpVersionInvolvingGenerateKeyfiles = "4.12"
-		ocpVersionInvolvingNmstateService   = "4.14"
 	)
 
 	BeforeEach(func() {
@@ -533,12 +532,13 @@ var _ = Describe("IgnitionBuilder", func() {
 			},
 		}
 
-		It("produces a valid ignition v3.1 spec with static ips paramters - ocp versions less than 4.14", func() {
+		It("produces a valid ignition v3.1 spec with static ips paramters - ocp versions less than MinimalVersionForNmstatectl", func() {
 			mockStaticNetworkConfig.EXPECT().GenerateStaticNetworkConfigData(gomock.Any(), formattedInput).Return(staticnetworkConfigOutput, nil).Times(1)
 			infraEnv.StaticNetworkConfig = formattedInput
 			infraEnv.Type = common.ImageTypePtr(models.ImageTypeFullIso)
 			infraEnv.OpenshiftVersion = ocpVersionInvolvingGenerateKeyfiles
 			mockMirrorRegistriesConfigBuilder.EXPECT().IsMirrorRegistriesConfigured().Return(false).Times(1)
+			mockStaticNetworkConfig.EXPECT().NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture).Return(false, nil).Times(1)
 			mockVersionHandler.EXPECT().GetReleaseImage(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("some error")).Times(1)
 			text, err := builder.FormatDiscoveryIgnitionFile(context.Background(), &infraEnv, ignitionConfig, false, auth.TypeRHSSO, "")
 			Expect(err).NotTo(HaveOccurred())
@@ -553,12 +553,13 @@ var _ = Describe("IgnitionBuilder", func() {
 			}
 			Expect(count).Should(Equal(3))
 		})
-		It("produces a valid ignition v3.1 spec with static ips paramters - ocp versions greater than/ equal to 4.14, x86 arch", func() {
+		It("produces a valid ignition v3.1 spec with static ips paramters - ocp versions greater than/ equal to MinimalVersionForNmstatectl, x86 arch", func() {
 			mockStaticNetworkConfig.EXPECT().GenerateStaticNetworkConfigDataYAML(formattedInput).Return(staticNetworkConfigNmpolicyOutput, nil).Times(1)
 			infraEnv.StaticNetworkConfig = formattedInput
 			infraEnv.Type = common.ImageTypePtr(models.ImageTypeFullIso)
-			infraEnv.OpenshiftVersion = ocpVersionInvolvingNmstateService
+			infraEnv.OpenshiftVersion = common.MinimalVersionForNmstatectl
 			infraEnv.CPUArchitecture = common.X86CPUArchitecture
+			mockStaticNetworkConfig.EXPECT().NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture).Return(true, nil).Times(1)
 			mockMirrorRegistriesConfigBuilder.EXPECT().IsMirrorRegistriesConfigured().Return(false).Times(1)
 			mockVersionHandler.EXPECT().GetReleaseImage(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("some error")).Times(1)
 			text, err := builder.FormatDiscoveryIgnitionFile(context.Background(), &infraEnv, ignitionConfig, false, auth.TypeRHSSO, "")
@@ -574,12 +575,13 @@ var _ = Describe("IgnitionBuilder", func() {
 			}
 			Expect(count).Should(Equal(3))
 		})
-		It("produces a valid ignition v3.1 spec with static ips paramters - ocp versions greater than/ equal to 4.14, arm arch", func() {
+		It("produces a valid ignition v3.1 spec with static ips paramters - ocp versions greater than/ equal to MinimalVersionForNmstatectl, arm arch", func() {
 			mockStaticNetworkConfig.EXPECT().GenerateStaticNetworkConfigData(gomock.Any(), formattedInput).Return(staticNetworkConfigNmpolicyOutput, nil).Times(1)
 			infraEnv.StaticNetworkConfig = formattedInput
 			infraEnv.Type = common.ImageTypePtr(models.ImageTypeFullIso)
-			infraEnv.OpenshiftVersion = ocpVersionInvolvingNmstateService
+			infraEnv.OpenshiftVersion = common.MinimalVersionForNmstatectl
 			infraEnv.CPUArchitecture = common.ARM64CPUArchitecture
+			mockStaticNetworkConfig.EXPECT().NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture).Return(false, nil).Times(1)
 			mockMirrorRegistriesConfigBuilder.EXPECT().IsMirrorRegistriesConfigured().Return(false).Times(1)
 			mockVersionHandler.EXPECT().GetReleaseImage(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("some error")).Times(1)
 			text, err := builder.FormatDiscoveryIgnitionFile(context.Background(), &infraEnv, ignitionConfig, false, auth.TypeRHSSO, "")
@@ -595,7 +597,7 @@ var _ = Describe("IgnitionBuilder", func() {
 			}
 			Expect(count).Should(Equal(3))
 		})
-		It("Doesn't include static network config for minimal isos - ocp versions less than 4.14", func() {
+		It("Doesn't include static network config for minimal isos - ocp versions less than MinimalVersionForNmstatectl", func() {
 			infraEnv.StaticNetworkConfig = formattedInput
 			infraEnv.Type = common.ImageTypePtr(models.ImageTypeMinimalIso)
 			mockMirrorRegistriesConfigBuilder.EXPECT().IsMirrorRegistriesConfigured().Return(false).Times(1)
@@ -614,12 +616,13 @@ var _ = Describe("IgnitionBuilder", func() {
 			Expect(count).Should(Equal(0))
 		})
 
-		It("Will include static network config for minimal iso type in infraenv if overridden in call to FormatDiscoveryIgnitionFile - ocp versions less than 4.14", func() {
+		It("Will include static network config for minimal iso type in infraenv if overridden in call to FormatDiscoveryIgnitionFile - ocp versions less than MinimalVersionForNmstatectl", func() {
 			mockStaticNetworkConfig.EXPECT().GenerateStaticNetworkConfigData(gomock.Any(), formattedInput).Return(staticnetworkConfigOutput, nil).Times(1)
 			mockVersionHandler.EXPECT().GetReleaseImage(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("some error")).Times(1)
 			infraEnv.StaticNetworkConfig = formattedInput
 			infraEnv.Type = common.ImageTypePtr(models.ImageTypeMinimalIso)
 			infraEnv.OpenshiftVersion = ocpVersionInvolvingGenerateKeyfiles
+			mockStaticNetworkConfig.EXPECT().NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture).Return(false, nil).Times(1)
 			mockMirrorRegistriesConfigBuilder.EXPECT().IsMirrorRegistriesConfigured().Return(false).Times(1)
 			text, err := builder.FormatDiscoveryIgnitionFile(context.Background(), &infraEnv, ignitionConfig, false, auth.TypeRHSSO, string(models.ImageTypeFullIso))
 			Expect(err).NotTo(HaveOccurred())
@@ -634,13 +637,14 @@ var _ = Describe("IgnitionBuilder", func() {
 			}
 			Expect(count).Should(Equal(3))
 		})
-		It("Will include static network config for minimal iso type in infraenv if overridden in call to FormatDiscoveryIgnitionFile - ocp versions greater than/ equal to 4.14, x86 arch", func() {
+		It("Will include static network config for minimal iso type in infraenv if overridden in call to FormatDiscoveryIgnitionFile - ocp versions greater than/ equal to MinimalVersionForNmstatectl, x86 arch", func() {
 			mockStaticNetworkConfig.EXPECT().GenerateStaticNetworkConfigDataYAML(formattedInput).Return(staticNetworkConfigNmpolicyOutput, nil).Times(1)
 			mockVersionHandler.EXPECT().GetReleaseImage(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("some error")).Times(1)
 			infraEnv.StaticNetworkConfig = formattedInput
 			infraEnv.Type = common.ImageTypePtr(models.ImageTypeMinimalIso)
-			infraEnv.OpenshiftVersion = ocpVersionInvolvingNmstateService
+			infraEnv.OpenshiftVersion = common.MinimalVersionForNmstatectl
 			infraEnv.CPUArchitecture = common.X86CPUArchitecture
+			mockStaticNetworkConfig.EXPECT().NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture).Return(true, nil).Times(1)
 			mockMirrorRegistriesConfigBuilder.EXPECT().IsMirrorRegistriesConfigured().Return(false).Times(1)
 			text, err := builder.FormatDiscoveryIgnitionFile(context.Background(), &infraEnv, ignitionConfig, false, auth.TypeRHSSO, string(models.ImageTypeFullIso))
 			Expect(err).NotTo(HaveOccurred())
@@ -655,13 +659,14 @@ var _ = Describe("IgnitionBuilder", func() {
 			}
 			Expect(count).Should(Equal(3))
 		})
-		It("Will include static network config for minimal iso type in infraenv if overridden in call to FormatDiscoveryIgnitionFile - ocp versions greater than/ equal to 4.14, arm arch", func() {
+		It("Will include static network config for minimal iso type in infraenv if overridden in call to FormatDiscoveryIgnitionFile - ocp versions greater than/ equal to MinimalVersionForNmstatectl, arm arch", func() {
 			mockStaticNetworkConfig.EXPECT().GenerateStaticNetworkConfigData(gomock.Any(), formattedInput).Return(staticNetworkConfigNmpolicyOutput, nil).Times(1)
 			mockVersionHandler.EXPECT().GetReleaseImage(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("some error")).Times(1)
 			infraEnv.StaticNetworkConfig = formattedInput
 			infraEnv.Type = common.ImageTypePtr(models.ImageTypeMinimalIso)
-			infraEnv.OpenshiftVersion = ocpVersionInvolvingNmstateService
+			infraEnv.OpenshiftVersion = common.MinimalVersionForNmstatectl
 			infraEnv.CPUArchitecture = common.ARM64CPUArchitecture
+			mockStaticNetworkConfig.EXPECT().NMStatectlServiceSupported(infraEnv.OpenshiftVersion, infraEnv.CPUArchitecture).Return(false, nil).Times(1)
 			mockMirrorRegistriesConfigBuilder.EXPECT().IsMirrorRegistriesConfigured().Return(false).Times(1)
 			text, err := builder.FormatDiscoveryIgnitionFile(context.Background(), &infraEnv, ignitionConfig, false, auth.TypeRHSSO, string(models.ImageTypeFullIso))
 			Expect(err).NotTo(HaveOccurred())
diff --git a/internal/isoeditor/rhcos_test.go b/internal/isoeditor/rhcos_test.go
index 4b3b3ca54d3..212205fc04e 100644
--- a/internal/isoeditor/rhcos_test.go
+++ b/internal/isoeditor/rhcos_test.go
@@ -20,7 +20,7 @@ func TestIsoEditor(t *testing.T) {
 }
 
 var _ = Describe("RamdiskImageArchive", func() {
-	It("adds a new archive correctly - ocp versions less than 4.14", func() {
+	It("adds a new archive correctly - ocp versions less than MinimalVersionForNmstatectl", func() {
 
 		clusterProxyInfo := ClusterProxyInfo{
 			HTTPProxy:  "http://10.10.1.1:3128",
@@ -90,7 +90,7 @@ var _ = Describe("RamdiskImageArchive", func() {
 			clusterProxyInfo.HTTPProxy, clusterProxyInfo.HTTPSProxy, clusterProxyInfo.NoProxy)
 		Expect(rootfsServiceConfigContent).To(Equal(rootfsServiceConfig))
 	})
-	It("returns nothing when given nothing - ocp versions less than 4.14", func() {
+	It("returns nothing when given nothing - ocp versions less than MinimalVersionForNmstatectl", func() {
 		archive, err := RamdiskImageArchive(
 			[]staticnetworkconfig.StaticNetworkConfigData{},
 			&ClusterProxyInfo{},
@@ -99,7 +99,7 @@ var _ = Describe("RamdiskImageArchive", func() {
 		Expect(archive).To(BeNil())
 	})
 
-	It("adds a new archive correctly - ocp versions greater than/ equal to 4.14", func() {
+	It("adds a new archive correctly - ocp versions greater than/ equal to MinimalVersionForNmstatectl", func() {
 
 		clusterProxyInfo := ClusterProxyInfo{
 			HTTPProxy:  "http://10.10.1.1:3128",
@@ -169,7 +169,7 @@ var _ = Describe("RamdiskImageArchive", func() {
 			clusterProxyInfo.HTTPProxy, clusterProxyInfo.HTTPSProxy, clusterProxyInfo.NoProxy)
 		Expect(rootfsServiceConfigContent).To(Equal(rootfsServiceConfig))
 	})
-	It("returns nothing when given nothing - ocp versions greater than/ equal to 4.14", func() {
+	It("returns nothing when given nothing - ocp versions greater than/ equal to MinimalVersionForNmstatectl", func() {
 		archive, err := RamdiskImageArchive(
 			[]staticnetworkconfig.StaticNetworkConfigData{},
 			&ClusterProxyInfo{},
diff --git a/pkg/staticnetworkconfig/generator_test.go b/pkg/staticnetworkconfig/generator_test.go
index 547c69255fc..ee030e908dd 100644
--- a/pkg/staticnetworkconfig/generator_test.go
+++ b/pkg/staticnetworkconfig/generator_test.go
@@ -22,7 +22,7 @@ func TestStaticNetworkConfig(t *testing.T) {
 
 var _ = Describe("StaticNetworkConfig.GenerateStaticNetworkConfigData - generateConfiguration", func() {
 	var (
-		staticNetworkGenerator = snc.New(logrus.New())
+		staticNetworkGenerator = snc.New(logrus.New(), snc.Config{MinVersionForNmstateService: "4.18"})
 	)
 
 	It("Fail with an empty host YAML", func() {
@@ -60,7 +60,7 @@ var _ = Describe("StaticNetworkConfig.GenerateStaticNetworkConfigData - generate
 
 var _ = Describe("validate mac interface mapping", func() {
 	var (
-		staticNetworkGenerator = snc.New(logrus.New())
+		staticNetworkGenerator = snc.New(logrus.New(), snc.Config{MinVersionForNmstateService: "4.18"})
 		singleInterfaceYAML    = `interfaces:
   - name: eth0
     type: ethernet
@@ -354,7 +354,7 @@ var _ = Describe("validate mac interface mapping", func() {
 			err := staticNetworkGenerator.ValidateStaticConfigParamsYAML(staticNetworkConfig, "4.14", common.X86CPUArchitecture, "agent-installer")
 			Expect(err).ToNot(HaveOccurred())
 		})
-		It("The mac-identifier field is temporarily not supported for flows other than ABI in OCP versions >= 4.14", func() {
+		It("The mac-identifier field is temporarily not supported for flows other than ABI in OCP versions >= 4.18", func() {
 			staticNetworkConfig := []*models.HostStaticNetworkConfig{
 				{
 					MacInterfaceMap: []*models.MacInterfaceMapItems0{
@@ -366,7 +366,7 @@ var _ = Describe("validate mac interface mapping", func() {
 					NetworkYaml: withMacIdentifier,
 				},
 			}
-			err := staticNetworkGenerator.ValidateStaticConfigParamsYAML(staticNetworkConfig, "4.14", common.X86CPUArchitecture, "")
+			err := staticNetworkGenerator.ValidateStaticConfigParamsYAML(staticNetworkConfig, "4.18", common.X86CPUArchitecture, "")
 			Expect(err).To(HaveOccurred())
 		})
 		It("mac-identifier field is supported in ocp-versions < 4.14", func() {
@@ -384,7 +384,7 @@ var _ = Describe("validate mac interface mapping", func() {
 			err := staticNetworkGenerator.ValidateStaticConfigParamsYAML(staticNetworkConfig, "4.13", common.X86CPUArchitecture, "")
 			Expect(err).ToNot(HaveOccurred())
 		})
-		It("mac-identifier field in the YAML, along with a differing MAC in the mac-map, is temporarily not supported for flows other than ABI in OCP versions >= 4.14", func() {
+		It("mac-identifier field in the YAML, along with a differing MAC in the mac-map, is temporarily not supported for flows other than ABI in OCP versions >= 4.18", func() {
 			staticNetworkConfig := []*models.HostStaticNetworkConfig{
 				{
 					MacInterfaceMap: []*models.MacInterfaceMapItems0{
@@ -396,7 +396,7 @@ var _ = Describe("validate mac interface mapping", func() {
 					NetworkYaml: withMacIdentifier,
 				},
 			}
-			err := staticNetworkGenerator.ValidateStaticConfigParamsYAML(staticNetworkConfig, "4.14", common.X86CPUArchitecture, "")
+			err := staticNetworkGenerator.ValidateStaticConfigParamsYAML(staticNetworkConfig, "4.18", common.X86CPUArchitecture, "")
 			Expect(err).To(HaveOccurred())
 		})
 		It("mac-identifier field in the YAML, along with a differing MAC in the mac-map, is allowed for ABI in OCP versions >= 4.14", func() {
@@ -434,7 +434,7 @@ var _ = Describe("validate mac interface mapping", func() {
 
 var _ = Describe("StaticNetworkConfig", func() {
 	var (
-		staticNetworkGenerator = snc.New(logrus.New())
+		staticNetworkGenerator = snc.New(logrus.New(), snc.Config{MinVersionForNmstateService: "4.18"})
 		multipleInterfacesYAML = `interfaces:
   - name: eth0
     type: ethernet
@@ -568,7 +568,7 @@ var _ = Describe("StaticNetworkConfig", func() {
 
 var _ = Describe("StaticNetworkConfig.GenerateStaticNetworkConfigDataYAML - generate nmpolicy", func() {
 	var (
-		staticNetworkGenerator = snc.New(logrus.New())
+		staticNetworkGenerator = snc.New(logrus.New(), snc.Config{MinVersionForNmstateService: "4.18"})
 
 		hostsYAML, hostsYAMLAndIni = `[{ "network_yaml": "%s" }]`, `[{ "network_yaml": "%s", "mac_interface_map": %s }]`
 
diff --git a/subsystem/infra_env_test.go b/subsystem/infra_env_test.go
index 75f8a6431f3..1be223d4b48 100644
--- a/subsystem/infra_env_test.go
+++ b/subsystem/infra_env_test.go
@@ -21,7 +21,6 @@ import (
 	"github.com/openshift/assisted-service/internal/bminventory"
 	"github.com/openshift/assisted-service/internal/common"
 	"github.com/openshift/assisted-service/models"
-	"github.com/openshift/assisted-service/pkg/staticnetworkconfig"
 )
 
 var registerInfraEnv = func(clusterID *strfmt.UUID, imageType models.ImageType) *models.InfraEnv {
@@ -355,15 +354,15 @@ var _ = Describe("Infra_Env", func() {
 		contents := buf.String()
 		Expect(len(contents)).ShouldNot(Equal(0))
 		Expect(contents).To(ContainSubstring("/etc/assisted/network/host0"))
-		if ocpVersion < staticnetworkconfig.MinimalVersionForNmstatectl || arch == common.ARM64CPUArchitecture {
+		if ocpVersion < common.MinimalVersionForNmstatectl || arch == common.ARM64CPUArchitecture {
 			Expect(contents).To(ContainSubstring("192.0.2.1/24"))
 		}
 		Expect(contents).To(ContainSubstring("eth0"))
 	},
-		Entry("ocp versions greater than/ equal to 4.14, x86 arch", staticnetworkconfig.MinimalVersionForNmstatectl, common.X86CPUArchitecture),
-		Entry("ocp versions greater than/ equal to 4.14, arm arch", staticnetworkconfig.MinimalVersionForNmstatectl, common.ARM64CPUArchitecture),
-		Entry("ocp versions less than 4.14, x86 arch", "4.12", common.X86CPUArchitecture),
-		Entry("ocp versions less than 4.14, arm arch", "4.12", common.ARM64CPUArchitecture),
+		Entry("ocp versions greater than/ equal to MinimalVersionForNmstatectl, x86 arch", common.MinimalVersionForNmstatectl, common.X86CPUArchitecture),
+		Entry("ocp versions greater than/ equal to MinimalVersionForNmstatectl, arm arch", common.MinimalVersionForNmstatectl, common.ARM64CPUArchitecture),
+		Entry("ocp versions less than MinimalVersionForNmstatectl, x86 arch", "4.12", common.X86CPUArchitecture),
+		Entry("ocp versions less than MinimalVersionForNmstatectl, arm arch", "4.12", common.ARM64CPUArchitecture),
 	)
 
 	It("download infra-env files invalid filename option", func() {