Skip to content

Commit aad1a1e

Browse files
authored
internal/scaffold/olm-catalog: refactor CSV updaters (#2250)
* internal/scaffold/olm-catalog: refactor CSV updaters to be intuitive and more extensible with csvUpdater interface internal/scaffold/olm-catalog/testdata: update CSV alm-examples go.mod,go.sum: revendor after updating operator-registry dep to v1.5.3 * update csv.go comment * update variable name * internal/scaffold/olm-catalog/descriptor: return CRDDescription from GetCRDDescriptorForGVK instead of passing it in as an argument * fix linter errors * rename GetCRDDescriptionForGVK
1 parent 77aa9d1 commit aad1a1e

File tree

6 files changed

+276
-311
lines changed

6 files changed

+276
-311
lines changed

internal/scaffold/olm-catalog/csv.go

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ package catalog
1616

1717
import (
1818
"fmt"
19+
"io/ioutil"
1920
"os"
2021
"path/filepath"
2122
"regexp"
23+
"sort"
2224
"strings"
2325
"sync"
2426

@@ -34,6 +36,8 @@ import (
3436
"github.com/pkg/errors"
3537
log "github.com/sirupsen/logrus"
3638
"github.com/spf13/afero"
39+
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
40+
"k8s.io/apimachinery/pkg/runtime/schema"
3741
)
3842

3943
const (
@@ -121,7 +125,7 @@ func (s *CSV) CustomRender() ([]byte, error) {
121125
if err = s.updateCSVVersions(csv); err != nil {
122126
return nil, err
123127
}
124-
if err = s.updateCSVFromManifestFiles(cfg, csv); err != nil {
128+
if err = s.updateCSVFromManifests(cfg, csv); err != nil {
125129
return nil, err
126130
}
127131
s.setCSVDefaultFields(csv)
@@ -322,50 +326,90 @@ func (s *CSV) updateCSVVersions(csv *olmapiv1alpha1.ClusterServiceVersion) error
322326

323327
// updateCSVFromManifestFiles gathers relevant data from generated and
324328
// user-defined manifests and updates csv.
325-
func (s *CSV) updateCSVFromManifestFiles(cfg *CSVConfig, csv *olmapiv1alpha1.ClusterServiceVersion) error {
326-
store := NewUpdaterStore()
327-
otherSpecs := make(map[string][][]byte)
329+
func (g *CSV) updateCSVFromManifests(cfg *CSVConfig, csv *olmapiv1alpha1.ClusterServiceVersion) (err error) {
328330
paths := append(cfg.CRDCRPaths, cfg.OperatorPath)
329331
paths = append(paths, cfg.RolePaths...)
330-
for _, f := range paths {
331-
yamlData, err := afero.ReadFile(s.getFS(), f)
332+
manifestGVKMap := map[schema.GroupVersionKind][][]byte{}
333+
crGVKSet := map[schema.GroupVersionKind]struct{}{}
334+
for _, path := range paths {
335+
info, err := g.getFS().Stat(path)
332336
if err != nil {
333337
return err
334338
}
335-
336-
scanner := yamlutil.NewYAMLScanner(yamlData)
339+
if info.IsDir() {
340+
continue
341+
}
342+
b, err := ioutil.ReadFile(path)
343+
if err != nil {
344+
return err
345+
}
346+
scanner := yamlutil.NewYAMLScanner(b)
337347
for scanner.Scan() {
338-
yamlSpec := scanner.Bytes()
339-
typeMeta, err := k8sutil.GetTypeMetaFromBytes(yamlSpec)
348+
manifest := scanner.Bytes()
349+
typeMeta, err := k8sutil.GetTypeMetaFromBytes(manifest)
340350
if err != nil {
341-
return errors.Wrapf(err, "error getting type metadata from manifest %s", f)
351+
log.Infof("No TypeMeta in %s, skipping file", path)
352+
continue
342353
}
343-
found, err := store.AddToUpdater(yamlSpec, typeMeta.Kind)
344-
if err != nil {
345-
return errors.Wrapf(err, "error adding manifest %s to CSV updaters", f)
346-
}
347-
if !found {
348-
id := gvkID(typeMeta.GroupVersionKind())
349-
if _, ok := otherSpecs[id]; !ok {
350-
otherSpecs[id] = make([][]byte, 0)
354+
gvk := typeMeta.GroupVersionKind()
355+
manifestGVKMap[gvk] = append(manifestGVKMap[gvk], manifest)
356+
switch typeMeta.Kind {
357+
case "CustomResourceDefinition":
358+
// Collect CRD kinds to filter them out from unsupported manifest types.
359+
// The CRD type version doesn't matter as long as it has a group, kind,
360+
// and versions in the expected fields.
361+
crd := apiextv1beta1.CustomResourceDefinition{}
362+
if err = yaml.Unmarshal(manifest, &crd); err != nil {
363+
return err
364+
}
365+
for _, ver := range crd.Spec.Versions {
366+
crGVK := schema.GroupVersionKind{
367+
Group: crd.Spec.Group,
368+
Version: ver.Name,
369+
Kind: crd.Spec.Names.Kind,
370+
}
371+
crGVKSet[crGVK] = struct{}{}
351372
}
352-
otherSpecs[id] = append(otherSpecs[id], yamlSpec)
353373
}
354374
}
355375
if err = scanner.Err(); err != nil {
356376
return err
357377
}
358378
}
359379

360-
for id := range store.crds.crIDs {
361-
if crSpecs, ok := otherSpecs[id]; ok {
362-
for _, spec := range crSpecs {
363-
if err := store.AddCR(spec); err != nil {
364-
return err
365-
}
380+
crUpdaters := crs{}
381+
for gvk, manifests := range manifestGVKMap {
382+
// We don't necessarily care about sorting by a field value, more about
383+
// consistent ordering.
384+
sort.Slice(manifests, func(i int, j int) bool {
385+
return string(manifests[i]) < string(manifests[j])
386+
})
387+
switch gvk.Kind {
388+
case "Role":
389+
err = roles(manifests).apply(csv)
390+
case "ClusterRole":
391+
err = clusterRoles(manifests).apply(csv)
392+
case "Deployment":
393+
err = deployments(manifests).apply(csv)
394+
case "CustomResourceDefinition":
395+
err = crds(manifests).apply(csv)
396+
default:
397+
if _, ok := crGVKSet[gvk]; ok {
398+
crUpdaters = append(crUpdaters, manifests...)
399+
} else {
400+
log.Infof("Skipping manifest %s", gvk)
366401
}
367402
}
403+
if err != nil {
404+
return err
405+
}
368406
}
369-
370-
return store.Apply(csv)
407+
// Re-sort CR's since they are appended in random order.
408+
sort.Slice(crUpdaters, func(i int, j int) bool {
409+
return string(crUpdaters[i]) < string(crUpdaters[j])
410+
})
411+
if err = crUpdaters.apply(csv); err != nil {
412+
return err
413+
}
414+
return nil
371415
}

internal/scaffold/olm-catalog/csv_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ func TestSetAndCheckOLMNamespaces(t *testing.T) {
175175

176176
// The test operator.yaml doesn't have "olm.targetNamespaces", so first
177177
// check that depHasOLMNamespaces() returns false.
178-
dep := &appsv1.Deployment{}
179-
if err := yaml.Unmarshal(depBytes, dep); err != nil {
178+
dep := appsv1.Deployment{}
179+
if err := yaml.Unmarshal(depBytes, &dep); err != nil {
180180
t.Fatalf("Failed to unmarshal Deployment bytes: %v", err)
181181
}
182182
if depHasOLMNamespaces(dep) {
@@ -185,22 +185,22 @@ func TestSetAndCheckOLMNamespaces(t *testing.T) {
185185

186186
// Insert "olm.targetNamespaces" into WATCH_NAMESPACE and check that
187187
// depHasOLMNamespaces() returns true.
188-
setWatchNamespacesEnv(dep)
188+
setWatchNamespacesEnv(&dep)
189189
if !depHasOLMNamespaces(dep) {
190190
t.Error("Expected depHasOLMNamespaces to return true, got false")
191191
}
192192

193193
// Overwrite WATCH_NAMESPACE and check that depHasOLMNamespaces() returns
194194
// false.
195-
overwriteContainerEnvVar(dep, k8sutil.WatchNamespaceEnvVar, newEnvVar("FOO", "bar"))
195+
overwriteContainerEnvVar(&dep, k8sutil.WatchNamespaceEnvVar, newEnvVar("FOO", "bar"))
196196
if depHasOLMNamespaces(dep) {
197197
t.Error("Expected depHasOLMNamespaces to return false, got true")
198198
}
199199

200200
// Insert "olm.targetNamespaces" elsewhere in the deployment pod spec
201201
// and check that depHasOLMNamespaces() returns true.
202-
dep = &appsv1.Deployment{}
203-
if err := yaml.Unmarshal(depBytes, dep); err != nil {
202+
dep = appsv1.Deployment{}
203+
if err := yaml.Unmarshal(depBytes, &dep); err != nil {
204204
t.Fatalf("Failed to unmarshal Deployment bytes: %v", err)
205205
}
206206
dep.Spec.Template.ObjectMeta.Labels["namespace"] = olmTNMeta

0 commit comments

Comments
 (0)