mirror of
https://github.com/stefanprodan/podinfo.git
synced 2026-04-07 03:26:54 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
357009a863 | ||
|
|
0f98770296 | ||
|
|
f9032836a6 | ||
|
|
5368c3fe10 | ||
|
|
b1207aa9b1 | ||
|
|
c7f9b521fa | ||
|
|
24405a5a5d | ||
|
|
5195b158fc | ||
|
|
532db405f8 | ||
|
|
2251bee699 | ||
|
|
8535efccb7 | ||
|
|
e008d1f261 | ||
|
|
22097353d2 | ||
|
|
c305843105 | ||
|
|
0d2c428859 | ||
|
|
ecaa7cf4d3 | ||
|
|
8447b6985b | ||
|
|
9371d6d153 | ||
|
|
20b8c1043c | ||
|
|
2d80c7a22d | ||
|
|
dc830d02a6 | ||
|
|
badf3271a1 | ||
|
|
9f9c2f3245 | ||
|
|
174d183056 | ||
|
|
7bb64e7567 | ||
|
|
49a4b31d53 | ||
|
|
c29e013a33 | ||
|
|
45ecda63bb | ||
|
|
4868f430c7 | ||
|
|
ca9c6bb4f8 | ||
|
|
86f3b1a57c | ||
|
|
b22dd96a54 | ||
|
|
5aaf95849e | ||
|
|
e197eca420 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github: stefanprodan
|
||||
4
.github/workflows/cve-scan.yml
vendored
4
.github/workflows/cve-scan.yml
vendored
@@ -3,7 +3,7 @@ name: cve-scan
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- "master"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
run: |
|
||||
IMAGE=test/podinfo:${GITHUB_SHA}
|
||||
docker build -t ${IMAGE} .
|
||||
echo "::set-output name=image::$IMAGE"
|
||||
echo "image=$IMAGE" >> $GITHUB_OUTPUT
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
|
||||
23
.github/workflows/release.yml
vendored
23
.github/workflows/release.yml
vendored
@@ -20,6 +20,18 @@ jobs:
|
||||
- uses: sigstore/cosign-installer@v3
|
||||
- uses: fluxcd/flux2/action@main
|
||||
- uses: stefanprodan/timoni/actions/setup@main
|
||||
- name: Setup Notation CLI
|
||||
uses: notaryproject/notation-action/setup@v1
|
||||
with:
|
||||
version: "1.1.0"
|
||||
- name: Setup Notation signing keys
|
||||
run: |
|
||||
mkdir -p ~/.config/notation/localkeys/
|
||||
cp ./.notation/signingkeys.json ~/.config/notation/
|
||||
cp ./.notation/notation.crt ~/.config/notation/localkeys/
|
||||
echo "$NOTATION_KEY" > ~/.config/notation/localkeys/notation.key
|
||||
env:
|
||||
NOTATION_KEY: ${{ secrets.NOTATION_SIGNING_KEY }}
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
@@ -101,7 +113,7 @@ jobs:
|
||||
--source="${{ github.event.repository.html_url }}" \
|
||||
--revision="${GITHUB_REF_NAME}/${GITHUB_SHA}"
|
||||
flux tag artifact oci://ghcr.io/stefanprodan/manifests/podinfo:${{ steps.prep.outputs.VERSION }} --tag latest
|
||||
- name: Sign OCI artifacts
|
||||
- name: Sign artifacts with Cosign
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
run: |
|
||||
@@ -129,7 +141,7 @@ jobs:
|
||||
--source="${{ github.event.repository.html_url }}" \
|
||||
--revision="${GITHUB_REF_NAME}/${GITHUB_SHA}"
|
||||
flux tag artifact oci://ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }} --tag latest
|
||||
- name: Sign config artifact
|
||||
- name: Sign config artifact with cso
|
||||
run: |
|
||||
echo "$COSIGN_KEY" > /tmp/cosign.key
|
||||
cosign sign -key /tmp/cosign.key ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }} --yes
|
||||
@@ -137,6 +149,13 @@ jobs:
|
||||
env:
|
||||
COSIGN_PASSWORD: ${{secrets.COSIGN_PASSWORD}}
|
||||
COSIGN_KEY: ${{secrets.COSIGN_KEY}}
|
||||
- name: Sign artifacts with Notation
|
||||
run: |
|
||||
notation sign --signature-format cose ghcr.io/stefanprodan/podinfo:${{ steps.prep.outputs.VERSION }}
|
||||
notation sign --signature-format cose ghcr.io/stefanprodan/charts/podinfo:${{ steps.prep.outputs.VERSION }}
|
||||
notation sign --signature-format cose ghcr.io/stefanprodan/manifests/podinfo:${{ steps.prep.outputs.VERSION }}
|
||||
notation sign --signature-format cose ghcr.io/stefanprodan/podinfo-deploy:${{ steps.prep.outputs.VERSION }}
|
||||
notation sign --signature-format cose ghcr.io/stefanprodan/podinfo-deploy:latest
|
||||
- uses: ./.github/actions/release-notes
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -23,3 +23,6 @@ bin/
|
||||
cue/cue.mod/gen/
|
||||
cue/go.mod
|
||||
cue/go.sum
|
||||
|
||||
.notation/podinfo.csr
|
||||
.notation/podinfo.key
|
||||
|
||||
15
.notation/README.md
Normal file
15
.notation/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Podinfo signed releases
|
||||
|
||||
Podinfo release assets such as the Helm chart and the Flux artifact
|
||||
are published to GitHub Container Registry and are signed with
|
||||
[Notation](https://github.com/notaryproject/notation).
|
||||
|
||||
## Generate signing keys
|
||||
|
||||
Generate a new signing key pair:
|
||||
|
||||
```sh
|
||||
openssl genrsa -out podinfo.key 2048
|
||||
openssl req -new -key podinfo.key -out podinfo.csr -config codesign.cnf
|
||||
openssl x509 -req -days 1826 -in podinfo.csr -signkey podinfo.key -out notation.crt -extensions v3_req -extfile codesign.cnf
|
||||
```
|
||||
18
.notation/codesign.cnf
Normal file
18
.notation/codesign.cnf
Normal file
@@ -0,0 +1,18 @@
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = privatekey.pem
|
||||
distinguished_name = req_distinguished_name
|
||||
req_extensions = v3_req
|
||||
prompt = no
|
||||
|
||||
[ req_distinguished_name ]
|
||||
C = RO
|
||||
ST = BU
|
||||
L = Bucharest
|
||||
O = Notary
|
||||
CN = stefanprodan.com
|
||||
|
||||
[ v3_req ]
|
||||
keyUsage = critical,digitalSignature
|
||||
extendedKeyUsage = critical,codeSigning
|
||||
#subjectKeyIdentifier = hash
|
||||
21
.notation/notation.crt
Normal file
21
.notation/notation.crt
Normal file
@@ -0,0 +1,21 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDbDCCAlSgAwIBAgIUP7zhmTw5XTWLcgBGkBEsErMOkz4wDQYJKoZIhvcNAQEL
|
||||
BQAwWjELMAkGA1UEBhMCUk8xCzAJBgNVBAgMAkJVMRIwEAYDVQQHDAlCdWNoYXJl
|
||||
c3QxDzANBgNVBAoMBk5vdGFyeTEZMBcGA1UEAwwQc3RlZmFucHJvZGFuLmNvbTAe
|
||||
Fw0yNDAyMjUxMDAyMzZaFw0yOTAyMjQxMDAyMzZaMFoxCzAJBgNVBAYTAlJPMQsw
|
||||
CQYDVQQIDAJCVTESMBAGA1UEBwwJQnVjaGFyZXN0MQ8wDQYDVQQKDAZOb3Rhcnkx
|
||||
GTAXBgNVBAMMEHN0ZWZhbnByb2Rhbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
|
||||
DwAwggEKAoIBAQDtH4oPi3SyX/DGv6NdjIvmApvD9eeSgsmHdwpAly8T9D2me+fx
|
||||
Z+wRNJmq4aq/A1anX+Sg28iwHzV+1WKpsHnjYzDAJSEYP2S8A5H1nGRKUoibdijw
|
||||
C3QBh5C75rjF/tmZVSX/Vgbf3HJJEsF4WUxWabLxoV2QLo7UlEsQd9+bSeKNMncx
|
||||
1+E6FdbRCrYo90iobvZJ8K/S2zCWq/JTeHfTnmSEDhx6nMJcaSjvMPn3zyauWcQw
|
||||
dDpkcaGiJ64fEJRT2OFxXv9u+vDmIMKzo/Wjbd+IzFj6YY4VisK88aU7tmDelnk5
|
||||
gQB9eu62PFoaVsYJp4VOhblFKvGJpQwbWB9BAgMBAAGjKjAoMA4GA1UdDwEB/wQE
|
||||
AwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||
6x+C6hAIbLwMvkNx4K5p7Qe/pLQR0VwQFAw10yr/5KSN+YKFpon6pQ0TebL7qll+
|
||||
uBGZvtQhN6v+DlnVqB7lvJKd+89isgirkkews5KwuXg7Gv5UPIugH0dXISZU8DMJ
|
||||
7J4oKREv5HzdFmfsUfNlQcfyVTjKL6UINXfKGdqNNxXxR9b4a1TY2JcmEhzBTHaq
|
||||
ZqX6HK784a0dB7aHgeFrFwPCCP4M684Hs7CFbk3jo2Ef4ljnB5AyWpe8pwCLMdRt
|
||||
UjSjL5xJWVQvRU+STQsPr6SvpokPCG4rLQyjgeYYk4CCj5piSxbSUZFavq8v1y7Y
|
||||
m91USVqfeUX7ZzjDxPHE2A==
|
||||
-----END CERTIFICATE-----
|
||||
10
.notation/signingkeys.json
Normal file
10
.notation/signingkeys.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"default": "stefanprodan.com",
|
||||
"keys": [
|
||||
{
|
||||
"name": "stefanprodan.com",
|
||||
"keyPath": "/home/runner/.config/notation/localkeys/notation.key",
|
||||
"certPath": "/home/runner/.config/notation/localkeys/notation.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
19
.notation/trustpolicy.json
Normal file
19
.notation/trustpolicy.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"trustPolicies": [
|
||||
{
|
||||
"name": "stefanprodan.com",
|
||||
"registryScopes": [
|
||||
"ghcr.io/stefanprodan/podinfo-deploy",
|
||||
"ghcr.io/stefanprodan/charts/podinfo"
|
||||
],
|
||||
"signatureVerification": {
|
||||
"level" : "strict"
|
||||
},
|
||||
"trustStores": [ "ca:stefanprodan.com" ],
|
||||
"trustedIdentities": [
|
||||
"x509.subject: C=RO, ST=BU, L=Bucharest, O=Notary, CN=stefanprodan.com"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -57,6 +57,8 @@ Web API:
|
||||
gRPC API:
|
||||
|
||||
* `/grpc.health.v1.Health/Check` health checking
|
||||
* `/grpc.EchoService/Echo` echos the received content
|
||||
* `/grpc.VersionService/Version` returns podinfo version and Git commit hash
|
||||
|
||||
Web UI:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
apiVersion: v1
|
||||
version: 6.5.4
|
||||
appVersion: 6.5.4
|
||||
version: 6.6.0
|
||||
appVersion: 6.6.0
|
||||
name: podinfo
|
||||
engine: gotpl
|
||||
description: Podinfo Helm chart for Kubernetes
|
||||
|
||||
@@ -8,7 +8,7 @@ backends: []
|
||||
|
||||
image:
|
||||
repository: ghcr.io/stefanprodan/podinfo
|
||||
tag: 6.5.4
|
||||
tag: 6.6.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
ui:
|
||||
|
||||
@@ -8,7 +8,7 @@ backends: []
|
||||
|
||||
image:
|
||||
repository: ghcr.io/stefanprodan/podinfo
|
||||
tag: 6.5.4
|
||||
tag: 6.6.0
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
ui:
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
|
||||
"github.com/stefanprodan/podinfo/pkg/api"
|
||||
"github.com/stefanprodan/podinfo/pkg/grpc"
|
||||
"github.com/stefanprodan/podinfo/pkg/api/grpc"
|
||||
"github.com/stefanprodan/podinfo/pkg/api/http"
|
||||
"github.com/stefanprodan/podinfo/pkg/signals"
|
||||
"github.com/stefanprodan/podinfo/pkg/version"
|
||||
go_grpc "google.golang.org/grpc"
|
||||
@@ -138,11 +138,13 @@ func main() {
|
||||
var grpcServer *go_grpc.Server
|
||||
if grpcCfg.Port > 0 {
|
||||
grpcSrv, _ := grpc.NewServer(&grpcCfg, logger)
|
||||
//grpcinfoSrv, _ := grpc.NewInfoServer(&grpcCfg)
|
||||
|
||||
grpcServer = grpcSrv.ListenAndServe()
|
||||
}
|
||||
|
||||
// load HTTP server config
|
||||
var srvCfg api.Config
|
||||
var srvCfg http.Config
|
||||
if err := viper.Unmarshal(&srvCfg); err != nil {
|
||||
logger.Panic("config unmarshal failed", zap.Error(err))
|
||||
}
|
||||
@@ -155,7 +157,7 @@ func main() {
|
||||
)
|
||||
|
||||
// start HTTP server
|
||||
srv, _ := api.NewServer(&srvCfg, logger)
|
||||
srv, _ := http.NewServer(&srvCfg, logger)
|
||||
httpServer, httpsServer, healthy, ready := srv.ListenAndServe()
|
||||
|
||||
// graceful shutdown
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.5.4
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.5.4
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -25,7 +25,7 @@ spec:
|
||||
serviceAccountName: webapp
|
||||
containers:
|
||||
- name: backend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.5.4
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -25,7 +25,7 @@ spec:
|
||||
serviceAccountName: webapp
|
||||
containers:
|
||||
- name: frontend
|
||||
image: ghcr.io/stefanprodan/podinfo:6.5.4
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: podinfod
|
||||
image: ghcr.io/stefanprodan/podinfo:6.5.4
|
||||
image: ghcr.io/stefanprodan/podinfo:6.6.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
@@ -72,3 +72,9 @@ spec:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
volumes:
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
|
||||
20
pkg/api/grpc/echo.go
Normal file
20
pkg/api/grpc/echo.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/stefanprodan/podinfo/pkg/api/grpc/echo"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type echoServer struct {
|
||||
echo.UnimplementedEchoServiceServer
|
||||
config *Config
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (s *echoServer) Echo (ctx context.Context, message *echo.Message) (*echo.Message, error){
|
||||
|
||||
s.logger.Info("Received message body from client:", zap.String("input body", message.Body))
|
||||
return &echo.Message {Body: message.Body}, nil
|
||||
}
|
||||
146
pkg/api/grpc/echo/echo.pb.go
Normal file
146
pkg/api/grpc/echo/echo.pb.go
Normal file
@@ -0,0 +1,146 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v4.24.3
|
||||
// source: echo/echo.proto
|
||||
|
||||
package echo
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Body string `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Message) Reset() {
|
||||
*x = Message{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_echo_echo_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Message) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Message) ProtoMessage() {}
|
||||
|
||||
func (x *Message) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_echo_echo_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Message.ProtoReflect.Descriptor instead.
|
||||
func (*Message) Descriptor() ([]byte, []int) {
|
||||
return file_echo_echo_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Message) GetBody() string {
|
||||
if x != nil {
|
||||
return x.Body
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_echo_echo_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_echo_echo_proto_rawDesc = []byte{
|
||||
0x0a, 0x0f, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x12, 0x04, 0x65, 0x63, 0x68, 0x6f, 0x22, 0x1d, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x32, 0x35, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x0d, 0x2e,
|
||||
0x65, 0x63, 0x68, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0d, 0x2e, 0x65,
|
||||
0x63, 0x68, 0x6f, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a,
|
||||
0x06, 0x2e, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_echo_echo_proto_rawDescOnce sync.Once
|
||||
file_echo_echo_proto_rawDescData = file_echo_echo_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_echo_echo_proto_rawDescGZIP() []byte {
|
||||
file_echo_echo_proto_rawDescOnce.Do(func() {
|
||||
file_echo_echo_proto_rawDescData = protoimpl.X.CompressGZIP(file_echo_echo_proto_rawDescData)
|
||||
})
|
||||
return file_echo_echo_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_echo_echo_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_echo_echo_proto_goTypes = []interface{}{
|
||||
(*Message)(nil), // 0: echo.Message
|
||||
}
|
||||
var file_echo_echo_proto_depIdxs = []int32{
|
||||
0, // 0: echo.EchoService.Echo:input_type -> echo.Message
|
||||
0, // 1: echo.EchoService.Echo:output_type -> echo.Message
|
||||
1, // [1:2] is the sub-list for method output_type
|
||||
0, // [0:1] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_echo_echo_proto_init() }
|
||||
func file_echo_echo_proto_init() {
|
||||
if File_echo_echo_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_echo_echo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Message); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_echo_echo_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_echo_echo_proto_goTypes,
|
||||
DependencyIndexes: file_echo_echo_proto_depIdxs,
|
||||
MessageInfos: file_echo_echo_proto_msgTypes,
|
||||
}.Build()
|
||||
File_echo_echo_proto = out.File
|
||||
file_echo_echo_proto_rawDesc = nil
|
||||
file_echo_echo_proto_goTypes = nil
|
||||
file_echo_echo_proto_depIdxs = nil
|
||||
}
|
||||
14
pkg/api/grpc/echo/echo.proto
Normal file
14
pkg/api/grpc/echo/echo.proto
Normal file
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "./echo";
|
||||
|
||||
package echo;
|
||||
|
||||
message Message {
|
||||
string body = 1;
|
||||
}
|
||||
|
||||
|
||||
service EchoService {
|
||||
rpc Echo(Message) returns (Message) {}
|
||||
}
|
||||
109
pkg/api/grpc/echo/echo_grpc.pb.go
Normal file
109
pkg/api/grpc/echo/echo_grpc.pb.go
Normal file
@@ -0,0 +1,109 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.24.3
|
||||
// source: echo/echo.proto
|
||||
|
||||
package echo
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
EchoService_Echo_FullMethodName = "/echo.EchoService/Echo"
|
||||
)
|
||||
|
||||
// EchoServiceClient is the client API for EchoService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type EchoServiceClient interface {
|
||||
Echo(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error)
|
||||
}
|
||||
|
||||
type echoServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewEchoServiceClient(cc grpc.ClientConnInterface) EchoServiceClient {
|
||||
return &echoServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *echoServiceClient) Echo(ctx context.Context, in *Message, opts ...grpc.CallOption) (*Message, error) {
|
||||
out := new(Message)
|
||||
err := c.cc.Invoke(ctx, EchoService_Echo_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// EchoServiceServer is the server API for EchoService service.
|
||||
// All implementations must embed UnimplementedEchoServiceServer
|
||||
// for forward compatibility
|
||||
type EchoServiceServer interface {
|
||||
Echo(context.Context, *Message) (*Message, error)
|
||||
mustEmbedUnimplementedEchoServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedEchoServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedEchoServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedEchoServiceServer) Echo(context.Context, *Message) (*Message, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Echo not implemented")
|
||||
}
|
||||
func (UnimplementedEchoServiceServer) mustEmbedUnimplementedEchoServiceServer() {}
|
||||
|
||||
// UnsafeEchoServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to EchoServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeEchoServiceServer interface {
|
||||
mustEmbedUnimplementedEchoServiceServer()
|
||||
}
|
||||
|
||||
func RegisterEchoServiceServer(s grpc.ServiceRegistrar, srv EchoServiceServer) {
|
||||
s.RegisterService(&EchoService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _EchoService_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Message)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(EchoServiceServer).Echo(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: EchoService_Echo_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(EchoServiceServer).Echo(ctx, req.(*Message))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// EchoService_ServiceDesc is the grpc.ServiceDesc for EchoService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var EchoService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "echo.EchoService",
|
||||
HandlerType: (*EchoServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Echo",
|
||||
Handler: _EchoService_Echo_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "echo/echo.proto",
|
||||
}
|
||||
70
pkg/api/grpc/echo_test.go
Normal file
70
pkg/api/grpc/echo_test.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stefanprodan/podinfo/pkg/api/grpc/echo"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/grpc/test/bufconn"
|
||||
)
|
||||
|
||||
func TestGrpcEcho(t *testing.T) {
|
||||
|
||||
// Server initialization
|
||||
// bufconn => uses in-memory connection instead of system network I/O
|
||||
lis := bufconn.Listen(1024*1024)
|
||||
t.Cleanup(func() {
|
||||
lis.Close()
|
||||
})
|
||||
|
||||
s := NewMockGrpcServer()
|
||||
srv := grpc.NewServer()
|
||||
t.Cleanup(func() {
|
||||
srv.Stop()
|
||||
})
|
||||
|
||||
echo.RegisterEchoServiceServer(srv, &echoServer{config: s.config, logger: s.logger})
|
||||
|
||||
go func(){
|
||||
if err := srv.Serve(lis); err != nil {
|
||||
log.Fatalf("srv.Serve %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// - Test
|
||||
dialer := func(context.Context, string) (net.Conn, error){
|
||||
return lis.Dial()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
conn, err := grpc.DialContext(ctx, "", grpc.WithContextDialer(dialer), grpc.WithInsecure())
|
||||
t.Cleanup(func() {
|
||||
conn.Close()
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("grpc.DialContext %v", err)
|
||||
}
|
||||
|
||||
client := echo.NewEchoServiceClient(conn)
|
||||
res , err := client.Echo(context.Background(), &echo.Message{Body:"test123-test"})
|
||||
|
||||
// Check the status code is what we expect.
|
||||
if _, ok := status.FromError(err); !ok {
|
||||
t.Errorf("Echo returned type %T, want %T", err, status.Error)
|
||||
}
|
||||
|
||||
// Check the response body is what we expect.
|
||||
expected := ".*body.*test123-test.*"
|
||||
r := regexp.MustCompile(expected)
|
||||
if !r.MatchString(res.String()) {
|
||||
t.Fatalf("Returned unexpected body:\ngot \n%v \nwant \n%s",
|
||||
res, expected)
|
||||
}
|
||||
}
|
||||
31
pkg/api/grpc/mock_grpc.go
Normal file
31
pkg/api/grpc/mock_grpc.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
||||
func NewMockGrpcServer() *Server {
|
||||
config := &Config{
|
||||
Port: 9999,
|
||||
// ServerShutdownTimeout: 5 * time.Second,
|
||||
// HttpServerTimeout: 30 * time.Second,
|
||||
BackendURL: []string{},
|
||||
ConfigPath: "/config",
|
||||
DataPath: "/data",
|
||||
// HttpClientTimeout: 30 * time.Second,
|
||||
UIColor: "blue",
|
||||
UIPath: ".ui",
|
||||
UIMessage: "Greetings",
|
||||
Hostname: "localhost",
|
||||
}
|
||||
|
||||
logger, _ := zap.NewDevelopment()
|
||||
|
||||
return &Server{
|
||||
//router: mux.NewRouter(),
|
||||
logger: logger,
|
||||
config: config,
|
||||
//tracer: trace.NewNoopTracerProvider().Tracer("mock"),
|
||||
}
|
||||
}
|
||||
24
pkg/api/grpc/panic.go
Normal file
24
pkg/api/grpc/panic.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
// "log"
|
||||
"os"
|
||||
|
||||
pb "github.com/stefanprodan/podinfo/pkg/api/grpc/panic"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type PanicServer struct {
|
||||
pb.UnimplementedPanicServiceServer
|
||||
config *Config
|
||||
logger *zap.Logger
|
||||
|
||||
}
|
||||
|
||||
func (s *PanicServer) Panic(ctx context.Context, req *pb.PanicRequest) (*pb.PanicResponse, error) {
|
||||
s.logger.Info("Panic command received")
|
||||
os.Exit(225)
|
||||
return &pb.PanicResponse{}, nil
|
||||
}
|
||||
|
||||
189
pkg/api/grpc/panic/panic.pb.go
Normal file
189
pkg/api/grpc/panic/panic.pb.go
Normal file
@@ -0,0 +1,189 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.6.1
|
||||
// source: panic.proto
|
||||
|
||||
package panic
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type PanicRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *PanicRequest) Reset() {
|
||||
*x = PanicRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_panic_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *PanicRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PanicRequest) ProtoMessage() {}
|
||||
|
||||
func (x *PanicRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_panic_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PanicRequest.ProtoReflect.Descriptor instead.
|
||||
func (*PanicRequest) Descriptor() ([]byte, []int) {
|
||||
return file_panic_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type PanicResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *PanicResponse) Reset() {
|
||||
*x = PanicResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_panic_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *PanicResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PanicResponse) ProtoMessage() {}
|
||||
|
||||
func (x *PanicResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_panic_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PanicResponse.ProtoReflect.Descriptor instead.
|
||||
func (*PanicResponse) Descriptor() ([]byte, []int) {
|
||||
return file_panic_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
var File_panic_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_panic_proto_rawDesc = []byte{
|
||||
0x0a, 0x0b, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70,
|
||||
0x61, 0x6e, 0x69, 0x63, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x44, 0x0a, 0x0c, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x12, 0x13,
|
||||
0x2e, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x2e, 0x50, 0x61, 0x6e, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x2e, 0x50, 0x61, 0x6e, 0x69,
|
||||
0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x09, 0x5a, 0x07, 0x2e,
|
||||
0x2f, 0x70, 0x61, 0x6e, 0x69, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_panic_proto_rawDescOnce sync.Once
|
||||
file_panic_proto_rawDescData = file_panic_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_panic_proto_rawDescGZIP() []byte {
|
||||
file_panic_proto_rawDescOnce.Do(func() {
|
||||
file_panic_proto_rawDescData = protoimpl.X.CompressGZIP(file_panic_proto_rawDescData)
|
||||
})
|
||||
return file_panic_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_panic_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_panic_proto_goTypes = []interface{}{
|
||||
(*PanicRequest)(nil), // 0: panic.PanicRequest
|
||||
(*PanicResponse)(nil), // 1: panic.PanicResponse
|
||||
}
|
||||
var file_panic_proto_depIdxs = []int32{
|
||||
0, // 0: panic.PanicService.Panic:input_type -> panic.PanicRequest
|
||||
1, // 1: panic.PanicService.Panic:output_type -> panic.PanicResponse
|
||||
1, // [1:2] is the sub-list for method output_type
|
||||
0, // [0:1] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_panic_proto_init() }
|
||||
func file_panic_proto_init() {
|
||||
if File_panic_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_panic_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*PanicRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_panic_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*PanicResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_panic_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_panic_proto_goTypes,
|
||||
DependencyIndexes: file_panic_proto_depIdxs,
|
||||
MessageInfos: file_panic_proto_msgTypes,
|
||||
}.Build()
|
||||
File_panic_proto = out.File
|
||||
file_panic_proto_rawDesc = nil
|
||||
file_panic_proto_goTypes = nil
|
||||
file_panic_proto_depIdxs = nil
|
||||
}
|
||||
17
pkg/api/grpc/panic/panic.proto
Normal file
17
pkg/api/grpc/panic/panic.proto
Normal file
@@ -0,0 +1,17 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "./panic";
|
||||
|
||||
package panic;
|
||||
|
||||
// The greeting service definition.
|
||||
service PanicService {
|
||||
rpc Panic (PanicRequest) returns (PanicResponse) {}
|
||||
}
|
||||
|
||||
message PanicRequest {
|
||||
}
|
||||
|
||||
message PanicResponse {
|
||||
}
|
||||
|
||||
105
pkg/api/grpc/panic/panic_grpc.pb.go
Normal file
105
pkg/api/grpc/panic/panic_grpc.pb.go
Normal file
@@ -0,0 +1,105 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.6.1
|
||||
// source: panic.proto
|
||||
|
||||
package panic
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// PanicServiceClient is the client API for PanicService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type PanicServiceClient interface {
|
||||
Panic(ctx context.Context, in *PanicRequest, opts ...grpc.CallOption) (*PanicResponse, error)
|
||||
}
|
||||
|
||||
type panicServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewPanicServiceClient(cc grpc.ClientConnInterface) PanicServiceClient {
|
||||
return &panicServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *panicServiceClient) Panic(ctx context.Context, in *PanicRequest, opts ...grpc.CallOption) (*PanicResponse, error) {
|
||||
out := new(PanicResponse)
|
||||
err := c.cc.Invoke(ctx, "/panic.PanicService/Panic", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// PanicServiceServer is the server API for PanicService service.
|
||||
// All implementations must embed UnimplementedPanicServiceServer
|
||||
// for forward compatibility
|
||||
type PanicServiceServer interface {
|
||||
Panic(context.Context, *PanicRequest) (*PanicResponse, error)
|
||||
mustEmbedUnimplementedPanicServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedPanicServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedPanicServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedPanicServiceServer) Panic(context.Context, *PanicRequest) (*PanicResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Panic not implemented")
|
||||
}
|
||||
func (UnimplementedPanicServiceServer) mustEmbedUnimplementedPanicServiceServer() {}
|
||||
|
||||
// UnsafePanicServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to PanicServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafePanicServiceServer interface {
|
||||
mustEmbedUnimplementedPanicServiceServer()
|
||||
}
|
||||
|
||||
func RegisterPanicServiceServer(s grpc.ServiceRegistrar, srv PanicServiceServer) {
|
||||
s.RegisterService(&PanicService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _PanicService_Panic_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(PanicRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(PanicServiceServer).Panic(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/panic.PanicService/Panic",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(PanicServiceServer).Panic(ctx, req.(*PanicRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// PanicService_ServiceDesc is the grpc.ServiceDesc for PanicService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var PanicService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "panic.PanicService",
|
||||
HandlerType: (*PanicServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Panic",
|
||||
Handler: _PanicService_Panic_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "panic.proto",
|
||||
}
|
||||
93
pkg/api/grpc/server.go
Normal file
93
pkg/api/grpc/server.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/stefanprodan/podinfo/pkg/api/grpc/echo"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/health"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
"google.golang.org/grpc/reflection"
|
||||
|
||||
"github.com/stefanprodan/podinfo/pkg/api/grpc/panic"
|
||||
"github.com/stefanprodan/podinfo/pkg/api/grpc/version"
|
||||
)
|
||||
|
||||
|
||||
type Server struct {
|
||||
logger *zap.Logger
|
||||
config *Config
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Port int `mapstructure:"grpc-port"`
|
||||
ServiceName string `mapstructure:"grpc-service-name"`
|
||||
|
||||
|
||||
BackendURL []string `mapstructure:"backend-url"`
|
||||
UILogo string `mapstructure:"ui-logo"`
|
||||
UIMessage string `mapstructure:"ui-message"`
|
||||
UIColor string `mapstructure:"ui-color"`
|
||||
UIPath string `mapstructure:"ui-path"`
|
||||
DataPath string `mapstructure:"data-path"`
|
||||
ConfigPath string `mapstructure:"config-path"`
|
||||
CertPath string `mapstructure:"cert-path"`
|
||||
Host string `mapstructure:"host"`
|
||||
//Port string `mapstructure:"port"`
|
||||
SecurePort string `mapstructure:"secure-port"`
|
||||
PortMetrics int `mapstructure:"port-metrics"`
|
||||
Hostname string `mapstructure:"hostname"`
|
||||
H2C bool `mapstructure:"h2c"`
|
||||
RandomDelay bool `mapstructure:"random-delay"`
|
||||
RandomDelayUnit string `mapstructure:"random-delay-unit"`
|
||||
RandomDelayMin int `mapstructure:"random-delay-min"`
|
||||
RandomDelayMax int `mapstructure:"random-delay-max"`
|
||||
RandomError bool `mapstructure:"random-error"`
|
||||
Unhealthy bool `mapstructure:"unhealthy"`
|
||||
Unready bool `mapstructure:"unready"`
|
||||
JWTSecret string `mapstructure:"jwt-secret"`
|
||||
CacheServer string `mapstructure:"cache-server"`
|
||||
|
||||
}
|
||||
|
||||
func NewServer(config *Config, logger *zap.Logger) (*Server, error) {
|
||||
srv := &Server{
|
||||
logger: logger,
|
||||
config: config,
|
||||
}
|
||||
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
|
||||
func (s *Server) ListenAndServe() *grpc.Server {
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%v", s.config.Port))
|
||||
if err != nil {
|
||||
s.logger.Fatal("failed to listen", zap.Int("port", s.config.Port))
|
||||
}
|
||||
|
||||
srv := grpc.NewServer()
|
||||
server := health.NewServer()
|
||||
|
||||
|
||||
// Register grpc apis for refection
|
||||
echo.RegisterEchoServiceServer(srv, &echoServer{config: s.config, logger: s.logger})
|
||||
|
||||
version.RegisterVersionServiceServer(srv, &VersionServer{config: s.config, logger: s.logger})
|
||||
panic.RegisterPanicServiceServer(srv, &PanicServer{config: s.config, logger: s.logger})
|
||||
|
||||
reflection.Register(srv)
|
||||
grpc_health_v1.RegisterHealthServer(srv, server)
|
||||
server.SetServingStatus(s.config.ServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
|
||||
|
||||
go func() {
|
||||
if err := srv.Serve(listener); err != nil {
|
||||
s.logger.Fatal("failed to serve", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
return srv
|
||||
}
|
||||
21
pkg/api/grpc/version.go
Normal file
21
pkg/api/grpc/version.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "github.com/stefanprodan/podinfo/pkg/api/grpc/version"
|
||||
"github.com/stefanprodan/podinfo/pkg/version"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type VersionServer struct {
|
||||
pb.UnimplementedVersionServiceServer
|
||||
config *Config
|
||||
logger *zap.Logger
|
||||
|
||||
}
|
||||
|
||||
func (s *VersionServer) Version(ctx context.Context, req *pb.VersionRequest) (*pb.VersionResponse, error) {
|
||||
return &pb.VersionResponse{Version: version.VERSION, Commit: version.REVISION}, nil
|
||||
}
|
||||
|
||||
211
pkg/api/grpc/version/version.pb.go
Normal file
211
pkg/api/grpc/version/version.pb.go
Normal file
@@ -0,0 +1,211 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.6.1
|
||||
// source: version.proto
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type VersionRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *VersionRequest) Reset() {
|
||||
*x = VersionRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_version_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *VersionRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*VersionRequest) ProtoMessage() {}
|
||||
|
||||
func (x *VersionRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_version_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use VersionRequest.ProtoReflect.Descriptor instead.
|
||||
func (*VersionRequest) Descriptor() ([]byte, []int) {
|
||||
return file_version_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type VersionResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Commit string `protobuf:"bytes,2,opt,name=commit,proto3" json:"commit,omitempty"`
|
||||
}
|
||||
|
||||
func (x *VersionResponse) Reset() {
|
||||
*x = VersionResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_version_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *VersionResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*VersionResponse) ProtoMessage() {}
|
||||
|
||||
func (x *VersionResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_version_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use VersionResponse.ProtoReflect.Descriptor instead.
|
||||
func (*VersionResponse) Descriptor() ([]byte, []int) {
|
||||
return file_version_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *VersionResponse) GetVersion() string {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *VersionResponse) GetCommit() string {
|
||||
if x != nil {
|
||||
return x.Commit
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_version_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_version_proto_rawDesc = []byte{
|
||||
0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
|
||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x10, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x43, 0x0a, 0x0f, 0x56, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
|
||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x32,
|
||||
0x50, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x12, 0x3e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x2e, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
|
||||
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_version_proto_rawDescOnce sync.Once
|
||||
file_version_proto_rawDescData = file_version_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_version_proto_rawDescGZIP() []byte {
|
||||
file_version_proto_rawDescOnce.Do(func() {
|
||||
file_version_proto_rawDescData = protoimpl.X.CompressGZIP(file_version_proto_rawDescData)
|
||||
})
|
||||
return file_version_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_version_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_version_proto_goTypes = []interface{}{
|
||||
(*VersionRequest)(nil), // 0: version.VersionRequest
|
||||
(*VersionResponse)(nil), // 1: version.VersionResponse
|
||||
}
|
||||
var file_version_proto_depIdxs = []int32{
|
||||
0, // 0: version.VersionService.Version:input_type -> version.VersionRequest
|
||||
1, // 1: version.VersionService.Version:output_type -> version.VersionResponse
|
||||
1, // [1:2] is the sub-list for method output_type
|
||||
0, // [0:1] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_version_proto_init() }
|
||||
func file_version_proto_init() {
|
||||
if File_version_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_version_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*VersionRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_version_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*VersionResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_version_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_version_proto_goTypes,
|
||||
DependencyIndexes: file_version_proto_depIdxs,
|
||||
MessageInfos: file_version_proto_msgTypes,
|
||||
}.Build()
|
||||
File_version_proto = out.File
|
||||
file_version_proto_rawDesc = nil
|
||||
file_version_proto_goTypes = nil
|
||||
file_version_proto_depIdxs = nil
|
||||
}
|
||||
18
pkg/api/grpc/version/version.proto
Normal file
18
pkg/api/grpc/version/version.proto
Normal file
@@ -0,0 +1,18 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "./version";
|
||||
|
||||
package version;
|
||||
|
||||
|
||||
service VersionService {
|
||||
rpc Version (VersionRequest) returns (VersionResponse) {}
|
||||
}
|
||||
|
||||
|
||||
message VersionRequest {}
|
||||
|
||||
message VersionResponse {
|
||||
string version = 1;
|
||||
string commit = 2;
|
||||
}
|
||||
105
pkg/api/grpc/version/version_grpc.pb.go
Normal file
105
pkg/api/grpc/version/version_grpc.pb.go
Normal file
@@ -0,0 +1,105 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.6.1
|
||||
// source: version.proto
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// VersionServiceClient is the client API for VersionService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type VersionServiceClient interface {
|
||||
Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error)
|
||||
}
|
||||
|
||||
type versionServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewVersionServiceClient(cc grpc.ClientConnInterface) VersionServiceClient {
|
||||
return &versionServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *versionServiceClient) Version(ctx context.Context, in *VersionRequest, opts ...grpc.CallOption) (*VersionResponse, error) {
|
||||
out := new(VersionResponse)
|
||||
err := c.cc.Invoke(ctx, "/version.VersionService/Version", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// VersionServiceServer is the server API for VersionService service.
|
||||
// All implementations must embed UnimplementedVersionServiceServer
|
||||
// for forward compatibility
|
||||
type VersionServiceServer interface {
|
||||
Version(context.Context, *VersionRequest) (*VersionResponse, error)
|
||||
mustEmbedUnimplementedVersionServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedVersionServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedVersionServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedVersionServiceServer) Version(context.Context, *VersionRequest) (*VersionResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Version not implemented")
|
||||
}
|
||||
func (UnimplementedVersionServiceServer) mustEmbedUnimplementedVersionServiceServer() {}
|
||||
|
||||
// UnsafeVersionServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to VersionServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeVersionServiceServer interface {
|
||||
mustEmbedUnimplementedVersionServiceServer()
|
||||
}
|
||||
|
||||
func RegisterVersionServiceServer(s grpc.ServiceRegistrar, srv VersionServiceServer) {
|
||||
s.RegisterService(&VersionService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _VersionService_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(VersionRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(VersionServiceServer).Version(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/version.VersionService/Version",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(VersionServiceServer).Version(ctx, req.(*VersionRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// VersionService_ServiceDesc is the grpc.ServiceDesc for VersionService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var VersionService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "version.VersionService",
|
||||
HandlerType: (*VersionServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Version",
|
||||
Handler: _VersionService_Version_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "version.proto",
|
||||
}
|
||||
72
pkg/api/grpc/version_test.go
Normal file
72
pkg/api/grpc/version_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/stefanprodan/podinfo/pkg/api/grpc/version"
|
||||
v "github.com/stefanprodan/podinfo/pkg/version"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/grpc/test/bufconn"
|
||||
)
|
||||
|
||||
func TestGrpcVersion(t *testing.T) {
|
||||
|
||||
// Server initialization
|
||||
// bufconn => uses in-memory connection instead of system network I/O
|
||||
lis := bufconn.Listen(1024*1024)
|
||||
t.Cleanup(func() {
|
||||
lis.Close()
|
||||
})
|
||||
|
||||
|
||||
srv := grpc.NewServer()
|
||||
t.Cleanup(func() {
|
||||
srv.Stop()
|
||||
})
|
||||
|
||||
version.RegisterVersionServiceServer(srv, &VersionServer{})
|
||||
|
||||
go func(){
|
||||
if err := srv.Serve(lis); err != nil {
|
||||
log.Fatalf("srv.Serve %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// - Test
|
||||
dialer := func(context.Context, string) (net.Conn, error){
|
||||
return lis.Dial()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
conn, err := grpc.DialContext(ctx, "", grpc.WithContextDialer(dialer), grpc.WithInsecure())
|
||||
t.Cleanup(func() {
|
||||
conn.Close()
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("grpc.DialContext %v", err)
|
||||
}
|
||||
|
||||
client := version.NewVersionServiceClient(conn)
|
||||
res , err := client.Version(context.Background(), &version.VersionRequest{})
|
||||
|
||||
// Check the status code is what we expect.
|
||||
if _, ok := status.FromError(err); !ok {
|
||||
t.Errorf("Version returned type %T, want %T", err, status.Error)
|
||||
}
|
||||
|
||||
// Check the response body is what we expect.
|
||||
expected := fmt.Sprintf(".*%s.*", v.VERSION)
|
||||
r := regexp.MustCompile(expected)
|
||||
if !r.MatchString(res.String()) {
|
||||
t.Fatalf("Returned unexpected body:\ngot \n%v \nwant \n%s",
|
||||
res, expected)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import "net/http"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"time"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
_ "github.com/stefanprodan/podinfo/pkg/api/docs"
|
||||
_ "github.com/stefanprodan/podinfo/pkg/api/http/docs"
|
||||
"github.com/stefanprodan/podinfo/pkg/fscache"
|
||||
httpSwagger "github.com/swaggo/http-swagger"
|
||||
"github.com/swaggo/swag"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -1,4 +1,4 @@
|
||||
package api
|
||||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1,52 +0,0 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/health"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
logger *zap.Logger
|
||||
config *Config
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Port int `mapstructure:"grpc-port"`
|
||||
ServiceName string `mapstructure:"grpc-service-name"`
|
||||
}
|
||||
|
||||
func NewServer(config *Config, logger *zap.Logger) (*Server, error) {
|
||||
srv := &Server{
|
||||
logger: logger,
|
||||
config: config,
|
||||
}
|
||||
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
func (s *Server) ListenAndServe() *grpc.Server {
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%v", s.config.Port))
|
||||
if err != nil {
|
||||
s.logger.Fatal("failed to listen", zap.Int("port", s.config.Port))
|
||||
}
|
||||
|
||||
srv := grpc.NewServer()
|
||||
server := health.NewServer()
|
||||
reflection.Register(srv)
|
||||
grpc_health_v1.RegisterHealthServer(srv, server)
|
||||
server.SetServingStatus(s.config.ServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
|
||||
|
||||
go func() {
|
||||
if err := srv.Serve(listener); err != nil {
|
||||
s.logger.Fatal("failed to serve", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
|
||||
return srv
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package version
|
||||
|
||||
var VERSION = "6.5.4"
|
||||
var VERSION = "6.6.0"
|
||||
var REVISION = "unknown"
|
||||
|
||||
@@ -9,7 +9,7 @@ package main
|
||||
values: {
|
||||
image: {
|
||||
repository: "ghcr.io/stefanprodan/podinfo"
|
||||
tag: "6.5.4"
|
||||
tag: "6.6.0"
|
||||
digest: ""
|
||||
}
|
||||
test: image: {
|
||||
|
||||
Reference in New Issue
Block a user