small pixel drawing of a pufferfish cascade

internal/agent/agent_endpoint.go

package agent

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"

	"git.j3s.sh/cascade/api"
	"github.com/hashicorp/serf/coordinate"
	"github.com/hashicorp/serf/serf"
)

type Self struct {
	Config      interface{}
	DebugConfig map[string]interface{}
	Coord       *coordinate.Coordinate
	Member      serf.Member
	Stats       map[string]map[string]string
	Meta        map[string]string
}

func (s *HTTPHandlers) agentSelf(w http.ResponseWriter, r *http.Request) {
	config := struct {
		NodeName     string
		Version      string
		BuildDate    string
		DNSBindAddr  string
		HTTPBindAddr string
		SerfBindAddr string
	}{
		NodeName:     s.agent.Config.NodeName,
		Version:      s.agent.Config.VersionWithMetadata(),
		DNSBindAddr:  s.agent.Config.DNSBindAddr.String(),
		HTTPBindAddr: s.agent.Config.HTTPBindAddr.String(),
		SerfBindAddr: s.agent.Config.SerfBindAddr.String(),
	}

	self := Self{
		Config: config,
	}

	json, err := s.marshalJSON(r, self)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, string(json))
}

// return s.agent.Members()
// func (s *HTTPHandlers) Index(resp http.ResponseWriter, req *http.Request) {
func (s *HTTPHandlers) agentMembers(w http.ResponseWriter, r *http.Request) {
	members := s.agent.Members()
	json, err := s.marshalJSON(r, members)
	if err != nil {
		fmt.Println(err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	fmt.Fprintf(w, string(json))
}

func (s *HTTPHandlers) agentServices(w http.ResponseWriter, r *http.Request) {
	services := s.agent.OwnedServices()
	buf, err := s.marshalJSON(r, services)
	if err != nil {
		s.agent.logger.Error("marshal services", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	w.Write(buf)
}

func (s *HTTPHandlers) agentServiceRegister(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut && r.Method != http.MethodPost {
		w.Header().Set("Allow", "PUT, POST")
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var svc api.AgentService
	if err := json.NewDecoder(r.Body).Decode(&svc); err != nil {
		http.Error(w, fmt.Sprintf("bad request: %s", err), http.StatusBadRequest)
		return
	}
	if svc.ID == "" {
		svc.ID = svc.Service
	}
	if svc.Service == "" {
		http.Error(w, "Service name required", http.StatusBadRequest)
		return
	}

	if err := s.agent.RegisterService(&svc); err != nil {
		s.agent.logger.Error("register service", err, "id", svc.ID)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
}

func (s *HTTPHandlers) agentServiceDeregister(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPut && r.Method != http.MethodPost {
		w.Header().Set("Allow", "PUT, POST")
		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
		return
	}

	id := strings.TrimPrefix(r.URL.Path, "/v1/agent/service/deregister/")
	if id == "" || strings.Contains(id, "/") {
		http.Error(w, "service ID required in path", http.StatusBadRequest)
		return
	}

	if err := s.agent.DeregisterService(id); err != nil {
		s.agent.logger.Error("deregister service", err, "id", id)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
}