mirror of
https://github.com/gomods/athens
synced 2026-02-03 11:00:32 +00:00
Version filtering (#1050)
* extend filtering logic and configuration to include version lists Module filtering is very useful, but many deployments will need to satisfy even more granular constrainsts. Enterprises may need approved lists specific down to the minor (or patch) version element. Version filtering logic is similar to the module filtering, in that it's a prefix match of the version requested against each entry in the version filter list. Closes #1045 * include version filtering in documentation with example * allow filtering when version is missing Endpoints that do not specify a version, such as "@v/list", only need to be filtered by module rules.
This commit is contained in:
committed by
Michal Pristas
parent
adb4dbb10f
commit
7811524c22
+29
-8
@@ -42,7 +42,7 @@ func NewFilter(filterFilePath string) (*Filter, error) {
|
||||
}
|
||||
|
||||
// AddRule adds rule for specified path
|
||||
func (f *Filter) AddRule(path string, rule FilterRule) {
|
||||
func (f *Filter) AddRule(path string, versions []string, rule FilterRule) {
|
||||
f.ensurePath(path)
|
||||
|
||||
segments := getPathSegments(path)
|
||||
@@ -62,13 +62,14 @@ func (f *Filter) AddRule(path string, rule FilterRule) {
|
||||
last := segments[len(segments)-1]
|
||||
rn := latest.next[last]
|
||||
rn.rule = rule
|
||||
rn.vers = versions
|
||||
latest.next[last] = rn
|
||||
}
|
||||
|
||||
// Rule returns the filter rule to be applied to the given path
|
||||
func (f *Filter) Rule(path string) FilterRule {
|
||||
func (f *Filter) Rule(path, version string) FilterRule {
|
||||
segs := getPathSegments(path)
|
||||
rule := f.getAssociatedRule(segs...)
|
||||
rule := f.getAssociatedRule(version, segs...)
|
||||
if rule == Default {
|
||||
rule = Include
|
||||
}
|
||||
@@ -88,7 +89,7 @@ func (f *Filter) ensurePath(path string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Filter) getAssociatedRule(path ...string) FilterRule {
|
||||
func (f *Filter) getAssociatedRule(version string, path ...string) FilterRule {
|
||||
if len(path) == 0 {
|
||||
return f.root.rule
|
||||
}
|
||||
@@ -100,7 +101,17 @@ func (f *Filter) getAssociatedRule(path ...string) FilterRule {
|
||||
break
|
||||
}
|
||||
rn = rn.next[p]
|
||||
rules = append(rules, rn.rule)
|
||||
// default to true if no version filter, false otherwise
|
||||
match := len(rn.vers) == 0
|
||||
for _, ver := range rn.vers {
|
||||
if strings.HasPrefix(version, ver) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if match || version == "" {
|
||||
rules = append(rules, rn.rule)
|
||||
}
|
||||
}
|
||||
|
||||
if len(rules) == 0 {
|
||||
@@ -140,7 +151,7 @@ func initFromConfig(filePath string) (*Filter, error) {
|
||||
}
|
||||
|
||||
split := strings.Split(line, " ")
|
||||
if len(split) > 2 {
|
||||
if len(split) > 3 {
|
||||
return nil, errors.E(op, "Invalid configuration found in filter file at the line "+strconv.Itoa(idx+1))
|
||||
}
|
||||
|
||||
@@ -158,12 +169,22 @@ func initFromConfig(filePath string) (*Filter, error) {
|
||||
}
|
||||
// is root config
|
||||
if len(split) == 1 {
|
||||
f.AddRule("", rule)
|
||||
f.AddRule("", nil, rule)
|
||||
continue
|
||||
}
|
||||
var vers []string
|
||||
if len(split) == 3 {
|
||||
vers = strings.Split(split[2], ",")
|
||||
for i := range vers {
|
||||
vers[i] = strings.TrimRight(vers[i], "*")
|
||||
if vers[i][len(vers[i])-1] != '.' && strings.Count(vers[i], ".") < 2 {
|
||||
vers[i] += "."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path := strings.TrimSpace(split[1])
|
||||
f.AddRule(path, rule)
|
||||
f.AddRule(path, vers, rule)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
@@ -3,4 +3,5 @@ package module
|
||||
type ruleNode struct {
|
||||
next map[string]ruleNode
|
||||
rule FilterRule
|
||||
vers []string
|
||||
}
|
||||
|
||||
+50
-27
@@ -52,13 +52,13 @@ func (t *FilterTests) Test_IgnoreSimple() {
|
||||
|
||||
f, err := NewFilter(filter)
|
||||
r.NoError(err)
|
||||
f.AddRule("github.com/a/b", Exclude)
|
||||
f.AddRule("github.com/a/b", nil, Exclude)
|
||||
|
||||
r.Equal(Include, f.Rule("github.com/a"))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b"))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b/c"))
|
||||
r.Equal(Include, f.Rule("github.com/d"))
|
||||
r.Equal(Include, f.Rule("bitbucket.com/a/b"))
|
||||
r.Equal(Include, f.Rule("github.com/a", ""))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b", ""))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b/c", ""))
|
||||
r.Equal(Include, f.Rule("github.com/d", ""))
|
||||
r.Equal(Include, f.Rule("bitbucket.com/a/b", ""))
|
||||
}
|
||||
|
||||
func (t *FilterTests) Test_IgnoreParentAllowChildren() {
|
||||
@@ -69,14 +69,14 @@ func (t *FilterTests) Test_IgnoreParentAllowChildren() {
|
||||
|
||||
f, err := NewFilter(filter)
|
||||
r.NoError(err)
|
||||
f.AddRule("github.com/a/b", Exclude)
|
||||
f.AddRule("github.com/a/b/c", Include)
|
||||
f.AddRule("github.com/a/b", nil, Exclude)
|
||||
f.AddRule("github.com/a/b/c", nil, Include)
|
||||
|
||||
r.Equal(Include, f.Rule("github.com/a"))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b"))
|
||||
r.Equal(Include, f.Rule("github.com/a/b/c"))
|
||||
r.Equal(Include, f.Rule("github.com/d"))
|
||||
r.Equal(Include, f.Rule("bitbucket.com/a/b"))
|
||||
r.Equal(Include, f.Rule("github.com/a", ""))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b", ""))
|
||||
r.Equal(Include, f.Rule("github.com/a/b/c", ""))
|
||||
r.Equal(Include, f.Rule("github.com/d", ""))
|
||||
r.Equal(Include, f.Rule("bitbucket.com/a/b", ""))
|
||||
}
|
||||
|
||||
func (t *FilterTests) Test_OnlyAllowed() {
|
||||
@@ -87,14 +87,14 @@ func (t *FilterTests) Test_OnlyAllowed() {
|
||||
|
||||
f, err := NewFilter(filter)
|
||||
r.NoError(err)
|
||||
f.AddRule("github.com/a/b", Include)
|
||||
f.AddRule("", Exclude)
|
||||
f.AddRule("github.com/a/b", nil, Include)
|
||||
f.AddRule("", nil, Exclude)
|
||||
|
||||
r.Equal(Exclude, f.Rule("github.com/a"))
|
||||
r.Equal(Include, f.Rule("github.com/a/b"))
|
||||
r.Equal(Include, f.Rule("github.com/a/b/c"))
|
||||
r.Equal(Exclude, f.Rule("github.com/d"))
|
||||
r.Equal(Exclude, f.Rule("bitbucket.com/a/b"))
|
||||
r.Equal(Exclude, f.Rule("github.com/a", ""))
|
||||
r.Equal(Include, f.Rule("github.com/a/b", ""))
|
||||
r.Equal(Include, f.Rule("github.com/a/b/c", ""))
|
||||
r.Equal(Exclude, f.Rule("github.com/d", ""))
|
||||
r.Equal(Exclude, f.Rule("bitbucket.com/a/b", ""))
|
||||
}
|
||||
|
||||
func (t *FilterTests) Test_Direct() {
|
||||
@@ -105,14 +105,32 @@ func (t *FilterTests) Test_Direct() {
|
||||
|
||||
f, err := NewFilter(filter)
|
||||
r.NoError(err)
|
||||
f.AddRule("github.com/a/b/c", Exclude)
|
||||
f.AddRule("github.com/a/b", Direct)
|
||||
f.AddRule("github.com/a", Include)
|
||||
f.AddRule("", Exclude)
|
||||
f.AddRule("github.com/a/b/c", nil, Exclude)
|
||||
f.AddRule("github.com/a/b", nil, Direct)
|
||||
f.AddRule("github.com/a", nil, Include)
|
||||
f.AddRule("", nil, Exclude)
|
||||
|
||||
r.Equal(Include, f.Rule("github.com/a"))
|
||||
r.Equal(Direct, f.Rule("github.com/a/b"))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b/c/d"))
|
||||
r.Equal(Include, f.Rule("github.com/a", ""))
|
||||
r.Equal(Direct, f.Rule("github.com/a/b", ""))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b/c/d", ""))
|
||||
}
|
||||
|
||||
func (t *FilterTests) Test_versionFilter() {
|
||||
r := t.Require()
|
||||
filter := tempFilterFile(t.T())
|
||||
defer os.Remove(filter)
|
||||
|
||||
f, err := NewFilter(filter)
|
||||
r.NoError(err)
|
||||
f.AddRule("", nil, Exclude)
|
||||
f.AddRule("github.com/a/b", []string{"v1."}, Include)
|
||||
f.AddRule("github.com/a/b/c", []string{"v1.2.", "v0.8."}, Direct)
|
||||
|
||||
r.Equal(Exclude, f.Rule("github.com/d/e", "v1.2.0"))
|
||||
r.Equal(Exclude, f.Rule("github.com/a/b", "v10.0.0"))
|
||||
r.Equal(Include, f.Rule("github.com/a/b", "v1.5.0"))
|
||||
r.Equal(Direct, f.Rule("github.com/a/b/c/d", "v1.2.3"))
|
||||
r.Equal(Include, f.Rule("github.com/a/b/c/d", "v1.3.4"))
|
||||
}
|
||||
|
||||
func (t *FilterTests) Test_initFromConfig() {
|
||||
@@ -133,6 +151,11 @@ func (t *FilterTests) Test_initFromConfig() {
|
||||
r.Nil(f)
|
||||
r.Error(err)
|
||||
|
||||
versionInput := []byte("+ github.com/a/b\n\n# some comment\n\n- github.com/c/d v1,v2.3.4,v3.2.*\n\nD github.com/x\n")
|
||||
ioutil.WriteFile(filterFile, versionInput, 0644)
|
||||
f, err = initFromConfig(filterFile)
|
||||
r.NotNil(f)
|
||||
r.NoError(err)
|
||||
}
|
||||
|
||||
func tempFilterFile(t *testing.T) (path string) {
|
||||
|
||||
Reference in New Issue
Block a user