mirror of https://github.com/status-im/go-waku.git
Feat: implement admin rest api (#827)
* feat: implement Admin rest API to fetch and add peers
This commit is contained in:
parent
9b9fc634cb
commit
3d69e78cf3
|
@ -505,7 +505,7 @@ func Execute(options NodeOptions) error {
|
||||||
var restServer *rest.WakuRest
|
var restServer *rest.WakuRest
|
||||||
if options.RESTServer.Enable {
|
if options.RESTServer.Enable {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
restServer = rest.NewWakuRest(wakuNode, options.RESTServer.Address, options.RESTServer.Port, options.PProf, options.RESTServer.RelayCacheCapacity, logger)
|
restServer = rest.NewWakuRest(wakuNode, options.RESTServer.Address, options.RESTServer.Port, options.PProf, options.RESTServer.Admin, options.RESTServer.RelayCacheCapacity, logger)
|
||||||
restServer.Start(ctx, &wg)
|
restServer.Start(ctx, &wg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
package rest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
"github.com/libp2p/go-libp2p/core/protocol"
|
||||||
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
|
"github.com/waku-org/go-waku/cmd/waku/server"
|
||||||
|
"github.com/waku-org/go-waku/logging"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/node"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/peerstore"
|
||||||
|
waku_proto "github.com/waku-org/go-waku/waku/v2/protocol"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AdminService struct {
|
||||||
|
node *node.WakuNode
|
||||||
|
mux *chi.Mux
|
||||||
|
log *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type WakuPeer struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
MultiAddrs []string `json:"multiaddrs"`
|
||||||
|
Protocols []string `json:"protocols"`
|
||||||
|
Connected bool `json:"connected"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WakuPeerInfo struct {
|
||||||
|
MultiAddr string `json:"multiaddr"`
|
||||||
|
Shards []int `json:"shards"`
|
||||||
|
Protocols []string `json:"protocols"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const routeAdminV1Peers = "/admin/v1/peers"
|
||||||
|
|
||||||
|
func NewAdminService(node *node.WakuNode, m *chi.Mux, log *zap.Logger) *AdminService {
|
||||||
|
d := &AdminService{
|
||||||
|
node: node,
|
||||||
|
mux: m,
|
||||||
|
log: log,
|
||||||
|
}
|
||||||
|
|
||||||
|
m.Get(routeAdminV1Peers, d.getV1Peers)
|
||||||
|
m.Post(routeAdminV1Peers, d.postV1Peer)
|
||||||
|
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminService) getV1Peers(w http.ResponseWriter, req *http.Request) {
|
||||||
|
peers, err := a.node.Peers()
|
||||||
|
if err != nil {
|
||||||
|
writeErrOrResponse(w, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response := make([]WakuPeer, 0)
|
||||||
|
for _, peer := range peers {
|
||||||
|
wPeer := WakuPeer{
|
||||||
|
ID: peer.ID.Pretty(),
|
||||||
|
Connected: peer.Connected,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range peer.Addrs {
|
||||||
|
wPeer.MultiAddrs = append(wPeer.MultiAddrs, addr.String())
|
||||||
|
}
|
||||||
|
for _, proto := range peer.Protocols {
|
||||||
|
if !server.IsWakuProtocol(proto) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wPeer.Protocols = append(wPeer.Protocols, string(proto))
|
||||||
|
}
|
||||||
|
response = append(response, wPeer)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeErrOrResponse(w, nil, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AdminService) postV1Peer(w http.ResponseWriter, req *http.Request) {
|
||||||
|
var pInfo WakuPeerInfo
|
||||||
|
var topics []string
|
||||||
|
var protos []protocol.ID
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(req.Body)
|
||||||
|
if err := decoder.Decode(&pInfo); err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer req.Body.Close()
|
||||||
|
|
||||||
|
addr, err := ma.NewMultiaddr(pInfo.MultiAddr)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("building multiaddr", zap.Error(err))
|
||||||
|
writeErrOrResponse(w, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, shard := range pInfo.Shards {
|
||||||
|
topic := waku_proto.NewStaticShardingPubsubTopic(waku_proto.ClusterIndex, uint16(shard))
|
||||||
|
topics = append(topics, topic.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := a.node.AddPeer(addr, peerstore.Static, topics, protos...)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("failed to add peer", zap.Error(err))
|
||||||
|
writeErrOrResponse(w, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a.log.Info("add peer successful", logging.HostID("peerID", id))
|
||||||
|
pi := peer.AddrInfo{ID: id, Addrs: []ma.Multiaddr{addr}}
|
||||||
|
err = a.node.Host().Connect(req.Context(), pi)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Error("failed to connect to peer", logging.HostID("peerID", id), zap.Error(err))
|
||||||
|
writeErrOrResponse(w, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
writeErrOrResponse(w, nil, nil)
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
openapi: 3.0.3
|
||||||
|
info:
|
||||||
|
title: Waku V2 node REST API
|
||||||
|
version: 1.0.0
|
||||||
|
contact:
|
||||||
|
name: VAC Team
|
||||||
|
url: https://forum.vac.dev/
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- name: admin
|
||||||
|
description: Admin REST API for WakuV2 node
|
||||||
|
|
||||||
|
paths:
|
||||||
|
/admin/v1/peers:
|
||||||
|
get:
|
||||||
|
summary: Get connected peers info
|
||||||
|
description: Retrieve information about connected peers.
|
||||||
|
operationId: getPeerInfo
|
||||||
|
tags:
|
||||||
|
- admin
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Information about a Waku v2 node.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/WakuPeer'
|
||||||
|
'5XX':
|
||||||
|
description: Unexpected error.
|
||||||
|
post:
|
||||||
|
summary: Adds new peer(s) to connect with
|
||||||
|
description: Adds new peer(s) to connect with.
|
||||||
|
operationId: postPeerInfo
|
||||||
|
tags:
|
||||||
|
- admin
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/WakuPeerInfo'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Ok
|
||||||
|
'400':
|
||||||
|
description: Cannot connect to one or more peers.
|
||||||
|
'5XX':
|
||||||
|
description: Unexpected error.
|
||||||
|
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
WakuPeerInfo:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- multiaddr
|
||||||
|
- shards
|
||||||
|
- protocols
|
||||||
|
protocols:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
shards:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
WakuPeer:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- addrs
|
||||||
|
- protocols
|
||||||
|
- connected
|
||||||
|
properties:
|
||||||
|
connected:
|
||||||
|
type: string
|
||||||
|
addrs:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
protocols:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
connected:
|
||||||
|
type: boolean
|
|
@ -21,7 +21,7 @@ type WakuRest struct {
|
||||||
relayService *RelayService
|
relayService *RelayService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWakuRest(node *node.WakuNode, address string, port int, enablePProf bool, relayCacheCapacity int, log *zap.Logger) *WakuRest {
|
func NewWakuRest(node *node.WakuNode, address string, port int, enablePProf bool, enableAdmin bool, relayCacheCapacity int, log *zap.Logger) *WakuRest {
|
||||||
wrpc := new(WakuRest)
|
wrpc := new(WakuRest)
|
||||||
wrpc.log = log.Named("rest")
|
wrpc.log = log.Named("rest")
|
||||||
|
|
||||||
|
@ -56,6 +56,10 @@ func NewWakuRest(node *node.WakuNode, address string, port int, enablePProf bool
|
||||||
wrpc.relayService = relayService
|
wrpc.relayService = relayService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if enableAdmin {
|
||||||
|
_ = NewAdminService(node, mux, wrpc.log)
|
||||||
|
}
|
||||||
|
|
||||||
return wrpc
|
return wrpc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ func TestWakuRest(t *testing.T) {
|
||||||
n, err := node.New(options)
|
n, err := node.New(options)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
rpc := NewWakuRest(n, "127.0.0.1", 8080, false, 10, utils.Logger())
|
rpc := NewWakuRest(n, "127.0.0.1", 8080, false, false, 10, utils.Logger())
|
||||||
require.NotNil(t, rpc.server)
|
require.NotNil(t, rpc.server)
|
||||||
require.Equal(t, rpc.server.Addr, "127.0.0.1:8080")
|
require.Equal(t, rpc.server.Addr, "127.0.0.1:8080")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,8 @@ import (
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"github.com/waku-org/go-waku/cmd/waku/server"
|
||||||
"github.com/waku-org/go-waku/waku/v2/node"
|
"github.com/waku-org/go-waku/waku/v2/node"
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
|
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_filter"
|
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
|
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
|
||||||
"github.com/waku-org/go-waku/waku/v2/protocol/store"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AdminService struct {
|
type AdminService struct {
|
||||||
|
@ -54,15 +50,6 @@ func (a *AdminService) PostV1Peers(req *http.Request, args *PeersArgs, reply *Su
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isWakuProtocol(protocol protocol.ID) bool {
|
|
||||||
return protocol == legacy_filter.FilterID_v20beta1 ||
|
|
||||||
protocol == filter.FilterPushID_v20beta1 ||
|
|
||||||
protocol == filter.FilterSubscribeID_v20beta1 ||
|
|
||||||
protocol == relay.WakuRelayID_v200 ||
|
|
||||||
protocol == lightpush.LightPushID_v20beta1 ||
|
|
||||||
protocol == store.StoreID_v20beta4
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AdminService) GetV1Peers(req *http.Request, args *GetPeersArgs, reply *PeersReply) error {
|
func (a *AdminService) GetV1Peers(req *http.Request, args *GetPeersArgs, reply *PeersReply) error {
|
||||||
peers, err := a.node.Peers()
|
peers, err := a.node.Peers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -72,7 +59,7 @@ func (a *AdminService) GetV1Peers(req *http.Request, args *GetPeersArgs, reply *
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
for _, addr := range peer.Addrs {
|
for _, addr := range peer.Addrs {
|
||||||
for _, proto := range peer.Protocols {
|
for _, proto := range peer.Protocols {
|
||||||
if !isWakuProtocol(proto) {
|
if !server.IsWakuProtocol(proto) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
*reply = append(*reply, PeerReply{
|
*reply = append(*reply, PeerReply{
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/libp2p/go-libp2p/core/protocol"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_filter"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
|
||||||
|
"github.com/waku-org/go-waku/waku/v2/protocol/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsWakuProtocol(protocol protocol.ID) bool {
|
||||||
|
return protocol == legacy_filter.FilterID_v20beta1 ||
|
||||||
|
protocol == filter.FilterPushID_v20beta1 ||
|
||||||
|
protocol == filter.FilterSubscribeID_v20beta1 ||
|
||||||
|
protocol == relay.WakuRelayID_v200 ||
|
||||||
|
protocol == lightpush.LightPushID_v20beta1 ||
|
||||||
|
protocol == store.StoreID_v20beta4
|
||||||
|
}
|
Loading…
Reference in New Issue