Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(registry): add expand names function #92

Merged
merged 5 commits into from
Dec 26, 2024
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
34 changes: 34 additions & 0 deletions pkg/registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package registry
import (
"context"
"fmt"
"sort"

"github.com/mb0/glob"
"github.com/sirupsen/logrus"
"github.com/stevenle/topsort"

Expand Down Expand Up @@ -196,6 +198,38 @@ func GetNames() []string {
return names
}

// ExpandNames takes a list of names and expands them based on a wildcard and returns all the names that match
func ExpandNames(names []string) []string {
var expandedNames []string
registeredNames := GetNames()

for _, name := range names {
matches, _ := glob.GlobStrings(registeredNames, name)
if matches == nil {
logrus.
WithField("handler", "ExpandNames").
WithField("name", name).
Trace("no expansion for name")

expandedNames = append(expandedNames, name)
continue
}

logrus.
WithField("handler", "ExpandNames").
WithField("name", name).
WithField("matches", matches).
Trace("expanded name")

expandedNames = append(expandedNames, matches...)
}

// Ensure predictable order
sort.Strings(expandedNames)

return expandedNames
}

// GetNamesForScope provides a string slice of all listers for a particular scope
func GetNamesForScope(scope Scope) []string {
var names []string
Expand Down
51 changes: 51 additions & 0 deletions pkg/registry/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,54 @@ func Test_GetListersV2_CircularDependency(t *testing.T) {
GetListersV2()
})
}

func TestExpandNames(t *testing.T) {
ClearRegistry()

// Note: this is necessary to test the panic when using coverage and multiple tests
defer func() {
if r := recover(); r != nil {
t.Logf("Recovered from panic: %v", r)
}
}()

rs := []string{"OpsOne", "OpsTwo", "TestingOne", "TestingTwo"}

for _, r := range rs {
Register(&Registration{
Name: r,
Scope: "test",
Lister: TestLister{},
})
}

cases := []struct {
name string
expected []string
}{
{
name: "Ops*",
expected: []string{"OpsOne", "OpsTwo"},
},
{
name: "OpsOne",
expected: []string{"OpsOne"},
},
{
name: "OpsThree",
expected: []string{"OpsThree"},
},
{
name: "Ops* Testing*",
expected: []string{"Ops* Testing*"},
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
expanded := ExpandNames([]string{c.name})

assert.Equal(t, c.expected, expanded)
})
}
}
22 changes: 22 additions & 0 deletions pkg/types/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,31 @@
// to a resource.
package types

import (
"github.com/mb0/glob"
)

// Collection is a collection of strings
type Collection []string

// Expand returns a collection by using the Collection which may contain glob patterns and match to the source
// and returns the expanded collection, if there are no matches, it includes the original element from the collection.
func (c Collection) Expand(base []string) Collection {
var expanded Collection
for _, sc := range c {
matches, _ := glob.GlobStrings(base, sc)

if matches == nil {
expanded = append(expanded, sc)
continue
}

expanded = append(expanded, matches...)
}

return expanded
}

// Intersect returns the intersection of two collections
func (c Collection) Intersect(o Collection) Collection {
mo := o.toMap()
Expand Down
2 changes: 1 addition & 1 deletion pkg/types/collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/ekristen/libnuke/pkg/types"
)

func TestSetInterset(t *testing.T) {
func TestSetIntersect(t *testing.T) {
s1 := types.Collection{"a", "b", "c"}
s2 := types.Collection{"b", "a", "d"}

Expand Down
11 changes: 7 additions & 4 deletions pkg/types/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,29 @@ func ResolveResourceTypes(
alternativeMappings map[string]string) Collection {
// Loop over the alternatives and build a list of the old style resource types
for _, cl := range alternatives {
expandedCl := cl.Expand(base)
oldStyle := Collection{}
for _, c := range cl {
for _, c := range expandedCl {
os, found := alternativeMappings[c]
if found {
oldStyle = append(oldStyle, os)
}
}

base = base.Union(cl)
base = base.Union(expandedCl)
base = base.Remove(oldStyle)
}

for _, i := range includes {
expandedI := i.Expand(base)
if len(i) > 0 {
base = base.Intersect(i)
base = base.Intersect(expandedI)
}
}

for _, e := range excludes {
base = base.Remove(e)
expandedE := e.Expand(base)
base = base.Remove(expandedE)
}

return base
Expand Down
33 changes: 33 additions & 0 deletions pkg/types/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
var emptyCollection []Collection
var emptyMapping = map[string]string{}
var baseCollection = Collection{"ResourceA", "ResourceB", "ResourceC", "ResourceD", "ResourceE", "ResourceF"}
var baseGlobCollection = Collection{"ServiceA1", "ServiceA2", "ServiceA3",
"ServiceB1", "ServiceB2", "ServiceB3", "ServiceC1", "ServiceC2", "ServiceC3"}

func TestResolveResourceTypes(t *testing.T) {
cases := []struct {
Expand Down Expand Up @@ -109,6 +111,37 @@ func TestResolveResourceTypes(t *testing.T) {
},
expected: Collection{"ResourceD", "ResourceF", "AlternativeA", "AlternativeC", "AlternativeE"},
},
{
name: "includes and excludes with globs",
base: baseGlobCollection,
includes: emptyCollection,
excludes: []Collection{
{"ServiceB*"},
},
expected: Collection{"ServiceA1", "ServiceA2", "ServiceA3", "ServiceC1", "ServiceC2", "ServiceC3"},
},
{
name: "excludes and includes with globs",
base: baseGlobCollection,
includes: []Collection{
{"ServiceA*"},
},
excludes: []Collection{
{"ServiceA2", "ServiceA3"},
},
expected: Collection{"ServiceA1"},
},
{
name: "excludes and includes with globs variant",
base: baseGlobCollection,
includes: []Collection{
{"ServiceA*", "ServiceB*"},
},
excludes: []Collection{
{"ServiceA2", "ServiceA3", "ServiceB2", "ServiceB3"},
},
expected: Collection{"ServiceA1", "ServiceB1"},
},
}

for _, tc := range cases {
Expand Down
Loading