[ARVADOS-ORG] updated: 7b3f87fdb0c524ab18305df586e89c639884c71e
Git user
git at public.curoverse.com
Thu Sep 28 10:44:33 EDT 2017
Summary of changes:
arvados-version-server/README | 23 +
arvados-version-server/arvados-version-server.go | 856 +++++++++++++++++++++
.../arvados-version-server.service | 13 +
.../arvados-version-server_test.go | 287 +++++++
arvados-version-server/usage.go | 33 +
5 files changed, 1212 insertions(+)
create mode 100644 arvados-version-server/README
create mode 100644 arvados-version-server/arvados-version-server.go
create mode 100644 arvados-version-server/arvados-version-server.service
create mode 100644 arvados-version-server/arvados-version-server_test.go
create mode 100644 arvados-version-server/usage.go
via 7b3f87fdb0c524ab18305df586e89c639884c71e (commit)
via fe162521548f3caf20cf0f83c4aa8e6249808e23 (commit)
via c72577bfb29e4fe09706701e87748cc77e8e2a14 (commit)
via bf2221b89a9bd8aada8dae1e64cc081fc2170607 (commit)
via abb57b119482e1a1447300dd3acf250569aecbfb (commit)
via 7919cb80fd9c8a8d3440af87ec7d082453e94e2f (commit)
from 7d92e252f916e1d1f183bea6cf279b80fc3c41de (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 7b3f87fdb0c524ab18305df586e89c639884c71e
Author: Ward Vandewege <ward at jhvc.com>
Date: Thu Sep 28 10:39:04 2017 -0400
Move arvados-version-server from the arvados-dev repository to this
repository.
No issue #
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <wvandewege at veritasgenetics.com>
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index cfce019..0000000
--- a/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-arvados-version-server
diff --git a/README b/arvados-version-server/README
similarity index 100%
rename from README
rename to arvados-version-server/README
diff --git a/arvados-version-server.go b/arvados-version-server/arvados-version-server.go
similarity index 100%
rename from arvados-version-server.go
rename to arvados-version-server/arvados-version-server.go
diff --git a/arvados-version-server.service b/arvados-version-server/arvados-version-server.service
similarity index 100%
rename from arvados-version-server.service
rename to arvados-version-server/arvados-version-server.service
diff --git a/arvados-version-server_test.go b/arvados-version-server/arvados-version-server_test.go
similarity index 100%
rename from arvados-version-server_test.go
rename to arvados-version-server/arvados-version-server_test.go
diff --git a/usage.go b/arvados-version-server/usage.go
similarity index 100%
rename from usage.go
rename to arvados-version-server/usage.go
commit fe162521548f3caf20cf0f83c4aa8e6249808e23
Author: Ward Vandewege <ward at curoverse.com>
Date: Sun Sep 24 20:34:40 2017 -0400
Make the short git hash length a configuration parameter, and default it
to 7 (which is the historical default for our packages).
For Debian Stretch, we're now using 9, but our pinning is done in such a
way that the extra characters at the end of the package name are no
problem.
refs #
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <wvandewege at veritasgenetics.com>
diff --git a/arvados-version-server.go b/arvados-version-server.go
index f377979..f92dc31 100644
--- a/arvados-version-server.go
+++ b/arvados-version-server.go
@@ -62,6 +62,7 @@ type Config struct {
CacheDirPath string
GitExecutablePath string
ListenPort string
+ ShortHashLength string
Packages []bundle
}
@@ -423,7 +424,7 @@ func versionFromGit(prefix string) (string, error) {
if err != nil {
return "", err
}
- cmdArgs := []string{"log", "-n1", "--first-parent", "--max-count=1", "--format=format:%h", "--abbrev=9", "."}
+ cmdArgs := []string{"log", "-n1", "--first-parent", "--max-count=1", "--format=format:%h", "--abbrev=" + theConfig.ShortHashLength, "."}
gitHash, err := exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output()
if err != nil {
logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
@@ -709,7 +710,7 @@ func packageVersionHandler(w http.ResponseWriter, r *http.Request) {
hash := r.URL.Path[11:]
// Empty hash or non-standard hash length? Normalize it.
- if len(hash) != 7 && len(hash) != 40 {
+ if string(len(hash)) != theConfig.ShortHashLength && len(hash) != 40 {
hash, err = normalizeRequestedHash(hash)
if err != nil {
m := report{"Error", err.Error()}
@@ -808,6 +809,10 @@ func main() {
theConfig.ListenPort = "80"
}
+ if theConfig.ShortHashLength == "" {
+ theConfig.ShortHashLength = "7"
+ }
+
http.HandleFunc("/v1/commit/", packageVersionHandler)
http.HandleFunc("/v1/about", aboutHandler)
http.HandleFunc("/v1/help", helpHandler)
diff --git a/arvados-version-server_test.go b/arvados-version-server_test.go
index 874c4b3..26e2824 100644
--- a/arvados-version-server_test.go
+++ b/arvados-version-server_test.go
@@ -49,13 +49,14 @@ func (s *ServerNotRequiredSuite) TestConfig(c *C) {
c.Check(config.CacheDirPath, Equals, "")
c.Check(config.GitExecutablePath, Equals, "")
c.Check(config.ListenPort, Equals, "")
+ c.Check(config.ShortHashLength, Equals, "")
// Test parsing of config data
tmpfile, err := ioutil.TempFile(os.TempDir(), "config")
c.Check(err, IsNil)
defer os.Remove(tmpfile.Name())
- argsS := `{"DirPath": "/x/y", "CacheDirPath": "/x/z", "GitExecutablePath": "/usr/local/bin/gitexecutable", "ListenPort": "12345"}`
+ argsS := `{"DirPath": "/x/y", "CacheDirPath": "/x/z", "GitExecutablePath": "/usr/local/bin/gitexecutable", "ListenPort": "12345", "ShortHashLength": "3"}`
_, err = tmpfile.Write([]byte(argsS))
c.Check(err, IsNil)
@@ -66,6 +67,7 @@ func (s *ServerNotRequiredSuite) TestConfig(c *C) {
c.Check(config.CacheDirPath, Equals, "/x/z")
c.Check(config.GitExecutablePath, Equals, "/usr/local/bin/gitexecutable")
c.Check(config.ListenPort, Equals, "12345")
+ c.Check(config.ShortHashLength, Equals, "3")
}
@@ -83,7 +85,7 @@ func runServer(c *C) {
tmpConfigFileName = tmpfile.Name()
- argsS := `{"DirPath": "", "CacheDirPath": "", "GitExecutablePath": "", "ListenPort": "12345"}`
+ argsS := `{"DirPath": "", "CacheDirPath": "", "GitExecutablePath": "", "ListenPort": "12345", "ShortHashLength": "9"}`
_, err = tmpfile.Write([]byte(argsS))
c.Check(err, IsNil)
diff --git a/usage.go b/usage.go
index b5ee85b..769b7b1 100644
--- a/usage.go
+++ b/usage.go
@@ -15,6 +15,7 @@ dirPath: "/tmp/arvados-version-server-checkout"
cacheDirPath: "/tmp/arvados-version-server-cache"
gitExecutablePath: "/usr/bin/git"
listenPort: 8080
+shortHashLength: 7
`)
func usage(fs *flag.FlagSet) {
commit c72577bfb29e4fe09706701e87748cc77e8e2a14
Author: Ward Vandewege <ward at curoverse.com>
Date: Sun Sep 24 14:39:41 2017 -0400
Newer git version (2.11.0) default to 9 characters for the abbreviated
git hash. Explicitly select a minimum of 9 in the code, and adjust tests
to have 9 characters for the return value that is checked.
No issue #
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <wvandewege at veritasgenetics.com>
diff --git a/arvados-version-server.go b/arvados-version-server.go
index 2f40df0..f377979 100644
--- a/arvados-version-server.go
+++ b/arvados-version-server.go
@@ -423,7 +423,7 @@ func versionFromGit(prefix string) (string, error) {
if err != nil {
return "", err
}
- cmdArgs := []string{"log", "-n1", "--first-parent", "--max-count=1", "--format=format:%h", "."}
+ cmdArgs := []string{"log", "-n1", "--first-parent", "--max-count=1", "--format=format:%h", "--abbrev=9", "."}
gitHash, err := exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output()
if err != nil {
logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
diff --git a/arvados-version-server_test.go b/arvados-version-server_test.go
index 347ab18..874c4b3 100644
--- a/arvados-version-server_test.go
+++ b/arvados-version-server_test.go
@@ -171,7 +171,7 @@ func (s *ServerRequiredSuite) TestResults(c *C) {
c.Check(err, Equals, nil)
c.Check(resp.StatusCode, Equals, 200)
body, err := ioutil.ReadAll(resp.Body)
- c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20130104011935.155848c\".*")
+ c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20130104011935.155848c15\".*")
}
// Check the arvados-src version string for a more recent commit
@@ -184,7 +184,7 @@ func (s *ServerRequiredSuite) TestResults(c *C) {
c.Check(err, Equals, nil)
c.Check(resp.StatusCode, Equals, 200)
body, err := ioutil.ReadAll(resp.Body)
- c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20161208152419.9c1a287\".*")
+ c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20161208152419.9c1a28719\".*")
}
// Check the arvados-src version string for a weirdly truncated commit
@@ -197,7 +197,7 @@ func (s *ServerRequiredSuite) TestResults(c *C) {
c.Check(err, Equals, nil)
c.Check(resp.StatusCode, Equals, 200)
body, err := ioutil.ReadAll(resp.Body)
- c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20161208152419.9c1a287\".*")
+ c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20161208152419.9c1a28719\".*")
}
// Check an invalid request hash
commit bf2221b89a9bd8aada8dae1e64cc081fc2170607
Author: Ward Vandewege <ward at curoverse.com>
Date: Thu Mar 23 17:05:48 2017 -0400
arvados-version-server:
* more refactoring
No issue #
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <wvandewege at veritasgenetics.com>
diff --git a/arvados-version-server.go b/arvados-version-server.go
index 9cb5c05..2f40df0 100644
--- a/arvados-version-server.go
+++ b/arvados-version-server.go
@@ -511,43 +511,45 @@ func normalizeRequestedHash(hash string) (string, error) {
}
func getPackageVersionsWorker(hash string) (gitHash string, goSDKTimestamp string, goSDKVersionWithoutPrefix string, pythonSDKTimestamp string, err error) {
+ gitHash = ""
+ goSDKTimestamp = ""
+ goSDKVersionWithoutPrefix = ""
+ pythonSDKTimestamp = ""
+
_, err = prepareGitCheckout(hash)
if err != nil {
- return "", "", "", "", err
+ return
}
// Get the git hash for the tree
gitHash, err = gitHashFull()
if err != nil {
- return "", "", "", "", err
+ return
}
// Get the git timestamp and version string for the sdk/go directory
err = os.Chdir(theConfig.DirPath + "/sdk/go")
if err != nil {
- goSDKTimestamp = ""
- goSDKVersionWithoutPrefix = ""
err = nil
} else {
goSDKTimestamp, err = timestampFromGit()
if err != nil {
- return "", "", "", "", err
+ return
}
goSDKVersionWithoutPrefix, err = versionFromGit("")
if err != nil {
- return "", "", "", "", err
+ return
}
}
// Get the git timestamp and version string for the sdk/python directory
err = os.Chdir(theConfig.DirPath + "/sdk/python")
if err != nil {
- pythonSDKTimestamp = ""
err = nil
} else {
pythonSDKTimestamp, err = timestampFromGit()
if err != nil {
- return "", "", "", "", err
+ return
}
}
commit abb57b119482e1a1447300dd3acf250569aecbfb
Author: Ward Vandewege <ward at curoverse.com>
Date: Fri Feb 24 17:57:47 2017 -0500
arvados-version-server:
* style improvements: don't stutter
* test improvement: stop printing log output during tests
No issue #
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <wvandewege at veritasgenetics.com>
diff --git a/arvados-version-server.go b/arvados-version-server.go
index 3a768f9..9cb5c05 100644
--- a/arvados-version-server.go
+++ b/arvados-version-server.go
@@ -11,6 +11,7 @@ import (
"git.curoverse.com/arvados.git/sdk/go/config"
"io"
"io/ioutil"
+ "log"
"net"
"net/http"
"os"
@@ -24,20 +25,20 @@ import (
var listener net.Listener
-type logStruct struct {
+type report struct {
Type string
Msg string
}
-type packageStruct struct {
- sourceDir string
- packageName string
- packageType string
- packageVersionType string
- packageVersionPrefix string
+type bundle struct {
+ sourceDir string
+ name string
+ packageType string
+ versionType string
+ versionPrefix string
}
-type returnStruct struct {
+type result struct {
RequestHash string
GitHash string
Versions map[string]map[string]string
@@ -45,13 +46,13 @@ type returnStruct struct {
Elapsed string
}
-type aboutStruct struct {
+type about struct {
Name string
Version string
URL string
}
-type helpStruct struct {
+type help struct {
Usage string
}
@@ -62,251 +63,251 @@ type Config struct {
GitExecutablePath string
ListenPort string
- Packages []packageStruct
+ Packages []bundle
}
var theConfig Config
const defaultConfigPath = "/etc/arvados/version-server/version-server.yml"
-func loadPackages() (packages []packageStruct) {
- packages = []packageStruct{
+func loadPackages() (packages []bundle) {
+ packages = []bundle{
{
- sourceDir: ".",
- packageName: "arvados-src",
- packageType: "distribution",
- packageVersionType: "git",
- packageVersionPrefix: "0.1",
+ sourceDir: ".",
+ name: "arvados-src",
+ packageType: "distribution",
+ versionType: "git",
+ versionPrefix: "0.1",
},
{
- sourceDir: "apps/workbench",
- packageName: "arvados-workbench",
- packageType: "distribution",
- packageVersionType: "git",
- packageVersionPrefix: "0.1",
+ sourceDir: "apps/workbench",
+ name: "arvados-workbench",
+ packageType: "distribution",
+ versionType: "git",
+ versionPrefix: "0.1",
},
{
- sourceDir: "sdk/cwl",
- packageName: "python-arvados-cwl-runner",
- packageType: "distribution",
- packageVersionType: "python",
- packageVersionPrefix: "1.0",
+ sourceDir: "sdk/cwl",
+ name: "python-arvados-cwl-runner",
+ packageType: "distribution",
+ versionType: "python",
+ versionPrefix: "1.0",
},
{
- sourceDir: "sdk/cwl",
- packageName: "arvados-cwl-runner",
- packageType: "python",
- packageVersionType: "python",
- packageVersionPrefix: "1.0",
+ sourceDir: "sdk/cwl",
+ name: "arvados-cwl-runner",
+ packageType: "python",
+ versionType: "python",
+ versionPrefix: "1.0",
},
{
- sourceDir: "sdk/cwl",
- packageName: "arvados/jobs",
- packageType: "docker",
- packageVersionType: "docker",
- packageVersionPrefix: "",
+ sourceDir: "sdk/cwl",
+ name: "arvados/jobs",
+ packageType: "docker",
+ versionType: "docker",
+ versionPrefix: "",
},
{
- sourceDir: "sdk/go/crunchrunner",
- packageName: "crunchrunner",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "sdk/go/crunchrunner",
+ name: "crunchrunner",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "sdk/pam",
- packageName: "libpam-arvados",
- packageType: "distribution",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "sdk/pam",
+ name: "libpam-arvados",
+ packageType: "distribution",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "sdk/pam",
- packageName: "arvados-pam",
- packageType: "python",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "sdk/pam",
+ name: "arvados-pam",
+ packageType: "python",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "sdk/python",
- packageName: "python-arvados-python-client",
- packageType: "distribution",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "sdk/python",
+ name: "python-arvados-python-client",
+ packageType: "distribution",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "sdk/python",
- packageName: "arvados-python-client",
- packageType: "python",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "sdk/python",
+ name: "arvados-python-client",
+ packageType: "python",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/api",
- packageName: "arvados-api-server",
- packageType: "distribution",
- packageVersionType: "git",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/api",
+ name: "arvados-api-server",
+ packageType: "distribution",
+ versionType: "git",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/arv-git-httpd",
- packageName: "arvados-git-httpd",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/arv-git-httpd",
+ name: "arvados-git-httpd",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/crunch-dispatch-local",
- packageName: "crunch-dispatch-local",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/crunch-dispatch-local",
+ name: "crunch-dispatch-local",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/crunch-dispatch-slurm",
- packageName: "crunch-dispatch-slurm",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/crunch-dispatch-slurm",
+ name: "crunch-dispatch-slurm",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/crunch-run",
- packageName: "crunch-run",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/crunch-run",
+ name: "crunch-run",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/crunchstat",
- packageName: "crunchstat",
- packageType: "distribution",
- packageVersionType: "git",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/crunchstat",
+ name: "crunchstat",
+ packageType: "distribution",
+ versionType: "git",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/dockercleaner",
- packageName: "arvados-docker-cleaner",
- packageType: "distribution",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/dockercleaner",
+ name: "arvados-docker-cleaner",
+ packageType: "distribution",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/fuse",
- packageName: "python-arvados-fuse",
- packageType: "distribution",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/fuse",
+ name: "python-arvados-fuse",
+ packageType: "distribution",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/fuse",
- packageName: "arvados_fuse",
- packageType: "python",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/fuse",
+ name: "arvados_fuse",
+ packageType: "python",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/keep-balance",
- packageName: "keep-balance",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/keep-balance",
+ name: "keep-balance",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/keepproxy",
- packageName: "keepproxy",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/keepproxy",
+ name: "keepproxy",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/keepstore",
- packageName: "keepstore",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/keepstore",
+ name: "keepstore",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/keep-web",
- packageName: "keep-web",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/keep-web",
+ name: "keep-web",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/nodemanager",
- packageName: "arvados-node-manager",
- packageType: "distribution",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/nodemanager",
+ name: "arvados-node-manager",
+ packageType: "distribution",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/nodemanager",
- packageName: "arvados-node-manager",
- packageType: "python",
- packageVersionType: "python",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/nodemanager",
+ name: "arvados-node-manager",
+ packageType: "python",
+ versionType: "python",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/ws",
- packageName: "arvados-ws",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/ws",
+ name: "arvados-ws",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "tools/crunchstat-summary",
- packageName: "crunchstat-summary",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "tools/crunchstat-summary",
+ name: "crunchstat-summary",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "tools/keep-block-check",
- packageName: "keep-block-check",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "tools/keep-block-check",
+ name: "keep-block-check",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "tools/keep-exercise",
- packageName: "keep-exercise",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "tools/keep-exercise",
+ name: "keep-exercise",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "tools/keep-rsync",
- packageName: "keep-rsync",
- packageType: "distribution",
- packageVersionType: "go",
- packageVersionPrefix: "0.1",
+ sourceDir: "tools/keep-rsync",
+ name: "keep-rsync",
+ packageType: "distribution",
+ versionType: "go",
+ versionPrefix: "0.1",
},
{
- sourceDir: "sdk/ruby",
- packageName: "arvados",
- packageType: "gem",
- packageVersionType: "ruby",
- packageVersionPrefix: "0.1",
+ sourceDir: "sdk/ruby",
+ name: "arvados",
+ packageType: "gem",
+ versionType: "ruby",
+ versionPrefix: "0.1",
},
{
- sourceDir: "sdk/cli",
- packageName: "arvados-cli",
- packageType: "gem",
- packageVersionType: "ruby",
- packageVersionPrefix: "0.1",
+ sourceDir: "sdk/cli",
+ name: "arvados-cli",
+ packageType: "gem",
+ versionType: "ruby",
+ versionPrefix: "0.1",
},
{
- sourceDir: "services/login-sync",
- packageName: "arvados-login-sync",
- packageType: "gem",
- packageVersionType: "ruby",
- packageVersionPrefix: "0.1",
+ sourceDir: "services/login-sync",
+ name: "arvados-login-sync",
+ packageType: "gem",
+ versionType: "ruby",
+ versionPrefix: "0.1",
},
}
return
}
-func lookupInCache(hash string) (returnStruct, error) {
+func lookupInCache(hash string) (result, error) {
statData, err := os.Stat(theConfig.CacheDirPath)
if os.IsNotExist(err) {
err = os.MkdirAll(theConfig.CacheDirPath, 0700)
@@ -316,19 +317,19 @@ func lookupInCache(hash string) (returnStruct, error) {
} else {
if !statData.IsDir() {
logError([]string{"The path", theConfig.CacheDirPath, "is not a directory"})
- return returnStruct{}, fmt.Errorf("The path %s is not a directory", theConfig.CacheDirPath)
+ return result{}, fmt.Errorf("The path %s is not a directory", theConfig.CacheDirPath)
}
}
file, e := ioutil.ReadFile(theConfig.CacheDirPath + "/" + hash)
if e != nil {
- return returnStruct{}, fmt.Errorf("File error: %v\n", e)
+ return result{}, fmt.Errorf("File error: %v\n", e)
}
- var m returnStruct
+ var m result
err = json.Unmarshal(file, &m)
return m, err
}
-func writeToCache(hash string, data returnStruct) (err error) {
+func writeToCache(hash string, data result) (err error) {
statData, err := os.Stat(theConfig.CacheDirPath)
if os.IsNotExist(err) {
err = os.MkdirAll(theConfig.CacheDirPath, 0700)
@@ -585,17 +586,17 @@ func getPackageVersions(hash string) (versions map[string]map[string]string, git
err = nil
continue
}
- packageName := p.packageName
+ name := p.name
var packageVersion string
- if (p.packageVersionType == "git") || (p.packageVersionType == "go") {
- packageVersion, err = versionFromGit(p.packageVersionPrefix)
+ if (p.versionType == "git") || (p.versionType == "go") {
+ packageVersion, err = versionFromGit(p.versionPrefix)
if err != nil {
return nil, "", err
}
}
- if p.packageVersionType == "go" {
+ if p.versionType == "go" {
var packageTimestamp string
packageTimestamp, err = timestampFromGit()
if err != nil {
@@ -603,31 +604,31 @@ func getPackageVersions(hash string) (versions map[string]map[string]string, git
}
if goSDKTimestamp > packageTimestamp {
- packageVersion = p.packageVersionPrefix + goSDKVersionWithoutPrefix
+ packageVersion = p.versionPrefix + goSDKVersionWithoutPrefix
}
- } else if p.packageVersionType == "python" {
+ } else if p.versionType == "python" {
// Not all of our packages that use our python sdk are automatically
// getting rebuilt when sdk/python changes. Yet.
- if p.packageName == "python-arvados-cwl-runner" {
+ if p.name == "python-arvados-cwl-runner" {
err = pythonSDKVersionCheck(pythonSDKTimestamp)
if err != nil {
return nil, "", err
}
}
- packageVersion, err = pythonVersionFromGit(p.packageVersionPrefix)
+ packageVersion, err = pythonVersionFromGit(p.versionPrefix)
if err != nil {
return nil, "", err
}
- } else if p.packageVersionType == "ruby" {
- packageVersion, err = rubyVersionFromGit(p.packageVersionPrefix)
+ } else if p.versionType == "ruby" {
+ packageVersion, err = rubyVersionFromGit(p.versionPrefix)
if err != nil {
return nil, "", err
}
- } else if p.packageVersionType == "docker" {
+ } else if p.versionType == "docker" {
// the arvados/jobs image version is always the latest of the
// sdk/python and the sdk/cwl version
- if p.packageName == "arvados/jobs" {
+ if p.name == "arvados/jobs" {
err = pythonSDKVersionCheck(pythonSDKTimestamp)
if err != nil {
return nil, "", err
@@ -642,18 +643,18 @@ func getPackageVersions(hash string) (versions map[string]map[string]string, git
if versions[strings.Title(p.packageType)] == nil {
versions[strings.Title(p.packageType)] = make(map[string]string)
}
- versions[strings.Title(p.packageType)][packageName] = packageVersion
+ versions[strings.Title(p.packageType)][name] = packageVersion
}
return
}
func logError(m []string) {
- fmt.Fprintln(os.Stderr, string(marshal(logStruct{"Error", strings.Join(m, " ")})))
+ log.Printf(string(marshal(report{"Error", strings.Join(m, " ")})))
}
func logNotice(m []string) {
- fmt.Fprintln(os.Stderr, string(marshal(logStruct{"Notice", strings.Join(m, " ")})))
+ log.Printf(string(marshal(report{"Notice", strings.Join(m, " ")})))
}
func marshal(message interface{}) (encoded []byte) {
@@ -693,12 +694,12 @@ func packageVersionHandler(w http.ResponseWriter, r *http.Request) {
// Sanity check the input RequestHash
match, err := regexp.MatchString("^([a-z0-9]+|)$", r.URL.Path[11:])
if err != nil {
- m := logStruct{"Error", "Error matching RequestHash"}
+ m := report{"Error", "Error matching RequestHash"}
marshalAndWrite(w, m)
return
}
if !match {
- m := logStruct{"Error", "Invalid RequestHash"}
+ m := report{"Error", "Invalid RequestHash"}
marshalAndWrite(w, m)
return
}
@@ -709,7 +710,7 @@ func packageVersionHandler(w http.ResponseWriter, r *http.Request) {
if len(hash) != 7 && len(hash) != 40 {
hash, err = normalizeRequestedHash(hash)
if err != nil {
- m := logStruct{"Error", err.Error()}
+ m := report{"Error", err.Error()}
marshalAndWrite(w, m)
return
}
@@ -724,11 +725,11 @@ func packageVersionHandler(w http.ResponseWriter, r *http.Request) {
} else {
packageVersions, gitHash, err = getPackageVersions(hash)
if err != nil {
- m := logStruct{"Error", err.Error()}
+ m := report{"Error", err.Error()}
marshalAndWrite(w, m)
return
}
- m := returnStruct{"", gitHash, packageVersions, true, ""}
+ m := result{"", gitHash, packageVersions, true, ""}
err = writeToCache(hash, m)
if err != nil {
logError([]string{"Unable to save entry in cache directory", theConfig.CacheDirPath})
@@ -736,19 +737,19 @@ func packageVersionHandler(w http.ResponseWriter, r *http.Request) {
cached = false
}
- m := returnStruct{hash, gitHash, packageVersions, cached, fmt.Sprintf("%v", time.Since(start))}
+ m := result{hash, gitHash, packageVersions, cached, fmt.Sprintf("%v", time.Since(start))}
marshalAndWrite(w, m)
}
func aboutHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
- m := aboutStruct{"Arvados Version Server", "0.1", "https://arvados.org"}
+ m := about{"Arvados Version Server", "0.1", "https://arvados.org"}
marshalAndWrite(w, m)
}
func helpHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
- m := helpStruct{"GET /v1/commit/ or GET /v1/commit/git-commit or GET /v1/about or GET /v1/help"}
+ m := help{"GET /v1/commit/ or GET /v1/commit/git-commit or GET /v1/about or GET /v1/help"}
marshalAndWrite(w, m)
}
diff --git a/arvados-version-server_test.go b/arvados-version-server_test.go
index bbbacdc..347ab18 100644
--- a/arvados-version-server_test.go
+++ b/arvados-version-server_test.go
@@ -111,12 +111,22 @@ func waitForListener() {
}
}
+func (s *ServerNotRequiredSuite) SetUpTest(c *C) {
+ // Discard standard log output
+ log.SetOutput(ioutil.Discard)
+}
+
func (s *ServerRequiredSuite) SetUpTest(c *C) {
- //arvadostest.ResetEnv()
+ // Discard standard log output
+ log.SetOutput(ioutil.Discard)
}
func (s *ServerRequiredSuite) TearDownSuite(c *C) {
- //arvadostest.StopKeep(2)
+ log.SetOutput(os.Stderr)
+}
+
+func (s *ServerNotRequiredSuite) TearDownSuite(c *C) {
+ log.SetOutput(os.Stderr)
}
func (s *ServerRequiredSuite) TestResults(c *C) {
commit 7919cb80fd9c8a8d3440af87ec7d082453e94e2f
Author: Ward Vandewege <ward at curoverse.com>
Date: Tue Feb 14 13:27:32 2017 -0500
Add a new component, arvados-version-server.
No issue #
Arvados-DCO-1.1-Signed-off-by: Ward Vandewege <wvandewege at veritasgenetics.com>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cfce019
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+arvados-version-server
diff --git a/README b/README
new file mode 100644
index 0000000..0ade59d
--- /dev/null
+++ b/README
@@ -0,0 +1,23 @@
+
+Build:
+
+ go build
+
+Test:
+
+ go test
+
+Run:
+
+ ./arvados-version-server
+
+Config file path:
+
+ /etc/arvados/version-server/version-server.yml
+
+Sample config file:
+
+DirPath: "/tmp/arvados-version-server-checkout"
+CacheDirPath: "/tmp/arvados-version-server-cache"
+GitExecutablePath: "/usr/bin/git"
+ListenPort: 8080
diff --git a/arvados-version-server.go b/arvados-version-server.go
new file mode 100644
index 0000000..3a768f9
--- /dev/null
+++ b/arvados-version-server.go
@@ -0,0 +1,848 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+package main
+
+import (
+ "encoding/json"
+ "flag"
+ "fmt"
+ "git.curoverse.com/arvados.git/sdk/go/config"
+ "io"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "os"
+ "os/exec"
+ "os/signal"
+ "regexp"
+ "strings"
+ "syscall"
+ "time"
+)
+
+var listener net.Listener
+
+type logStruct struct {
+ Type string
+ Msg string
+}
+
+type packageStruct struct {
+ sourceDir string
+ packageName string
+ packageType string
+ packageVersionType string
+ packageVersionPrefix string
+}
+
+type returnStruct struct {
+ RequestHash string
+ GitHash string
+ Versions map[string]map[string]string
+ Cached bool
+ Elapsed string
+}
+
+type aboutStruct struct {
+ Name string
+ Version string
+ URL string
+}
+
+type helpStruct struct {
+ Usage string
+}
+
+// Config structure
+type Config struct {
+ DirPath string
+ CacheDirPath string
+ GitExecutablePath string
+ ListenPort string
+
+ Packages []packageStruct
+}
+
+var theConfig Config
+
+const defaultConfigPath = "/etc/arvados/version-server/version-server.yml"
+
+func loadPackages() (packages []packageStruct) {
+ packages = []packageStruct{
+ {
+ sourceDir: ".",
+ packageName: "arvados-src",
+ packageType: "distribution",
+ packageVersionType: "git",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "apps/workbench",
+ packageName: "arvados-workbench",
+ packageType: "distribution",
+ packageVersionType: "git",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "sdk/cwl",
+ packageName: "python-arvados-cwl-runner",
+ packageType: "distribution",
+ packageVersionType: "python",
+ packageVersionPrefix: "1.0",
+ },
+ {
+ sourceDir: "sdk/cwl",
+ packageName: "arvados-cwl-runner",
+ packageType: "python",
+ packageVersionType: "python",
+ packageVersionPrefix: "1.0",
+ },
+ {
+ sourceDir: "sdk/cwl",
+ packageName: "arvados/jobs",
+ packageType: "docker",
+ packageVersionType: "docker",
+ packageVersionPrefix: "",
+ },
+ {
+ sourceDir: "sdk/go/crunchrunner",
+ packageName: "crunchrunner",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "sdk/pam",
+ packageName: "libpam-arvados",
+ packageType: "distribution",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "sdk/pam",
+ packageName: "arvados-pam",
+ packageType: "python",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "sdk/python",
+ packageName: "python-arvados-python-client",
+ packageType: "distribution",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "sdk/python",
+ packageName: "arvados-python-client",
+ packageType: "python",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/api",
+ packageName: "arvados-api-server",
+ packageType: "distribution",
+ packageVersionType: "git",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/arv-git-httpd",
+ packageName: "arvados-git-httpd",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/crunch-dispatch-local",
+ packageName: "crunch-dispatch-local",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/crunch-dispatch-slurm",
+ packageName: "crunch-dispatch-slurm",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/crunch-run",
+ packageName: "crunch-run",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/crunchstat",
+ packageName: "crunchstat",
+ packageType: "distribution",
+ packageVersionType: "git",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/dockercleaner",
+ packageName: "arvados-docker-cleaner",
+ packageType: "distribution",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/fuse",
+ packageName: "python-arvados-fuse",
+ packageType: "distribution",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/fuse",
+ packageName: "arvados_fuse",
+ packageType: "python",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/keep-balance",
+ packageName: "keep-balance",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/keepproxy",
+ packageName: "keepproxy",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/keepstore",
+ packageName: "keepstore",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/keep-web",
+ packageName: "keep-web",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/nodemanager",
+ packageName: "arvados-node-manager",
+ packageType: "distribution",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/nodemanager",
+ packageName: "arvados-node-manager",
+ packageType: "python",
+ packageVersionType: "python",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/ws",
+ packageName: "arvados-ws",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "tools/crunchstat-summary",
+ packageName: "crunchstat-summary",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "tools/keep-block-check",
+ packageName: "keep-block-check",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "tools/keep-exercise",
+ packageName: "keep-exercise",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "tools/keep-rsync",
+ packageName: "keep-rsync",
+ packageType: "distribution",
+ packageVersionType: "go",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "sdk/ruby",
+ packageName: "arvados",
+ packageType: "gem",
+ packageVersionType: "ruby",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "sdk/cli",
+ packageName: "arvados-cli",
+ packageType: "gem",
+ packageVersionType: "ruby",
+ packageVersionPrefix: "0.1",
+ },
+ {
+ sourceDir: "services/login-sync",
+ packageName: "arvados-login-sync",
+ packageType: "gem",
+ packageVersionType: "ruby",
+ packageVersionPrefix: "0.1",
+ },
+ }
+ return
+}
+
+func lookupInCache(hash string) (returnStruct, error) {
+ statData, err := os.Stat(theConfig.CacheDirPath)
+ if os.IsNotExist(err) {
+ err = os.MkdirAll(theConfig.CacheDirPath, 0700)
+ if err != nil {
+ logError([]string{"Error creating directory", theConfig.CacheDirPath, ":", err.Error()})
+ }
+ } else {
+ if !statData.IsDir() {
+ logError([]string{"The path", theConfig.CacheDirPath, "is not a directory"})
+ return returnStruct{}, fmt.Errorf("The path %s is not a directory", theConfig.CacheDirPath)
+ }
+ }
+ file, e := ioutil.ReadFile(theConfig.CacheDirPath + "/" + hash)
+ if e != nil {
+ return returnStruct{}, fmt.Errorf("File error: %v\n", e)
+ }
+ var m returnStruct
+ err = json.Unmarshal(file, &m)
+ return m, err
+}
+
+func writeToCache(hash string, data returnStruct) (err error) {
+ statData, err := os.Stat(theConfig.CacheDirPath)
+ if os.IsNotExist(err) {
+ err = os.MkdirAll(theConfig.CacheDirPath, 0700)
+ if err != nil {
+ logError([]string{"Error creating directory", theConfig.CacheDirPath, ":", err.Error()})
+ }
+ } else {
+ if !statData.IsDir() {
+ logError([]string{"The path", theConfig.CacheDirPath, "is not a directory"})
+ return fmt.Errorf("The path %s is not a directory", theConfig.CacheDirPath)
+ }
+ }
+
+ jsonData, err := json.Marshal(data)
+ if err != nil {
+ return
+ }
+ err = ioutil.WriteFile(theConfig.CacheDirPath+"/"+hash, jsonData, 0644)
+ return
+}
+
+func prepareGitPath(hash string) error {
+ statData, err := os.Stat(theConfig.DirPath)
+ if os.IsNotExist(err) {
+ err = os.MkdirAll(theConfig.DirPath, 0700)
+ if err != nil {
+ logError([]string{"Error creating directory", theConfig.DirPath, ":", err.Error()})
+ return fmt.Errorf("Error creating directory %s", theConfig.DirPath)
+ }
+ cmdArgs := []string{"clone", "https://github.com/curoverse/arvados.git", theConfig.DirPath}
+ if _, err = exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output(); err != nil {
+ logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
+ return fmt.Errorf("There was an error cloning the repository")
+ }
+ } else {
+ if !statData.IsDir() {
+ logError([]string{"The path", theConfig.DirPath, "is not a directory"})
+ return fmt.Errorf("The path %s is not a directory", theConfig.DirPath)
+ }
+ }
+ return nil
+}
+
+func prepareGitCheckout(hash string) (string, error) {
+ err := prepareGitPath(hash)
+ if err != nil {
+ return "", err
+ }
+ err = os.Chdir(theConfig.DirPath)
+ if err != nil {
+ logError([]string{"Error changing directory to", theConfig.DirPath})
+ return "", fmt.Errorf("Error changing directory to %s", theConfig.DirPath)
+ }
+ cmdArgs := []string{"fetch", "--all"}
+ if _, err := exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output(); err != nil {
+ logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
+ return "", fmt.Errorf("There was an error fetching all remotes")
+ }
+ if hash == "" {
+ hash = "master"
+ }
+ cmdArgs = []string{"checkout", hash}
+ if _, err := exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output(); err != nil {
+ logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
+ return "", fmt.Errorf("There was an error checking out the requested revision")
+ }
+ if hash == "master" {
+ cmdArgs := []string{"reset", "--hard", "origin/master"}
+ if _, err := exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output(); err != nil {
+ logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
+ return "", fmt.Errorf("There was an error fetching all remotes")
+ }
+ }
+ return "", nil
+}
+
+// Generates the hash for the latest git commit for the current working directory
+func gitHashFull() (string, error) {
+ cmdArgs := []string{"log", "-n1", "--first-parent", "--max-count=1", "--format=format:%H", "."}
+ cmdOut, err := exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output()
+ if err != nil {
+ logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
+ return "", fmt.Errorf("There was an error getting the git hash for this revision")
+ }
+ return string(cmdOut), nil
+}
+
+// Generates a version number from the git log for the current working directory
+func versionFromGit(prefix string) (string, error) {
+ gitTs, err := getGitTs()
+ if err != nil {
+ return "", err
+ }
+ cmdArgs := []string{"log", "-n1", "--first-parent", "--max-count=1", "--format=format:%h", "."}
+ gitHash, err := exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output()
+ if err != nil {
+ logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
+ return "", fmt.Errorf("There was an error getting the git hash for this revision")
+ }
+ cmdName := "/bin/date"
+ cmdArgs = []string{"-ud", "@" + string(gitTs), "+%Y%m%d%H%M%S"}
+ date, err := exec.Command(cmdName, cmdArgs...).Output()
+ if err != nil {
+ logError([]string{"There was an error running the command ", cmdName, strings.Join(cmdArgs, " "), err.Error()})
+ return "", fmt.Errorf("There was an error converting the datestamp for this revision")
+ }
+
+ return fmt.Sprintf("%s.%s.%s", strings.TrimSpace(prefix), strings.TrimSpace(string(date)), strings.TrimSpace(string(gitHash))), nil
+}
+
+// Generates a python package version number from the git log for the current working directory
+func rubyVersionFromGit(prefix string) (string, error) {
+ gitTs, err := getGitTs()
+ if err != nil {
+ return "", err
+ }
+ cmdName := "/bin/date"
+ cmdArgs := []string{"-ud", "@" + string(gitTs), "+%Y%m%d%H%M%S"}
+ date, err := exec.Command(cmdName, cmdArgs...).Output()
+ if err != nil {
+ logError([]string{"There was an error running the command ", cmdName, strings.Join(cmdArgs, " "), err.Error()})
+ return "", fmt.Errorf("There was an error converting the datestamp for this revision")
+ }
+
+ return fmt.Sprintf("%s.%s", strings.TrimSpace(prefix), strings.TrimSpace(string(date))), nil
+}
+
+// Generates a python package version number from the git log for the current working directory
+func pythonVersionFromGit(prefix string) (string, error) {
+ rv, err := rubyVersionFromGit(prefix)
+ if err != nil {
+ return "", err
+ }
+ return rv, nil
+}
+
+// Generates a docker image version number from the git log for the current working directory
+func dockerVersionFromGit() (string, error) {
+ rv, err := gitHashFull()
+ if err != nil {
+ return "", err
+ }
+ return rv, nil
+}
+
+func getGitTs() (gitTs []byte, err error) {
+ cmdArgs := []string{"log", "-n1", "--first-parent", "--max-count=1", "--format=format:%ct", "."}
+ gitTs, err = exec.Command(theConfig.GitExecutablePath, cmdArgs...).Output()
+ if err != nil {
+ logError([]string{"There was an error running the command ", theConfig.GitExecutablePath, strings.Join(cmdArgs, " "), err.Error()})
+ return nil, fmt.Errorf("There was an error getting the git hash for this revision")
+ }
+ return
+}
+
+// Generates a timestamp from the git log for the current working directory
+func timestampFromGit() (string, error) {
+ gitTs, err := getGitTs()
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%s", strings.TrimSpace(string(gitTs))), nil
+}
+
+func normalizeRequestedHash(hash string) (string, error) {
+ _, err := prepareGitCheckout(hash)
+ if err != nil {
+ return "", err
+ }
+
+ // Get the git hash for the tree
+ var gitHash string
+ gitHash, err = gitHashFull()
+ if err != nil {
+ return "", err
+ }
+
+ return gitHash, nil
+}
+
+func getPackageVersionsWorker(hash string) (gitHash string, goSDKTimestamp string, goSDKVersionWithoutPrefix string, pythonSDKTimestamp string, err error) {
+ _, err = prepareGitCheckout(hash)
+ if err != nil {
+ return "", "", "", "", err
+ }
+
+ // Get the git hash for the tree
+ gitHash, err = gitHashFull()
+ if err != nil {
+ return "", "", "", "", err
+ }
+
+ // Get the git timestamp and version string for the sdk/go directory
+ err = os.Chdir(theConfig.DirPath + "/sdk/go")
+ if err != nil {
+ goSDKTimestamp = ""
+ goSDKVersionWithoutPrefix = ""
+ err = nil
+ } else {
+ goSDKTimestamp, err = timestampFromGit()
+ if err != nil {
+ return "", "", "", "", err
+ }
+ goSDKVersionWithoutPrefix, err = versionFromGit("")
+ if err != nil {
+ return "", "", "", "", err
+ }
+ }
+
+ // Get the git timestamp and version string for the sdk/python directory
+ err = os.Chdir(theConfig.DirPath + "/sdk/python")
+ if err != nil {
+ pythonSDKTimestamp = ""
+ err = nil
+ } else {
+ pythonSDKTimestamp, err = timestampFromGit()
+ if err != nil {
+ return "", "", "", "", err
+ }
+ }
+
+ return
+}
+
+func pythonSDKVersionCheck(pythonSDKTimestamp string) (err error) {
+ var packageTimestamp string
+ packageTimestamp, err = timestampFromGit()
+ if err != nil {
+ return
+ }
+
+ if pythonSDKTimestamp > packageTimestamp {
+ err = os.Chdir(theConfig.DirPath + "/sdk/python")
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
+func getPackageVersions(hash string) (versions map[string]map[string]string, gitHash string, err error) {
+ versions = make(map[string]map[string]string)
+
+ gitHash, goSDKTimestamp, goSDKVersionWithoutPrefix, pythonSDKTimestamp, err := getPackageVersionsWorker(hash)
+ if err != nil {
+ return nil, "", err
+ }
+
+ for _, p := range theConfig.Packages {
+ err = os.Chdir(theConfig.DirPath + "/" + p.sourceDir)
+ if err != nil {
+ // Skip those packages for which the source directory doesn't exist
+ // in this revision of the source tree.
+ err = nil
+ continue
+ }
+ packageName := p.packageName
+
+ var packageVersion string
+
+ if (p.packageVersionType == "git") || (p.packageVersionType == "go") {
+ packageVersion, err = versionFromGit(p.packageVersionPrefix)
+ if err != nil {
+ return nil, "", err
+ }
+ }
+ if p.packageVersionType == "go" {
+ var packageTimestamp string
+ packageTimestamp, err = timestampFromGit()
+ if err != nil {
+ return nil, "", err
+ }
+
+ if goSDKTimestamp > packageTimestamp {
+ packageVersion = p.packageVersionPrefix + goSDKVersionWithoutPrefix
+ }
+ } else if p.packageVersionType == "python" {
+ // Not all of our packages that use our python sdk are automatically
+ // getting rebuilt when sdk/python changes. Yet.
+ if p.packageName == "python-arvados-cwl-runner" {
+ err = pythonSDKVersionCheck(pythonSDKTimestamp)
+ if err != nil {
+ return nil, "", err
+ }
+ }
+
+ packageVersion, err = pythonVersionFromGit(p.packageVersionPrefix)
+ if err != nil {
+ return nil, "", err
+ }
+ } else if p.packageVersionType == "ruby" {
+ packageVersion, err = rubyVersionFromGit(p.packageVersionPrefix)
+ if err != nil {
+ return nil, "", err
+ }
+ } else if p.packageVersionType == "docker" {
+ // the arvados/jobs image version is always the latest of the
+ // sdk/python and the sdk/cwl version
+ if p.packageName == "arvados/jobs" {
+ err = pythonSDKVersionCheck(pythonSDKTimestamp)
+ if err != nil {
+ return nil, "", err
+ }
+ }
+ packageVersion, err = dockerVersionFromGit()
+ if err != nil {
+ return nil, "", err
+ }
+ }
+
+ if versions[strings.Title(p.packageType)] == nil {
+ versions[strings.Title(p.packageType)] = make(map[string]string)
+ }
+ versions[strings.Title(p.packageType)][packageName] = packageVersion
+ }
+
+ return
+}
+
+func logError(m []string) {
+ fmt.Fprintln(os.Stderr, string(marshal(logStruct{"Error", strings.Join(m, " ")})))
+}
+
+func logNotice(m []string) {
+ fmt.Fprintln(os.Stderr, string(marshal(logStruct{"Notice", strings.Join(m, " ")})))
+}
+
+func marshal(message interface{}) (encoded []byte) {
+ encoded, err := json.Marshal(message)
+ if err != nil {
+ // do not call logError here because that would create an infinite loop
+ fmt.Fprintln(os.Stderr, "{\"Error\": \"Unable to marshal message into json:", message, "\"}")
+ return nil
+ }
+ return
+}
+
+func marshalAndWrite(w io.Writer, message interface{}) {
+ b := marshal(message)
+ if b == nil {
+ errorMessage := "{\n\"Error\": \"Unspecified error\"\n}"
+ _, err := io.WriteString(w, errorMessage)
+ if err != nil {
+ // do not call logError (it calls marshal and that function has already failed at this point)
+ fmt.Fprintln(os.Stderr, "{\"Error\": \"Unable to write message to client\"}")
+ }
+ } else {
+ _, err := w.Write(b)
+ if err != nil {
+ logError([]string{"Unable to write message to client:", string(b)})
+ }
+ }
+}
+
+func packageVersionHandler(w http.ResponseWriter, r *http.Request) {
+ start := time.Now()
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+
+ var packageVersions map[string]map[string]string
+ var cached bool
+
+ // Sanity check the input RequestHash
+ match, err := regexp.MatchString("^([a-z0-9]+|)$", r.URL.Path[11:])
+ if err != nil {
+ m := logStruct{"Error", "Error matching RequestHash"}
+ marshalAndWrite(w, m)
+ return
+ }
+ if !match {
+ m := logStruct{"Error", "Invalid RequestHash"}
+ marshalAndWrite(w, m)
+ return
+ }
+
+ hash := r.URL.Path[11:]
+
+ // Empty hash or non-standard hash length? Normalize it.
+ if len(hash) != 7 && len(hash) != 40 {
+ hash, err = normalizeRequestedHash(hash)
+ if err != nil {
+ m := logStruct{"Error", err.Error()}
+ marshalAndWrite(w, m)
+ return
+ }
+ }
+
+ var gitHash string
+ rs, err := lookupInCache(hash)
+ if err == nil {
+ packageVersions = rs.Versions
+ gitHash = rs.GitHash
+ cached = true
+ } else {
+ packageVersions, gitHash, err = getPackageVersions(hash)
+ if err != nil {
+ m := logStruct{"Error", err.Error()}
+ marshalAndWrite(w, m)
+ return
+ }
+ m := returnStruct{"", gitHash, packageVersions, true, ""}
+ err = writeToCache(hash, m)
+ if err != nil {
+ logError([]string{"Unable to save entry in cache directory", theConfig.CacheDirPath})
+ }
+ cached = false
+ }
+
+ m := returnStruct{hash, gitHash, packageVersions, cached, fmt.Sprintf("%v", time.Since(start))}
+ marshalAndWrite(w, m)
+}
+
+func aboutHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ m := aboutStruct{"Arvados Version Server", "0.1", "https://arvados.org"}
+ marshalAndWrite(w, m)
+}
+
+func helpHandler(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+ m := helpStruct{"GET /v1/commit/ or GET /v1/commit/git-commit or GET /v1/about or GET /v1/help"}
+ marshalAndWrite(w, m)
+}
+
+func parseFlags() (configPath *string) {
+
+ flags := flag.NewFlagSet("arvados-version-server", flag.ExitOnError)
+ flags.Usage = func() { usage(flags) }
+
+ configPath = flags.String(
+ "config",
+ defaultConfigPath,
+ "`path` to YAML configuration file")
+
+ // Parse args; omit the first arg which is the command name
+ err := flags.Parse(os.Args[1:])
+ if err != nil {
+ logError([]string{"Unable to parse command line arguments:", err.Error()})
+ os.Exit(1)
+ }
+
+ return
+}
+
+func main() {
+ err := os.Setenv("TZ", "UTC")
+ if err != nil {
+ logError([]string{"Error setting environment variable:", err.Error()})
+ os.Exit(1)
+ }
+
+ configPath := parseFlags()
+
+ err = readConfig(&theConfig, *configPath, defaultConfigPath)
+ if err != nil {
+ logError([]string{"Unable to start Arvados Version Server:", err.Error()})
+ os.Exit(1)
+ }
+
+ theConfig.Packages = loadPackages()
+
+ if theConfig.DirPath == "" {
+ theConfig.DirPath = "/tmp/arvados-version-server-checkout"
+ }
+
+ if theConfig.CacheDirPath == "" {
+ theConfig.CacheDirPath = "/tmp/arvados-version-server-cache"
+ }
+
+ if theConfig.GitExecutablePath == "" {
+ theConfig.GitExecutablePath = "/usr/bin/git"
+ }
+
+ if theConfig.ListenPort == "" {
+ theConfig.ListenPort = "80"
+ }
+
+ http.HandleFunc("/v1/commit/", packageVersionHandler)
+ http.HandleFunc("/v1/about", aboutHandler)
+ http.HandleFunc("/v1/help", helpHandler)
+ http.HandleFunc("/v1", helpHandler)
+ http.HandleFunc("/", helpHandler)
+ logNotice([]string{"Arvados Version Server listening on port", theConfig.ListenPort})
+
+ listener, err = net.Listen("tcp", ":"+theConfig.ListenPort)
+
+ if err != nil {
+ logError([]string{"Unable to start Arvados Version Server:", err.Error()})
+ os.Exit(1)
+ }
+
+ // Shut down the server gracefully (by closing the listener)
+ // if SIGTERM is received.
+ term := make(chan os.Signal, 1)
+ go func(sig <-chan os.Signal) {
+ <-sig
+ logError([]string{"caught signal"})
+ _ = listener.Close()
+ }(term)
+ signal.Notify(term, syscall.SIGTERM)
+ signal.Notify(term, syscall.SIGINT)
+
+ // Start serving requests.
+ _ = http.Serve(listener, nil)
+ // http.Serve returns an error when it gets the term or int signal
+
+ logNotice([]string{"Arvados Version Server shutting down"})
+
+}
+
+func readConfig(cfg interface{}, path string, defaultConfigPath string) error {
+ err := config.LoadFile(cfg, path)
+ if err != nil && os.IsNotExist(err) && path == defaultConfigPath {
+ logNotice([]string{"Config not specified. Continue with default configuration."})
+ err = nil
+ }
+ return err
+}
diff --git a/arvados-version-server.service b/arvados-version-server.service
new file mode 100644
index 0000000..ffc318c
--- /dev/null
+++ b/arvados-version-server.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Arvados version server
+Documentation=https://doc.arvados.org/
+After=network.target
+AssertPathExists=/etc/arvados/version-server/version-server.yml
+
+[Service]
+Type=notify
+ExecStart=/usr/bin/arvados-version-server
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/arvados-version-server_test.go b/arvados-version-server_test.go
new file mode 100644
index 0000000..bbbacdc
--- /dev/null
+++ b/arvados-version-server_test.go
@@ -0,0 +1,275 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+package main
+
+import (
+ "fmt"
+ . "gopkg.in/check.v1"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "testing"
+ "time"
+)
+
+// Hook gocheck into the "go test" runner.
+func Test(t *testing.T) { TestingT(t) }
+
+// Gocheck boilerplate
+var _ = Suite(&ServerRequiredSuite{})
+var _ = Suite(&ServerNotRequiredSuite{})
+
+type ServerRequiredSuite struct{}
+type ServerNotRequiredSuite struct{}
+
+var tmpConfigFileName string
+
+func closeListener() {
+ if listener != nil {
+ listener.Close()
+ }
+}
+
+func (s *ServerNotRequiredSuite) TestConfig(c *C) {
+ var config Config
+
+ // A specified but non-existing config path needs to result in an error
+ err := readConfig(&config, "/nosuchdir89j7879/8hjwr7ojgyy7", defaultConfigPath)
+ c.Assert(err, NotNil)
+
+ // No configuration file but default configuration path specified
+ // should result in the default config being used
+ err = readConfig(&config, "/nosuchdir89j7879/8hjwr7ojgyy7", "/nosuchdir89j7879/8hjwr7ojgyy7")
+ c.Assert(err, IsNil)
+
+ c.Check(config.DirPath, Equals, "")
+ c.Check(config.CacheDirPath, Equals, "")
+ c.Check(config.GitExecutablePath, Equals, "")
+ c.Check(config.ListenPort, Equals, "")
+
+ // Test parsing of config data
+ tmpfile, err := ioutil.TempFile(os.TempDir(), "config")
+ c.Check(err, IsNil)
+ defer os.Remove(tmpfile.Name())
+
+ argsS := `{"DirPath": "/x/y", "CacheDirPath": "/x/z", "GitExecutablePath": "/usr/local/bin/gitexecutable", "ListenPort": "12345"}`
+ _, err = tmpfile.Write([]byte(argsS))
+ c.Check(err, IsNil)
+
+ err = readConfig(&config, tmpfile.Name(), defaultConfigPath)
+ c.Assert(err, IsNil)
+
+ c.Check(config.DirPath, Equals, "/x/y")
+ c.Check(config.CacheDirPath, Equals, "/x/z")
+ c.Check(config.GitExecutablePath, Equals, "/usr/local/bin/gitexecutable")
+ c.Check(config.ListenPort, Equals, "12345")
+
+}
+
+func (s *ServerNotRequiredSuite) TestFlags(c *C) {
+
+ args := []string{"arvados-version-server"}
+ os.Args = append(args)
+ //go main()
+
+}
+
+func runServer(c *C) {
+ tmpfile, err := ioutil.TempFile(os.TempDir(), "config")
+ c.Check(err, IsNil)
+
+ tmpConfigFileName = tmpfile.Name()
+
+ argsS := `{"DirPath": "", "CacheDirPath": "", "GitExecutablePath": "", "ListenPort": "12345"}`
+ _, err = tmpfile.Write([]byte(argsS))
+ c.Check(err, IsNil)
+
+ args := []string{"arvados-version-server"}
+ os.Args = append(args, "-config", tmpfile.Name())
+ listener = nil
+ go main()
+ waitForListener()
+}
+
+func clearCache(c *C) {
+ err := os.RemoveAll(theConfig.CacheDirPath)
+ c.Check(err, IsNil)
+}
+
+func waitForListener() {
+ const (
+ ms = 5
+ )
+ for i := 0; listener == nil && i < 10000; i += ms {
+ time.Sleep(ms * time.Millisecond)
+ }
+ if listener == nil {
+ log.Fatalf("Timed out waiting for listener to start")
+ }
+}
+
+func (s *ServerRequiredSuite) SetUpTest(c *C) {
+ //arvadostest.ResetEnv()
+}
+
+func (s *ServerRequiredSuite) TearDownSuite(c *C) {
+ //arvadostest.StopKeep(2)
+}
+
+func (s *ServerRequiredSuite) TestResults(c *C) {
+ runServer(c)
+ clearCache(c)
+ defer closeListener()
+ defer os.Remove(tmpConfigFileName)
+
+ // Test the about handler
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/about"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"Name\":\"Arvados Version Server\".*")
+ }
+
+ // Test the help handler
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/help"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"Usage\":\"GET /v1/commit/ or GET /v1/commit/git-commit or GET /v1/about or GET /v1/help\".*")
+ }
+
+ // Check the arvados-src version string for the first commit
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/155848c15844554a5d5fd50f9577aa2e19767d9e"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20130104011935.155848c\".*")
+ }
+
+ // Check the arvados-src version string for a more recent commit
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/9c1a28719df89a68b83cee07e3e0ab87c1712f69"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20161208152419.9c1a287\".*")
+ }
+
+ // Check the arvados-src version string for a weirdly truncated commit
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/9c1a28719df89"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"arvados-src\":\"0.1.20161208152419.9c1a287\".*")
+ }
+
+ // Check an invalid request hash
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/____"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"Type\":\"Error\".*")
+ c.Check(string(body), Matches, ".*\"Msg\":\"Invalid RequestHash\".*")
+ }
+
+ // Check an invalid request hash of improper length
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"Type\":\"Error\".*")
+ c.Check(string(body), Matches, ".*\"Msg\":\"There was an error checking out the requested revision\".*")
+ }
+
+ // Check the python-arvados-cwl-runner version string for a *merge* commit where the python sdk version takes precedence
+ // This does not test the "if pythonSDKTimestamp > packageTimestamp" conditional block in func pythonSDKVersionCheck
+ // which appears to be a consequence of the --first-parent argument we pass to git log (exactly why, I don't understand yet)
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/965565ddc62635928a6b043158fd683738961c8c"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"python-arvados-cwl-runner\":\"1.0.20161216221537\".*")
+ }
+
+ // Check the python-arvados-cwl-runner version string for a non-merge commit where the python sdk version takes precedence
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/697e73b0605b6c182f1051e97ed370d5afa7d954"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ body, err := ioutil.ReadAll(resp.Body)
+ c.Check(string(body), Matches, ".*\"python-arvados-cwl-runner\":\"1.0.20161216215418\".*")
+ }
+
+ // Check passing 'master' as revision
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/master"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ _, err = ioutil.ReadAll(resp.Body)
+ // c.Check(string(body), Matches, ".*\"python-arvados-cwl-runner\":\"1.0.20161216215418\".*")
+ }
+
+ // Check passing '' as revision
+ {
+ client := http.Client{}
+ req, err := http.NewRequest("GET",
+ fmt.Sprintf("http://%s/%s", listener.Addr().String(), "v1/commit/"),
+ nil)
+ resp, err := client.Do(req)
+ c.Check(err, Equals, nil)
+ c.Check(resp.StatusCode, Equals, 200)
+ _, err = ioutil.ReadAll(resp.Body)
+ // c.Check(string(body), Matches, ".*\"python-arvados-cwl-runner\":\"1.0.20161216215418\".*")
+ }
+
+}
diff --git a/usage.go b/usage.go
new file mode 100644
index 0000000..b5ee85b
--- /dev/null
+++ b/usage.go
@@ -0,0 +1,32 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+)
+
+var exampleConfigFile = []byte(`
+dirPath: "/tmp/arvados-version-server-checkout"
+cacheDirPath: "/tmp/arvados-version-server-cache"
+gitExecutablePath: "/usr/bin/git"
+listenPort: 8080
+`)
+
+func usage(fs *flag.FlagSet) {
+ fmt.Fprintf(os.Stderr, `
+Arvados Version Server is a JSON REST service that generates package version
+numbers for a given git commit hash.
+
+Options:
+`)
+ fs.PrintDefaults()
+ fmt.Fprintf(os.Stderr, `
+Example config file:
+%s
+`, exampleConfigFile)
+}
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list