Skip to content

Commit c6b1437

Browse files
committed
remove all traces of GVK template feature
- clean up every instance of the GVK templating feature - add last minute change for RWMutex instead of Mutex - this is the second commit that should be reviewed later when it comes time to re-enable the GVK code Signed-off-by: John Hunkins <[email protected]>
1 parent 6c2902b commit c6b1437

File tree

4 files changed

+32
-622
lines changed

4 files changed

+32
-622
lines changed

pkg/controller/operators/catalogtemplate/operator.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ type Operator struct {
4141
lister operatorlister.OperatorLister // union of versioned informer listers
4242
catalogSourceTemplateQueueSet *queueinformer.ResourceQueueSet // work queues for a catalog source update
4343
resyncPeriod func() time.Duration // period of time between resync
44-
ctx context.Context // context used for shutting down
4544
}
4645

4746
func NewOperator(ctx context.Context, kubeconfigPath string, logger *logrus.Logger, resync time.Duration, operatorNamespace string) (*Operator, error) {
@@ -94,7 +93,6 @@ func NewOperator(ctx context.Context, kubeconfigPath string, logger *logrus.Logg
9493
lister: lister,
9594
catalogSourceTemplateQueueSet: queueinformer.NewEmptyResourceQueueSet(),
9695
resyncPeriod: resyncPeriod,
97-
ctx: ctx,
9896
}
9997

10098
// Wire OLM CR sharedIndexInformers
@@ -106,13 +104,11 @@ func NewOperator(ctx context.Context, kubeconfigPath string, logger *logrus.Logg
106104
catalogTemplateSrcQueue := workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "catalogSourceTemplate")
107105
op.catalogSourceTemplateQueueSet.Set(metav1.NamespaceAll, catalogTemplateSrcQueue)
108106
catsrcQueueInformer, err := queueinformer.NewQueueInformer(
109-
op.ctx,
110-
// TODO: commented out sections I don't think are necessary
111-
// queueinformer.WithMetricsProvider(metrics.NewMetricsCatalogSource(op.lister.OperatorsV1alpha1().CatalogSourceLister())),
107+
ctx,
112108
queueinformer.WithLogger(op.logger),
113109
queueinformer.WithQueue(catalogTemplateSrcQueue),
114110
queueinformer.WithInformer(catsrcInformer.Informer()),
115-
queueinformer.WithSyncer(queueinformer.LegacySyncHandler(op.syncCatalogSources).ToSyncer()), // ToSyncerWithDelete(op.handleCatSrcDeletion)), TODO do we need to handle deletion specially?
111+
queueinformer.WithSyncer(queueinformer.LegacySyncHandler(op.syncCatalogSources).ToSyncer()),
116112
)
117113
if err != nil {
118114
return nil, err
@@ -142,9 +138,6 @@ func (o *Operator) syncCatalogSources(obj interface{}) error {
142138
})
143139
logger.Info("syncing catalog source for annotation templates")
144140

145-
// this is our opportunity to discover GVK templates and setup watchers (if possible)
146-
catalogsource.InitializeCatalogSourceTemplates(outputCatalogSource)
147-
148141
catalogImageTemplate := catalogsource.GetCatalogTemplateAnnotation(outputCatalogSource)
149142
if catalogImageTemplate == "" {
150143
logger.Debug("this catalog source is not participating in template replacement")

pkg/lib/catalogsource/image_template.go

Lines changed: 7 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
package catalogsource
22

33
import (
4-
"bytes"
5-
"encoding/json"
64
"fmt"
7-
"reflect"
85
"regexp"
96
"strconv"
107
"strings"
118
"sync"
129

1310
"github.com/blang/semver/v4"
14-
15-
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1611
"github.com/sirupsen/logrus"
17-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
18-
"k8s.io/apimachinery/pkg/runtime/schema"
1912
"k8s.io/apimachinery/pkg/version"
20-
"k8s.io/client-go/util/jsonpath"
13+
14+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
2115
)
2216

2317
const (
@@ -30,21 +24,6 @@ const (
3024
capGrpKubeMinorV = "kubeminorv"
3125
// capGrpKubePatchV is a capture group name for a kube patch version
3226
capGrpKubePatchV = "kubepatchv"
33-
// capGrpGvk is a capture group name for a dynamic template that uses its own subgroups
34-
capGrpGvk = "gvk"
35-
36-
// capSubgrpGroup is a sub capture group name used in a dynamic template
37-
capSubgrpGroup = "group"
38-
// capSubgrpVersion is a sub capture group name used in a dynamic template
39-
capSubgrpVersion = "version"
40-
// capSubgrpKind is a sub capture group name used in a dynamic template
41-
capSubgrpKind = "kind"
42-
// capSubgrpName is a sub capture group name used in a dynamic template
43-
capSubgrpName = "name"
44-
// capSubgrpNamespace is a sub capture group name used in a dynamic template
45-
capSubgrpNamespace = "namespace"
46-
// capSubgrpJsonpath is a sub capture group name used in a dynamic template
47-
capSubgrpJsonpath = "jsonpath"
4827

4928
// static templates
5029

@@ -55,9 +34,6 @@ const (
5534
// TemplKubePatchV is a template that represents the kube patch version
5635
TemplKubePatchV = "{kube_patch_version}"
5736

58-
// templGvk is a dynamic template that uses its own subgroups
59-
templGvk = "{group:(?P<group>.*?),version:(?P<version>.*?),kind:(?P<kind>.*?),name:(?P<name>.*?),namespace:(?P<namespace>.*?),jsonpath:(?P<jsonpath>{.*?})}"
60-
6137
// templateMissing represents a value that could not be obtained from the cluster
6238
templateMissing = "missing"
6339

@@ -72,17 +48,7 @@ const (
7248
var templateNameToReplacementValuesMap = map[string]string{}
7349

7450
// templateMutex is a package scoped mutex for synchronizing access to templateNameToReplacementValuesMap
75-
var templateMutex sync.Mutex
76-
77-
// convertToKey is a function that creates a key for templateNameToReplacementValuesMap based on a GVK key and json path
78-
func convertToKey(key GVK_Key, jsonPath string) string {
79-
return fmt.Sprintf("{group:%s,version:%s,kind:%s,name:%s,namespace:%s,jsonpath:%s}", key.Group, key.Version, key.Kind, key.name, key.namespace, jsonPath)
80-
}
81-
82-
// gvkToJSONPathMap is a multimap (i.e. one key with multiple values) where each value is
83-
// zero or more JSON paths. In other words the user could specify multiple JSON path references
84-
// for the same kubernetes manifest
85-
var gvkToJSONPathMap = map[GVK_Key][]string{}
51+
var templateMutex sync.RWMutex
8652

8753
func init() {
8854
// Handle known static templates
@@ -106,10 +72,9 @@ func initializeIfNeeded(templateKey string) {
10672
// resetMaps is only useful for test cases
10773
func resetMaps() {
10874
templateMutex.Lock()
109-
defer templateMutex.Unlock()
110-
11175
templateNameToReplacementValuesMap = map[string]string{}
112-
gvkToJSONPathMap = map[GVK_Key][]string{}
76+
templateMutex.Unlock()
77+
11378
initializeIfNeeded(TemplKubeMajorV)
11479
initializeIfNeeded(TemplKubeMinorV)
11580
initializeIfNeeded(TemplKubePatchV)
@@ -139,13 +104,10 @@ var regexList = regexEntries{
139104
{capGrpKubeMajorV, TemplKubeMajorV},
140105
{capGrpKubeMinorV, TemplKubeMinorV},
141106
{capGrpKubePatchV, TemplKubePatchV},
142-
{capGrpGvk, templGvk},
143107
}
144108

145109
var regexImageTemplates = regexp.MustCompile(regexList.String())
146110

147-
var regexGVKTemplate = regexp.MustCompile(templGvk)
148-
149111
// ReplaceTemplates takes a catalog image reference containing templates (i.e. catalogImageTemplate)
150112
// and attempts to replace the templates with actual values (if available).
151113
// The return value processedCatalogImageTemplate represents the catalog image reference after processing.
@@ -155,8 +117,8 @@ var regexGVKTemplate = regexp.MustCompile(templGvk)
155117
// fetched yet). Providing an empty catalogImageTemplate results in empty processedCatalogImageTemplate and
156118
// zero length unresolvedTemplates
157119
func ReplaceTemplates(catalogImageTemplate string) (processedCatalogImageTemplate string, unresolvedTemplates []string) {
158-
templateMutex.Lock()
159-
defer templateMutex.Unlock()
120+
templateMutex.RLock()
121+
defer templateMutex.RUnlock()
160122

161123
// init to empty slice
162124
unresolvedTemplates = []string{}
@@ -200,161 +162,6 @@ func GetCatalogTemplateAnnotation(catalogSource *v1alpha1.CatalogSource) string
200162
}
201163
}
202164

203-
// GVK_Key uniquely represents a Group/Version/Kind (with optional name/namespace)
204-
// and can be used as a key for retrieval of data associated with this key
205-
type GVK_Key struct {
206-
schema.GroupVersionKind
207-
name string
208-
namespace string
209-
}
210-
211-
func InitializeCatalogSourceTemplates(catalogSource *v1alpha1.CatalogSource) []GVK_Key {
212-
213-
// capture a list of keys that were found in this catalog source
214-
foundGVKs := []GVK_Key{}
215-
216-
// findNamedMatches will return a map whose key is the named capture group, and value is the value of the capture group
217-
findNamedMatches := func(str string) map[string]string {
218-
// Note: matches and names indices are "in sync"
219-
matches := regexGVKTemplate.FindStringSubmatch(str)
220-
names := regexGVKTemplate.SubexpNames()
221-
222-
results := map[string]string{}
223-
for i, match := range matches {
224-
// only add named groups to the map
225-
if names[i] != "" {
226-
results[names[i]] = match
227-
}
228-
}
229-
return results
230-
}
231-
232-
catalogImageTemplate := GetCatalogTemplateAnnotation(catalogSource)
233-
if catalogImageTemplate == "" {
234-
// bail out since there's nothing to do here
235-
return foundGVKs
236-
}
237-
238-
/* Handle GVK templates */
239-
240-
// get every GVK template available (if any)
241-
gvkTemplates := regexGVKTemplate.FindAllString(catalogImageTemplate, -1)
242-
// add each GVK template for later use, initializing to missing value
243-
for _, gvkTemplate := range gvkTemplates {
244-
initializeIfNeeded(gvkTemplate)
245-
246-
// get the sub groups
247-
subGroupMap := findNamedMatches(gvkTemplate)
248-
249-
// create GVKTemplate to use as a key... add values from the subgroups as best we can, defaults to empty string for values not found
250-
key := GVK_Key{
251-
GroupVersionKind: schema.GroupVersionKind{Group: subGroupMap[capSubgrpGroup], Version: subGroupMap[capSubgrpVersion], Kind: subGroupMap[capSubgrpKind]},
252-
name: subGroupMap[capSubgrpName],
253-
namespace: subGroupMap[capSubgrpNamespace],
254-
}
255-
jsonPath := subGroupMap[capSubgrpJsonpath]
256-
257-
// see if we've already added this key (don't add duplicates)
258-
gvkPresent := false
259-
for _, existingGVK := range foundGVKs {
260-
if reflect.DeepEqual(existingGVK, key) {
261-
gvkPresent = true
262-
}
263-
}
264-
if !gvkPresent {
265-
foundGVKs = append(foundGVKs, key)
266-
}
267-
268-
// add this entry to the map and append the jsonPath to the array
269-
if existingJsonPaths, ok := gvkToJSONPathMap[key]; ok {
270-
// map already has this key, now find out if we've already added this path
271-
foundEntry := false
272-
for _, existingJsonPath := range existingJsonPaths {
273-
if jsonPath == existingJsonPath {
274-
foundEntry = true
275-
}
276-
}
277-
// if we did not find a jsonpath entry then add it now
278-
if !foundEntry {
279-
gvkToJSONPathMap[key] = append(gvkToJSONPathMap[key], jsonPath)
280-
}
281-
} else {
282-
gvkToJSONPathMap[key] = append(gvkToJSONPathMap[key], jsonPath)
283-
}
284-
285-
}
286-
287-
return foundGVKs
288-
}
289-
290-
func UpdateGVKValue(u *unstructured.Unstructured, logger *logrus.Logger) {
291-
templateMutex.Lock()
292-
defer templateMutex.Unlock()
293-
294-
// reconstitute the key
295-
key := GVK_Key{
296-
GroupVersionKind: u.GetObjectKind().GroupVersionKind(),
297-
name: u.GetName(),
298-
namespace: u.GetNamespace(),
299-
}
300-
301-
// find the JSON paths
302-
if jsonPaths, ok := gvkToJSONPathMap[key]; ok {
303-
304-
// convert the unstructured object into JSON as bytes
305-
jsonBytes, err := u.MarshalJSON()
306-
if err != nil {
307-
logger.WithError(err).Warn("unable to convert kube manifest to JSON")
308-
}
309-
310-
// pass the JSON as bytes through the go json library so its in the right format
311-
var processedJSON interface{}
312-
err = json.Unmarshal(jsonBytes, &processedJSON)
313-
if err != nil {
314-
logger.WithError(err).Warn("unable to convert kube manifest json data into usable form")
315-
}
316-
317-
for _, jsonPath := range jsonPaths {
318-
319-
gvkLogger := logger.WithFields(logrus.Fields{
320-
"gvk": u.GetObjectKind().GroupVersionKind().String(),
321-
"jsonPath": jsonPath,
322-
})
323-
// create the json path parser
324-
jsonPathParser := jsonpath.New("GVK path parser")
325-
326-
// parse the json path template
327-
err = jsonPathParser.Parse(jsonPath)
328-
if err != nil {
329-
gvkLogger.WithError(err).Warn("unable to parse json path template")
330-
continue
331-
}
332-
333-
// execute the parser using the JSON data writing the results into a buffer
334-
buf := new(bytes.Buffer)
335-
err = jsonPathParser.Execute(buf, processedJSON)
336-
if err != nil {
337-
gvkLogger.WithError(err).Warn("unable to execute json path parsing")
338-
continue
339-
}
340-
341-
templateMapKey := convertToKey(key, jsonPath)
342-
templateMapValue := buf.String()
343-
344-
if jsonPath == templateMapValue {
345-
// the jsonpath is exactly the same as the templateMapValue, this means
346-
// that the jsonpath was probably invalid, so don't update
347-
gvkLogger.Debugf("jsonpath %q is likely invalid (maybe curly braces are missing?)", jsonPath)
348-
continue
349-
}
350-
// reconstruct the key for the template replacement map and add
351-
// whatever we got from the json path execution
352-
templateNameToReplacementValuesMap[templateMapKey] = templateMapValue
353-
gvkLogger.Debugf("updated templateNameToReplacementValuesMap: key=%q value%q", templateMapKey, templateMapValue)
354-
}
355-
}
356-
}
357-
358165
func UpdateKubeVersion(serverVersion *version.Info, logger *logrus.Logger) {
359166
templateMutex.Lock()
360167
defer templateMutex.Unlock()

0 commit comments

Comments
 (0)