jilo-agent/go/main.go

159 lines
4.6 KiB
Go
Raw Normal View History

/*
Jilo Agent
Description: Remote agent for Jilo Web with http API
Author: Yasen Pramatarov
License: GPLv2
Project URL: https://lindeas.com/jilo
Year: 2024
Version: 0.1
*/
package main
import (
"encoding/json"
"fmt"
2024-09-02 19:28:45 +00:00
"io/ioutil"
"log"
"net/http"
2024-09-02 19:28:45 +00:00
"os"
"os/exec"
"strconv"
"strings"
)
2024-09-02 19:28:45 +00:00
// Config holds the structure of the configuration file
type Config struct {
AgentPort int `json:"agent_port"`
NginxPort int `json:"nginx_port"`
2024-09-02 20:01:15 +00:00
JicofoStatsURL string `json:"jicofo_stats_url"`
2024-09-02 19:28:45 +00:00
}
// NginxData holds the nginx data structure for the API response to /nginx
type NginxData struct {
2024-09-02 19:28:45 +00:00
NginxState string `json:"nginx_state"`
NginxConnections int `json:"nginx_connections"`
}
2024-09-02 19:28:45 +00:00
// JicofoData holds the Jicofo data structure for the API response to /jicofo
type JicofoData struct {
JicofoState string `json:"jicofo_state"`
JicofoAPIData map[string]interface{} `json:"jicofo_api_data"`
}
2024-09-02 20:01:15 +00:00
// getServiceState checks the status of the speciied service
func getServiceState(service string) string {
output, err := exec.Command("systemctl", "is-active", service).Output()
if err != nil {
2024-09-02 20:01:15 +00:00
log.Printf("Error checking the service \"%v\" state: %v", service, err)
2024-09-02 19:34:38 +00:00
return "error"
}
state := strings.TrimSpace(string(output))
if state == "active" {
return "running"
}
return "not running"
}
// getNginxConnections gets the number of active connections to the specified web port
2024-09-02 20:01:15 +00:00
func getNginxConnections(port int) int {
cmd := fmt.Sprintf("netstat -an | grep ':%d' | wc -l", port)
2024-09-02 19:28:45 +00:00
output, err := exec.Command("bash", "-c", cmd).Output()
if err != nil {
log.Printf("Error counting the Nginx connections: %v", err)
return -1
}
connections := strings.TrimSpace(string(output))
connectionsInt, err := strconv.Atoi(connections)
if err != nil {
log.Printf("Error converting connections to integer number: %v", err)
return -1
}
return connectionsInt
}
2024-09-02 20:01:15 +00:00
// getJitsiAPIData gets the response from the specified Jitsi stats API
func getJitsiAPIData(service string, url string) map[string]interface{} {
cmd := fmt.Sprintf("curl -s %v", url)
output, err := exec.Command("bash", "-c", cmd).Output()
2024-09-02 19:28:45 +00:00
if err != nil {
2024-09-02 20:01:15 +00:00
log.Printf("Error getting the \"%v\" API stats: %v", service, err)
return map[string]interface{}{"error": "failed to get the Jitsi API stats"}
2024-09-02 19:28:45 +00:00
}
var result map[string]interface{}
if err := json.Unmarshal(output, &result); err != nil {
log.Printf("Error in parsing the JSON: %v", err)
return map[string]interface{}{"error": "invalid JSON format"}
}
return result
}
// loadConfig loads the configuration from a JSON config file
func loadConfig(filename string) (Config, error) {
var config Config
file, err := os.Open(filename)
if err != nil {
return config, err
}
defer file.Close()
bytes, err := ioutil.ReadAll(file)
if err != nil {
return config, err
}
if err := json.Unmarshal(bytes, &config); err != nil {
return config, err
}
return config, nil
}
// nginxHandler handles the /nginx endpoint
2024-09-02 19:28:45 +00:00
func nginxHandler(config Config, w http.ResponseWriter, r *http.Request) {
data := NginxData {
2024-09-02 20:01:15 +00:00
NginxState: getServiceState("nginx"),
2024-09-02 19:28:45 +00:00
NginxConnections: getNginxConnections(config.NginxPort),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
}
2024-09-02 19:34:38 +00:00
// jicofoHandler handles the /jicofo endpoint
func jicofoHandler(config Config, w http.ResponseWriter, r *http.Request) {
data := JicofoData {
2024-09-02 20:01:15 +00:00
JicofoState: getServiceState("jicofo"),
JicofoAPIData: getJitsiAPIData("jicofo", config.JicofoStatsURL),
2024-09-02 19:34:38 +00:00
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
}
// main sets up the http server and the routes
func main() {
2024-09-02 19:28:45 +00:00
// load the configuration
2024-09-02 20:01:15 +00:00
config, err := loadConfig("jilo-agent.json")
2024-09-02 19:28:45 +00:00
if err != nil {
log.Fatalf("Error loading the config file: %v\n", err)
}
// endpoints
http.HandleFunc("/nginx", func(w http.ResponseWriter, r *http.Request) {
nginxHandler(config, w, r)
})
2024-09-02 19:34:38 +00:00
http.HandleFunc("/jicofo", func(w http.ResponseWriter, r *http.Request) {
jicofoHandler(config, w, r)
})
2024-09-02 19:28:45 +00:00
// start the http server
agentPortStr := fmt.Sprintf(":%d", config.AgentPort)
2024-09-02 19:34:38 +00:00
fmt.Printf("Starting Jilo agent server on port %d.\n", config.AgentPort)
2024-09-02 19:28:45 +00:00
if err := http.ListenAndServe(agentPortStr, nil); err != nil {
log.Fatalf("Could not start the server: %v\n", err)
}
}