Skip to content

Commit

Permalink
version: Add a version command
Browse files Browse the repository at this point in the history
And adjust 'runc --version' to print exactly the same content.

The:

  $ COMMAND --version

interface is a popular one for this information and makes a lot of
sense for single-action commands.  For example, printf(1) [1] is only
ever going to do one meaningful thing, so --version, --help, and other
command-like actions work well as options.

Umbrella commands with multiple sub-commands, on the other hand, have
a more consistent interface if '... and exit' actions get their own
sub-commands.  That allows you to declare an interface like:

  $ COMMAND [global-options] SUB-COMMAND [sub-command-specific-options] [sub-command-specific-arguments]

without having to say "except if you use a sub-command-like global
option, in which case SUB-COMMAND is not allowed".

With this commit, we add support for 'version' while keeping
--version, because while 'version' makes more sense for umbrella
commands, a user may not know if runc is an umbrella command when they
ask for the version.

Existing umbrella commands are not particularly consistent:

* git(1) supports both --version and 'version', --help and 'help'.
* btrfs(8) supports both --version and 'version', --help and 'help'.
* ip(1) supports -V / -Version and 'help'.
* npm supports 'version' and 'help'.
* pip supports '--version', --help and 'help'.

Setting .Version to the empty string takes advantage of the {{if
.Version}} conditional [2] to avoid --help showing:

  VERSION:
     0.0.0

because we are no longer setting .Version.  I floated a few options
[4], and Mike Brown (the only one with a preference) was in favor of
dropping the VERSION section [5] (which turned out to not need a
AppHelpTemplate adjustment ;).

The help tests ensure that attempting to remove "VERSION" from the
help output does not change the output (i.e. that the output didn't
contain "VERSION" to begin with).  That protects us from subsequent
urfave/cli changes breaking the empty-string .Version approach.

[1]: http://www.man7.org/linux/man-pages/man1/printf.1.html
[2]: /~https://github.com/urfave/cli/blob/v1.18.1/README.md#customization-1
[3]: #940 (comment)
[4]: #940 (comment)
[5]: #940 (comment)

Signed-off-by: W. Trevor King <wking@tremily.us>
  • Loading branch information
wking committed Sep 8, 2016
1 parent 99c683a commit e09dd4f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 20 deletions.
22 changes: 4 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,11 @@ package main
import (
"fmt"
"os"
"strings"

"github.com/Sirupsen/logrus"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli"
)

// version will be populated by the Makefile, read from
// VERSION file of the source code.
var version = ""

// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""

const (
specConfig = "config.json"
usage = `Open Container Initiative runtime
Expand Down Expand Up @@ -49,16 +39,11 @@ func main() {
app := cli.NewApp()
app.Name = "runc"
app.Usage = usage
app.Version = ""

var v []string
if version != "" {
v = append(v, version)
}
if gitCommit != "" {
v = append(v, fmt.Sprintf("commit: %s", gitCommit))
cli.VersionPrinter = func(context *cli.Context) {
printVersion(context)
}
v = append(v, fmt.Sprintf("spec: %s", specs.Version))
app.Version = strings.Join(v, "\n")
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "debug",
Expand Down Expand Up @@ -107,6 +92,7 @@ func main() {
startCommand,
stateCommand,
updateCommand,
versionCommand,
}
app.Before = func(context *cli.Context) error {
if context.GlobalBool("debug") {
Expand Down
2 changes: 2 additions & 0 deletions tests/integration/help.bats
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ load helpers
[ "$status" -eq 0 ]
[[ ${lines[0]} =~ NAME:+ ]]
[[ ${lines[1]} =~ runc\ '-'\ Open\ Container\ Initiative\ runtime+ ]]
[ "${output}" = "${output/VERSION/}" ]

runc --help
[ "$status" -eq 0 ]
[[ ${lines[0]} =~ NAME:+ ]]
[[ ${lines[1]} =~ runc\ '-'\ Open\ Container\ Initiative\ runtime+ ]]
[ "${output}" = "${output/VERSION/}" ]
}

@test "runc command -h" {
Expand Down
12 changes: 10 additions & 2 deletions tests/integration/version.bats
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@

load helpers

@test "runc version" {
@test "runc --version" {
runc -v
[ "$status" -eq 0 ]
[[ ${lines[0]} =~ runc\ version\ [0-9]+\.[0-9]+\.[0-9]+ ]]
[[ ${lines[0]} =~ runC\ [0-9]+\.[0-9]+\.[0-9]+ ]]
[[ ${lines[1]} =~ commit:+ ]]
[[ ${lines[2]} =~ spec:\ [0-9]+\.[0-9]+\.[0-9]+ ]]
}

@test "runc version" {
runc version
[ "$status" -eq 0 ]
[[ ${lines[0]} =~ runC\ [0-9]+\.[0-9]+\.[0-9]+ ]]
[[ ${lines[1]} =~ commit:+ ]]
[[ ${lines[2]} =~ spec:\ [0-9]+\.[0-9]+\.[0-9]+ ]]
}
43 changes: 43 additions & 0 deletions version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"fmt"
"os"

"github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli"
)

// version will be populated by the Makefile, read from
// VERSION file of the source code.
var version = ""

// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""

var versionCommand = cli.Command{
Name: "version",
Usage: "output the runtime version",
Description: `The version command outputs the runtime version.`,
Action: printVersion,
}

func printVersion(context *cli.Context) (err error) {
if version == "" {
_, err = os.Stdout.WriteString("runC unknown\n")
} else {
_, err = os.Stdout.WriteString(fmt.Sprintf("runC %s\n", version))
}
if err != nil {
return err
}
if gitCommit != "" {
_, err = os.Stdout.WriteString(fmt.Sprintf("commit: %s\n", gitCommit))
if err != nil {
return err
}
}
_, err = os.Stdout.WriteString(fmt.Sprintf("spec: %s\n", specs.Version))
return err
}

0 comments on commit e09dd4f

Please sign in to comment.