Skip to content

Commit 0ab82cf

Browse files
authored
Add initial code for collector service (#30)
* Add initial code for collector service * update makefile to change name * Adding fileserver to read and write from files * Add ability to store snapshots in the file servers * Add snapshot and export capabilities for collector service * Fix collector code * Add collector service and add prestop lifecycle hook to register snapshots * Update gas for hermes * update version of chart
1 parent b35f3f3 commit 0ab82cf

File tree

20 files changed

+1062
-5
lines changed

20 files changed

+1062
-5
lines changed

charts/devnet/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type: application
1515
# This is the chart version. This version number should be incremented each time you make changes
1616
# to the chart and its templates, including the app version.
1717
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18-
version: 0.1.10
18+
version: 0.1.11
1919

2020
# This is the version number of the application being deployed. This version number should be
2121
# incremented each time you make changes to the application. Versions are not expected to
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
3+
CHAIN_ID="${CHAIN_ID:=osmosis-1}"
4+
VAL_NAME="${VAL_NAME:=osmosis}"
5+
CHAIN_DIR="${CHAIN_DIR:=$HOME/.osmosisd}"
6+
COLLECTOR_HOST="${COLLECTOR_HOST}"
7+
8+
set -euxo pipefail
9+
10+
snapshot_name=data_${VAL_NAME}_$(date "+%F-%H-%M-%S")
11+
12+
# Create the snapshot that will be uploaded
13+
function create_snapshot {
14+
tar -czvf /opt/${snapshot_name}.tar.gz $CHAIN_DIR/data
15+
}
16+
17+
# Register the snapshot to the collector service
18+
function register_snapshot {
19+
url=${COLLECTOR_HOST}/chains/${CHAIN_ID}/validators/${VAL_NAME}/snapshots/${snapshot_name}.tar.gz
20+
curl -v -i ${url} -H'Content-Encoding: gzip' -H'Content-TYPE: application/gzip' --data-binary @/opt/${snapshot_name}.tar.gz
21+
}
22+
23+
create_snapshot
24+
register_snapshot

charts/devnet/templates/chain/genesis.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ spec:
109109
env:
110110
{{- include "devnet.defaultEvnVars" $defaultChain | indent 12 }}
111111
{{- include "devnet.evnVars" $chain | indent 12 }}
112+
- name: COLLECTOR_SERVICE
113+
value: collector
114+
- name: COLLECTOR_PORT
115+
value: "8070"
112116
command:
113117
- bash
114118
- "-c"
@@ -124,6 +128,24 @@ spec:
124128
name: node
125129
- mountPath: /configs
126130
name: addresses
131+
- mountPath: /scripts
132+
name: scripts
133+
{{- if $.Values.collector.enabled }}
134+
lifecycle:
135+
preStop:
136+
exec:
137+
command:
138+
- bash
139+
- "-c"
140+
- "-e"
141+
- |
142+
VAL_INDEX=${HOSTNAME##*-}
143+
VAL_NAME=$(jq -r ".genesis[$VAL_INDEX].name" /configs/keys.json)
144+
echo "Validator Index: $VAL_INDEX, Key name: $VAL_NAME"
145+
146+
COLLECTOR_HOST=http://$COLLECTOR_SERVICE.$NAMESPACE.svc.cluster.local:$COLLECTOR_PORT
147+
VAL_NAME=$VAL_NAME COLLECTOR_HOST=$COLLECTOR_HOST bash -e /scripts/register_snapshots.sh
148+
{{- end }}
127149
- name: exposer
128150
image: {{ $.Values.exposer.image }}
129151
imagePullPolicy: Always

charts/devnet/templates/chain/validator.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ spec:
132132
{{- include "devnet.defaultEvnVars" $defaultChain | indent 12 }}
133133
{{- include "devnet.evnVars" $chain | indent 12 }}
134134
{{- include "devnet.genesisVars" $dataExposer | indent 12}}
135+
- name: COLLECTOR_SERVICE
136+
value: collector
137+
- name: COLLECTOR_PORT
138+
value: "8070"
135139
command:
136140
- bash
137141
- "-c"
@@ -158,6 +162,21 @@ spec:
158162
$CHAIN_BIN keys list | jq
159163
160164
VAL_NAME=$VAL_NAME bash -e /scripts/create_validator.sh
165+
{{- if $.Values.collector.enabled }}
166+
preStop:
167+
exec:
168+
command:
169+
- bash
170+
- "-c"
171+
- "-e"
172+
- |
173+
VAL_INDEX=${HOSTNAME##*-}
174+
VAL_NAME=$(jq -r ".validators[$VAL_INDEX].name" /configs/keys.json)
175+
echo "Validator Index: $VAL_INDEX, Key name: $VAL_NAME"
176+
177+
COLLECTOR_HOST=http://$COLLECTOR_SERVICE.$NAMESPACE.svc.cluster.local:$COLLECTOR_PORT
178+
VAL_NAME=$VAL_NAME COLLECTOR_HOST=$COLLECTOR_HOST bash -e /scripts/register_snapshots.sh
179+
{{- end }}
161180
resources: {{- include "devnet.validator.resources" $chain | trim | nindent 12 }}
162181
volumeMounts:
163182
- mountPath: {{ $defaultChain.home }}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{{- if .Values.collector.enabled }}
2+
---
3+
apiVersion: v1
4+
kind: Service
5+
metadata:
6+
name: collector
7+
labels:
8+
app.kubernetes.io/name: collector
9+
spec:
10+
clusterIP: None
11+
ports:
12+
- name: collector
13+
port: 8070
14+
protocol: TCP
15+
targetPort: 8070
16+
selector:
17+
app.kubernetes.io/name: collector
18+
---
19+
apiVersion: apps/v1
20+
kind: Deployment
21+
metadata:
22+
name: collector
23+
spec:
24+
replicas: 1
25+
revisionHistoryLimit: 3
26+
selector:
27+
matchLabels:
28+
app.kubernetes.io/instance: collector
29+
app.kubernetes.io/name: collector
30+
template:
31+
metadata:
32+
annotations:
33+
quality: release
34+
role: api-gateway
35+
sla: high
36+
tier: gateway
37+
labels:
38+
app.kubernetes.io/instance: collector
39+
app.kubernetes.io/type: collector
40+
app.kubernetes.io/name: collector
41+
app.kubernetes.io/version: {{ $.Chart.AppVersion }}
42+
spec:
43+
containers:
44+
- name: collector
45+
image: {{ .Values.collector.image }}
46+
imagePullPolicy: Always
47+
env:
48+
- name: COLLECTOR_ADDR
49+
value: ":8070"
50+
- name: COLLECTOR_DIR_PATH
51+
value: /opt/collector
52+
command: [ "collector" ]
53+
resources:
54+
limits:
55+
cpu: "1"
56+
memory: 4Gi
57+
requests:
58+
cpu: "0.5"
59+
memory: 2Gi
60+
volumeMounts:
61+
- mountPath: /opt/collector
62+
name: collector
63+
readinessProbe:
64+
tcpSocket:
65+
port: 8070
66+
initialDelaySeconds: 60
67+
periodSeconds: 30
68+
livenessProbe:
69+
tcpSocket:
70+
port: 8070
71+
initialDelaySeconds: 60
72+
periodSeconds: 30
73+
volumes:
74+
- name: collector
75+
emptyDir: {}
76+
---
77+
{{- end }}

charts/devnet/templates/relayers/hermes/configmap.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ data:
8989
websocket_addr = "ws://{{ $chain }}-genesis.{{ $.Release.Namespace }}.svc.cluster.local:26657/websocket"
9090
{{- with index $.Values.defaultChains $fullchain.type }}
9191
account_prefix = "{{ .prefix }}"
92-
gas_price = { price = 0.025, denom = "{{ .denom }}" }
92+
gas_price = { price = 0.25, denom = "{{ .denom }}" }
9393
{{- end }}
94-
default_gas = 50000000
95-
max_gas = 100000000
94+
default_gas = 500000000
95+
max_gas = 1000000000
9696
rpc_timeout = "10s"
9797
store_prefix = "ibc"
9898
gas_multiplier = 1.5

charts/devnet/values.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,10 @@ chainRegistry:
187187
image: anmol1696/chain-registry
188188
ports:
189189
rest: 8090
190+
191+
collector:
192+
enabled: false
193+
image: anmol1696/collector:latest
194+
localhost: true
195+
ports:
196+
rest: 8070

collector/Dockerfile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
FROM golang:1.19-alpine AS build-env
2+
3+
# Set up dependencies
4+
ENV PACKAGES curl make git libc-dev bash gcc linux-headers
5+
6+
# Set working directory for the build
7+
WORKDIR /usr/local/share/app
8+
9+
# Add source files
10+
COPY . .
11+
12+
# Install minimum necessary dependencies, build Cosmos SDK, remove packages
13+
RUN apk add --no-cache $PACKAGES && go build -mod readonly -o collector ./...
14+
15+
# Final image
16+
FROM alpine:3.16
17+
18+
# Install ca-certificates
19+
RUN apk add --update ca-certificates jq bash curl
20+
WORKDIR /usr/local/share/app
21+
22+
RUN ls /usr/bin
23+
24+
# Copy over binaries from the build-env
25+
COPY --from=build-env /usr/local/share/app/collector /usr/bin/collector
26+
27+
EXPOSE 8081

collector/Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
DOCKER := $(shell which docker)
2+
DOCKER_REPO_NAME := anmol1696
3+
DOCKER_IMAGE := collector
4+
DOCKER_TAG_NAME := latest
5+
6+
DOCKER_ARGS += --platform linux/amd64
7+
8+
docker-build:
9+
$(DOCKER) buildx build $(DOCKER_ARGS) \
10+
-t $(DOCKER_REPO_NAME)/$(DOCKER_IMAGE):$(DOCKER_TAG_NAME) .
11+
12+
docker-build-push: docker-build
13+
$(DOCKER) push $(DOCKER_REPO_NAME)/$(DOCKER_IMAGE):$(DOCKER_TAG_NAME)
14+
15+
docker-run:
16+
$(DOCKER) run --rm -it --entrypoint /bin/bash $(DOCKER_REPO_NAME)/$(DOCKER_IMAGE):$(DOCKER_TAG_NAME)

collector/app.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"time"
7+
8+
"github.com/go-chi/chi"
9+
"github.com/go-chi/chi/middleware"
10+
"github.com/go-chi/render"
11+
"go.uber.org/zap"
12+
)
13+
14+
type AppServer struct {
15+
config *Config
16+
db *FileDB
17+
logger *zap.Logger
18+
server *http.Server
19+
router http.Handler
20+
}
21+
22+
func NewAppServer(config *Config) (*AppServer, error) {
23+
log, err := NewLogger(config)
24+
if err != nil {
25+
return nil, err
26+
}
27+
log.Info(
28+
"Starting the service",
29+
zap.String("prog", Prog),
30+
zap.String("version", Version),
31+
zap.Any("config", config),
32+
)
33+
34+
app := &AppServer{
35+
config: config,
36+
logger: log,
37+
db: NewFileDB(log, config.DirPath),
38+
}
39+
40+
// Setup routes
41+
router, err := app.Router()
42+
if err != nil {
43+
log.Error("Error setting up routes", zap.Error(err))
44+
return nil, err
45+
}
46+
app.router = router
47+
48+
return app, err
49+
}
50+
51+
func (a *AppServer) Router() (*chi.Mux, error) {
52+
router := chi.NewRouter()
53+
router.MethodNotAllowed(MethodNotAllowed)
54+
router.NotFound(NotFound)
55+
56+
// Set middleware
57+
router.Use(a.panicRecovery)
58+
router.Use(render.SetContentType(render.ContentTypeJSON))
59+
60+
// Setup routes
61+
// handler of export states
62+
router.Get("/chains", a.GetChains)
63+
router.Route("/chains/{chain}/validators/{validator}", func(r chi.Router) {
64+
r.Get("/exports", a.GetChainExports)
65+
r.Get("/exports/{id}", a.GetChainExport)
66+
r.Post("/exports/{id}", a.SetChainExport)
67+
r.Get("/snapshots", a.GetChainSnapshots)
68+
r.Get("/snapshots/{id}", a.GetChainSnapshot)
69+
r.Post("/snapshots/{id}", a.SetChainSnapshot)
70+
})
71+
72+
return router, nil
73+
}
74+
75+
func (a *AppServer) loggingMiddleware(next http.Handler) http.Handler {
76+
fn := func(w http.ResponseWriter, r *http.Request) {
77+
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
78+
start := time.Now()
79+
defer func() {
80+
a.logger.Info("client request",
81+
zap.Duration("latency", time.Since(start)),
82+
zap.Int("status", ww.Status()),
83+
zap.Int("bytes", ww.BytesWritten()),
84+
zap.String("client_ip", r.RemoteAddr),
85+
zap.String("method", r.Method),
86+
zap.String("path", r.URL.Path),
87+
zap.String("request-id", middleware.GetReqID(r.Context())))
88+
}()
89+
90+
next.ServeHTTP(ww, r)
91+
}
92+
return http.HandlerFunc(fn)
93+
}
94+
95+
func (a *AppServer) panicRecovery(next http.Handler) http.Handler {
96+
fn := func(w http.ResponseWriter, r *http.Request) {
97+
defer func() {
98+
if rc := recover(); rc != nil {
99+
err, ok := rc.(error)
100+
if !ok {
101+
err = fmt.Errorf("panic: %v", rc)
102+
}
103+
a.logger.Error("panic error",
104+
zap.String("request-id", middleware.GetReqID(r.Context())),
105+
zap.Error(err))
106+
107+
render.Render(w, r, ErrInternalServer)
108+
return
109+
}
110+
}()
111+
next.ServeHTTP(w, r)
112+
}
113+
return http.HandlerFunc(fn)
114+
}
115+
116+
func (a *AppServer) Run() error {
117+
a.logger.Info("App starting", zap.Any("Config", a.config))
118+
119+
// Setup server
120+
server := &http.Server{
121+
Addr: a.config.Addr,
122+
Handler: a.router,
123+
}
124+
a.server = server
125+
126+
// Start http server as long-running go routine
127+
go func() {
128+
if err := server.ListenAndServe(); err != nil {
129+
a.logger.Error("failed to start the App HTTP server", zap.Error(err))
130+
}
131+
}()
132+
133+
return nil
134+
}

0 commit comments

Comments
 (0)