Skip to content

Commit 6627a2d

Browse files
authored
✨ Support extenion compat with addon as regex. (#782)
Both the analyzer and tech-discovery both use the same providers. An extension having compatibility with multiple addons is not a common/mainstream use case. To get around this, we have defined a duplicate set of extensions for each provider. One with compatibility with the `analyzer` addon and the other for the `tech-discovery` addon. After a recent refactor of the generic extension into multiple extensions (go, python, nodejs), it became obvious that maintain the duplicate set of extensions is painful and likely error prone. It seems a better approach is to change `Extention.Spec.Addon` to (optionally) define a regex. This approach caters to the mainstream use case that extensions have compatibility with one addon. It also avoids making the field an _array_ requiring a CRD change. This is which is MUCH simpler. The existing extensions will need to be updated to be compatible with both addons. Example (java extension): ``` addon: ^(analyzer|tech-discovery)$ ``` The `discovery-` extensions would be deleted. --------- Signed-off-by: Jeff Ortel <jortel@redhat.com>
1 parent 0986cad commit 6627a2d

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

settings/hub.go

+1
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ func (r *Hub) namespace() (ns string, err error) {
368368
// build returns the hub build version.
369369
// This is expected to be the output of `git describe`.
370370
// Examples:
371+
//
371372
// v0.6.0-ea89gcd
372373
// v0.6.0
373374
func (r *Hub) build() (version string, err error) {

task/error.go

+19
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,25 @@ func (e *SelectorNotValid) Retry() (r bool) {
231231
return
232232
}
233233

234+
// ExtAddonNotValid reports extension addon ref error.
235+
type ExtAddonNotValid struct {
236+
Extension string
237+
Reason string
238+
}
239+
240+
func (e *ExtAddonNotValid) Error() string {
241+
return fmt.Sprintf(
242+
"Extension '%s' addon ref not valid. reason: %s",
243+
e.Extension,
244+
e.Reason)
245+
}
246+
247+
func (e *ExtAddonNotValid) Is(err error) (matched bool) {
248+
var inst *ExtAddonNotValid
249+
matched = errors.As(err, &inst)
250+
return
251+
}
252+
234253
// PriorityNotFound report priority class not found.
235254
type PriorityNotFound struct {
236255
Name string

task/manager.go

+34-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"io"
99
"os"
1010
"path"
11+
"regexp"
1112
"sort"
1213
"strconv"
1314
"strings"
@@ -88,6 +89,10 @@ const (
8889
Cache = "cache"
8990
)
9091

92+
var (
93+
IsRegex = regexp.MustCompile("[^0-9A-Za-z_-]")
94+
)
95+
9196
var (
9297
Settings = &settings.Settings
9398
Log = logr.WithName("task-scheduler")
@@ -555,7 +560,11 @@ func (m *Manager) selectExtensions(task *Task, addon *crd.Addon) (err error) {
555560
matched := false
556561
selector := NewSelector(m.DB, task)
557562
for _, extension := range m.cluster.Extensions() {
558-
if extension.Spec.Addon != addon.Name {
563+
matched, err = m.matchAddon(extension, addon)
564+
if err != nil {
565+
return
566+
}
567+
if !matched {
559568
continue
560569
}
561570
matched, err = selector.Match(extension.Spec.Selector)
@@ -570,6 +579,30 @@ func (m *Manager) selectExtensions(task *Task, addon *crd.Addon) (err error) {
570579
return
571580
}
572581

582+
// matchAddon - returns true when the extension's `addon`
583+
// (ref) matches the addon name.
584+
// The `ref` is matched as a REGEX when it contains
585+
// characters other than: [0-9A-Za-z_].
586+
func (m *Manager) matchAddon(extension *crd.Extension, addon *crd.Addon) (matched bool, err error) {
587+
ref := strings.TrimSpace(extension.Spec.Addon)
588+
p := IsRegex
589+
if p.MatchString(ref) {
590+
p, err = regexp.Compile(ref)
591+
if err != nil {
592+
err = &ExtAddonNotValid{
593+
Extension: extension.Name,
594+
Reason: err.Error(),
595+
}
596+
return
597+
}
598+
matched = p.MatchString(addon.Name)
599+
} else {
600+
601+
matched = addon.Name == ref
602+
}
603+
return
604+
}
605+
573606
// postpone Postpones a task as needed based on rules.
574607
// postpone order:
575608
// - priority (lower)

task/task_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,34 @@ func TestPriorityGraph(t *testing.T) {
135135
deps := pE.graph(ready[0], ready)
136136
g.Expect(len(deps)).To(gomega.Equal(2))
137137
}
138+
139+
func TestAddonRegex(t *testing.T) {
140+
g := gomega.NewGomegaWithT(t)
141+
m := Manager{}
142+
addonA := &crd.Addon{}
143+
addonA.Name = "A"
144+
addonB := &crd.Addon{}
145+
addonB.Name = "B"
146+
// direct.
147+
ext := &crd.Extension{}
148+
ext.Name = "Test"
149+
ext.Spec.Addon = "A"
150+
matched, err := m.matchAddon(ext, addonA)
151+
g.Expect(err).To(gomega.BeNil())
152+
g.Expect(matched).To(gomega.BeTrue())
153+
matched, err = m.matchAddon(ext, addonB)
154+
g.Expect(err).To(gomega.BeNil())
155+
g.Expect(matched).To(gomega.BeFalse())
156+
// regex.
157+
ext.Spec.Addon = "^(A|B)$"
158+
matched, err = m.matchAddon(ext, addonA)
159+
g.Expect(err).To(gomega.BeNil())
160+
g.Expect(matched).To(gomega.BeTrue())
161+
matched, err = m.matchAddon(ext, addonB)
162+
g.Expect(err).To(gomega.BeNil())
163+
g.Expect(matched).To(gomega.BeTrue())
164+
// regex not valid.
165+
ext.Spec.Addon = "(]$"
166+
matched, err = m.matchAddon(ext, addonA)
167+
g.Expect(err).ToNot(gomega.BeNil())
168+
}

0 commit comments

Comments
 (0)