github.com/danielqsj/helm@v2.0.0-alpha.4.0.20160908204436-976e0ba5199b+incompatible/cmd/helm/helm.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main // import "k8s.io/helm/cmd/helm" 18 19 import ( 20 "errors" 21 "fmt" 22 "io" 23 "os" 24 "strings" 25 26 "github.com/spf13/cobra" 27 "google.golang.org/grpc" 28 ) 29 30 const ( 31 homeEnvVar = "HELM_HOME" 32 hostEnvVar = "HELM_HOST" 33 tillerNamespace = "kube-system" 34 ) 35 36 var ( 37 helmHome string 38 tillerHost string 39 ) 40 41 // flagDebug is a signal that the user wants additional output. 42 var flagDebug bool 43 44 var globalUsage = `The Kubernetes package manager 45 46 To begin working with Helm, run the 'helm init' command: 47 48 $ helm init 49 50 This will install Tiller to your running Kubernetes cluster. 51 It will also set up any necessary local configuration. 52 53 Common actions from this point include: 54 55 - helm search: search for charts 56 - helm fetch: download a chart to your local directory to view 57 - helm install: upload the chart to Kubernetes 58 - helm list: list releases of charts 59 60 Environment: 61 $HELM_HOME Set an alternative location for Helm files. By default, these are stored in ~/.helm 62 $HELM_HOST Set an alternative Tiller host. The format is host:port. 63 $KUBECONFIG Set an alternate Kubernetes configuration file (default: "~/.kube/config"). 64 ` 65 66 func newRootCmd(out io.Writer) *cobra.Command { 67 cmd := &cobra.Command{ 68 Use: "helm", 69 Short: "The Helm package manager for Kubernetes.", 70 Long: globalUsage, 71 SilenceUsage: true, 72 PersistentPostRun: func(cmd *cobra.Command, args []string) { 73 teardown() 74 }, 75 } 76 home := os.Getenv(homeEnvVar) 77 if home == "" { 78 home = "$HOME/.helm" 79 } 80 thost := os.Getenv(hostEnvVar) 81 p := cmd.PersistentFlags() 82 p.StringVar(&helmHome, "home", home, "location of your Helm config. Overrides $HELM_HOME.") 83 p.StringVar(&tillerHost, "host", thost, "address of tiller. Overrides $HELM_HOST.") 84 p.BoolVarP(&flagDebug, "debug", "", false, "enable verbose output") 85 86 cmd.AddCommand( 87 newCreateCmd(out), 88 newDeleteCmd(nil, out), 89 newGetCmd(nil, out), 90 newInitCmd(out), 91 newInspectCmd(nil, out), 92 newInstallCmd(nil, out), 93 newListCmd(nil, out), 94 newStatusCmd(nil, out), 95 newUpgradeCmd(nil, out), 96 newRollbackCmd(nil, out), 97 newPackageCmd(nil, out), 98 newFetchCmd(out), 99 newVerifyCmd(out), 100 newUpdateCmd(out), 101 ) 102 return cmd 103 } 104 105 // RootCommand is the top-level command for Helm. 106 var RootCommand = newRootCmd(os.Stdout) 107 108 func main() { 109 cmd := RootCommand 110 if err := cmd.Execute(); err != nil { 111 os.Exit(1) 112 } 113 } 114 115 func setupConnection(c *cobra.Command, args []string) error { 116 if tillerHost == "" { 117 tunnel, err := newTillerPortForwarder(tillerNamespace) 118 if err != nil { 119 return err 120 } 121 122 tillerHost = fmt.Sprintf(":%d", tunnel.Local) 123 if flagDebug { 124 fmt.Printf("Created tunnel using local port: '%d'\n", tunnel.Local) 125 } 126 } 127 128 // Set up the gRPC config. 129 if flagDebug { 130 fmt.Printf("Server: %q\n", tillerHost) 131 } 132 return nil 133 } 134 135 func teardown() { 136 if tunnel != nil { 137 tunnel.Close() 138 } 139 } 140 141 func checkArgsLength(expectedNum, actualNum int, requiredArgs ...string) error { 142 if actualNum != expectedNum { 143 arg := "arguments" 144 if expectedNum == 1 { 145 arg = "argument" 146 } 147 return fmt.Errorf("This command needs %v %s: %s", expectedNum, arg, strings.Join(requiredArgs, ", ")) 148 } 149 return nil 150 } 151 152 // requireInit is a PreRunE implementation for validating that $HELM_HOME is configured. 153 func requireInit(cmd *cobra.Command, args []string) error { 154 err := requireHome() 155 if err != nil { 156 return fmt.Errorf("%s (try running 'helm init')", err) 157 } 158 return nil 159 } 160 161 // prettyError unwraps or rewrites certain errors to make them more user-friendly. 162 func prettyError(err error) error { 163 if err == nil { 164 return nil 165 } 166 // This is ridiculous. Why is 'grpc.rpcError' not exported? The least they 167 // could do is throw an interface on the lib that would let us get back 168 // the desc. Instead, we have to pass ALL errors through this. 169 return errors.New(grpc.ErrorDesc(err)) 170 }