diff --git a/client/main.go b/client/main.go index 8c04534..de51bb5 100644 --- a/client/main.go +++ b/client/main.go @@ -114,6 +114,31 @@ func (l *LobbyClient) GetDiscoveries() ([]server.Discovery, error) { return discoveries, nil } +// Resolve returns list of hostnames that have given label +func (l *LobbyClient) Resolve(label server.Label) ([]string, error) { + l.init() + + path := fmt.Sprintf("/v1/resolve?label=%s", label.String()) + method := "GET" + + var hostnames []string + + status, body, err := l.call(method, path, "") + if err != nil { + return hostnames, err + } + if status != 200 { + return hostnames, fmt.Errorf("non-200 response: %s", body) + } + + err = json.Unmarshal([]byte(body), &hostnames) + if err != nil { + return hostnames, fmt.Errorf("response parsing error: %v", err) + } + + return hostnames, nil +} + // Find discoveries by their labels func (l *LobbyClient) FindByLabels(labels server.Labels) ([]server.Discovery, error) { l.init() diff --git a/ctl/main.go b/ctl/main.go index 3761674..f170e96 100644 --- a/ctl/main.go +++ b/ctl/main.go @@ -14,6 +14,7 @@ func Usage() { flag.Usage() fmt.Println("") fmt.Println("Commands:") + fmt.Println(" resolve label returns list of hostnames with given label") 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 labels [LABEL] ... returns list of all registered discovery packets with given labels (OR)") @@ -68,6 +69,25 @@ func main() { } switch flag.Args()[0] { + case "resolve": + if len(flag.Args()) == 2 { + hostnames, err := client.Resolve(server.Label(flag.Arg(1))) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + if *jsonOutput { + printJSON(hostnames) + } else { + for _, hostname := range hostnames { + fmt.Println(hostname) + } + } + } else { + Usage() + os.Exit(0) + } + case "discoveries": var discoveries []server.Discovery var err error diff --git a/daemon/handlers.go b/daemon/handlers.go index 96cd966..00929cb 100644 --- a/daemon/handlers.go +++ b/daemon/handlers.go @@ -28,6 +28,20 @@ func listHandler(c echo.Context) error { return c.JSONPretty(200, discoveries, " ") } +// resolveHandler returns hostname(s) based on another label +func resolveHandler(c echo.Context) error { + label := c.QueryParam("label") // This is label we will use to filter discovery packets + + output := []string{} + + discoveries := discoveryStorage.Filter([]string{label}) + for _, discovery := range discoveries { + output = append(output, discovery.Hostname) + } + + return c.JSONPretty(http.StatusOK, output, " ") +} + func prometheusHandler(c echo.Context) error { name := c.Param("name") diff --git a/daemon/main.go b/daemon/main.go index 9e2f753..1ffd6fe 100644 --- a/daemon/main.go +++ b/daemon/main.go @@ -204,7 +204,6 @@ func main() { if err != nil { log.Printf("discovery changed error: %v", err) } - // If config.Register is false this instance won't be registered with other nodes if config.Register { // This is background process that sends the message @@ -225,7 +224,6 @@ func main() { } else { log.Println("standalone mode, I won't register myself") } - // -------- // REST API // -------- @@ -237,10 +235,10 @@ func main() { } e.Use(middleware.Logger()) e.Use(middleware.Recover()) - // Routes if !config.DisableAPI { e.GET("/", listHandler) + e.GET("/v1/resolve", resolveHandler) e.GET("/v1/discovery", getIdentificationHandler) e.GET("/v1/discoveries", listHandler) e.POST("/v1/labels", addLabelsHandler) @@ -251,7 +249,6 @@ func main() { // ------------------------------ // Termination signals processing // ------------------------------ - signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) @@ -267,7 +264,6 @@ func main() { } e.Shutdown(context.TODO()) }(e, config) - // Start server // In most cases this will end expectedly so it doesn't make sense to use the echo's approach to treat this message as an error. e.Logger.Info(e.Start(config.Host + ":" + strconv.Itoa(int(config.Port)))) diff --git a/daemon/prometheus.go b/daemon/prometheus.go index 69868e0..78b6ea0 100644 --- a/daemon/prometheus.go +++ b/daemon/prometheus.go @@ -39,7 +39,7 @@ func preparePrometheusOutput(name string, discoveries []server.Discovery) Promet labels := map[string]string{} - for _, label := range discovery.FindLabels("prometheus:" + name + ":") { + for _, label := range discovery.FindLabelsByPrefix("prometheus:" + name + ":") { trimmed := strings.TrimPrefix(label.String(), "prometheus:"+name+":") parts := strings.SplitN(trimmed, ":", 2) if len(parts) == 2 { diff --git a/daemon/update.go b/daemon/update.go index a98f25f..d6b3c8b 100644 --- a/daemon/update.go +++ b/daemon/update.go @@ -95,6 +95,8 @@ func discoveryChangeLoop() { // packet is somehow different than the localone. This can be used to trigger // some action in the local machine. func discoveryChange(discovery server.Discovery) error { - changeDetectedChannel <- true + if len(config.Callback) > 0 { + changeDetectedChannel <- true + } return nil } diff --git a/server/discovery.go b/server/discovery.go index 3d5fd6d..4a97cd4 100644 --- a/server/discovery.go +++ b/server/discovery.go @@ -45,9 +45,9 @@ func (d *Discovery) Bytes() ([]byte, error) { return data, err } -// FindLabels returns list of labels with given prefix. For example "service:ns" has prefix "service" or "service:". +// FindLabelsByPrefix returns list of labels with given prefix. For example "service:ns" has prefix "service" or "service:". // It doesn't have to be prefix, but for example "service:test" will match "service:test" and also "service:test2". -func (d *Discovery) FindLabels(prefix string) Labels { +func (d *Discovery) FindLabelsByPrefix(prefix string) Labels { labels := Labels{} for _, label := range d.Labels { if strings.HasPrefix(label.String(), prefix) { diff --git a/server/discovery_test.go b/server/discovery_test.go index b0186ea..90ca3b2 100644 --- a/server/discovery_test.go +++ b/server/discovery_test.go @@ -27,7 +27,7 @@ func TestDiscovery(t *testing.T) { assert.False(t, discovery.IsAlive(), "discovery not suppose to be alive") discovery.LastCheck = now - assert.Equal(t, Labels{Label("service:test")}, discovery.FindLabels("service")) + assert.Equal(t, Labels{Label("service:test")}, discovery.FindLabelsByPrefix("service")) assert.Equal(t, nil, discovery.Validate()) // TODO: This needs more love content, err := json.Marshal(&discovery)