Search by labels and prefixes

Implemented in API and ctl.
This commit is contained in:
Adam Štrauch 2021-09-05 17:30:21 +02:00
parent b120970054
commit c6cb674053
Signed by: cx
GPG Key ID: 018304FFA8988F8D
5 changed files with 105 additions and 16 deletions

View File

@ -179,13 +179,13 @@ It uses Go client library also located in this repository.
So far the REST API is super simple and it has only two endpoints: So far the REST API is super simple and it has only two endpoints:
``` ```
GET / # Same as /v1/discoveries GET / # Same as /v1/discoveries
GET /v1/discovery # Returns current local discovery packet GET /v1/discovery # Returns current local discovery packet
GET /v1/discoveries # Returns list of all discovered servers and their labels. GET /v1/discoveries # Returns list of all discovered servers and their labels.
GET /v1/discoveries?labels=LABELS # output will be filtered based on one or multiple labels separated by comma GET /v1/discoveries?labels=LABELS&prefixes=PREFIXES # output will be filtered based on one or multiple labels separated by comma or it can search for given prefixes, only one of those will be used
GET /v1/prometheus/:name # Generates output for Prometheus's SD config, name is group of the monitoring services described above. GET /v1/prometheus/:name # Generates output for Prometheus's SD config, name is group of the monitoring services described above.
POST /v1/labels # Add runtime labels that will persist over daemon restarts. Labels should be in the body of the request, one line per one label. POST /v1/labels # Add runtime labels that will persist over daemon restarts. Labels should be in the body of the request, one line per one label.
DELETE /v1/labels # Delete runtime labels. One label per line. Can't affect the labels from environment variables or labels added from the LabelPath. DELETE /v1/labels # Delete runtime labels. One label per line. Can't affect the labels from environment variables or labels added from the LabelPath.
``` ```
If there is an error the error message is returned as plain text. If there is an error the error message is returned as plain text.

View File

@ -115,13 +115,38 @@ func (l *LobbyClient) GetDiscoveries() ([]server.Discovery, error) {
} }
// Find discoveries by their labels // Find discoveries by their labels
func (l *LobbyClient) FindByLabels(labels server.Labels) (server.Discoveries, error) { func (l *LobbyClient) FindByLabels(labels server.Labels) ([]server.Discovery, error) {
l.init() l.init()
path := fmt.Sprintf("/v1/discoveries?labels=%s", strings.Join(labels.StringSlice(), ",")) path := fmt.Sprintf("/v1/discoveries?labels=%s", strings.Join(labels.StringSlice(), ","))
method := "GET" method := "GET"
var discoveries server.Discoveries var discoveries []server.Discovery
status, body, err := l.call(method, path, "")
if err != nil {
return discoveries, err
}
if status != 200 {
return discoveries, fmt.Errorf("non-200 response: %s", body)
}
err = json.Unmarshal([]byte(body), &discoveries)
if err != nil {
return discoveries, fmt.Errorf("response parsing error: %v", err)
}
return discoveries, nil
}
// Find discoveries by label prefixes
func (l *LobbyClient) FindByPrefixes(prefixes []string) ([]server.Discovery, error) {
l.init()
path := fmt.Sprintf("/v1/discoveries?prefixes=%s", strings.Join(prefixes, ","))
method := "GET"
var discoveries []server.Discovery
status, body, err := l.call(method, path, "") status, body, err := l.call(method, path, "")
if err != nil { if err != nil {

View File

@ -14,10 +14,12 @@ func Usage() {
flag.Usage() flag.Usage()
fmt.Println("") fmt.Println("")
fmt.Println("Commands:") fmt.Println("Commands:")
fmt.Println(" discovery returns discovery packet of the server where the client is connected to") fmt.Println(" discovery returns discovery packet of the server where the client is connected to")
fmt.Println(" discoveries returns list of all registered discovery packets") fmt.Println(" discoveries returns list of all registered discovery packets")
fmt.Println(" labels add LABEL [LABEL] ... adds new runtime labels") fmt.Println(" discoveries labels [LABEL] ... returns list of all registered discovery packets with given labels (OR)")
fmt.Println(" labels del LABEL [LABEL] ... deletes runtime labels") fmt.Println(" discoveries search [LABEL] ... returns list of all registered discovery packets with given label prefixes (OR)")
fmt.Println(" labels add LABEL [LABEL] ... adds new runtime labels")
fmt.Println(" labels del LABEL [LABEL] ... deletes runtime labels")
} }
func main() { func main() {
@ -66,10 +68,41 @@ func main() {
switch flag.Args()[0] { switch flag.Args()[0] {
case "discoveries": case "discoveries":
discoveries, err := client.GetDiscoveries() var discoveries []server.Discovery
if err != nil { var err error
fmt.Println(err)
if len(flag.Args()) > 2 {
if flag.Arg(1) == "labels" {
labels := []server.Label{}
for _, label := range flag.Args()[2:] {
labels = append(labels, server.Label(label))
}
discoveries, err = client.FindByLabels(labels)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
} else if flag.Arg(1) == "search" {
discoveries, err = client.FindByPrefixes(flag.Args()[2:])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
} else {
fmt.Println("ERROR: unknown usage of discoveries arguments")
fmt.Println("")
Usage()
os.Exit(0)
}
} else {
discoveries, err = client.GetDiscoveries()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
} }
printDiscoveries(discoveries) printDiscoveries(discoveries)
case "discovery": case "discovery":
discovery, err := client.GetDiscovery() discovery, err := client.GetDiscovery()

View File

@ -12,12 +12,15 @@ import (
func listHandler(c echo.Context) error { func listHandler(c echo.Context) error {
labels := c.QueryParam("labels") labels := c.QueryParam("labels")
prefixes := c.QueryParam("prefixes")
var discoveries []server.Discovery var discoveries []server.Discovery
if len(labels) > 0 { if len(labels) > 0 {
labelsFilterSlice := strings.Split(labels, ",") labelsFilterSlice := strings.Split(labels, ",")
discoveries = discoveryStorage.Filter(labelsFilterSlice) discoveries = discoveryStorage.Filter(labelsFilterSlice)
} else if len(prefixes) > 0 {
discoveries = discoveryStorage.FilterPrefix(strings.Split(prefixes, ","))
} else { } else {
discoveries = discoveryStorage.GetAll() discoveries = discoveryStorage.GetAll()
} }

View File

@ -148,6 +148,7 @@ func (d *Discoveries) GetAll() []Discovery {
return d.activeServers return d.activeServers
} }
// Filter returns list of discoveries based on given labels
func (d *Discoveries) Filter(labelsFilter []string) []Discovery { func (d *Discoveries) Filter(labelsFilter []string) []Discovery {
newSet := []Discovery{} newSet := []Discovery{}
@ -174,6 +175,33 @@ func (d *Discoveries) Filter(labelsFilter []string) []Discovery {
return newSet return newSet
} }
// Filter returns list of discoveries based on given label prefixes.
func (d *Discoveries) FilterPrefix(prefixes []string) []Discovery {
newSet := []Discovery{}
var found bool
if len(prefixes) > 0 {
for _, discovery := range d.activeServers {
found = false
for _, label := range discovery.Labels {
for _, prefix := range prefixes {
if strings.HasPrefix(label.String(), prefix) {
newSet = append(newSet, discovery)
found = true
break
}
}
if found {
break
}
}
}
}
return newSet
}
// Clean checks loops over last check values for each discovery object and removes it if it's passed // Clean checks loops over last check values for each discovery object and removes it if it's passed
func (d *Discoveries) Clean() { func (d *Discoveries) Clean() {
newSet := []Discovery{} newSet := []Discovery{}