Skip to content
This repository was archived by the owner on Jul 16, 2021. It is now read-only.

Commit d840dd1

Browse files
authored
Improve user agent and version handling in chart-repo command (#558)
1 parent 8e57bc2 commit d840dd1

File tree

7 files changed

+92
-14
lines changed

7 files changed

+92
-14
lines changed

.circleci/config.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,13 @@ jobs:
110110
- run: |
111111
CMDS=(chart-repo chartsvc)
112112
for CMD in ${CMDS[@]}; do
113-
make -C cmd/${CMD} docker-build
113+
# If we are in a release we pass the version to the build process to bake the version
114+
# By default, if no passed it will use the commit sha
115+
if [[ -n "${CIRCLE_TAG}" ]]; then
116+
makeArgs="VERSION=${CIRCLE_TAG}"
117+
fi
118+
119+
make -C cmd/${CMD} $makeArgs docker-build
114120
done
115121
116122
if [[ -z "${CIRCLE_PULL_REQUEST}" && -n "${DOCKER_USERNAME}" && -n "${DOCKER_PASSWORD}" ]] && [[ "${CIRCLE_BRANCH}" == "master" || -n "${CIRCLE_TAG}" ]]; then

cmd/chart-repo/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
FROM golang:1.11 as builder
22
COPY . /go/src/github.com/helm/monocular
33
WORKDIR /go/src/github.com/helm/monocular
4-
RUN CGO_ENABLED=0 go build -a -installsuffix cgo ./cmd/chart-repo
4+
5+
ARG VERSION
6+
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags "-X main.version=$VERSION" ./cmd/chart-repo
57

68
FROM scratch
79
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

cmd/chart-repo/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
IMAGE_REPO ?= quay.io/helmpack/chart-repo
22
IMAGE_TAG ?= latest
3+
# Version of the binary to be produced
4+
VERSION ?= $$(git rev-parse HEAD)
35

46
docker-build:
57
# We use the context of the root dir
6-
docker build --pull --rm -t ${IMAGE_REPO}:${IMAGE_TAG} -f Dockerfile ../../
8+
docker build --pull --rm -t ${IMAGE_REPO}:${IMAGE_TAG} --build-arg "VERSION=${VERSION}" -f Dockerfile ../../

cmd/chart-repo/chart_repo.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424

2525
var rootCmd = &cobra.Command{
2626
Use: "chart-repo",
27-
Short: "Kubeapps Chart Repository utility",
27+
Short: "Chart Repository utility",
2828
Run: func(cmd *cobra.Command, args []string) {
2929
cmd.Help()
3030
},
@@ -45,6 +45,9 @@ func init() {
4545
cmd.Flags().String("mongo-url", "localhost", "MongoDB URL (see https://godoc.org/github.com/globalsign/mgo#Dial for format)")
4646
cmd.Flags().String("mongo-database", "charts", "MongoDB database")
4747
cmd.Flags().String("mongo-user", "", "MongoDB user")
48+
// see version.go
49+
cmd.Flags().StringVarP(&userAgentComment, "user-agent-comment", "", "", "UserAgent comment used during outbound requests")
4850
cmd.Flags().Bool("debug", false, "verbose logging")
4951
}
52+
rootCmd.AddCommand(versionCmd)
5053
}

cmd/chart-repo/utils.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,12 @@ func fetchRepoIndex(r repo) (*helmrepo.IndexFile, error) {
166166
log.WithFields(log.Fields{"url": req.URL.String()}).WithError(err).Error("could not build repo index request")
167167
return nil, err
168168
}
169-
req.Header.Set("User-Agent", userAgent)
169+
170+
req.Header.Set("User-Agent", userAgent())
170171
if len(r.AuthorizationHeader) > 0 {
171172
req.Header.Set("Authorization", r.AuthorizationHeader)
172173
}
174+
173175
res, err := netClient.Do(req)
174176
if res != nil {
175177
defer res.Body.Close()
@@ -278,7 +280,7 @@ func fetchAndImportIcon(dbSession datastore.Session, c chart) error {
278280
if err != nil {
279281
return err
280282
}
281-
req.Header.Set("User-Agent", userAgent)
283+
req.Header.Set("User-Agent", userAgent())
282284
if len(c.Repo.AuthorizationHeader) > 0 {
283285
req.Header.Set("Authorization", c.Repo.AuthorizationHeader)
284286
}
@@ -328,7 +330,7 @@ func fetchAndImportFiles(dbSession datastore.Session, name string, r repo, cv ch
328330
if err != nil {
329331
return err
330332
}
331-
req.Header.Set("User-Agent", userAgent)
333+
req.Header.Set("User-Agent", userAgent())
332334
if len(r.AuthorizationHeader) > 0 {
333335
req.Header.Set("Authorization", r.AuthorizationHeader)
334336
}

cmd/chart-repo/utils_test.go

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,7 @@ func (h *goodHTTPClient) Do(req *http.Request) (*http.Response, error) {
6666
if req.URL.Host == "subpath.test" && req.URL.Path != "/subpath/index.yaml" {
6767
w.WriteHeader(500)
6868
}
69-
// Ensure we're sending the right User-Agent
70-
if !strings.Contains(req.Header.Get("User-Agent"), "chart-repo-sync") {
71-
w.WriteHeader(500)
72-
}
69+
7370
w.Write([]byte(validRepoIndexYAML))
7471
return w.Result(), nil
7572
}
@@ -206,6 +203,44 @@ func Test_fetchRepoIndex(t *testing.T) {
206203
})
207204
}
208205

206+
func Test_fetchRepoIndexUserAgent(t *testing.T) {
207+
tests := []struct {
208+
name string
209+
version string
210+
userAgentComment string
211+
expectedUserAgent string
212+
}{
213+
{"default user agent", "", "", "chart-repo/devel"},
214+
{"custom version no app", "1.0", "", "chart-repo/1.0"},
215+
{"custom version and app", "1.0", "monocular/1.2", "chart-repo/1.0 (monocular/1.2)"},
216+
}
217+
218+
for _, tt := range tests {
219+
t.Run(tt.name, func(t *testing.T) {
220+
// Override global variables used to generate the userAgent
221+
if tt.version != "" {
222+
version = tt.version
223+
}
224+
225+
if tt.userAgentComment != "" {
226+
userAgentComment = tt.userAgentComment
227+
}
228+
229+
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
230+
assert.Equal(t, tt.expectedUserAgent, req.Header.Get("User-Agent"), "expected user agent")
231+
rw.Write([]byte(validRepoIndexYAML))
232+
}))
233+
// Close the server when test finishes
234+
defer server.Close()
235+
236+
netClient = server.Client()
237+
238+
_, err := fetchRepoIndex(repo{URL: server.URL})
239+
assert.NoErr(t, err)
240+
})
241+
}
242+
}
243+
209244
func Test_parseRepoIndex(t *testing.T) {
210245
tests := []struct {
211246
name string

cmd/chart-repo/version.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,35 @@ limitations under the License.
1616

1717
package main
1818

19-
const (
20-
version = "0.3.0"
21-
userAgent = "chart-repo-sync/" + version
19+
import (
20+
"fmt"
21+
22+
"github.com/spf13/cobra"
23+
)
24+
25+
var (
26+
version = "devel"
27+
userAgentComment string
2228
)
29+
30+
// Returns the user agent to be used during calls to the chart repositories
31+
// Examples:
32+
// chart-repo/devel
33+
// chart-repo/1.0
34+
// chart-repo/1.0 (monocular v1.0-beta4)
35+
// More info here https://github.com/kubeapps/kubeapps/issues/767#issuecomment-436835938
36+
func userAgent() string {
37+
ua := "chart-repo/" + version
38+
if userAgentComment != "" {
39+
ua = fmt.Sprintf("%s (%s)", ua, userAgentComment)
40+
}
41+
return ua
42+
}
43+
44+
var versionCmd = &cobra.Command{
45+
Use: "version",
46+
Short: "returns version information",
47+
Run: func(cmd *cobra.Command, args []string) {
48+
fmt.Println(version)
49+
},
50+
}

0 commit comments

Comments
 (0)