lobby/client/main.go

227 lines
5.2 KiB
Go

package client
import (
"encoding/json"
"errors"
"fmt"
"strings"
"github.com/by-cx/lobby/server"
"github.com/go-resty/resty/v2"
)
// Encapsulation of Lobby's client code
type LobbyClient struct {
Proto string
Host string
Port uint
Token string
}
func (l *LobbyClient) init() {
if len(l.Proto) == 0 {
l.Host = "http"
}
if len(l.Host) == 0 {
l.Host = "localhost"
}
if l.Port == 0 {
l.Port = 1313
}
}
// calls the backend API with given method, path and request body and returns status code, response body and error if there is any.
// Method can be GET, POST or DELETE.
// Path should start with / and it can contain query parameters too.
func (l *LobbyClient) call(method, path, body string) (uint, string, error) {
client := resty.New().R()
if len(l.Token) != 0 {
client = client.SetHeader("Authorization", fmt.Sprintf("Token %s", l.Token))
}
if strings.ToUpper(method) == "GET" {
resp, err := client.Get(fmt.Sprintf("%s://%s:%d%s", l.Proto, l.Host, l.Port, path))
if err != nil {
return 0, "", err
}
return uint(resp.StatusCode()), string(resp.Body()), nil
} else if strings.ToUpper(method) == "POST" {
resp, err := client.SetBody(body).Post(fmt.Sprintf("%s://%s:%d%s", l.Proto, l.Host, l.Port, path))
if err != nil {
return 0, "", err
}
return uint(resp.StatusCode()), string(resp.Body()), nil
} else if strings.ToUpper(method) == "DELETE" {
resp, err := client.SetBody(body).Delete(fmt.Sprintf("%s://%s:%d%s", l.Proto, l.Host, l.Port, path))
if err != nil {
return 0, "", err
}
return uint(resp.StatusCode()), string(resp.Body()), nil
} else {
return 0, "", errors.New("unsupported method")
}
}
// Returns discovery object of local machine
func (l *LobbyClient) GetDiscovery() (server.Discovery, error) {
l.init()
var discovery server.Discovery
path := "/v1/discovery"
method := "GET"
status, body, err := l.call(method, path, "")
if err != nil {
return discovery, err
}
if status != 200 {
return discovery, fmt.Errorf("non-200 response: %s", body)
}
err = json.Unmarshal([]byte(body), &discovery)
if err != nil {
return discovery, fmt.Errorf("response parsing error: %v", err)
}
return discovery, nil
}
// Returns all registered discovery packets
func (l *LobbyClient) GetDiscoveries() ([]server.Discovery, error) {
l.init()
path := "/v1/discoveries"
method := "GET"
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
}
// 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()
path := fmt.Sprintf("/v1/discoveries?labels=%s", strings.Join(labels.StringSlice(), ","))
method := "GET"
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, "")
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
}
// Adds runtime labels for the local machine
func (l *LobbyClient) AddLabels(labels server.Labels) error {
l.init()
path := "/v1/labels"
method := "POST"
status, body, err := l.call(method, path, strings.Join(labels.StringSlice(), "\n"))
if err != nil {
return err
}
if status != 200 {
return fmt.Errorf("non-200 response: %s", body)
}
return nil
}
// Removes runtime labels of the local machine
func (l *LobbyClient) DeleteLabels(labels server.Labels) error {
l.init()
path := "/v1/labels"
method := "DELETE"
status, body, err := l.call(method, path, strings.Join(labels.StringSlice(), "\n"))
if err != nil {
return err
}
if status != 200 {
return fmt.Errorf("non-200 response: %s", body)
}
return nil
}