From ae8b8b5a5b4943df04f55dbec6c6db7e497d72c8 Mon Sep 17 00:00:00 2001 From: MD-Levitan Date: Mon, 3 May 2021 20:49:40 +0300 Subject: Add feature to delete service --- application_router.go | 21 ++++++- frontend/src/components/panels/ServicesPane.js | 15 +++++ services_controller.go | 19 +++++- storage.go | 80 +++++++++++++++++++++++++- 4 files changed, 130 insertions(+), 5 deletions(-) diff --git a/application_router.go b/application_router.go index 6d65960..1288eb1 100644 --- a/application_router.go +++ b/application_router.go @@ -20,14 +20,15 @@ package main import ( "errors" "fmt" - "github.com/gin-gonic/contrib/static" - "github.com/gin-gonic/gin" - log "github.com/sirupsen/logrus" "net/http" "os" "path/filepath" "strings" "time" + + "github.com/gin-gonic/contrib/static" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" ) func CreateApplicationRouter(applicationContext *ApplicationContext, @@ -389,6 +390,20 @@ func CreateApplicationRouter(applicationContext *ApplicationContext, } }) + api.DELETE("/services", func(c *gin.Context) { + var service Service + if err := c.ShouldBindJSON(&service); err != nil { + badRequest(c, err) + return + } + if err := applicationContext.ServicesController.DeleteService(c, service); err == nil { + success(c, service) + notificationController.Notify("services.edit", service) + } else { + unprocessableEntity(c, err) + } + }) + api.GET("/statistics", func(c *gin.Context) { var filter StatisticsFilter if err := c.ShouldBindQuery(&filter); err != nil { diff --git a/frontend/src/components/panels/ServicesPane.js b/frontend/src/components/panels/ServicesPane.js index 5986804..9f89485 100644 --- a/frontend/src/components/panels/ServicesPane.js +++ b/frontend/src/components/panels/ServicesPane.js @@ -85,6 +85,19 @@ class ServicesPane extends Component { } }; + deleteService = () => { + const service = this.state.currentService; + if (this.validateService(service)) { + backend.delete("/api/services", service).then((res) => { + this.reset(); + this.setState({serviceStatusCode: res.status}); + this.loadServices(); + }).catch((res) => { + this.setState({serviceStatusCode: res.status, serviceResponse: JSON.stringify(res.json)}); + }); + } + }; + validateService = (service) => { let valid = true; if (!validation.isValidPort(service.port, true)) { @@ -207,6 +220,8 @@ class ServicesPane extends Component { + {isUpdate ? : ""} diff --git a/services_controller.go b/services_controller.go index e5fa200..566f6ba 100644 --- a/services_controller.go +++ b/services_controller.go @@ -20,8 +20,9 @@ package main import ( "context" "errors" - log "github.com/sirupsen/logrus" "sync" + + log "github.com/sirupsen/logrus" ) type Service struct { @@ -79,3 +80,19 @@ func (sc *ServicesController) GetServices() map[uint16]Service { sc.mutex.Unlock() return services } + +func (sc *ServicesController) DeleteService(c context.Context, service Service) error { + sc.mutex.Lock() + defer sc.mutex.Unlock() + + if err := sc.storage.Delete(Services).Context(c).Filter(OrderedDocument{{"_id", service.Port}}).One(); err != nil { + log.Println(service) + log.Println(err) + return errors.New(err.Error()) + } else { + log.Println(err) + log.Println(sc.services) + delete(sc.services, service.Port) + return nil + } +} diff --git a/storage.go b/storage.go index 8505bfe..29694a3 100644 --- a/storage.go +++ b/storage.go @@ -21,11 +21,12 @@ import ( "context" "errors" "fmt" + "time" + "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" - "time" ) // Collections names @@ -46,6 +47,7 @@ type Storage interface { Insert(collectionName string) InsertOperation Update(collectionName string) UpdateOperation Find(collectionName string) FindOperation + Delete(collectionName string) DeleteOperation } type MongoStorage struct { @@ -399,3 +401,79 @@ func (storage *MongoStorage) Find(collectionName string) FindOperation { } return op } + +// Delete one/many + +type DeleteOperation interface { + Context(ctx context.Context) DeleteOperation + Filter(filter OrderedDocument) DeleteOperation + One() error + Many() error +} + +func (storage *MongoStorage) Delete(collectionName string) DeleteOperation { + collection, ok := storage.collections[collectionName] + op := MongoDeleteOperation{ + collection: collection, + opts: options.Delete(), + } + if !ok { + op.err = errors.New("invalid collection: " + collectionName) + } + return op +} + +type MongoDeleteOperation struct { + collection *mongo.Collection + ctx context.Context + opts *options.DeleteOptions + filter OrderedDocument + err error +} + +func (do MongoDeleteOperation) Context(ctx context.Context) DeleteOperation { + do.ctx = ctx + return do +} + +func (do MongoDeleteOperation) Filter(filter OrderedDocument) DeleteOperation { + for _, elem := range filter { + do.filter = append(do.filter, primitive.E{Key: elem.Key, Value: elem.Value}) + } + + return do +} + +func (do MongoDeleteOperation) One() error { + if do.err != nil { + return do.err + } + + result, err := do.collection.DeleteOne(do.ctx, do.filter, do.opts) + if err != nil { + return err + } + + if result.DeletedCount == 0 { + return errors.New("nothing to delete") + } + + return nil +} + +func (do MongoDeleteOperation) Many() error { + if do.err != nil { + return do.err + } + + result, err := do.collection.DeleteMany(do.ctx, do.filter, do.opts) + if err != nil { + return err + } + + if result.DeletedCount == 0 { + return errors.New("nothing to delete") + } + + return nil +} -- cgit v1.2.3-70-g09d2