diff --git a/.gitignore b/.gitignore index 1938740..09f1d9e 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ output/* ubnt-freifunk-map-api +config.json diff --git a/example.config.json b/example.config.json new file mode 100644 index 0000000..ca7db0b --- /dev/null +++ b/example.config.json @@ -0,0 +1,15 @@ +{ + "unms": { + "enabled": true, + "unmsAPIUrl": "https://unifi.freifunk-troisdorf.de/v2.1", + "APItoken": "API TOKEN", + "devicesURL": "https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api/raw/branch/master/" + }, + "unifi": { + "enabled": true, + "APIUrl": "https://unifi.freifunk-troisdorf.de:8443", + "user": "APIuser", + "password": "PASSWORD", + "ucDevicesURL": "https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api/raw/branch/master/" + } +} \ No newline at end of file diff --git a/main.go b/main.go index 8c82485..e9dcd30 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "log" "net/http" "net/http/cookiejar" + "os" "strconv" "strings" "time" @@ -17,20 +18,15 @@ import ( _ "git.nils.zone/nils/prettify" ) -// types - const ( - baseURL = "https://unifi.freifunk-troisdorf.de/v2.1" - ucBaseURL = "https://unifi.freifunk-troisdorf.de:8443" - iso8601 = "2006-01-02T15:04:05-0700" + iso8601 = "2006-01-02T15:04:05-0700" ) // flags -var token = flag.String("token", "", "Defines the x-auth-token") -var ucUser = flag.String("ucUser", "", "Defines the Unifi API User") -var ucPass = flag.String("ucPass", "", "Defines the Unifi API Password") +var configPath = flag.String("configPath", "config.json", "Path to config.json") var version = "development" var delay time.Duration = 60 * time.Second +var conf = loadconfig(*configPath) func main() { log.Printf("starting version %s...\n", version) @@ -38,16 +34,9 @@ func main() { flag.Parse() // check if flags are set - if *token == "" { - log.Fatalln("Please specify an API token via the flag '-token'") + if *configPath == "" { + log.Fatalln("Please specify path to config.json flag '-configPath'") } - if *ucPass == "" { - log.Fatalln("Please specify an API Password via the flag '-ucPass'") - } - if *ucUser == "" { - log.Fatalln("Please specify an API User via the flag '-ucUser'") - } - // start API processing (runs in a loop) go processAPIs() @@ -55,36 +44,15 @@ func main() { serveJSON() } -//switch Unifi AP Mod IDs to Names -func lookupModels(model string) string { - switch model { - case "BZ2", "U2S48", "U2Sv2": - return "Unifi AP" - case "BZ2LR", "U2L48", "U2Lv2": - return "UniFi AP-LR" - case "U7E", "U7Ev2": - return "UniFi AP-AC" - case "U7HD", "U7SHD": - return "UniFi AP-HD" - case "UXSDM": - return "UniFi AP-BaseStationXG" - case "UCMSH": - return "AP-MeshXG" - case "U7MP": - return "AP-AC-Mesh-Pro" - case "U7LR": - return "UniFi AP-AC-LR" - case "U7LT": - return "UniFi AP-AC-Lite" - case "U7P": - return "UniFi AP-Pro" - case "U7MSH": - return "UniFi AP-AC-Mesh" - case "U7PG2": - return "UniFi AP-AC-Pro" - default: - return "Unifi Gerät" +func loadconfig(file string) config { + var config config + configFile, err := os.Open(file) + if err != nil { + log.Fatalln(err) } + jsonParse := json.NewDecoder(configFile) + jsonParse.Decode(&config) + return config } //int to bool converter @@ -100,23 +68,23 @@ func processUcAPIs() ([]node, []link) { //get list of Unifi devices to display var nodes []node var links []link - d, err := getDevices("ucDevices.json") + d, err := getDevices(conf.Unifi.UCDevicesURL) if err != nil { log.Fatalln(err) } //call Unifi Controller - ucAPI := newAPI(*ucUser, *ucPass, ucBaseURL) + ucAPI := newAPI(conf.Unifi.User, conf.Unifi.Password, conf.Unifi.APIURL) //login ucAPI.ucLogin() //get all Sites from Controller sites, err := ucAPI.ucGetSites() if err != nil { - panic(err) + log.Fatalln(err) } //get all devices in all sites devices, err := ucAPI.ucGetDevices(sites) if err != nil { - panic(err) + log.Fatalln(err) } //build nodes struct @@ -135,11 +103,11 @@ func processUcAPIs() ([]node, []link) { load, err := strconv.ParseFloat(currentDevice.Sysstats.CPU, 64) if err != nil { - panic(err) + log.Fatalln(err) } mem, err := strconv.ParseFloat(currentDevice.Sysstats.Memory, 64) if err != nil { - panic(err) + log.Fatalln(err) } nodes = append(nodes, node{ @@ -185,7 +153,7 @@ func processUNMSAPI() ([]node, []link) { var links []link var nodes []node - d, err := getDevices("devices.json") + d, err := getDevices(conf.Unms.DevicesURL) if err != nil { log.Fatalln(err) } @@ -276,12 +244,16 @@ func processAPIs() { var nodes []node var links []link - unmsNodes, unmsLinks := processUNMSAPI() - ucNodes, ucLinks := processUcAPIs() - nodes = append(nodes, unmsNodes...) - nodes = append(nodes, ucNodes...) - links = append(links, unmsLinks...) - links = append(links, ucLinks...) + if conf.Unms.Enabled == true { + unmsNodes, unmsLinks := processUNMSAPI() + nodes = append(nodes, unmsNodes...) + links = append(links, unmsLinks...) + } + if conf.Unifi.Enabled == true { + ucNodes, ucLinks := processUcAPIs() + nodes = append(nodes, ucNodes...) + links = append(links, ucLinks...) + } // assemble final struct o := output{ @@ -311,43 +283,41 @@ func getFile(url string) []byte { return byteValue } -func getDevices(file string) (devices, error) { +func getDevices(url string) (devices, error) { // get devices from JSON file - jsonFile := getFile("https://git.freifunk-rhein-sieg.net/Freifunk-Troisdorf/ubnt-freifunk-map-api/raw/branch/master/" + file) + jsonFile := getFile(url) // read file to bytes // variable for d var d devices // unmarshal to struct - json.Unmarshal(jsonFile, &d) + err := json.Unmarshal(jsonFile, &d) + if err != nil { + fmt.Println("can´t get devices file from " + url) + log.Fatal(err) + } return d, nil } func callUnifiAPI(url string, i interface{}) error { - request, err := http.NewRequest(http.MethodGet, baseURL+url, nil) + request, err := http.NewRequest(http.MethodGet, conf.Unms.UnmsAPIURL+url, nil) if err != nil { - return errors.New(fmt.Sprint("can't set request", baseURL+url)) + return errors.New(fmt.Sprint("can't set request", conf.Unms.UnmsAPIURL+url)) } - request.Header.Set("x-auth-token", *token) + request.Header.Set("x-auth-token", conf.Unms.APItoken) client := &http.Client{} response, err := client.Do(request) if err != nil { - return fmt.Errorf("can't get request %s with x-auth-token %s", baseURL+url, *token) + return fmt.Errorf("can't get request %s with x-auth-token %s", conf.Unms.UnmsAPIURL+url, conf.Unms.APItoken) + } + if response.StatusCode != 200 { + log.Fatalln("Can´t call UNMS API, check token and URL. HTTP Status: ", response.StatusCode) } - data, err := ioutil.ReadAll(response.Body) defer response.Body.Close() if err != nil { return fmt.Errorf("can't read response body: %+v", response.Body) } - // try to fetch errors - var a apiResponse - json.Unmarshal(data, &a) - - if a.StatusCode != 0 { - return fmt.Errorf("got following errorcode from API: %d %s %s", a.StatusCode, a.Error, a.Message) - } - // no error occurred, unmarshal to struct json.Unmarshal(data, &i) return nil diff --git a/types.go b/types.go index 069e28c..1f69650 100644 --- a/types.go +++ b/types.go @@ -10,6 +10,22 @@ import ( "time" ) +type config struct { + Unms struct { + Enabled bool `json:"enabled"` + UnmsAPIURL string `json:"unmsAPIUrl"` + APItoken string `json:"APItoken"` + DevicesURL string `json:"devicesURL"` + } `json:"unms"` + Unifi struct { + Enabled bool `json:"enabled"` + APIURL string `json:"APIUrl"` + User string `json:"user"` + Password string `json:"password"` + UCDevicesURL string `json:"ucDevicesURL"` + } `json:"unifi"` +} + type device struct { Name string `json:"name"` MAC string `json:"mac"` @@ -178,3 +194,35 @@ type ucAPIData struct { baseURL string client *http.Client } + +//switch Unifi AP Mod IDs to Names +func lookupModels(model string) string { + switch model { + case "BZ2", "U2S48", "U2Sv2": + return "Unifi AP" + case "BZ2LR", "U2L48", "U2Lv2": + return "UniFi AP-LR" + case "U7E", "U7Ev2": + return "UniFi AP-AC" + case "U7HD", "U7SHD": + return "UniFi AP-HD" + case "UXSDM": + return "UniFi AP-BaseStationXG" + case "UCMSH": + return "AP-MeshXG" + case "U7MP": + return "AP-AC-Mesh-Pro" + case "U7LR": + return "UniFi AP-AC-LR" + case "U7LT": + return "UniFi AP-AC-Lite" + case "U7P": + return "UniFi AP-Pro" + case "U7MSH": + return "UniFi AP-AC-Mesh" + case "U7PG2": + return "UniFi AP-AC-Pro" + default: + return "Unifi Gerät" + } +}