github.com/openshift/installer@v1.4.17/pkg/asset/ignition/bootstrap/cvoignore.go (about)

     1  package bootstrap
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  
     8  	"github.com/pkg/errors"
     9  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    10  	"sigs.k8s.io/yaml"
    11  
    12  	configv1 "github.com/openshift/api/config/v1"
    13  	"github.com/openshift/installer/pkg/asset"
    14  	"github.com/openshift/installer/pkg/asset/manifests"
    15  )
    16  
    17  var (
    18  	_ asset.WritableAsset = (*CVOIgnore)(nil)
    19  )
    20  
    21  const (
    22  	cvoOverridesFilename      = "manifests/cvo-overrides.yaml"
    23  	originalOverridesFilename = "original_cvo_overrides.patch"
    24  )
    25  
    26  // CVOIgnore adds bootstrap files needed to inform CVO to ignore resources for which the installer is providing manifests.
    27  type CVOIgnore struct {
    28  	FileList []*asset.File
    29  }
    30  
    31  // Name returns a human friendly name for the operator
    32  func (a *CVOIgnore) Name() string {
    33  	return "CVO Ignore"
    34  }
    35  
    36  // Dependencies returns all of the dependencies directly needed by the CVOIgnore asset
    37  func (a *CVOIgnore) Dependencies() []asset.Asset {
    38  	return []asset.Asset{
    39  		&manifests.Manifests{},
    40  		&manifests.Openshift{},
    41  	}
    42  }
    43  
    44  // Generate generates the respective operator config.yml files
    45  func (a *CVOIgnore) Generate(_ context.Context, dependencies asset.Parents) error {
    46  	operators := &manifests.Manifests{}
    47  	openshiftManifests := &manifests.Openshift{}
    48  	dependencies.Get(operators, openshiftManifests)
    49  
    50  	var clusterVersion *unstructured.Unstructured
    51  	var ignoredResources []interface{}
    52  	var files []*asset.File
    53  	files = append(files, operators.FileList...)
    54  	files = append(files, openshiftManifests.FileList...)
    55  
    56  	seen := make(map[string]string, len(files))
    57  	for _, file := range files {
    58  		u := &unstructured.Unstructured{}
    59  		if err := yaml.Unmarshal(file.Data, u); err != nil {
    60  			return errors.Wrapf(err, "could not unmarshal %q", file.Filename)
    61  		}
    62  		group := u.GetObjectKind().GroupVersionKind().Group
    63  		kind := u.GetKind()
    64  		namespace := u.GetNamespace()
    65  		name := u.GetName()
    66  
    67  		key := fmt.Sprintf("%s |! %s |! %s |! %s", group, kind, namespace, name)
    68  		if previousFile, ok := seen[key]; ok {
    69  			return fmt.Errorf("multiple manifests for group %s kind %s namespace %s name %s: %s, %s", group, kind, namespace, name, previousFile, file.Filename)
    70  		}
    71  		seen[key] = file.Filename
    72  
    73  		if file.Filename == cvoOverridesFilename {
    74  			clusterVersion = u
    75  			continue
    76  		}
    77  		ignoredResources = append(ignoredResources,
    78  			configv1.ComponentOverride{
    79  				Kind:      kind,
    80  				Group:     group,
    81  				Namespace: namespace,
    82  				Name:      name,
    83  				Unmanaged: true,
    84  			})
    85  	}
    86  
    87  	specAsInterface, ok := clusterVersion.Object["spec"]
    88  	if !ok {
    89  		specAsInterface = map[string]interface{}{}
    90  		clusterVersion.Object["spec"] = specAsInterface
    91  	}
    92  	spec, ok := specAsInterface.(map[string]interface{})
    93  	if !ok {
    94  		return errors.Errorf("unexpected type (%T) for .spec in clusterversion", specAsInterface)
    95  	}
    96  	originalOverridesAsInterface := spec["overrides"]
    97  	originalOverrides, ok := originalOverridesAsInterface.([]interface{})
    98  	if !ok && originalOverridesAsInterface != nil {
    99  		return errors.Errorf("unexpected type (%T) for .spec.overrides in clusterversion", originalOverridesAsInterface)
   100  	}
   101  	originalOverridesPatch := map[string]interface{}{
   102  		"spec": map[string]interface{}{
   103  			"overrides": originalOverrides,
   104  		},
   105  	}
   106  	spec["overrides"] = append(ignoredResources, originalOverrides...)
   107  
   108  	cvData, err := yaml.Marshal(clusterVersion)
   109  	if err != nil {
   110  		return errors.Wrap(err, "error marshalling clusterversion")
   111  	}
   112  	a.FileList = append(a.FileList, &asset.File{
   113  		Filename: cvoOverridesFilename,
   114  		Data:     cvData,
   115  	})
   116  
   117  	origOverrideData, err := json.Marshal(originalOverridesPatch)
   118  	if err != nil {
   119  		return errors.Wrap(err, "error marshalling original overrides")
   120  	}
   121  	a.FileList = append(a.FileList, &asset.File{
   122  		Filename: originalOverridesFilename,
   123  		Data:     origOverrideData,
   124  	})
   125  
   126  	return nil
   127  }
   128  
   129  // Files returns the files generated by the asset.
   130  func (a *CVOIgnore) Files() []*asset.File {
   131  	return a.FileList
   132  }
   133  
   134  // Load does nothing as the file should not be loaded from disk.
   135  func (a *CVOIgnore) Load(f asset.FileFetcher) (bool, error) {
   136  	return false, nil
   137  }