github.com/m3db/m3@v1.5.0/src/cluster/placementhandler/delete_all.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package placementhandler 22 23 import ( 24 "encoding/json" 25 "net/http" 26 "path" 27 "time" 28 29 "github.com/m3db/m3/src/cluster/kv" 30 "github.com/m3db/m3/src/cluster/placementhandler/handleroptions" 31 "github.com/m3db/m3/src/query/api/v1/route" 32 "github.com/m3db/m3/src/query/util/logging" 33 xhttp "github.com/m3db/m3/src/x/net/http" 34 35 "go.uber.org/zap" 36 ) 37 38 const ( 39 // DeleteAllHTTPMethod is the HTTP method used with this resource. 40 DeleteAllHTTPMethod = http.MethodDelete 41 ) 42 43 var ( 44 // M3DBDeleteAllURL is the url for the handler to delete all placements (with the DELETE method) 45 // for the M3DB service. 46 M3DBDeleteAllURL = path.Join(route.Prefix, M3DBServicePlacementPathName) 47 48 // M3AggDeleteAllURL is the url for the handler to delete all placements (with the DELETE method) 49 // for the M3Agg service. 50 M3AggDeleteAllURL = path.Join(route.Prefix, M3AggServicePlacementPathName) 51 52 // M3CoordinatorDeleteAllURL is the url for the handler to delete all placements (with the DELETE method) 53 // for the M3Coordinator service. 54 M3CoordinatorDeleteAllURL = path.Join(route.Prefix, M3CoordinatorServicePlacementPathName) 55 ) 56 57 // DeleteAllHandler is the handler to delete all placements. 58 type DeleteAllHandler Handler 59 60 // NewDeleteAllHandler returns a new instance of DeleteAllHandler. 61 func NewDeleteAllHandler(opts HandlerOptions) *DeleteAllHandler { 62 return &DeleteAllHandler{HandlerOptions: opts, nowFn: time.Now} 63 } 64 65 func (h *DeleteAllHandler) ServeHTTP( 66 svc handleroptions.ServiceNameAndDefaults, 67 w http.ResponseWriter, 68 r *http.Request, 69 ) { 70 var ( 71 ctx = r.Context() 72 logger = logging.WithContext(ctx, h.instrumentOptions) 73 opts = handleroptions.NewServiceOptions(svc, r.Header, h.m3AggServiceOptions) 74 ) 75 76 service, err := Service(h.clusterClient, opts, 77 Handler(*h).PlacementConfig(), h.nowFn(), nil) 78 if err != nil { 79 xhttp.WriteError(w, err) 80 return 81 } 82 83 curPlacement, err := service.Placement() 84 if err != nil { 85 if err == kv.ErrNotFound { 86 logger.Info("cannot delete placement", 87 zap.String("service", svc.ServiceName), 88 zap.Error(err)) 89 xhttp.WriteError(w, xhttp.NewError(err, http.StatusNotFound)) 90 return 91 } 92 93 logger.Error("unable to fetch placement", zap.Error(err)) 94 xhttp.WriteError(w, err) 95 return 96 } 97 98 if err := service.Delete(); err != nil { 99 logger.Error("error deleting placement", zap.Error(err)) 100 xhttp.WriteError(w, err) 101 return 102 } 103 104 // Now need to delete aggregator related keys (e.g. for shardsets) if required. 105 if svc.ServiceName == handleroptions.M3AggregatorServiceName { 106 instances := curPlacement.Instances() 107 shardSetIDs := make([]uint32, 0, len(instances)) 108 for _, elem := range instances { 109 value := elem.ShardSetID() 110 found := false 111 for _, existing := range shardSetIDs { 112 if existing == value { 113 found = true 114 break 115 } 116 } 117 if !found { 118 shardSetIDs = append(shardSetIDs, value) 119 } 120 } 121 122 err := deleteAggregatorShardSetIDRelatedKeys(svc, opts, 123 h.clusterClient, shardSetIDs) 124 if err != nil { 125 logger.Error("error removing aggregator keys for instances", 126 zap.Error(err)) 127 xhttp.WriteError(w, err) 128 return 129 } 130 } 131 132 json.NewEncoder(w).Encode(struct { 133 Deleted bool `json:"deleted"` 134 }{ 135 Deleted: true, 136 }) 137 }