Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/libraries/go/lib/pkg/version/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ load("@rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "version",
srcs = [
"handler.go",
"http.go",
"version.go",
],
Expand All @@ -28,6 +29,7 @@ go_library(
go_test(
name = "version_test",
srcs = [
"handler_test.go",
"http_test.go",
"version_test.go",
],
Expand Down
85 changes: 85 additions & 0 deletions src/libraries/go/lib/pkg/version/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: Apache-2.0

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

import (
"encoding/json"
"net/http"
"runtime/debug"
)

// Info holds the resolved build metadata returned by the GET /info endpoint.
type Info struct {
Service string `json:"service"`
Version string `json:"version"`
Commit string `json:"commit"`
}

// Handler returns an http.Handler that serves build info as JSON.
// Service, Version, and Commit are resolved from the package-level ldflags vars
// (Service, Version, GitHash), with buildinfo used as a fallback for Commit
// when GitHash is empty.
func Handler() http.Handler {
return HandlerFor(Service, Version, GitHash)
}

// HandlerFor returns an http.Handler using the provided service, version, and
// commit values, falling back to buildinfo for commit when commit is empty.
// Use this for services that maintain their own ldflags vars rather than
// pointing directly at this package.
func HandlerFor(service, ver, commit string) http.Handler {
info := resolve(service, ver, commit)
body, _ := json.Marshal(info)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write(body)
})
}

// resolve builds an Info by combining the given service/ver/commit,
// falling back to runtime buildinfo for commit when empty.
func resolve(service, ver, commit string) Info {
if commit == "" {
commit = commitFromBuildInfo()
}
if service == "" {
service = "unknown"
}
if ver == "" {
ver = "unknown"
}
if commit == "" {
commit = "unknown"
}
return Info{Service: service, Version: ver, Commit: commit}
}

// commitFromBuildInfo reads the VCS revision from Go's embedded build info
// (available when built inside a git repository without -buildvcs=false).
func commitFromBuildInfo() string {
info, ok := debug.ReadBuildInfo()
if !ok {
return ""
}
for _, s := range info.Settings {
if s.Key == "vcs.revision" {
return s.Value
}
}
return ""
}
128 changes: 128 additions & 0 deletions src/libraries/go/lib/pkg/version/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: Apache-2.0

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package version

import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestHandlerFor(t *testing.T) {
tests := []struct {
name string
service string
ver string
commit string
wantService string
wantVersion string
wantCommit string
}{
{
name: "all set",
service: "nvcf-my-service",
ver: "1.2.3",
commit: "abc1234",
wantService: "nvcf-my-service",
wantVersion: "1.2.3",
wantCommit: "abc1234",
},
{
name: "empty service falls back to unknown",
service: "",
ver: "1.2.3",
commit: "abc1234",
wantService: "unknown",
wantVersion: "1.2.3",
wantCommit: "abc1234",
},
{
name: "empty version falls back to unknown",
service: "nvcf-my-service",
ver: "",
commit: "abc1234",
wantService: "nvcf-my-service",
wantVersion: "unknown",
wantCommit: "abc1234",
},
{
name: "empty commit falls back to buildinfo or unknown",
service: "nvcf-my-service",
ver: "1.2.3",
commit: "",
wantService: "nvcf-my-service",
wantVersion: "1.2.3",
// commit will be whatever buildinfo provides in the test binary,
// or "unknown" -- just assert it is non-empty string
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/info", nil)
HandlerFor(tc.service, tc.ver, tc.commit).ServeHTTP(w, r)

assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "application/json", w.Header().Get("Content-Type"))

var got Info
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &got))

if tc.wantService != "" {
assert.Equal(t, tc.wantService, got.Service)
}
if tc.wantVersion != "" {
assert.Equal(t, tc.wantVersion, got.Version)
}
if tc.wantCommit != "" {
assert.Equal(t, tc.wantCommit, got.Commit)
}
assert.NotEmpty(t, got.Commit)
})
}
}

func TestHandler(t *testing.T) {
t.Cleanup(func() {
Service = ""
Version = ""
GitHash = ""
})

Service = "nvcf-my-service"
Version = "2.0.0"
GitHash = "deadbeef"

w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/info", nil)
Handler().ServeHTTP(w, r)

assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "application/json", w.Header().Get("Content-Type"))

var got Info
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &got))
assert.Equal(t, "nvcf-my-service", got.Service)
assert.Equal(t, "2.0.0", got.Version)
assert.Equal(t, "deadbeef", got.Commit)
}
1 change: 1 addition & 0 deletions src/libraries/go/lib/pkg/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import "strings"

// Following variables are set by CI during compilation.
var (
Service string
Version string
GitHash string
// Dirty is set to "true" if current git working directory has
Expand Down
Loading