Skip to content
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
8 changes: 8 additions & 0 deletions docs/v3/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -5656,6 +5656,14 @@
"type": "integer"
}
},
{
"name": "search",
"in": "query",
"description": "Find matching text",
"schema": {
"type": "string"
}
},
{
"name": "offset",
"in": "query",
Expand Down
17 changes: 12 additions & 5 deletions manager/controllers/systemtags.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package controllers

import (
"app/base/database"
"app/base/utils"
"errors"
"net/http"

"app/base/database"
"app/base/utils"

"app/manager/middlewares"

"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -48,16 +49,22 @@ var SystemTagsOpts = ListOpts{
},
StableSort: "tag",
DefaultSort: "tag",
SearchFields: []string{
"sq.tag->>'namespace'",
"sq.tag->>'key'",
"sq.tag->>'value'",
Comment on lines +52 to +55
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Avoid hard-coding the SQL alias in SearchFields to reduce coupling and future breakage risk

These SearchFields are tightly coupled to the sq alias (for example, "sq.tag->>'namespace'"). If the table/CTE alias changes, search will silently break. Either make these expressions independent of the outer alias (if supported), or centralize them in a shared constant/helper used by both the query builder and SearchFields so alias updates are done in one place.

Suggested implementation:

	SearchFields: []string{
		"tag->>'namespace'",
		"tag->>'key'",
		"tag->>'value'",
	},

This change assumes that the query builder / underlying SQL does not require an explicit table/CTE alias prefix for these expressions. If the current implementation does require the alias (e.g. because multiple tables expose a tag column), you should instead:

  1. Introduce a shared constant or helper (e.g. const systemTagAlias = "sq" or a function that formats search fields for a given alias) in this file or a shared package.
  2. Use that constant/helper both where the alias is defined in the SQL/CTE and here in SearchFields, so alias changes are centralized.

Comment on lines +52 to +55
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question for my understanding, how did you determine these 3 fields should be searched?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this is based on how tag searching works (or is intended to work) in Insights 😅
the tags consist of namespace, key and value parts, and they should be searchable on all those parts 🔍

},
}

// @Summary Show me systems tags applicable to this application
// @Description Show me systems tags applicable to this application
// @ID listSystemTags
// @Security RhIdentity
// @Produce json
// @Param sort query string false "Sort field" Enums(tag, count)
// @Param limit query int fals "Limit for paging"
// @Param offset query int false "Offset for paging"
// @Param sort query string false "Sort field" Enums(tag, count)
// @Param limit query int false "Limit for paging"
// @Param search query string false "Find matching text"
// @Param offset query int false "Offset for paging"
// @Success 200 {object} SystemTagsResponse
// @Failure 400 {object} utils.ErrorResponse
// @Failure 500 {object} utils.ErrorResponse
Expand Down
38 changes: 37 additions & 1 deletion manager/controllers/systemtags_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package controllers

import (
"app/base/core"
"net/http"
"testing"

"app/base/core"

"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -76,3 +77,38 @@ func TestSystemTagsListBadRequestOnIdtSort(t *testing.T) {
w := CreateRequestRouterWithAccount("GET", "/", "", "?sort=id", nil, "", SystemTagListHandler, 1)
assert.Equal(t, 400, w.Code)
}

func TestSystemTagsListSearch(t *testing.T) {
core.SetupTest(t)

w := CreateRequestRouterWithAccount("GET", "/", "", "?search=k3", nil, "", SystemTagListHandler, 1)

var output SystemTagsResponse
CheckResponse(t, w, http.StatusOK, &output)

assert.Equal(t, 2, len(output.Data))
assert.Equal(t, 2, output.Meta.TotalItems)
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
assert.Equal(t, "k3", output.Meta.Search)

assert.Equal(t, 1, output.Data[0].Count)
assert.Equal(t, "k3", output.Data[0].Tag.Key)
assert.Equal(t, "ns1", output.Data[0].Tag.Namespace)
assert.Equal(t, "val3", output.Data[0].Tag.Value)

assert.Equal(t, 3, output.Data[1].Count)
assert.Equal(t, "k3", output.Data[1].Tag.Key)
assert.Equal(t, "ns1", output.Data[1].Tag.Namespace)
assert.Equal(t, "val4", output.Data[1].Tag.Value)
}

func TestSystemTagsListSearchUnknown(t *testing.T) {
core.SetupTest(t)

w := CreateRequestRouterWithAccount("GET", "/", "", "?search=unknown", nil, "", SystemTagListHandler, 1)

var output SystemTagsResponse
CheckResponse(t, w, http.StatusOK, &output)

assert.Equal(t, 0, len(output.Data))
assert.Equal(t, "unknown", output.Meta.Search)
}
Loading