This commit is contained in:
parent
fea744957b
commit
c88d0e2739
1 changed files with 135 additions and 14 deletions
149
main.go
149
main.go
|
@ -1,8 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"crypto/tls"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
|
@ -12,19 +13,39 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type K8sList struct {
|
||||
type K8sRawList struct {
|
||||
Items []json.RawMessage `json:"items"`
|
||||
}
|
||||
|
||||
type BackendServer struct {
|
||||
Name string
|
||||
Address string
|
||||
Port int
|
||||
Cookie string
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
Name string
|
||||
Balance string
|
||||
Servers []BackendServer
|
||||
}
|
||||
|
||||
func getEnv(key, fallback string) string {
|
||||
if val, exists := os.LookupEnv(key); exists && val != "" {
|
||||
if val, ok := os.LookupEnv(key); ok && val != "" {
|
||||
return val
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func hashString(input string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(input))
|
||||
return hex.EncodeToString(h.Sum(nil))[:8]
|
||||
}
|
||||
|
||||
func getTemplate(path string) (*template.Template, error) {
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
|
@ -42,6 +63,7 @@ func getK8sResources(k8sHost, token string, verifySSL bool, resource string) ([]
|
|||
}
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("User-Agent", "gateway-config")
|
||||
|
||||
client := &http.Client{}
|
||||
if !verifySSL {
|
||||
|
@ -62,7 +84,7 @@ func getK8sResources(k8sHost, token string, verifySSL bool, resource string) ([]
|
|||
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var list K8sList
|
||||
var list K8sRawList
|
||||
if err := json.NewDecoder(resp.Body).Decode(&list); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -84,29 +106,128 @@ func main() {
|
|||
log.Fatalf("Invalid KUBERNETES_VERIFYSSL value: %v", err)
|
||||
}
|
||||
|
||||
services, err := getK8sResources(k8sHost, k8sToken, verifySSL, "services")
|
||||
servicesRaw, err := getK8sResources(k8sHost, k8sToken, verifySSL, "services")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get services: %v", err)
|
||||
}
|
||||
endpoints, err := getK8sResources(k8sHost, k8sToken, verifySSL, "endpoints")
|
||||
endpointsRaw, err := getK8sResources(k8sHost, k8sToken, verifySSL, "endpoints")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get endpoints: %v", err)
|
||||
}
|
||||
|
||||
tmplAbsPath, _ := filepath.Abs(templatePath)
|
||||
type Service struct {
|
||||
Metadata struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
} `json:"metadata"`
|
||||
Spec struct {
|
||||
Type string `json:"type"`
|
||||
Ports []struct {
|
||||
Port int `json:"port"`
|
||||
} `json:"ports"`
|
||||
} `json:"spec"`
|
||||
}
|
||||
|
||||
type EndpointSubsetAddress struct {
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
|
||||
type EndpointSubsetPort struct {
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
type EndpointSubset struct {
|
||||
Addresses []EndpointSubsetAddress `json:"addresses"`
|
||||
Ports []EndpointSubsetPort `json:"ports"`
|
||||
}
|
||||
|
||||
type Endpoint struct {
|
||||
Metadata struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
} `json:"metadata"`
|
||||
Subsets []EndpointSubset `json:"subsets"`
|
||||
}
|
||||
|
||||
services := make([]Service, 0, len(servicesRaw))
|
||||
for _, raw := range servicesRaw {
|
||||
var svc Service
|
||||
if err := json.Unmarshal(raw, &svc); err != nil {
|
||||
log.Printf("Warn: failed to unmarshal service: %v", err)
|
||||
continue
|
||||
}
|
||||
services = append(services, svc)
|
||||
}
|
||||
|
||||
endpoints := make([]Endpoint, 0, len(endpointsRaw))
|
||||
for _, raw := range endpointsRaw {
|
||||
var ep Endpoint
|
||||
if err := json.Unmarshal(raw, &ep); err != nil {
|
||||
log.Printf("Warn: failed to unmarshal endpoint: %v", err)
|
||||
continue
|
||||
}
|
||||
endpoints = append(endpoints, ep)
|
||||
}
|
||||
|
||||
endpointMap := make(map[string]Endpoint)
|
||||
for _, ep := range endpoints {
|
||||
key := ep.Metadata.Namespace + "/" + ep.Metadata.Name
|
||||
endpointMap[key] = ep
|
||||
}
|
||||
|
||||
backends := []Backend{}
|
||||
|
||||
for _, svc := range services {
|
||||
if svc.Spec.Type != "LoadBalancer" {
|
||||
continue
|
||||
}
|
||||
key := svc.Metadata.Namespace + "/" + svc.Metadata.Name
|
||||
ep, found := endpointMap[key]
|
||||
if !found || len(ep.Subsets) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
b := Backend{
|
||||
Name: "SRV_" + strings.ReplaceAll(svc.Metadata.Name, " ", "-"),
|
||||
Balance: "leastconn",
|
||||
}
|
||||
|
||||
servers := []BackendServer{}
|
||||
serverIndex := 1
|
||||
for _, subset := range ep.Subsets {
|
||||
for _, addr := range subset.Addresses {
|
||||
for _, port := range subset.Ports {
|
||||
cookie := hashString(fmt.Sprintf("%s-%s-%d", svc.Metadata.Name, addr.IP, port.Port))
|
||||
serverName := fmt.Sprintf("%s_%d", svc.Metadata.Name, serverIndex)
|
||||
serverIndex++
|
||||
|
||||
servers = append(servers, BackendServer{
|
||||
Name: serverName,
|
||||
Address: addr.IP,
|
||||
Port: port.Port,
|
||||
Cookie: cookie,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
b.Servers = servers
|
||||
|
||||
backends = append(backends, b)
|
||||
}
|
||||
|
||||
tmplAbsPath, err := filepath.Abs(templatePath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get absolute path: %v", err)
|
||||
}
|
||||
tmpl, err := getTemplate(tmplAbsPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse template: %v", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = tmpl.Execute(&buf, map[string]interface{}{
|
||||
"services": services,
|
||||
"endpoints": endpoints,
|
||||
err = tmpl.Execute(os.Stdout, map[string]interface{}{
|
||||
"backends": backends,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to render template: %v", err)
|
||||
log.Fatalf("Failed to execute template: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(buf.String())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue