mirror of https://github.com/helm/helm
commit
5f1803fe63
@ -1,22 +1,57 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/deis/tiller/pkg/client"
|
||||||
|
"github.com/deis/tiller/pkg/kubectl"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const longDesc = `
|
||||||
|
This command installs Tiller (the helm server side component) onto your
|
||||||
|
Kubernetes Cluster and sets up local configuration in $HELM_HOME (default: ~/.helm/)
|
||||||
|
`
|
||||||
|
|
||||||
|
var tillerImg string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
initCmd.Flags().StringVarP(&tillerImg, "tiller-image", "i", "", "override tiller image")
|
||||||
RootCommand.AddCommand(initCmd)
|
RootCommand.AddCommand(initCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
var initCmd = &cobra.Command{
|
var initCmd = &cobra.Command{
|
||||||
Use: "init",
|
Use: "init",
|
||||||
Short: "Initialize Helm on both client and server.",
|
Short: "Initialize Helm on both client and server.",
|
||||||
Long: `Add long help here`,
|
Long: longDesc,
|
||||||
Run: runInit,
|
RunE: RunInit,
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunInit initializes local config and installs tiller to Kubernetes Cluster
|
||||||
|
func RunInit(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return errors.New("This command does not accept arguments. \n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: take value of global flag kubectl and pass that in
|
||||||
|
runner := buildKubectlRunner("")
|
||||||
|
|
||||||
|
i := client.NewInstaller()
|
||||||
|
i.Tiller["Image"] = tillerImg
|
||||||
|
|
||||||
|
out, err := i.Install(runner)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error installing %s %s", string(out), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Tiller (the helm server side component) has been installed into your Kubernetes Cluster.\n")
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runInit(cmd *cobra.Command, args []string) {
|
func buildKubectlRunner(kubectlPath string) kubectl.Runner {
|
||||||
fmt.Fprintln(stdout, "Init was called.")
|
if kubectlPath != "" {
|
||||||
|
kubectl.Path = kubectlPath
|
||||||
|
}
|
||||||
|
return &kubectl.RealRunner{}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInit(t *testing.T) {
|
||||||
|
//TODO: call command and make sure no error is returned
|
||||||
|
//TODO: check local config
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/Masterminds/sprig"
|
||||||
|
"github.com/deis/tiller/pkg/kubectl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Installer creates a new Installer
|
||||||
|
func NewInstaller() *Installer {
|
||||||
|
return &Installer{
|
||||||
|
Metadata: map[string]interface{}{},
|
||||||
|
Tiller: map[string]interface{}{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install uses kubectl to install tiller
|
||||||
|
//
|
||||||
|
// Returns the string output received from the operation, and an error if the
|
||||||
|
// command failed.
|
||||||
|
func (i *Installer) Install(runner kubectl.Runner) (string, error) {
|
||||||
|
b, err := i.expand()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
o, err := runner.Create(b)
|
||||||
|
return string(o), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Installer) expand() ([]byte, error) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
t := template.Must(template.New("manifest").Funcs(sprig.TxtFuncMap()).Parse(InstallYAML))
|
||||||
|
err := t.Execute(&b, i)
|
||||||
|
return b.Bytes(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstallYAML is the installation YAML for DM.
|
||||||
|
const InstallYAML = `
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: helm
|
||||||
|
name: helm-namespace
|
||||||
|
name: helm
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ReplicationController
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: helm
|
||||||
|
name: tiller
|
||||||
|
name: tiller-rc
|
||||||
|
namespace: helm
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
app: helm
|
||||||
|
name: tiller
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: helm
|
||||||
|
name: tiller
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env: []
|
||||||
|
image: {{default "gcr.io/deis-sandbox/tiller:canary" .Tiller.Image}}
|
||||||
|
name: tiller
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: tiller
|
||||||
|
imagePullPolicy: Always
|
||||||
|
---
|
||||||
|
`
|
@ -0,0 +1,32 @@
|
|||||||
|
package kubectl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cmd struct {
|
||||||
|
*exec.Cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func command(args ...string) *cmd {
|
||||||
|
return &cmd{exec.Command(Path, args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assignStdin(cmd *cmd, in []byte) {
|
||||||
|
cmd.Stdin = bytes.NewBuffer(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *cmd) String() string {
|
||||||
|
var stdin string
|
||||||
|
|
||||||
|
if c.Stdin != nil {
|
||||||
|
b, _ := ioutil.ReadAll(c.Stdin)
|
||||||
|
stdin = fmt.Sprintf("< %s", string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("[CMD] %s %s", strings.Join(c.Args, " "), stdin)
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package kubectl
|
||||||
|
|
||||||
|
// Create uploads a chart to Kubernetes
|
||||||
|
func (r RealRunner) Create(stdin []byte) ([]byte, error) {
|
||||||
|
args := []string{"create", "-f", "-"}
|
||||||
|
|
||||||
|
cmd := command(args...)
|
||||||
|
assignStdin(cmd, stdin)
|
||||||
|
|
||||||
|
return cmd.CombinedOutput()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create returns the commands to kubectl
|
||||||
|
func (r PrintRunner) Create(stdin []byte) ([]byte, error) {
|
||||||
|
args := []string{"create", "-f", "-"}
|
||||||
|
|
||||||
|
cmd := command(args...)
|
||||||
|
assignStdin(cmd, stdin)
|
||||||
|
|
||||||
|
return []byte(cmd.String()), nil
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package kubectl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPrintCreate(t *testing.T) {
|
||||||
|
var client Runner = PrintRunner{}
|
||||||
|
|
||||||
|
expected := `[CMD] kubectl create -f - < some stdin data`
|
||||||
|
|
||||||
|
out, err := client.Create([]byte("some stdin data"))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := string(out)
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Fatalf("actual %s != expected %s", actual, expected)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package kubectl
|
||||||
|
|
||||||
|
// Path is the path of the kubectl binary
|
||||||
|
var Path = "kubectl"
|
||||||
|
|
||||||
|
// Runner is an interface to wrap kubectl convenience methods
|
||||||
|
type Runner interface {
|
||||||
|
// Create uploads a chart to Kubernetes
|
||||||
|
Create(stdin []byte) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RealRunner implements Runner to execute kubectl commands
|
||||||
|
type RealRunner struct{}
|
||||||
|
|
||||||
|
// PrintRunner implements Runner to return a []byte of the command to be executed
|
||||||
|
type PrintRunner struct{}
|
||||||
|
|
||||||
|
// Client stores the instance of Runner
|
||||||
|
var Client Runner = RealRunner{}
|
@ -0,0 +1,12 @@
|
|||||||
|
package kubectl
|
||||||
|
|
||||||
|
type TestRunner struct {
|
||||||
|
Runner
|
||||||
|
|
||||||
|
out []byte
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r TestRunner) Create(stdin []byte, ns string) ([]byte, error) {
|
||||||
|
return r.out, r.err
|
||||||
|
}
|
Loading…
Reference in new issue