Skip to content

Commit d8c06e8

Browse files
authored
feat: customize comet rpc and p2p ports (#485)
* feat: customize comet rpc and p2p ports * config set p2p addr * add test * unnecessary cast * fix test
1 parent 876808a commit d8c06e8

File tree

8 files changed

+162
-52
lines changed

8 files changed

+162
-52
lines changed

api/v1/cosmosfullnode_types.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ limitations under the License.
1717
package v1
1818

1919
import (
20+
"strconv"
21+
"strings"
22+
2023
corev1 "k8s.io/api/core/v1"
2124
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2225
"k8s.io/apimachinery/pkg/util/intstr"
@@ -596,6 +599,14 @@ type ChainVersion struct {
596599

597600
// CometConfig configures the config.toml.
598601
type CometConfig struct {
602+
// RPC listen address. Defaults to tcp://0.0.0.0:26657
603+
// +optional
604+
RPCListenAddress string `json:"rpcListenAddress"`
605+
606+
// P2P listen address. Defaults to tcp://0.0.0.0:26656
607+
// +optional
608+
P2PListenAddress string `json:"p2pListenAddress"`
609+
599610
// Comma delimited list of p2p nodes in <ID>@<IP>:<PORT> format to keep persistent p2p connections.
600611
// +kubebuilder:validation:MinLength:=1
601612
// +optional
@@ -642,6 +653,39 @@ type CometConfig struct {
642653
TomlOverrides *string `json:"overrides"`
643654
}
644655

656+
const (
657+
defaultRPCPort = 26657
658+
defaultP2PPort = 26656
659+
)
660+
661+
func (c CometConfig) RPCPort() int32 {
662+
if c.RPCListenAddress == "" {
663+
return defaultRPCPort
664+
}
665+
portSplit := strings.Split(c.RPCListenAddress, ":")
666+
667+
port, err := strconv.ParseInt(portSplit[len(portSplit)-1], 10, 32)
668+
if err != nil {
669+
return defaultRPCPort
670+
}
671+
672+
return int32(port)
673+
}
674+
675+
func (c CometConfig) P2PPort() int32 {
676+
if c.P2PListenAddress == "" {
677+
return defaultP2PPort
678+
}
679+
portSplit := strings.Split(c.P2PListenAddress, ":")
680+
681+
port, err := strconv.ParseInt(portSplit[len(portSplit)-1], 10, 32)
682+
if err != nil {
683+
return defaultP2PPort
684+
}
685+
686+
return int32(port)
687+
}
688+
645689
// SDKAppConfig configures the cosmos sdk application app.toml.
646690
type SDKAppConfig struct {
647691
// The minimum gas prices a validator is willing to accept for processing a

config/crd/bases/cosmos.strange.love_cosmosfullnodes.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ spec:
222222
WARNING: Overriding may clobber some values that the operator sets such as persistent_peers, private_peer_ids,
223223
and unconditional_peer_ids. Use the dedicated fields for these values which will merge values.
224224
type: string
225+
p2pListenAddress:
226+
description: P2P listen address. Defaults to tcp://0.0.0.0:26656
227+
type: string
225228
peers:
226229
description: Comma delimited list of p2p nodes in <ID>@<IP>:<PORT>
227230
format to keep persistent p2p connections.
@@ -231,6 +234,9 @@ spec:
231234
description: Comma delimited list of node/peer IDs to keep
232235
private (will not be gossiped to other peers)
233236
type: string
237+
rpcListenAddress:
238+
description: RPC listen address. Defaults to tcp://0.0.0.0:26657
239+
type: string
234240
seeds:
235241
description: Comma delimited list of p2p seed nodes in <ID>@<IP>:<PORT>
236242
format.

internal/cosmos/status_collector.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,19 @@ func (coll StatusCollector) Collect(ctx context.Context, pods []corev1.Pod) Stat
4747
statuses[i].Err = errors.New("pod has no IP")
4848
return nil
4949
}
50-
host := fmt.Sprintf("http://%s:26657", ip)
50+
var rpcPort int32 = 26657
51+
for _, c := range pod.Spec.Containers {
52+
if c.Name == "node" {
53+
for _, p := range c.Ports {
54+
if p.Name == "rpc" {
55+
rpcPort = p.ContainerPort
56+
break
57+
}
58+
}
59+
break
60+
}
61+
}
62+
host := fmt.Sprintf("http://%s:%d", ip, rpcPort)
5163
cctx, cancel := context.WithTimeout(ctx, coll.timeout)
5264
defer cancel()
5365
resp, err := coll.comet.Status(cctx, host)

internal/fullnode/configmap_builder.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,28 @@ func addConfigToml(buf *bytes.Buffer, cmData map[string]string, crd *cosmosv1.Co
192192
}
193193
}
194194

195+
if comet.P2PListenAddress != "" {
196+
p2p["laddr"] = comet.P2PListenAddress
197+
}
198+
195199
base["p2p"] = p2p
196200

201+
var rpcLaddr = "tcp://0.0.0.0:26657"
202+
if comet.RPCListenAddress != "" {
203+
rpcLaddr = comet.RPCListenAddress
204+
}
205+
206+
rpc := decodedToml{
207+
"laddr": rpcLaddr,
208+
}
209+
197210
if v := comet.CorsAllowedOrigins; v != nil {
198-
base["rpc"] = decodedToml{
199-
"cors_allowed_origins": v,
200-
"cors-allowed-origins": v,
201-
}
211+
rpc["cors_allowed_origins"] = v
212+
rpc["cors-allowed-origins"] = v
202213
}
203214

215+
base["rpc"] = rpc
216+
204217
dst := defaultComet()
205218

206219
mergemap.Merge(dst, base)

internal/fullnode/peer_collector.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
// Peer contains information about a peer.
1818
type Peer struct {
19+
P2PPort int32
1920
NodeID string
2021
PrivateAddress string // Only the private address my-service.namespace.svc.cluster.local:<port>
2122
ExternalAddress string // Only the address <external-ip-or-hostname>:<port>. Not all peers will be external.
@@ -31,7 +32,7 @@ func (peer Peer) PrivatePeer() string {
3132
// ExternalPeer returns the full external address of the peer in the format <node_id>@<external_address>:<port>.
3233
func (peer Peer) ExternalPeer() string {
3334
if peer.ExternalAddress == "" {
34-
return peer.NodeID + "@" + net.JoinHostPort("0.0.0.0", strconv.Itoa(p2pPort))
35+
return peer.NodeID + "@" + net.JoinHostPort("0.0.0.0", strconv.Itoa(int(peer.P2PPort)))
3536
}
3637
return peer.NodeID + "@" + peer.ExternalAddress
3738
}
@@ -119,7 +120,9 @@ func (c PeerCollector) Collect(ctx context.Context, crd *cosmosv1.CosmosFullNode
119120
}
120121

121122
svcName := p2pServiceName(crd, i)
123+
p2pPort := crd.Spec.ChainSpec.Comet.P2PPort()
122124
peers[c.objectKey(crd, i)] = Peer{
125+
P2PPort: p2pPort,
123126
NodeID: nodeKey.NodeKey.ID(),
124127
PrivateAddress: fmt.Sprintf("%s.%s.svc.%s:%d", svcName, crd.Namespace, clusterDomain, p2pPort),
125128
}
@@ -159,7 +162,7 @@ func (c PeerCollector) addExternalAddress(ctx context.Context, peers Peers, crd
159162
lb := ingress[0]
160163
host := lo.Ternary(lb.IP != "", lb.IP, lb.Hostname)
161164
if host != "" {
162-
info.ExternalAddress = net.JoinHostPort(host, strconv.Itoa(p2pPort))
165+
info.ExternalAddress = net.JoinHostPort(host, strconv.FormatInt(int64(crd.Spec.ChainSpec.Comet.P2PPort()), 10))
163166
}
164167
return nil
165168
}

internal/fullnode/pod_builder.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func NewPodBuilder(crd *cosmosv1.CosmosFullNode) PodBuilder {
8484
Command: []string{startCmd},
8585
Args: startArgs,
8686
Env: envVars(crd),
87-
Ports: buildPorts(crd.Spec.Type),
87+
Ports: buildPorts(crd),
8888
Resources: tpl.Resources,
8989
ReadinessProbe: probes[0],
9090
ImagePullPolicy: tpl.ImagePullPolicy,
@@ -96,7 +96,7 @@ func NewPodBuilder(crd *cosmosv1.CosmosFullNode) PodBuilder {
9696
// Available images: https://github.com/orgs/strangelove-ventures/packages?repo_name=cosmos-operator
9797
// IMPORTANT: Must use v0.6.2 or later.
9898
Image: "ghcr.io/strangelove-ventures/cosmos-operator:" + version.DockerTag(),
99-
Command: []string{"/manager", "healthcheck"},
99+
Command: []string{"/manager", "healthcheck", "--rpc-host", fmt.Sprintf("http://localhost:%d", crd.Spec.ChainSpec.Comet.RPCPort())},
100100
Ports: []corev1.ContainerPort{{ContainerPort: healthCheckPort, Protocol: corev1.ProtocolTCP}},
101101
Resources: corev1.ResourceRequirements{
102102
Requests: corev1.ResourceList{
@@ -148,7 +148,7 @@ func podReadinessProbes(crd *cosmosv1.CosmosFullNode) []*corev1.Probe {
148148
ProbeHandler: corev1.ProbeHandler{
149149
HTTPGet: &corev1.HTTPGetAction{
150150
Path: "/health",
151-
Port: intstr.FromInt(rpcPort),
151+
Port: intstr.FromInt(int(crd.Spec.ChainSpec.Comet.RPCPort())),
152152
Scheme: corev1.URISchemeHTTP,
153153
},
154154
},

internal/fullnode/pod_builder_test.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,36 @@ func TestPodBuilder(t *testing.T) {
147147
}
148148
})
149149

150+
t.Run("override ports", func(t *testing.T) {
151+
crd := defaultCRD()
152+
crd.Spec.ChainSpec.Comet.RPCListenAddress = "tcp://0.0.0.0:27147"
153+
crd.Spec.ChainSpec.Comet.P2PListenAddress = "tcp://0.0.0.0:27146"
154+
pod, err := NewPodBuilder(&crd).Build()
155+
require.NoError(t, err)
156+
ports := pod.Spec.Containers[0].Ports
157+
158+
require.Equal(t, 7, len(ports))
159+
160+
for i, tt := range []struct {
161+
Name string
162+
Port int32
163+
}{
164+
{"api", 1317},
165+
{"rosetta", 8080},
166+
{"grpc", 9090},
167+
{"prometheus", 26660},
168+
{"p2p", 27146},
169+
{"rpc", 27147},
170+
{"grpc-web", 9091},
171+
} {
172+
port := ports[i]
173+
require.Equal(t, tt.Name, port.Name, tt)
174+
require.Equal(t, corev1.ProtocolTCP, port.Protocol)
175+
require.Equal(t, tt.Port, port.ContainerPort)
176+
require.Zero(t, port.HostPort)
177+
}
178+
})
179+
150180
t.Run("ports - sentry", func(t *testing.T) {
151181
crd := defaultCRD()
152182
crd.Spec.Type = cosmosv1.Sentry
@@ -269,7 +299,7 @@ func TestPodBuilder(t *testing.T) {
269299
healthContainer := pod.Spec.Containers[1]
270300
require.Equal(t, "healthcheck", healthContainer.Name)
271301
require.Equal(t, "ghcr.io/strangelove-ventures/cosmos-operator:latest", healthContainer.Image)
272-
require.Equal(t, []string{"/manager", "healthcheck"}, healthContainer.Command)
302+
require.Equal(t, []string{"/manager", "healthcheck", "--rpc-host", "http://localhost:26657"}, healthContainer.Command)
273303
require.Empty(t, healthContainer.Args)
274304
require.Empty(t, healthContainer.ImagePullPolicy)
275305
require.NotEmpty(t, healthContainer.Resources)

internal/fullnode/ports.go

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,60 +9,62 @@ const (
99
apiPort = 1317
1010
grpcPort = 9090
1111
grpcWebPort = 9091
12-
p2pPort = 26656
1312
privvalPort = 1234
1413
promPort = 26660
1514
rosettaPort = 8080
15+
p2pPort = 26656
1616
rpcPort = 26657
1717
)
1818

19-
func buildPorts(nodeType cosmosv1.FullNodeType) []corev1.ContainerPort {
20-
switch nodeType {
19+
func buildPorts(crd *cosmosv1.CosmosFullNode) []corev1.ContainerPort {
20+
switch crd.Spec.Type {
2121
case cosmosv1.Sentry:
22-
return append(defaultPorts[:], corev1.ContainerPort{
22+
return append(ports(crd), corev1.ContainerPort{
2323
Name: "privval",
2424
ContainerPort: privvalPort,
2525
Protocol: corev1.ProtocolTCP,
2626
})
2727
default:
28-
return defaultPorts[:]
28+
return ports(crd)
2929
}
3030
}
3131

32-
var defaultPorts = [...]corev1.ContainerPort{
33-
{
34-
Name: "api",
35-
Protocol: corev1.ProtocolTCP,
36-
ContainerPort: apiPort,
37-
},
38-
{
39-
Name: "rosetta",
40-
Protocol: corev1.ProtocolTCP,
41-
ContainerPort: rosettaPort,
42-
},
43-
{
44-
Name: "grpc",
45-
Protocol: corev1.ProtocolTCP,
46-
ContainerPort: grpcPort,
47-
},
48-
{
49-
Name: "prometheus",
50-
Protocol: corev1.ProtocolTCP,
51-
ContainerPort: promPort,
52-
},
53-
{
54-
Name: "p2p",
55-
Protocol: corev1.ProtocolTCP,
56-
ContainerPort: p2pPort,
57-
},
58-
{
59-
Name: "rpc",
60-
Protocol: corev1.ProtocolTCP,
61-
ContainerPort: rpcPort,
62-
},
63-
{
64-
Name: "grpc-web",
65-
Protocol: corev1.ProtocolTCP,
66-
ContainerPort: grpcWebPort,
67-
},
32+
func ports(crd *cosmosv1.CosmosFullNode) []corev1.ContainerPort {
33+
return []corev1.ContainerPort{
34+
{
35+
Name: "api",
36+
Protocol: corev1.ProtocolTCP,
37+
ContainerPort: apiPort,
38+
},
39+
{
40+
Name: "rosetta",
41+
Protocol: corev1.ProtocolTCP,
42+
ContainerPort: rosettaPort,
43+
},
44+
{
45+
Name: "grpc",
46+
Protocol: corev1.ProtocolTCP,
47+
ContainerPort: grpcPort,
48+
},
49+
{
50+
Name: "prometheus",
51+
Protocol: corev1.ProtocolTCP,
52+
ContainerPort: promPort,
53+
},
54+
{
55+
Name: "p2p",
56+
Protocol: corev1.ProtocolTCP,
57+
ContainerPort: crd.Spec.ChainSpec.Comet.P2PPort(),
58+
},
59+
{
60+
Name: "rpc",
61+
Protocol: corev1.ProtocolTCP,
62+
ContainerPort: crd.Spec.ChainSpec.Comet.RPCPort(),
63+
},
64+
{
65+
Name: "grpc-web",
66+
Protocol: corev1.ProtocolTCP,
67+
ContainerPort: grpcWebPort,
68+
},
69+
}
6870
}

0 commit comments

Comments
 (0)