From 7bd1f44491cc18504aad18de1c9c4100810985fd Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Sat, 24 Jun 2017 13:17:28 -0700 Subject: [PATCH] Add support for helm package info in useragent (#4592) --- cmd/update-main.go | 34 +++++++++++++++++++++++++++++++++ cmd/update-main_test.go | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/cmd/update-main.go b/cmd/update-main.go index a0e7953ba..96641e67a 100644 --- a/cmd/update-main.go +++ b/cmd/update-main.go @@ -17,6 +17,7 @@ package cmd import ( + "bufio" "fmt" "io/ioutil" "net/http" @@ -140,6 +141,30 @@ func IsKubernetes() bool { return os.Getenv("KUBERNETES_SERVICE_HOST") != "" } +// Minio Helm chart uses DownwardAPIFile to write pod label info to /podinfo/labels +// More info: https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/#store-pod-fields +// Check if this is Helm package installation and report helm chart version +func getHelmVersion(helmInfoFilePath string) string { + // Read the file exists. + helmInfoFile, err := os.Open(helmInfoFilePath) + // Log errors and return "" as Minio can be deployed without Helm charts as well. + if err != nil && !os.IsNotExist(err) { + errorIf(err, "Unable to read %s", helmInfoFilePath) + return "" + } + + scanner := bufio.NewScanner(helmInfoFile) + for scanner.Scan() { + if strings.Contains(scanner.Text(), "chart=") { + helmChartVersion := strings.TrimPrefix(scanner.Text(), "chart=") + // remove quotes from the chart version + return strings.Trim(helmChartVersion, `"`) + } + } + + return "" +} + func isSourceBuild(minioVersion string) bool { _, err := time.Parse(time.RFC3339, minioVersion) return err != nil @@ -182,6 +207,15 @@ func getUserAgent(mode string) string { userAgent += " Minio/" + "universe-" + universePkgVersion } } + + if IsKubernetes() { + // In Kubernetes environment, try to fetch the helm package version + helmChartVersion := getHelmVersion("/podinfo/labels") + if helmChartVersion != "" { + userAgent += " Minio/" + "helm-" + helmChartVersion + } + } + return userAgent } diff --git a/cmd/update-main_test.go b/cmd/update-main_test.go index 175f97f2b..7e5bc15c5 100644 --- a/cmd/update-main_test.go +++ b/cmd/update-main_test.go @@ -235,6 +235,48 @@ func TestIsKubernetes(t *testing.T) { } } +// Tests if the environment we are running is Helm chart. +func TestGetHelmVersion(t *testing.T) { + createTempFile := func(content string) string { + tmpfile, err := ioutil.TempFile("", "helm-testfile-") + if err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + if _, err = tmpfile.Write([]byte(content)); err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + if err = tmpfile.Close(); err != nil { + t.Fatalf("Unable to create temporary file. %s", err) + } + return tmpfile.Name() + } + + filename := createTempFile( + `app="virtuous-rat-minio" +chart="minio-0.1.3" +heritage="Tiller" +pod-template-hash="818089471"`) + + defer os.Remove(filename) + + testCases := []struct { + filename string + expectedResult string + }{ + {"", ""}, + {"/tmp/non-existing-file", ""}, + {filename, "minio-0.1.3"}, + } + + for _, testCase := range testCases { + result := getHelmVersion(testCase.filename) + + if testCase.expectedResult != result { + t.Fatalf("result: expected: %v, got: %v", testCase.expectedResult, result) + } + } +} + // Tests if the environment we are running is in docker. func TestIsDocker(t *testing.T) { createTempFile := func(content string) string {