Commit c41ccddf authored by Adam Reese's avatar Adam Reese Committed by GitHub

Merge pull request #852 from adamreese/fix/namespace-tunnel

fix(tunnel): allow tunneling to non-default namespace
parents bde2232a 573e5aa7
......@@ -17,8 +17,11 @@ const (
hostEnvVar = "HELM_HOST"
)
var helmHome string
var tillerHost string
var (
helmHome string
tillerHost string
tillerNamespace string
)
// flagDebug is a signal that the user wants additional output.
var flagDebug bool
......@@ -61,6 +64,7 @@ func init() {
p := RootCommand.PersistentFlags()
p.StringVar(&helmHome, "home", home, "location of your Helm config. Overrides $HELM_HOME.")
p.StringVar(&tillerHost, "host", thost, "address of tiller. Overrides $HELM_HOST.")
p.StringVarP(&tillerNamespace, "namespace", "", "", "kubernetes namespace")
p.BoolVarP(&flagDebug, "debug", "", false, "enable verbose output")
}
......@@ -72,8 +76,7 @@ func main() {
func setupConnection(c *cobra.Command, args []string) error {
if tillerHost == "" {
// Should failure fall back to default host?
tunnel, err := newTillerPortForwarder()
tunnel, err := newTillerPortForwarder(tillerNamespace)
if err != nil {
return err
}
......
......@@ -17,9 +17,7 @@ Kubernetes Cluster and sets up local configuration in $HELM_HOME (default: ~/.he
var (
tillerImg string
tillerNamespace string
clientOnly bool
initSkipNamespace bool
defaultRepository = "kubernetes-charts"
defaultRepositoryURL = "http://storage.googleapis.com/kubernetes-charts"
)
......@@ -28,8 +26,6 @@ func init() {
f := initCmd.Flags()
f.StringVarP(&tillerImg, "tiller-image", "i", "", "override tiller image")
f.BoolVarP(&clientOnly, "client-only", "c", false, "If set does not install tiller")
f.BoolVarP(&initSkipNamespace, "skip-namespace", "s", false, "Do not attempt to create a namespace. Assume the namespace is already there.")
f.StringVarP(&tillerNamespace, "namespace", "n", "helm", "set the tiller namespace")
RootCommand.AddCommand(initCmd)
}
......@@ -63,12 +59,7 @@ func runInit(cmd *cobra.Command, args []string) error {
}
func installTiller() error {
i := client.NewInstaller()
i.Tiller["Image"] = tillerImg
i.Tiller["Namespace"] = tillerNamespace
err := i.Install(flagDebug, !initSkipNamespace)
if err != nil {
if err := client.Install(tillerNamespace, tillerImg, flagDebug); err != nil {
return fmt.Errorf("error installing: %s", err)
}
fmt.Println("\nTiller (the helm server side component) has been installed into your Kubernetes Cluster.")
......
......@@ -12,14 +12,14 @@ import (
// TODO refactor out this global var
var tunnel *kube.Tunnel
func newTillerPortForwarder() (*kube.Tunnel, error) {
podName, err := getTillerPodName("helm")
func newTillerPortForwarder(namespace string) (*kube.Tunnel, error) {
podName, err := getTillerPodName(namespace)
if err != nil {
return nil, err
}
// FIXME use a constain that is accessible on init
const tillerPort = 44134
return kube.New(nil).ForwardPort("helm", podName, tillerPort)
return kube.New(nil).ForwardPort(namespace, podName, tillerPort)
}
func getTillerPodName(namespace string) (string, error) {
......
......@@ -10,49 +10,33 @@ import (
"k8s.io/helm/pkg/kube"
)
// Installer installs tiller into Kubernetes
//
// See InstallYAML.
type Installer struct {
// Metadata holds any global metadata attributes for the resources
Metadata map[string]interface{}
// Tiller specific metadata
Tiller map[string]interface{}
}
// NewInstaller creates a new Installer
func NewInstaller() *Installer {
return &Installer{
Metadata: map[string]interface{}{},
Tiller: map[string]interface{}{},
}
}
// Install uses kubernetes client to install tiller
//
// Returns the string output received from the operation, and an error if the
// command failed.
//
// If verbose is true, this will print the manifest to stdout.
//
// If createNS is true, this will also create the namespace.
func (i *Installer) Install(verbose, createNS bool) error {
var b bytes.Buffer
func Install(namespace, image string, verbose bool) error {
kc := kube.New(nil)
// Add namespace
if createNS {
nstpl := template.New("namespace").Funcs(sprig.TxtFuncMap())
if err := template.Must(nstpl.Parse(NamespaceYAML)).Execute(&b, i); err != nil {
if namespace == "" {
ns, _, err := kc.DefaultNamespace()
if err != nil {
return err
}
namespace = ns
}
var b bytes.Buffer
// Add main install YAML
istpl := template.New("install").Funcs(sprig.TxtFuncMap())
if err := template.Must(istpl.Parse(InstallYAML)).Execute(&b, i); err != nil {
cfg := struct {
Namespace, Image string
}{namespace, image}
if err := template.Must(istpl.Parse(InstallYAML)).Execute(&b, cfg); err != nil {
return err
}
......@@ -60,24 +44,12 @@ func (i *Installer) Install(verbose, createNS bool) error {
fmt.Println(b.String())
}
return kube.New(nil).Create(i.Tiller["Namespace"].(string), &b)
return kc.Create(namespace, &b)
}
// NamespaceYAML is the installation for a namespace.
const NamespaceYAML = `
---{{$namespace := default "helm" .Tiller.Namespace}}
apiVersion: v1
kind: Namespace
metadata:
labels:
app: helm
name: helm-namespace
name: {{$namespace}}
`
// InstallYAML is the installation YAML for DM.
const InstallYAML = `
---{{$namespace := default "helm" .Tiller.Namespace}}
---
apiVersion: v1
kind: ReplicationController
metadata:
......@@ -85,7 +57,7 @@ metadata:
app: helm
name: tiller
name: tiller-rc
namespace: {{$namespace}}
namespace: {{ .Namespace }}
spec:
replicas: 1
selector:
......@@ -103,7 +75,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: {{default "gcr.io/kubernetes-helm/tiller:canary" .Tiller.Image}}
image: {{default "gcr.io/kubernetes-helm/tiller:canary" .Image}}
name: tiller
ports:
- containerPort: 44134
......
......@@ -4,6 +4,8 @@ import (
"fmt"
"io"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
......@@ -28,6 +30,9 @@ type ResourceActorFunc func(*resource.Info) error
//
// Namespace will set the namespace
func (c *Client) Create(namespace string, reader io.Reader) error {
if err := c.ensureNamespace(namespace); err != nil {
return err
}
return perform(c, namespace, reader, createResource)
}
......@@ -44,7 +49,7 @@ func perform(c *Client, namespace string, reader io.Reader, fn ResourceActorFunc
r := c.NewBuilder(includeThirdPartyAPIs).
ContinueOnError().
NamespaceParam(namespace).
RequireNamespace().
DefaultNamespace().
Stream(reader, "").
Flatten().
Do()
......@@ -83,3 +88,18 @@ func createResource(info *resource.Info) error {
func deleteResource(info *resource.Info) error {
return resource.NewHelper(info.Client, info.Mapping).Delete(info.Namespace, info.Name)
}
func (c *Client) ensureNamespace(namespace string) error {
client, err := c.Client()
if err != nil {
return err
}
ns := &api.Namespace{}
ns.Name = namespace
_, err = client.Namespaces().Create(ns)
if err != nil && !errors.IsAlreadyExists(err) {
return err
}
return nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment