Skip to content

Commit

Permalink
nodes: filtering by multiple tags (#377)
Browse files Browse the repository at this point in the history
* nodes: add a test for filtering by multiple tags

Signed-off-by: Victoria Jeffrey <[email protected]>

* nodes: make the test pass! (filter by mult tags)

Signed-off-by: Victoria Jeffrey <[email protected]>

* expect two nodes, not one

Signed-off-by: Victoria Jeffrey <[email protected]>

* clean up the filtering logic a bit

Signed-off-by: Victoria Jeffrey <[email protected]>
  • Loading branch information
victoria jeffrey authored May 21, 2019
1 parent 959e6a9 commit f7212f8
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ def cleanup
Common::Filter.new(key: "environment", values: ["trou"]),
Common::Filter.new(key: "group", values: ["mak", "do"])
])
assert_equal(1, filtered_nodes_by_tags.total)
assert_equal(2, filtered_nodes_by_tags.total)
end

it "does not include deleted jobs in job list" do
Expand Down
29 changes: 27 additions & 2 deletions components/nodemanager-service/pgdb/filtering.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ func mergeFilters(mergeableFilters []*common.Filter) ([]common.Filter, error) {
return filters, nil
}

func handleTagFilters(tagFilters []common.Filter) (string, error) {
var tagConditions []string
for _, filter := range tagFilters {
tagKeyFilter := strings.TrimPrefix(filter.Key, "tags:")
newTagCondition, err := wherePatternMatchTags(tagKeyFilter, filter.Values, "t")
if err != nil {
return "", errors.Wrap(err, "buildWhereFilter error")
}
if filter.Exclude {
newTagCondition = fmt.Sprintf("NOT (%s)", newTagCondition)
}
tagConditions = append(tagConditions, newTagCondition)
}
return strings.Join(tagConditions, " OR "), nil
}

// Takes a filter map (should be validated for content) and table abbreviation and returns a wherefilter
func buildWhereFilter(mergeableFilters []*common.Filter, tableAbbrev string, filterField map[string]string) (whereFilter string, err error) {
if len(mergeableFilters) == 0 {
Expand All @@ -50,12 +66,13 @@ func buildWhereFilter(mergeableFilters []*common.Filter, tableAbbrev string, fil
}

var conditions []string
var tagFilters []common.Filter
for _, filter := range filters {
var newCondition string
var err error
if strings.HasPrefix(filter.Key, "tags:") {
tagKeyFilter := strings.TrimPrefix(filter.Key, "tags:")
newCondition, err = wherePatternMatchTags(tagKeyFilter, filter.Values, "t")
tagFilters = append(tagFilters, filter)
continue
} else {
switch filterField[filter.Key] {
case "":
Expand Down Expand Up @@ -84,6 +101,14 @@ func buildWhereFilter(mergeableFilters []*common.Filter, tableAbbrev string, fil
conditions = append(conditions, newCondition)
}

if len(tagFilters) > 0 {
tagCondition, err := handleTagFilters(tagFilters)
if err != nil {
return "", errors.Wrap(err, "buildWhereFilter error building tags")
}
conditions = append(conditions, tagCondition)
}

whereFilter = fmt.Sprintf("WHERE (%s)", strings.Join(conditions, " AND "))
logrus.Debugf("buildWhereFilter, whereFilter=%s", whereFilter)
return whereFilter, nil
Expand Down
27 changes: 27 additions & 0 deletions components/nodemanager-service/pgdb/nodes_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,33 @@ func (suite *NodesIntegrationSuite) TestGetNodesCanFilterByTags() {
suite.Equal("Taco Node", fetchedNodes[0].Name)
}

func (suite *NodesIntegrationSuite) TestGetNodesCanFilterByMultipleTags() {
_, err := suite.Database.AddNode(&nodes.Node{Name: "Taco Node", Manager: "automate", Tags: []*common.Kv{{Key: "tacos", Value: "yes"}}, TargetConfig: &nodes.TargetConfig{}})
suite.Require().NoError(err)

_, err = suite.Database.AddNode(&nodes.Node{Name: "Nacho Node", Manager: "automate", Tags: []*common.Kv{{Key: "nachos", Value: "yes"}}, TargetConfig: &nodes.TargetConfig{}})
suite.Require().NoError(err)

_, err = suite.Database.AddNode(&nodes.Node{Name: "No Nacho Node", Manager: "automate", Tags: []*common.Kv{{Key: "nachos", Value: "no"}}, TargetConfig: &nodes.TargetConfig{}})
suite.Require().NoError(err)

filter1 := &common.Filter{
Key: "tacos",
Values: []string{"yes"},
}
filter2 := &common.Filter{
Key: "nachos",
Values: []string{"yes"},
}
fetchedNodes, count, err := suite.Database.GetNodes("name", nodes.Query_ASC, 1, 100, []*common.Filter{filter1, filter2})
suite.Require().NoError(err)

suite.Equal(2, len(fetchedNodes))
suite.Equal(&pgdb.TotalCount{Total: 2, Unreachable: 0, Reachable: 0, Unknown: 3}, count)
suite.Equal("Nacho Node", fetchedNodes[0].GetName())
suite.Equal("Taco Node", fetchedNodes[1].GetName())
}

func (suite *NodesIntegrationSuite) TestGetNodesCanFilterByProjects() {
node1Id, err := suite.Database.AddNode(&nodes.Node{Name: "Taco Node", Projects: []string{"Favorite Food", "Taco Bell Menu"}})
suite.Require().NoError(err)
Expand Down

0 comments on commit f7212f8

Please sign in to comment.