github.com/coreos/mantle@v0.13.0/cli/cli.go (about) 1 // Copyright 2014 CoreOS, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cli 16 17 import ( 18 "os" 19 20 "github.com/coreos/pkg/capnslog" 21 "github.com/spf13/cobra" 22 23 "github.com/coreos/mantle/system/exec" 24 "github.com/coreos/mantle/version" 25 ) 26 27 var ( 28 versionCmd = &cobra.Command{ 29 Use: "version", 30 Short: "Print the version number and exit.", 31 Run: func(cmd *cobra.Command, args []string) { 32 cmd.Printf("mantle/%s version %s\n", 33 cmd.Root().Name(), version.Version) 34 }, 35 } 36 37 logDebug bool 38 logVerbose bool 39 logLevel = capnslog.NOTICE 40 41 plog = capnslog.NewPackageLogger("github.com/coreos/mantle", "cli") 42 ) 43 44 // Execute sets up common features that all mantle commands should share 45 // and then executes the command. It does not return. 46 func Execute(main *cobra.Command) { 47 // If we were invoked via a multicall entrypoint run it instead. 48 // TODO(marineam): should we figure out a way to initialize logging? 49 exec.MaybeExec() 50 51 main.AddCommand(versionCmd) 52 53 // TODO(marineam): pflags defines the Value interface differently, 54 // update capnslog accordingly... 55 main.PersistentFlags().Var(&logLevel, "log-level", 56 "Set global log level.") 57 main.PersistentFlags().BoolVarP(&logVerbose, "verbose", "v", false, 58 "Alias for --log-level=INFO") 59 main.PersistentFlags().BoolVarP(&logDebug, "debug", "d", false, 60 "Alias for --log-level=DEBUG") 61 62 WrapPreRun(main, func(cmd *cobra.Command, args []string) error { 63 startLogging(cmd) 64 return nil 65 }) 66 67 if err := main.Execute(); err != nil { 68 plog.Fatal(err) 69 } 70 os.Exit(0) 71 } 72 73 func setRepoLogLevel(repo string, l capnslog.LogLevel) { 74 r, err := capnslog.GetRepoLogger(repo) 75 if err != nil { 76 return // don't care if it isn't linked in 77 } 78 r.SetRepoLogLevel(l) 79 } 80 81 func startLogging(cmd *cobra.Command) { 82 switch { 83 case logDebug: 84 logLevel = capnslog.DEBUG 85 case logVerbose: 86 logLevel = capnslog.INFO 87 } 88 89 capnslog.SetFormatter(capnslog.NewStringFormatter(cmd.Out())) 90 capnslog.SetGlobalLogLevel(logLevel) 91 92 // In the context of the internally linked etcd, the NOTICE messages 93 // aren't really interesting, so translate NOTICE to WARNING instead. 94 if logLevel == capnslog.NOTICE { 95 // etcd sure has a lot of repos in its repo 96 setRepoLogLevel("github.com/coreos/etcd", capnslog.WARNING) 97 setRepoLogLevel("github.com/coreos/etcd/etcdserver", capnslog.WARNING) 98 setRepoLogLevel("github.com/coreos/etcd/etcdserver/etcdhttp", capnslog.WARNING) 99 setRepoLogLevel("github.com/coreos/etcd/pkg", capnslog.WARNING) 100 } 101 102 plog.Infof("Started logging at level %s", logLevel) 103 } 104 105 type PreRunEFunc func(cmd *cobra.Command, args []string) error 106 107 func WrapPreRun(root *cobra.Command, f PreRunEFunc) { 108 preRun, preRunE := root.PersistentPreRun, root.PersistentPreRunE 109 root.PersistentPreRun, root.PersistentPreRunE = nil, nil 110 111 root.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { 112 if err := f(cmd, args); err != nil { 113 return err 114 } 115 if preRun != nil { 116 preRun(cmd, args) 117 } else if preRunE != nil { 118 return preRunE(cmd, args) 119 } 120 return nil 121 } 122 }