package main import ( "encoding/json" "fmt" "html/template" "io" "net/http" "strconv" ) const apiKey = "4e75b8927940adc29e2e1eac042bf92bcddd57fe" const netboxBaseURL = "https://netbox.internal.faercol.me/api/" type Device struct { ID int `json:"id"` Name string `json:"name"` } type Object struct { Device Device `json:"device"` } type CableTermination struct { Object Object `json:"object"` } type Cable struct { ID int `json:"id"` ATerminations []CableTermination `json:"a_terminations"` BTerminations []CableTermination `json:"b_terminations"` } type VM struct { ID int `json:"id"` Name string `json:"name"` Device Device `json:"device"` } type vmsResponse struct { Results []VM `json:"results"` } type deviceResponse struct { Results []Device `json:"results"` } type cableResponse struct { Results []Cable `json:"results"` } type ElementData struct { ID string `json:"id"` Source string `json:"source,omitempty"` Target string `json:"target,omitempty"` Parent string `json:"parent,omitempty"` } type Element struct { Data ElementData `json:"data"` Classes []string `json:"classes"` } func GetDevices() ([]Device, error) { query, err := http.NewRequest("GET", netboxBaseURL+"dcim/devices", nil) if err != nil { return nil, err } query.Header.Set("Authorization", "Token "+apiKey) resp, err := http.DefaultClient.Do(query) if err != nil { return nil, err } var res deviceResponse respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if err := json.Unmarshal(respBody, &res); err != nil { return nil, err } return res.Results, nil } func GetCables() ([]Cable, error) { query, err := http.NewRequest("GET", netboxBaseURL+"dcim/cables", nil) if err != nil { return nil, err } query.Header.Set("Authorization", "Token "+apiKey) resp, err := http.DefaultClient.Do(query) if err != nil { return nil, err } var res cableResponse respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if err := json.Unmarshal(respBody, &res); err != nil { return nil, err } return res.Results, nil } func GetVMs() ([]VM, error) { query, err := http.NewRequest("GET", netboxBaseURL+"virtualization/virtual-machines", nil) if err != nil { return nil, err } query.Header.Set("Authorization", "Token "+apiKey) resp, err := http.DefaultClient.Do(query) if err != nil { return nil, err } var res vmsResponse respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if err := json.Unmarshal(respBody, &res); err != nil { return nil, err } return res.Results, nil } func main() { srv := http.NewServeMux() srv.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) { fmt.Println("Serving static file") fs := http.FileServer(http.Dir("./static")) http.StripPrefix("/static", fs).ServeHTTP(w, r) }) srv.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) { fmt.Println("Serving API route") devices, err := GetDevices() if err != nil { fmt.Printf("Failed to get devices: %s\n", err) w.WriteHeader(500) return } cables, err := GetCables() if err != nil { fmt.Printf("Failed to get cables: %s\n", err) w.WriteHeader(500) return } vms, err := GetVMs() if err != nil { fmt.Printf("Failed to get VMs: %s\n", err) w.WriteHeader(500) return } resp := []Element{} for _, d := range devices { resp = append(resp, Element{Data: ElementData{ID: d.Name}}) } for _, c := range cables { resp = append(resp, Element{Data: ElementData{ID: "link-" + strconv.FormatInt(int64(c.ID), 10), Source: c.ATerminations[0].Object.Device.Name, Target: c.BTerminations[0].Object.Device.Name}}) } for _, v := range vms { resp = append(resp, Element{Data: ElementData{ID: v.Name}}, Element{Data: ElementData{ID: "vm-" + strconv.FormatInt(int64(v.ID), 10), Source: v.Name, Target: v.Device.Name}, Classes: []string{"edge", "virtual-edge"}}) } respBody, err := json.Marshal(resp) if err != nil { fmt.Printf("Failed to serialize data: %s\n", err) w.WriteHeader(500) return } w.Write(respBody) }) srv.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Println("Serving main root") tpl, err := template.New("index.html").ParseFiles("templates/index.html") if err != nil { fmt.Printf("Failed to read template: %s\n", err) w.WriteHeader(500) return } if err := tpl.Execute(w, nil); err != nil { fmt.Printf("Failed to execute template: %s\n", err) w.WriteHeader(500) return } }) if err := http.ListenAndServe("127.0.0.1:5000", srv); err != nil { panic(err) } }