Skip to content

Commit e8df9e5

Browse files
authored
Merge pull request #28 from parca-dev/headers
Add ability to attach arbitrary headers
2 parents e0009c8 + 05af7bb commit e8df9e5

File tree

3 files changed

+192
-67
lines changed

3 files changed

+192
-67
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,4 @@ jobs:
6363
run: make vet
6464

6565
- name: Lint
66-
uses: golangci/golangci-lint-action@v6
66+
uses: golangci/golangci-lint-action@v9

.golangci.yml

Lines changed: 136 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,87 @@
1-
run:
2-
deadline: 5m
3-
1+
version: "2"
42
linters:
5-
presets:
6-
- bugs
7-
- comment
8-
- error
9-
- format
10-
- import
11-
- metalinter
12-
- performance
13-
- style
14-
- unused
3+
enable:
4+
- asasalint
5+
- asciicheck
6+
- bidichk
7+
- bodyclose
8+
- canonicalheader
9+
- containedctx
10+
- contextcheck
11+
- copyloopvar
12+
- decorder
13+
- depguard
14+
- dogsled
15+
- dupl
16+
- dupword
17+
- durationcheck
18+
- errchkjson
19+
- errname
20+
- errorlint
21+
- exhaustive
22+
- exptostd
23+
- fatcontext
24+
- forbidigo
25+
- forcetypeassert
26+
- ginkgolinter
27+
- gocheckcompilerdirectives
28+
- gochecknoinits
29+
- gochecksumtype
30+
- goconst
31+
- gocritic
32+
- godot
33+
- goheader
34+
- gomodguard
35+
- goprintffuncname
36+
- gosec
37+
- gosmopolitan
38+
- grouper
39+
- iface
40+
- importas
41+
- inamedparam
42+
- interfacebloat
43+
- intrange
44+
- loggercheck
45+
- makezero
46+
- mirror
47+
- misspell
48+
- mnd
49+
- musttag
50+
- nakedret
51+
- nilerr
52+
- nilnesserr
53+
- nilnil
54+
- noctx
55+
- nolintlint
56+
- nonamedreturns
57+
- nosprintfhostport
58+
- perfsprint
59+
- prealloc
60+
- predeclared
61+
- promlinter
62+
- protogetter
63+
- reassign
64+
- recvcheck
65+
- revive
66+
- rowserrcheck
67+
- sloglint
68+
- spancheck
69+
- sqlclosecheck
70+
- staticcheck
71+
- tagalign
72+
- tagliatelle
73+
- testifylint
74+
- tparallel
75+
- unconvert
76+
- unparam
77+
- usestdlibvars
78+
- wastedassign
79+
- whitespace
80+
- zerologlint
1581
disable:
82+
- err113
1683
- exhaustruct
1784
- funlen
18-
- gci
1985
- gochecknoglobals
2086
- godox
2187
- gomoddirectives
@@ -27,41 +93,60 @@ linters:
2793
- varnamelen
2894
- wrapcheck
2995
- wsl
30-
- err113
31-
32-
issues:
33-
exclude-rules:
34-
- path: _test.go
35-
linters:
36-
- errcheck
37-
38-
linters-settings:
39-
depguard:
40-
rules:
41-
Main:
42-
deny:
43-
- pkg: sync/atomic
44-
desc: Use go.uber.org/atomic instead of sync/atomic
45-
- pkg: github.com/stretchr/testify/assert
46-
desc: Use github.com/stretchr/testify/require instead of github.com/stretchr/testify/assert
47-
- pkg: github.com/go-kit/kit/log
48-
desc: Use github.com/go-kit/log instead of github.com/go-kit/kit/log
49-
- pkg: github.com/pkg/errors
50-
desc: Use fmt.Errorf instead
51-
errcheck:
52-
exclude-functions: ./.errcheck_excludes.txt
53-
goimports:
54-
local-prefixes: github.com/parca-dev/parca-debuginfo
55-
gofumpt:
56-
extra-rules: true
57-
misspell:
58-
locale: US
59-
revive:
96+
settings:
97+
cyclop:
98+
max-complexity: 15
99+
depguard:
100+
rules:
101+
Main:
102+
deny:
103+
- pkg: sync/atomic
104+
desc: Use go.uber.org/atomic instead of sync/atomic
105+
- pkg: github.com/stretchr/testify/assert
106+
desc: Use github.com/stretchr/testify/require instead of github.com/stretchr/testify/assert
107+
- pkg: github.com/go-kit/kit/log
108+
desc: Use github.com/go-kit/log instead of github.com/go-kit/kit/log
109+
- pkg: github.com/pkg/errors
110+
desc: Use fmt.Errorf instead
111+
errcheck:
112+
exclude-functions:
113+
- (github.com/go-kit/log.Logger).Log
114+
misspell:
115+
locale: US
116+
revive:
117+
rules:
118+
- name: unexported-return
119+
severity: warning
120+
disabled: true
121+
exclusions:
122+
generated: lax
123+
presets:
124+
- comments
125+
- common-false-positives
126+
- legacy
127+
- std-error-handling
60128
rules:
61-
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return
62-
- name: unexported-return
63-
severity: warning
64-
disabled: true
65-
cyclop:
66-
# The maximal code complexity to report.
67-
max-complexity: 15
129+
- linters:
130+
- errcheck
131+
path: _test.go
132+
paths:
133+
- third_party$
134+
- builtin$
135+
- examples$
136+
formatters:
137+
enable:
138+
- gofmt
139+
- gofumpt
140+
- goimports
141+
settings:
142+
gofumpt:
143+
extra-rules: true
144+
goimports:
145+
local-prefixes:
146+
- github.com/parca-dev/parca-debuginfo
147+
exclusions:
148+
generated: lax
149+
paths:
150+
- third_party$
151+
- builtin$
152+
- examples$

cmd/parca-debuginfo/main.go

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,29 @@ import (
4343
"google.golang.org/grpc"
4444
"google.golang.org/grpc/credentials"
4545
"google.golang.org/grpc/credentials/insecure"
46+
"google.golang.org/grpc/metadata"
4647
)
4748

4849
const (
49-
LogLevelDebug = "debug"
50+
LogLevelDebug = "debug"
51+
headerKeyValuePairElements = 2
5052
)
5153

5254
type flags struct {
5355
LogLevel string `kong:"enum='error,warn,info,debug',help='Log level.',default='info'"`
5456

5557
Upload struct {
56-
StoreAddress string `kong:"required,help='gRPC address to sends symbols to.'"`
57-
BearerToken string `kong:"help='Bearer token to authenticate with store.',env='PARCA_DEBUGINFO_BEARER_TOKEN'"`
58-
BearerTokenFile string `kong:"help='File to read bearer token from to authenticate with store.'"`
59-
Insecure bool `kong:"help='Send gRPC requests via plaintext instead of TLS.'"`
60-
InsecureSkipVerify bool `kong:"help='Skip TLS certificate verification.'"`
61-
NoExtract bool `kong:"help='Do not extract debug information from binaries, just upload the binary as is.'"`
62-
NoInitiate bool `kong:"help='Do not initiate the upload, just check if it should be initiated.'"`
63-
Force bool `kong:"help='Force upload even if the Build ID is already uploaded.'"`
64-
Type string `kong:"enum='debuginfo,executable,sources',help='Type of the debug information to upload.',default='debuginfo'"`
65-
BuildID string `kong:"help='Build ID of the binary to upload.'"`
58+
StoreAddress string `kong:"required,help='gRPC address to sends symbols to.'"`
59+
BearerToken string `kong:"help='Bearer token to authenticate with store.',env='PARCA_DEBUGINFO_BEARER_TOKEN'"`
60+
BearerTokenFile string `kong:"help='File to read bearer token from to authenticate with store.'"`
61+
Insecure bool `kong:"help='Send gRPC requests via plaintext instead of TLS.'"`
62+
InsecureSkipVerify bool `kong:"help='Skip TLS certificate verification.'"`
63+
GRPCHeaders map[string]string `kong:"help='Additional gRPC headers to send with each request (key=value pairs).'"`
64+
NoExtract bool `kong:"help='Do not extract debug information from binaries, just upload the binary as is.'"`
65+
NoInitiate bool `kong:"help='Do not initiate the upload, just check if it should be initiated.'"`
66+
Force bool `kong:"help='Force upload even if the Build ID is already uploaded.'"`
67+
Type string `kong:"enum='debuginfo,executable,sources',help='Type of the debug information to upload.',default='debuginfo'"`
68+
BuildID string `kong:"help='Build ID of the binary to upload.'"`
6669

6770
Path string `kong:"required,arg,name='path',help='Paths to upload.',type:'path'"`
6871
} `cmd:"" help:"Upload debug information files."`
@@ -429,10 +432,25 @@ func grpcConn(reg prometheus.Registerer, flags flags) (*grpc.ClientConn, error)
429432
met.EnableClientHandlingTimeHistogram()
430433
reg.MustRegister(met)
431434

435+
unaryInterceptors := []grpc.UnaryClientInterceptor{
436+
met.UnaryClientInterceptor(),
437+
}
438+
streamInterceptors := []grpc.StreamClientInterceptor{}
439+
440+
if len(flags.Upload.GRPCHeaders) > 0 {
441+
unaryInterceptors = append(
442+
[]grpc.UnaryClientInterceptor{customHeadersUnaryInterceptor(flags.Upload.GRPCHeaders)},
443+
unaryInterceptors...,
444+
)
445+
streamInterceptors = append(
446+
[]grpc.StreamClientInterceptor{customHeadersStreamInterceptor(flags.Upload.GRPCHeaders)},
447+
streamInterceptors...,
448+
)
449+
}
450+
432451
opts := []grpc.DialOption{
433-
grpc.WithUnaryInterceptor(
434-
met.UnaryClientInterceptor(),
435-
),
452+
grpc.WithChainUnaryInterceptor(unaryInterceptors...),
453+
grpc.WithChainStreamInterceptor(streamInterceptors...),
436454
}
437455
if flags.Upload.Insecure {
438456
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
@@ -480,6 +498,28 @@ func (t *perRequestBearerToken) RequireTransportSecurity() bool {
480498
return !t.insecure
481499
}
482500

501+
func customHeadersUnaryInterceptor(headers map[string]string) grpc.UnaryClientInterceptor {
502+
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
503+
kvPairs := make([]string, 0, len(headers)*headerKeyValuePairElements)
504+
for key, value := range headers {
505+
kvPairs = append(kvPairs, key, value)
506+
}
507+
newCtx := metadata.AppendToOutgoingContext(ctx, kvPairs...)
508+
return invoker(newCtx, method, req, reply, cc, opts...)
509+
}
510+
}
511+
512+
func customHeadersStreamInterceptor(headers map[string]string) grpc.StreamClientInterceptor {
513+
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
514+
kvPairs := make([]string, 0, len(headers)*headerKeyValuePairElements)
515+
for key, value := range headers {
516+
kvPairs = append(kvPairs, key, value)
517+
}
518+
newCtx := metadata.AppendToOutgoingContext(ctx, kvPairs...)
519+
return streamer(newCtx, desc, cc, method, opts...)
520+
}
521+
}
522+
483523
func uploadViaSignedURL(ctx context.Context, url string, r io.Reader) error {
484524
req, err := http.NewRequestWithContext(ctx, http.MethodPut, url, r)
485525
if err != nil {
@@ -587,7 +627,7 @@ func getNoteHexString(sectionBytes []byte, name string, noteType uint32) (string
587627

588628
// read descsz and compute the last index of the note data
589629
dataSize := binary.LittleEndian.Uint32(sectionBytes[idx-4 : idx])
590-
idxDataEnd := uint64(idxDataStart) + uint64(dataSize) //nolint:gosec
630+
idxDataEnd := uint64(idxDataStart) + uint64(dataSize)
591631

592632
// Check sanity (64 is totally arbitrary, as we only use it for Linux ID and Build ID)
593633
if idxDataEnd > uint64(len(sectionBytes)) || dataSize > 64 {

0 commit comments

Comments
 (0)