Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions pkg/operator/render/options/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,16 @@ type ManifestConfig struct {
ImagePullPolicy string
}

// FileConfig
type FileConfig struct {
// BootstrapConfig holds the rendered control plane component config file for bootstrapping (phase 1).
BootstrapConfig []byte

// Assets holds the loaded assets like certs and keys.
Assets map[string][]byte

// RenderedManifests are the files, content, and (optionally) decoded objects that were passed to the command
// as already present to be created by cluster-bootstrap.
RenderedManifests []RenderedManifest
}

type RenderedManifests []RenderedManifest

type RenderedManifest struct {
OriginalFilename string
Content []byte
Expand All @@ -60,16 +57,16 @@ type TemplateData struct {
FileConfig
}

func (c *FileConfig) ListManifestOfType(gvk schema.GroupVersionKind) []RenderedManifest {
func (c RenderedManifests) ListManifestOfType(gvk schema.GroupVersionKind) []RenderedManifest {
ret := []RenderedManifest{}
for i := range c.RenderedManifests {
obj, err := c.RenderedManifests[i].GetDecodedObj()
for i := range c {
obj, err := c[i].GetDecodedObj()
if err != nil {
klog.Warningf("failure to read %q: %v", c.RenderedManifests[i].OriginalFilename, err)
klog.Warningf("failure to read %q: %v", c[i].OriginalFilename, err)
continue
}
if obj.GetObjectKind().GroupVersionKind() == gvk {
ret = append(ret, c.RenderedManifests[i])
ret = append(ret, c[i])
}
}

Expand Down
91 changes: 73 additions & 18 deletions pkg/operator/render/options/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import (
"text/template"

"github.com/ghodss/yaml"
"github.com/spf13/pflag"

"k8s.io/apimachinery/pkg/runtime/schema"

configv1 "github.com/openshift/api/config/v1"
"github.com/openshift/library-go/pkg/assets"
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
"github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/runtime/schema"
)

// GenericOptions contains the generic render command options.
Expand All @@ -31,7 +31,8 @@ type GenericOptions struct {
AssetInputDir string
AssetOutputDir string

FeatureSet string
FeatureSet string
PayloadVersion string
}

type Template struct {
Expand All @@ -57,6 +58,8 @@ func (o *GenericOptions) AddFlags(fs *pflag.FlagSet, configGVK schema.GroupVersi
fs.StringVar(&o.FeatureSet, "feature-set", o.FeatureSet, "Enables features that are not part of the default feature set.")
fs.StringSliceVar(&o.RenderedManifestInputFilenames, "rendered-manifest-files", o.RenderedManifestInputFilenames,
"files or directories containing yaml or json manifests that will be created via cluster-bootstrapping.")
fs.StringVar(&o.PayloadVersion, "payload-version", o.PayloadVersion, "Version that will eventually be placed into ClusterOperator.status. This normally comes from the CVO set via env var: OPERATOR_IMAGE_VERSION.")

}

type gvkOutput struct {
Expand Down Expand Up @@ -102,6 +105,71 @@ func (o *GenericOptions) Validate() error {
return nil
}

func (o *GenericOptions) ReadInputManifests() (RenderedManifests, error) {
ret := RenderedManifests{}
for _, filename := range o.RenderedManifestInputFilenames {
manifestContent, err := assets.LoadFilesRecursively(filename)
if err != nil {
return nil, fmt.Errorf("failed loading rendered manifest inputs from %q: %w", filename, err)
}
for manifestFile, content := range manifestContent {
ret = append(ret, RenderedManifest{
OriginalFilename: manifestFile,
Content: content,
})
}
}

return ret, nil
}

func (o *GenericOptions) FeatureGates() (featuregates.FeatureGateAccess, error) {
if len(o.PayloadVersion) == 0 {
return nil, fmt.Errorf("cannot return FeatureGate without payload version")
}
if len(o.RenderedManifestInputFilenames) == 0 {
return nil, fmt.Errorf("cannot return FeatureGate without rendered manifests")
}

inputManifest, err := o.ReadInputManifests()
if err != nil {
return nil, fmt.Errorf("error reading input manifests: %w", err)
}
featureGates := inputManifest.ListManifestOfType(configv1.GroupVersion.WithKind("FeatureGate"))
if len(featureGates) == 0 {
return nil, fmt.Errorf("no FeatureGates found in manfest dir: %v", o.RenderedManifestInputFilenames)
}
var prev *RenderedManifest
var featureGate *configv1.FeatureGate
for i := range featureGates {
curr := featureGates[i]
decodedObj, err := curr.GetDecodedObj()
if err != nil {
return nil, fmt.Errorf("decoding failure for %q: %w", curr.OriginalFilename, err)
}
currFeatureGate, ok := decodedObj.(*configv1.FeatureGate)
if !ok {
return nil, fmt.Errorf("wrong obj type for %q: %T: %v", curr.OriginalFilename, decodedObj, curr.Content)
}
if featureGate == nil {
prev = &curr
featureGate = currFeatureGate
continue
}

if !equality.Semantic.DeepEqual(featureGate, currFeatureGate) {
return nil, fmt.Errorf("FeatureGate manifests disagree: %q and %q, with \n%v\n%v ", prev.OriginalFilename, curr.OriginalFilename, prev.Content, curr.Content)
}
}

ret, err := featuregates.NewHardcodedFeatureGateAccessFromFeatureGate(featureGate, o.PayloadVersion)
if err != nil {
return nil, fmt.Errorf("error creating feature accessor: %w", err)
}

return ret, nil
}

// ApplyTo applies the options to the given config struct using the provided text/template data.
func (o *GenericOptions) ApplyTo(cfg *FileConfig, defaultConfig, bootstrapOverrides Template, templateData interface{}, specialCases map[string]resourcemerge.MergeFunc) error {
var err error
Expand All @@ -116,19 +184,6 @@ func (o *GenericOptions) ApplyTo(cfg *FileConfig, defaultConfig, bootstrapOverri
return fmt.Errorf("failed loading assets from %q: %v", o.AssetInputDir, err)
}

for _, filename := range o.RenderedManifestInputFilenames {
manifestContent, err := assets.LoadFilesRecursively(filename)
if err != nil {
return fmt.Errorf("failed loading rendered manifest inputs from %q: %w", filename, err)
}
for manifestFile, content := range manifestContent {
cfg.RenderedManifests = append(cfg.RenderedManifests, RenderedManifest{
OriginalFilename: manifestFile,
Content: content,
})
}
}

return nil
}

Expand Down