github.com/polarismesh/polaris@v1.17.8/apiserver/httpserver/admin_access.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package httpserver
    19  
    20  import (
    21  	"context"
    22  	"encoding/json"
    23  	"net/http"
    24  	"strconv"
    25  
    26  	"github.com/emicklei/go-restful/v3"
    27  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    28  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    29  
    30  	"github.com/polarismesh/polaris/admin"
    31  	"github.com/polarismesh/polaris/apiserver/httpserver/docs"
    32  	httpcommon "github.com/polarismesh/polaris/apiserver/httpserver/utils"
    33  	api "github.com/polarismesh/polaris/common/api/v1"
    34  	"github.com/polarismesh/polaris/common/model"
    35  	"github.com/polarismesh/polaris/common/utils"
    36  )
    37  
    38  // GetIndexServer get index server
    39  func (h *HTTPServer) GetIndexServer() *restful.WebService {
    40  	ws := new(restful.WebService)
    41  
    42  	ws.Route(ws.GET("/").To(h.index))
    43  
    44  	return ws
    45  }
    46  
    47  // index  URL: "/"
    48  func (h *HTTPServer) index(_ *restful.Request, rsp *restful.Response) {
    49  	_, _ = rsp.Write([]byte("Polaris Server"))
    50  }
    51  
    52  // GetMaintainAccessServer 运维接口
    53  func (h *HTTPServer) GetAdminAccessServer() *restful.WebService {
    54  	ws := new(restful.WebService)
    55  	ws.Path("/maintain/v1").Consumes(restful.MIME_JSON).Produces(restful.MIME_JSON)
    56  
    57  	ws.Route(docs.EnrichGetServerConnectionsApiDocs(ws.GET("/apiserver/conn").To(h.GetServerConnections)))
    58  	ws.Route(docs.EnrichGetServerConnStatsApiDocs(ws.GET("/apiserver/conn/stats").To(h.GetServerConnStats)))
    59  	ws.Route(docs.EnrichCloseConnectionsApiDocs(ws.POST("apiserver/conn/close").To(h.CloseConnections)))
    60  	ws.Route(docs.EnrichFreeOSMemoryApiDocs(ws.POST("/memory/free").To(h.FreeOSMemory)))
    61  	ws.Route(docs.EnrichCleanInstanceApiDocs(ws.POST("/instance/clean").To(h.CleanInstance)))
    62  	ws.Route(docs.EnrichBatchCleanInstancesApiDocs(ws.POST("/instance/batchclean").To(h.BatchCleanInstances)))
    63  	ws.Route(docs.EnrichGetLastHeartbeatApiDocs(ws.GET("/instance/heartbeat").To(h.GetLastHeartbeat)))
    64  	ws.Route(docs.EnrichGetLogOutputLevelApiDocs(ws.GET("/log/outputlevel").To(h.GetLogOutputLevel)))
    65  	ws.Route(docs.EnrichSetLogOutputLevelApiDocs(ws.PUT("/log/outputlevel").To(h.SetLogOutputLevel)))
    66  	ws.Route(docs.EnrichListLeaderElectionsApiDocs(ws.GET("/leaders").To(h.ListLeaderElections)))
    67  	ws.Route(docs.EnrichReleaseLeaderElectionApiDocs(ws.POST("/leaders/release").To(h.ReleaseLeaderElection)))
    68  	ws.Route(docs.EnrichGetCMDBInfoApiDocs(ws.GET("/cmdb/info").To(h.GetCMDBInfo)))
    69  	ws.Route(docs.EnrichGetReportClientsApiDocs(ws.GET("/report/clients").To(h.GetReportClients)))
    70  	return ws
    71  }
    72  
    73  // GetServerConnections 查看server的连接数
    74  // query参数:protocol,必须,查看指定协议server
    75  //
    76  //	host,可选,查看指定host
    77  func (h *HTTPServer) GetServerConnections(req *restful.Request, rsp *restful.Response) {
    78  	ctx := initContext(req)
    79  	params := httpcommon.ParseQueryParams(req)
    80  	connReq := admin.ConnReq{
    81  		Protocol: params["protocol"],
    82  		Host:     params["host"],
    83  	}
    84  
    85  	ret, err := h.maintainServer.GetServerConnections(ctx, &connReq)
    86  	if err != nil {
    87  		_ = rsp.WriteError(http.StatusBadRequest, err)
    88  	} else {
    89  		_ = rsp.WriteEntity(ret)
    90  	}
    91  }
    92  
    93  // GetServerConnStats 获取连接缓存里面的统计信息
    94  func (h *HTTPServer) GetServerConnStats(req *restful.Request, rsp *restful.Response) {
    95  	ctx := initContext(req)
    96  	params := httpcommon.ParseQueryParams(req)
    97  
    98  	var amount int
    99  	if amountStr, ok := params["amount"]; ok {
   100  		if n, err := strconv.Atoi(amountStr); err == nil {
   101  			amount = n
   102  		}
   103  	}
   104  
   105  	connReq := admin.ConnReq{
   106  		Protocol: params["protocol"],
   107  		Host:     params["host"],
   108  		Amount:   amount,
   109  	}
   110  
   111  	ret, err := h.maintainServer.GetServerConnStats(ctx, &connReq)
   112  	if err != nil {
   113  		_ = rsp.WriteError(http.StatusBadRequest, err)
   114  	} else {
   115  		_ = rsp.WriteAsJson(ret)
   116  	}
   117  }
   118  
   119  // CloseConnections 关闭指定client ip的连接
   120  func (h *HTTPServer) CloseConnections(req *restful.Request, rsp *restful.Response) {
   121  	log.Info("[MAINTAIN] Start doing close connections")
   122  	ctx := initContext(req)
   123  	var connReqs []admin.ConnReq
   124  	decoder := json.NewDecoder(req.Request.Body)
   125  	if err := decoder.Decode(&connReqs); err != nil {
   126  		log.Errorf("[MAINTAIN] close connection decode body err: %s", err.Error())
   127  		_ = rsp.WriteError(http.StatusBadRequest, err)
   128  		return
   129  	}
   130  	for _, entry := range connReqs {
   131  		if entry.Protocol == "" {
   132  			log.Errorf("[MAINTAIN] close connection missing protocol")
   133  			_ = rsp.WriteErrorString(http.StatusBadRequest, "missing protocol")
   134  			return
   135  		}
   136  		if entry.Host == "" {
   137  			log.Errorf("[MAINTAIN] close connection missing host")
   138  			_ = rsp.WriteErrorString(http.StatusBadRequest, "missing host")
   139  			return
   140  		}
   141  	}
   142  
   143  	if err := h.maintainServer.CloseConnections(ctx, connReqs); err != nil {
   144  		_ = rsp.WriteError(http.StatusBadRequest, err)
   145  	}
   146  }
   147  
   148  // FreeOSMemory 增加一个释放系统内存的接口
   149  func (h *HTTPServer) FreeOSMemory(req *restful.Request, rsp *restful.Response) {
   150  	ctx := initContext(req)
   151  	if err := h.maintainServer.FreeOSMemory(ctx); err != nil {
   152  		_ = rsp.WriteError(http.StatusBadRequest, err)
   153  	}
   154  }
   155  
   156  // CleanInstance 彻底清理flag=1的实例运维接口
   157  // 支持一个个清理
   158  func (h *HTTPServer) CleanInstance(req *restful.Request, rsp *restful.Response) {
   159  	handler := &httpcommon.Handler{
   160  		Request:  req,
   161  		Response: rsp,
   162  	}
   163  
   164  	instance := &apiservice.Instance{}
   165  	ctx, err := handler.Parse(instance)
   166  	if err != nil {
   167  		handler.WriteHeaderAndProto(api.NewResponseWithMsg(apimodel.Code_ParseException, err.Error()))
   168  		return
   169  	}
   170  
   171  	handler.WriteHeaderAndProto(h.maintainServer.CleanInstance(ctx, instance))
   172  }
   173  
   174  func (h *HTTPServer) BatchCleanInstances(req *restful.Request, rsp *restful.Response) {
   175  	ctx := initContext(req)
   176  
   177  	var param struct {
   178  		BatchSize uint32 `json:"batch_size"`
   179  	}
   180  
   181  	if err := httpcommon.ParseJsonBody(req, &param); err != nil {
   182  		_ = rsp.WriteError(http.StatusBadRequest, err)
   183  		return
   184  	}
   185  
   186  	if count, err := h.maintainServer.BatchCleanInstances(ctx, param.BatchSize); err != nil {
   187  		_ = rsp.WriteError(http.StatusInternalServerError, err)
   188  	} else {
   189  		var ret struct {
   190  			RowsAffected uint32 `json:"rows_affected"`
   191  		}
   192  		ret.RowsAffected = count
   193  		_ = rsp.WriteAsJson(ret)
   194  	}
   195  
   196  }
   197  
   198  // GetLastHeartbeat 获取实例,上一次心跳的时间
   199  func (h *HTTPServer) GetLastHeartbeat(req *restful.Request, rsp *restful.Response) {
   200  	ctx := initContext(req)
   201  	handler := &httpcommon.Handler{
   202  		Request:  req,
   203  		Response: rsp,
   204  	}
   205  	params := httpcommon.ParseQueryParams(req)
   206  	instance := &apiservice.Instance{}
   207  	if id, ok := params["id"]; ok && id != "" {
   208  		instance.Id = utils.NewStringValue(id)
   209  	} else {
   210  		instance.Service = utils.NewStringValue(params["service"])
   211  		instance.Namespace = utils.NewStringValue(params["namespace"])
   212  		instance.VpcId = utils.NewStringValue(params["vpc_id"])
   213  		instance.Host = utils.NewStringValue(params["host"])
   214  		port, _ := strconv.Atoi(params["port"])
   215  		instance.Port = utils.NewUInt32Value(uint32(port))
   216  	}
   217  
   218  	ret := h.maintainServer.GetLastHeartbeat(ctx, instance)
   219  	handler.WriteHeaderAndProto(ret)
   220  }
   221  
   222  // GetLogOutputLevel 获取日志输出级别
   223  func (h *HTTPServer) GetLogOutputLevel(req *restful.Request, rsp *restful.Response) {
   224  	ctx := initContext(req)
   225  
   226  	out, err := h.maintainServer.GetLogOutputLevel(ctx)
   227  	if err != nil {
   228  		_ = rsp.WriteError(http.StatusBadRequest, err)
   229  	} else {
   230  		_ = rsp.WriteAsJson(out)
   231  	}
   232  }
   233  
   234  // SetLogOutputLevel 设置日志输出级别
   235  func (h *HTTPServer) SetLogOutputLevel(req *restful.Request, rsp *restful.Response) {
   236  	ctx := initContext(req)
   237  
   238  	var scopeLogLevel struct {
   239  		Scope string `json:"scope"`
   240  		Level string `json:"level"`
   241  	}
   242  
   243  	if err := httpcommon.ParseJsonBody(req, &scopeLogLevel); err != nil {
   244  		_ = rsp.WriteErrorString(http.StatusBadRequest, err.Error())
   245  		return
   246  	}
   247  
   248  	if err := h.maintainServer.SetLogOutputLevel(ctx, scopeLogLevel.Scope, scopeLogLevel.Level); err != nil {
   249  		_ = rsp.WriteErrorString(http.StatusBadRequest, err.Error())
   250  		return
   251  	}
   252  
   253  	_ = rsp.WriteEntity("ok")
   254  }
   255  
   256  func (h *HTTPServer) ListLeaderElections(req *restful.Request, rsp *restful.Response) {
   257  	ctx := initContext(req)
   258  	leaders, err := h.maintainServer.ListLeaderElections(ctx)
   259  	if err != nil {
   260  		_ = rsp.WriteError(http.StatusBadRequest, err)
   261  		return
   262  	}
   263  	if leaders == nil {
   264  		leaders = []*model.LeaderElection{}
   265  	}
   266  
   267  	_ = rsp.WriteAsJson(leaders)
   268  }
   269  
   270  func (h *HTTPServer) ReleaseLeaderElection(req *restful.Request, rsp *restful.Response) {
   271  	ctx := initContext(req)
   272  	var releasedElection struct {
   273  		ElectKey string `json:"electKey"`
   274  	}
   275  	if err := httpcommon.ParseJsonBody(req, &releasedElection); err != nil {
   276  		_ = rsp.WriteErrorString(http.StatusBadRequest, err.Error())
   277  		return
   278  	}
   279  	if err := h.maintainServer.ReleaseLeaderElection(ctx, releasedElection.ElectKey); err != nil {
   280  		_ = rsp.WriteErrorString(http.StatusBadRequest, err.Error())
   281  		return
   282  	}
   283  	_ = rsp.WriteEntity("ok")
   284  }
   285  
   286  func (h *HTTPServer) GetCMDBInfo(req *restful.Request, rsp *restful.Response) {
   287  	ctx := initContext(req)
   288  
   289  	ret, err := h.maintainServer.GetCMDBInfo(ctx)
   290  	if err != nil {
   291  		_ = rsp.WriteErrorString(http.StatusBadRequest, err.Error())
   292  		return
   293  	}
   294  	_ = rsp.WriteAsJson(ret)
   295  }
   296  
   297  func initContext(req *restful.Request) context.Context {
   298  	ctx := context.Background()
   299  
   300  	authToken := req.HeaderParameter(utils.HeaderAuthTokenKey)
   301  	if authToken != "" {
   302  		ctx = context.WithValue(ctx, utils.ContextAuthTokenKey, authToken)
   303  	}
   304  
   305  	return ctx
   306  }