sermoni

"Service monitor" / cronjob status service
Log | Files | Refs

commit d36567cdb98f151b0aa292d6e7985085f0dd994f
parent d4e63376100b182b24649581e16fcf4f642961a3
Author: Vetle Haflan <vetle@haflan.dev>
Date:   Mon, 13 Apr 2020 20:58:38 +0200

Complete event management MVP ++

Diffstat:
Minternal/events/events.go | 4++--
Minternal/http/events.go | 15++++++++++-----
Minternal/http/services.go | 20+++++++++++++++++---
Minternal/services/services.go | 9++++++---
Mui/src/App.vue | 7+++----
Mui/src/Events.vue | 33++++++++++++++++++++++++++++++---
Mui/src/Services.vue | 25+++++++++++++++++++++++--
Mui/src/requests.js | 18++++++++++++++----
8 files changed, 105 insertions(+), 26 deletions(-)

diff --git a/internal/events/events.go b/internal/events/events.go @@ -60,10 +60,10 @@ func GetAll() (events []*Event) { func Delete(idInt uint64) error { db := database.GetDB() id := database.Uint64ToBytes(idInt) - return db.View(func(tx *bbolt.Tx) error { + return db.Update(func(tx *bbolt.Tx) error { b := tx.Bucket(database.BucketKeyEvents) if b == nil { - log.Panic("The events bucket does notexist") + log.Panic("The events bucket does not exist") } return b.DeleteBucket(id) }) diff --git a/internal/http/events.go b/internal/http/events.go @@ -8,6 +8,9 @@ import ( "net/http" "sermoni/internal/events" "sermoni/internal/services" + "strconv" + + "github.com/gorilla/mux" ) const headerServiceToken = "Service-Token" @@ -35,12 +38,14 @@ func getEvents(w http.ResponseWriter, r *http.Request) { // TODO: This is still a placeholder! func deleteEvent(w http.ResponseWriter, r *http.Request) { - /* - vars := mux.Vars(r) - id, _ := strconv.ParseUint(vars["id"], 10, 64) - err := events.Delete(id) + vars := mux.Vars(r) + id, _ := strconv.ParseUint(vars["id"], 10, 64) + err := events.Delete(id) + if err != nil { + // TODO: Non-existing error is not an internal server error fmt.Println(err) - */ + w.WriteHeader(http.StatusInternalServerError) + } } func reportEvent(w http.ResponseWriter, r *http.Request) { diff --git a/internal/http/services.go b/internal/http/services.go @@ -1,15 +1,29 @@ package http import ( + "encoding/json" "net/http" + "sermoni/internal/services" + "strconv" + + "github.com/gorilla/mux" ) func getServices(w http.ResponseWriter, r *http.Request) { - return + s := services.GetAll() + data, err := json.Marshal(s) + check(err) + w.Write(data) } func postService(w http.ResponseWriter, r *http.Request) { - return + } func deleteService(w http.ResponseWriter, r *http.Request) { - return + vars := mux.Vars(r) + id, _ := strconv.ParseUint(vars["id"], 10, 64) + err := services.Delete(id) + if err != nil { + // TODO: Non-existing error is not an internal server error + w.WriteHeader(http.StatusInternalServerError) + } } diff --git a/internal/services/services.go b/internal/services/services.go @@ -23,7 +23,8 @@ type Service struct { Name string `json:"name"` // service name, usually on the format 'service @ server' Description string `json:"description"` // more detailed description of the service ExpectationPeriod uint64 `json:"period"` // set if the service is expected to report periodically, format is UnixTime (milli?) - MaxNumberEvents uint64 `json:"maxevents"` // set if the service is expected to report periodically, format is UnixTime (milli?) + MaxNumberEvents uint64 `json:"maxevents"` // max number of events to keep in DB at once - when limit is reached, oldest will be deleted + Token string `json:"token"` // service token - this is stored in the service-token bucket, not the services bucket } // GetByToken returns the service structure associated with the token string, if there @@ -57,11 +58,13 @@ func GetAll() (services []*Service) { } // Go through all k-v pairs in the service *tokens* bucket, in order to get service bucket IDs - // Use the ID to get the service bucket and create service fromBucket - return stb.ForEach(func(_, id []byte) error { + // Use the ID to get the service bucket and create service fromBucket, then set the service token + // using the key from the stb + return stb.ForEach(func(token, id []byte) error { sb := b.Bucket(id) service := new(Service) service.fromBucket(id, sb) + service.Token = string(token) services = append(services, service) return nil }) diff --git a/ui/src/App.vue b/ui/src/App.vue @@ -4,7 +4,7 @@ <div id="bar"> <div style="font-size: 1.5em; color: #bbf">&gt; sermoni</div> <div @click="togglePage" style="margin-left: auto;"> - <Eye :service-view="this.serviceView"/> + <Eye :service-view="this.serviceView" style="cursor: pointer;"/> </div> </div> </header> @@ -60,7 +60,6 @@ mounted() { api.init( successData => { - console.log(successData); if (successData.authenticated) { this.page = Events; } else { @@ -68,8 +67,8 @@ } }, errorData => { - console.log(errorData); - // TODO: set color of header to '#f5c6cb' + console.error(errorData); + this.error = true; } ) } diff --git a/ui/src/Events.vue b/ui/src/Events.vue @@ -9,6 +9,7 @@ <!--<mq-layout mq="md+">--> <div class="event-field">{{ e.title }}</div> <!--</mq-layout>--> + <button @click="deleteEvent(e.id)">&times;</button> </div> <div v-show="false"> more info here </div> </div> @@ -38,6 +39,19 @@ } else { return { color: "#000", backgroundColor: "#fff" }; } + }, + deleteEvent(id) { + api.deleteEvent(id, + success => { + this.loadedEvents = this.loadedEvents.filter( + e => e.id !== id + ); + }, + error => { + console.error(error) + this.$emit("error"); + } + ); } }, computed: { @@ -51,9 +65,15 @@ } }, mounted() { - api.getEvents(successData => { - this.loadedEvents = successData; - }); + api.getEvents( + successData => { + this.loadedEvents = successData; + }, + error => { + console.error(error); + this.$emit("error"); + } + ); } } @@ -80,4 +100,11 @@ margin: 0; padding: 0; } +button { + cursor: pointer; + background-color: inherit; + border: none; + text-align: center; + font-size: 16px; +} </style> diff --git a/ui/src/Services.vue b/ui/src/Services.vue @@ -1,12 +1,33 @@ <template> <div class="services-wrapper"> - nothing here yet + <div v-for="service in services"> + {{ service.name }} : + <input type="text" service.description }} : + <input type="text" :value="service.token"> + </div> </div> </template> <script> + import api from "./requests.js"; export default { - name: "Services" + name: "Services", + data() { + return { + services: [] + } + }, + mounted() { + api.getServices( + services => { + this.services = services; + }, + error => { + console.log(error); + this.$emit("error"); + } + ); + } } </script> diff --git a/ui/src/requests.js b/ui/src/requests.js @@ -7,6 +7,7 @@ export default { postService, deleteService, getEvents, + deleteEvent, } /***** Login and authentication *****/ @@ -48,8 +49,12 @@ function logout(passphrase, successHandler, errorHandler) { /***** Service management *****/ -function getServices() { - +function getServices(successHandler, errorHandler) { + request({ + url: "/services", + success: successHandler, + error: errorHandler + }); } function postService(service) { @@ -72,8 +77,13 @@ function getEvents(successHandler, errorHandler) { }); } -function deleteEvent(id) { - +function deleteEvent(id, successHandler, errorHandler) { + request({ + url: "/events/" + id, + method: "DELETE", + success: successHandler, + error: errorHandler + }); }