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
|
||||
if options.RESTServer.Enable {
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
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.log = log.Named("rest")
|
||||
|
||||
|
@ -56,6 +56,10 @@ func NewWakuRest(node *node.WakuNode, address string, port int, enablePProf bool
|
|||
wrpc.relayService = relayService
|
||||
}
|
||||
|
||||
if enableAdmin {
|
||||
_ = NewAdminService(node, mux, wrpc.log)
|
||||
}
|
||||
|
||||
return wrpc
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ func TestWakuRest(t *testing.T) {
|
|||
n, err := node.New(options)
|
||||
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.Equal(t, rpc.server.Addr, "127.0.0.1:8080")
|
||||
}
|
||||
|
|
|
@ -7,12 +7,8 @@ import (
|
|||
ma "github.com/multiformats/go-multiaddr"
|
||||
"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/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 {
|
||||
|
@ -54,15 +50,6 @@ func (a *AdminService) PostV1Peers(req *http.Request, args *PeersArgs, reply *Su
|
|||
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 {
|
||||
peers, err := a.node.Peers()
|
||||
if err != nil {
|
||||
|
@ -72,7 +59,7 @@ func (a *AdminService) GetV1Peers(req *http.Request, args *GetPeersArgs, reply *
|
|||
for _, peer := range peers {
|
||||
for _, addr := range peer.Addrs {
|
||||
for _, proto := range peer.Protocols {
|
||||
if !isWakuProtocol(proto) {
|
||||
if !server.IsWakuProtocol(proto) {
|
||||
continue
|
||||
}
|
||||
*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