diff --git a/Makefile b/Makefile index a6c06941b..bc1aee33c 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,11 @@ endif BASEIMAGE_RELEASE = 0.3.1 PKGNAME = github.com/hyperledger/$(PROJECT_NAME) +METADATA_VAR = Version=$(PROJECT_VERSION) + +GO_LDFLAGS = $(patsubst %,-X $(PKGNAME)/cmd.%,$(METADATA_VAR)) +export GO_LDFLAGS + DOCKER_ORG = hyperledger IMAGES = $(PROJECT_NAME) FVTIMAGE = $(PROJECT_NAME)-fvt @@ -89,7 +94,7 @@ fabric-ca-server: bin/fabric-ca-server bin/%: @echo "Building ${@F} in bin directory ..." - @mkdir -p bin && go build -o bin/${@F} $(path-map.${@F}) + @mkdir -p bin && go build -o bin/${@F} -ldflags "$(GO_LDFLAGS)" $(path-map.${@F}) @echo "Built bin/${@F}" # We (re)build a package within a docker context but persist the $GOPATH/pkg diff --git a/cmd/fabric-ca-client/main_test.go b/cmd/fabric-ca-client/main_test.go index 2fa14840f..84eccc5f9 100644 --- a/cmd/fabric-ca-client/main_test.go +++ b/cmd/fabric-ca-client/main_test.go @@ -876,6 +876,13 @@ func testGetCACertConfigFile(t *testing.T) error { return nil } +func TestVersion(t *testing.T) { + err := RunMain([]string{cmdName, "version"}) + if err != nil { + t.Error("Failed to get fabric-ca-client version: ", err) + } +} + func getServer() *lib.Server { return &lib.Server{ HomeDir: ".", @@ -940,9 +947,8 @@ func extraArgErrorTest(in *TestData, t *testing.T) { assert.Error(t, errors.New("Should have resulted in an error as extra agruments provided")) } if err != nil { - if !strings.Contains(err.Error(), "Extra arguments") { - assert.Error(t, fmt.Errorf("Failed for other reason besides extra argument: %s", err)) - } + assert.Contains(t, err.Error(), "Unrecognized arguments found", + "Failed for other reason besides unrecognized argument") } } diff --git a/cmd/fabric-ca-client/version.go b/cmd/fabric-ca-client/version.go new file mode 100644 index 000000000..92d12e6a5 --- /dev/null +++ b/cmd/fabric-ca-client/version.go @@ -0,0 +1,37 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +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 main + +import ( + "fmt" + + "github.com/hyperledger/fabric-ca/cmd" + "github.com/spf13/cobra" +) + +// versionCmd represents the "version" command +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Prints Fabric CA Client version", + Run: func(cmd *cobra.Command, args []string) { + fmt.Print(metadata.GetVersionInfo(cmdName)) + }, +} + +func init() { + rootCmd.AddCommand(versionCmd) +} diff --git a/cmd/fabric-ca-server/config.go b/cmd/fabric-ca-server/config.go index f4f2972e3..7d541701f 100644 --- a/cmd/fabric-ca-server/config.go +++ b/cmd/fabric-ca-server/config.go @@ -378,12 +378,12 @@ var ( // cfgFileName is the name of the config file cfgFileName string // serverCfg is the server's config - serverCfg *lib.ServerConfig + serverCfg *lib.ServerConfig + extraArgsError = "Unrecognized arguments found: %v\n\n%s" ) // Initialize config -func configInit() (err error) { - +func configInit(cmd string) (err error) { // Make the config file name absolute if !filepath.IsAbs(cfgFileName) { cfgFileName, err = filepath.Abs(cfgFileName) diff --git a/cmd/fabric-ca-server/init.go b/cmd/fabric-ca-server/init.go index ee96f635e..e71d9929d 100644 --- a/cmd/fabric-ca-server/init.go +++ b/cmd/fabric-ca-server/init.go @@ -39,14 +39,22 @@ var initCmd = &cobra.Command{ func init() { initCmd.RunE = runInit + initCmd.PreRunE = func(cmd *cobra.Command, args []string) error { + if len(args) > 0 { + return fmt.Errorf(extraArgsError, args, cmd.UsageString()) + } + + err := configInit(cmd.Name()) + if err != nil { + return err + } + return nil + } rootCmd.AddCommand(initCmd) } // The server init main logic func runInit(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - return fmt.Errorf("Usage: too many arguments.\n%s", initCmd.UsageString()) - } err := getServer().Init(false) if err != nil { util.Fatal("Initialization failure: %s", err) diff --git a/cmd/fabric-ca-server/main.go b/cmd/fabric-ca-server/main.go index 2760f84b4..34265a5a5 100644 --- a/cmd/fabric-ca-server/main.go +++ b/cmd/fabric-ca-server/main.go @@ -33,12 +33,8 @@ var ( Use: cmdName, Short: longName, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - err := configInit() - if err != nil { - return err - } - cmd.SilenceUsage = true util.CmdRunBegin() + cmd.SilenceUsage = true return nil }, } diff --git a/cmd/fabric-ca-server/main_test.go b/cmd/fabric-ca-server/main_test.go index 0249e3993..9ae10afed 100644 --- a/cmd/fabric-ca-server/main_test.go +++ b/cmd/fabric-ca-server/main_test.go @@ -116,7 +116,7 @@ func TestErrors(t *testing.T) { errorCases := []TestData{ {[]string{cmdName, "init", "-c", initYaml}, "option is required"}, {[]string{cmdName, "init", "-n", "acme.com", "-b", "user::"}, "Failed to read"}, - {[]string{cmdName, "init", "-b", "user:pass", "-n", "acme.com", "ca.key"}, "too many arguments"}, + {[]string{cmdName, "init", "-b", "user:pass", "-n", "acme.com", "ca.key"}, "Unrecognized arguments found"}, {[]string{cmdName, "init", "-c", badSyntaxYaml, "-b", "user:pass"}, "Incorrect format"}, {[]string{cmdName, "init", "-c", initYaml, "-b", fmt.Sprintf("%s:foo", longUserName)}, "than 1024 characters"}, {[]string{cmdName, "init", "-c", fmt.Sprintf("/tmp/%s.yaml", longFileName), "-b", "user:pass"}, "file name too long"}, @@ -125,7 +125,7 @@ func TestErrors(t *testing.T) { {[]string{cmdName, "init", "-c", initYaml, "-b", "user:"}, "empty password"}, {[]string{cmdName, "bogus", "-c", initYaml, "-b", "user:pass"}, "unknown command"}, {[]string{cmdName, "start", "-c"}, "needs an argument:"}, - {[]string{cmdName, "start", "-c", startYaml, "-b", "user:pass", "ca.key"}, "too many arguments"}, + {[]string{cmdName, "start", "-c", startYaml, "-b", "user:pass", "ca.key"}, "Unrecognized arguments found"}, } // Explicitly set the default for ca.name to "", this is to test if server @@ -267,6 +267,13 @@ func TestMultiCA(t *testing.T) { cleanUpMultiCAFiles() } +func TestVersion(t *testing.T) { + err := RunMain([]string{cmdName, "version"}) + if err != nil { + t.Error("Failed to get fabric-ca-server version: ", err) + } +} + // Run server with specified args and check if the configuration and datasource // files exist in the specified locations func checkConfigAndDBLoc(t *testing.T, args TestData, cfgFile string, dsFile string) { diff --git a/cmd/fabric-ca-server/start.go b/cmd/fabric-ca-server/start.go index 7df9062e0..e3dc69486 100644 --- a/cmd/fabric-ca-server/start.go +++ b/cmd/fabric-ca-server/start.go @@ -30,14 +30,22 @@ var startCmd = &cobra.Command{ func init() { startCmd.RunE = runStart + startCmd.PreRunE = func(cmd *cobra.Command, args []string) error { + if len(args) > 0 { + return fmt.Errorf(extraArgsError, args, cmd.UsageString()) + } + + err := configInit(cmd.Name()) + if err != nil { + return err + } + return nil + } rootCmd.AddCommand(startCmd) } // The server start main logic func runStart(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - return fmt.Errorf("Usage: too many arguments.\n%s", startCmd.UsageString()) - } err := getServer().Start() if err != nil { return err diff --git a/cmd/fabric-ca-server/version.go b/cmd/fabric-ca-server/version.go new file mode 100644 index 000000000..80b796bcf --- /dev/null +++ b/cmd/fabric-ca-server/version.go @@ -0,0 +1,37 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +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 main + +import ( + "fmt" + + "github.com/hyperledger/fabric-ca/cmd" + "github.com/spf13/cobra" +) + +// versionCmd represents the "version" command +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Prints Fabric CA Server version", + Run: func(cmd *cobra.Command, args []string) { + fmt.Print(metadata.GetVersionInfo(cmdName)) + }, +} + +func init() { + rootCmd.AddCommand(versionCmd) +} diff --git a/cmd/metadata.go b/cmd/metadata.go new file mode 100644 index 000000000..292d72351 --- /dev/null +++ b/cmd/metadata.go @@ -0,0 +1,37 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +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 metadata + +import ( + "fmt" + "runtime" +) + +// Version specifies fabric-ca Client version +// It is defined by the Makefile and passed in with ldflags +var Version string + +// GetVersionInfo returns version information for the peer +func GetVersionInfo(prgName string) string { + if Version == "" { + Version = "development build" + } + + return fmt.Sprintf("%s:\n Version: %s\n Go version: %s\n OS/Arch: %s\n", + prgName, Version, runtime.Version(), + fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)) +} diff --git a/cmd/metadata_test.go b/cmd/metadata_test.go new file mode 100644 index 000000000..2b5cb4c00 --- /dev/null +++ b/cmd/metadata_test.go @@ -0,0 +1,33 @@ +/* +Copyright IBM Corp. 2017 All Rights Reserved. + +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 metadata_test + +import ( + "testing" + + "github.com/hyperledger/fabric-ca/cmd" + "github.com/stretchr/testify/assert" +) + +func TestGetVersionInfo(t *testing.T) { + info := metadata.GetVersionInfo("fabric-ca-client") + assert.Contains(t, info, "Version: development build") + + metadata.Version = "1.0.0" + info = metadata.GetVersionInfo("fabric-ca-client") + assert.Contains(t, info, "Version: 1.0.0") +}