mirror of https://github.com/helm/helm
Merge 66fba7054f
into fb8dd39268
commit
6d9b5dc3e4
@ -1,31 +1,17 @@
|
||||
machine:
|
||||
environment:
|
||||
GLIDE_VERSION: "0.10.1"
|
||||
GO15VENDOREXPERIMENT: 1
|
||||
GOPATH: /usr/local/go_workspace
|
||||
HOME: /home/ubuntu
|
||||
IMPORT_PATH: "github.com/kubernetes/helm"
|
||||
PATH: $HOME/go/bin:$PATH
|
||||
GOROOT: $HOME/go
|
||||
IMPORT_PATH: "${GOPATH%%:*}/src/github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}"
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- mkdir -p $HOME/go
|
||||
- wget "https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz"
|
||||
- tar -C $HOME -xzf go1.6.linux-amd64.tar.gz
|
||||
- go version
|
||||
- go env
|
||||
- sudo chown -R $(whoami):staff /usr/local
|
||||
- cd $GOPATH
|
||||
- mkdir -p $GOPATH/src/$IMPORT_PATH
|
||||
- cd $HOME/helm
|
||||
- rsync -az --delete ./ "$GOPATH/src/$IMPORT_PATH/"
|
||||
- wget "https://github.com/Masterminds/glide/releases/download/$GLIDE_VERSION/glide-$GLIDE_VERSION-linux-amd64.tar.gz"
|
||||
- mkdir -p $HOME/bin
|
||||
- tar -vxz -C $HOME/bin --strip=1 -f glide-$GLIDE_VERSION-linux-amd64.tar.gz
|
||||
- export PATH="$HOME/bin:$PATH" GLIDE_HOME="$HOME/.glide"
|
||||
- cd $GOPATH/src/$IMPORT_PATH
|
||||
- sudo add-apt-repository -y ppa:masterminds/glide && sudo apt-get update; sudo apt-get install glide
|
||||
- mkdir -p "${IMPORT_PATH}"
|
||||
- mv "~/${CIRCLE_PROJECT_REPONAME}" "${IMPORT_PATH%/*}"
|
||||
- cd "${IMPORT_PATH}"
|
||||
|
||||
test:
|
||||
override:
|
||||
- cd $GOPATH/src/$IMPORT_PATH && make bootstrap test
|
||||
- make bootstrap test test-e2e
|
||||
|
@ -0,0 +1,83 @@
|
||||
// build +e2e
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Cmd provides helpers for command output
|
||||
type Cmd struct {
|
||||
t *testing.T
|
||||
path string
|
||||
args []string
|
||||
ran bool
|
||||
status error
|
||||
stdout, stderr bytes.Buffer
|
||||
}
|
||||
|
||||
func (h *Cmd) String() string {
|
||||
return fmt.Sprintf("%s %s", h.path, strings.Join(h.args, " "))
|
||||
}
|
||||
|
||||
func (h *Cmd) exec() error {
|
||||
cmd := exec.Command(h.path, h.args...)
|
||||
h.stdout.Reset()
|
||||
h.stderr.Reset()
|
||||
cmd.Stdout = &h.stdout
|
||||
cmd.Stderr = &h.stderr
|
||||
|
||||
h.t.Logf("Executing command: %s", h)
|
||||
start := time.Now()
|
||||
h.status = cmd.Run()
|
||||
h.t.Logf("Finished in %v", time.Since(start))
|
||||
|
||||
if h.stdout.Len() > 0 {
|
||||
h.t.Logf("standard output:\n%s", h.stdout.String())
|
||||
}
|
||||
if h.stderr.Len() > 0 {
|
||||
h.t.Logf("standard error: %s\n", h.stderr.String())
|
||||
}
|
||||
|
||||
h.ran = true
|
||||
return h.status
|
||||
}
|
||||
|
||||
// Stdout returns standard output of the Cmd run as a string.
|
||||
func (h *Cmd) Stdout() string {
|
||||
if !h.ran {
|
||||
h.t.Fatal("internal testsuite error: stdout called before run")
|
||||
}
|
||||
return h.stdout.String()
|
||||
}
|
||||
|
||||
// Stderr returns standard error of the Cmd run as a string.
|
||||
func (h *Cmd) Stderr() string {
|
||||
if !h.ran {
|
||||
h.t.Fatal("internal testsuite error: stdout called before run")
|
||||
}
|
||||
return h.stderr.String()
|
||||
}
|
||||
|
||||
func (c *Cmd) Match(exp string) bool {
|
||||
re := regexp.MustCompile(exp)
|
||||
return re.MatchString(c.Stdout())
|
||||
}
|
||||
|
||||
func (h *Cmd) StdoutContains(substring string) bool {
|
||||
return strings.Contains(h.Stdout(), substring)
|
||||
}
|
||||
|
||||
func (h *Cmd) StderrContains(substring string) bool {
|
||||
return strings.Contains(h.Stderr(), substring)
|
||||
}
|
||||
|
||||
func (h *Cmd) Contains(substring string) bool {
|
||||
return h.StdoutContains(substring) || h.StderrContains(substring)
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
// build +e2e
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
namespace = "helm"
|
||||
apiProxy = "/api/v1/proxy/namespaces/" + namespace + "/services/manager-service:manager/"
|
||||
)
|
||||
|
||||
type HelmContext struct {
|
||||
t *testing.T
|
||||
Path string
|
||||
Host string
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
func NewHelmContext(t *testing.T) *HelmContext {
|
||||
return &HelmContext{
|
||||
t: t,
|
||||
Path: "../../bin/helm",
|
||||
Timeout: time.Second * 20,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HelmContext) MustRun(args ...string) *Cmd {
|
||||
cmd := h.newCmd(args...)
|
||||
if status := cmd.exec(); status != nil {
|
||||
h.t.Errorf("helm %v failed unexpectedly: %v", args, status)
|
||||
h.t.Errorf("%s", cmd.Stderr())
|
||||
h.t.FailNow()
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (h *HelmContext) Run(args ...string) *Cmd {
|
||||
cmd := h.newCmd(args...)
|
||||
cmd.exec()
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (h *HelmContext) RunFail(args ...string) *Cmd {
|
||||
cmd := h.newCmd(args...)
|
||||
if status := cmd.exec(); status == nil {
|
||||
h.t.Fatalf("helm unexpected to fail: %v %v", args, status)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (h *HelmContext) newCmd(args ...string) *Cmd {
|
||||
//args = append([]string{"--host", h.Host}, args...)
|
||||
return &Cmd{
|
||||
t: h.t,
|
||||
path: h.Path,
|
||||
args: args,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HelmContext) Running() bool {
|
||||
// FIXME tiller does not have a healthz endpoint
|
||||
return true
|
||||
|
||||
//endpoint := h.Host + "healthz"
|
||||
//resp, err := http.Get(endpoint)
|
||||
//if err != nil {
|
||||
//h.t.Errorf("Could not GET %s: %s", endpoint, err)
|
||||
//}
|
||||
//return resp.StatusCode == 200
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
// build +e2e
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
const (
|
||||
timeout = 180 * time.Second
|
||||
poll = 2 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
chart = flag.String("chart", "gs://kubernetes-charts-testing/redis-2.tgz", "Chart to deploy")
|
||||
tillerImage = flag.String("tiller-image", "", "The full image name of the Docker image for resourcifier.")
|
||||
)
|
||||
|
||||
func logKubeEnv(k *KubeContext) {
|
||||
config := k.Run("config", "view", "--flatten", "--minify").Stdout()
|
||||
k.t.Logf("Kubernetes Environment\n%s", config)
|
||||
}
|
||||
|
||||
func TestHelm(t *testing.T) {
|
||||
kube := NewKubeContext(t)
|
||||
helm := NewHelmContext(t)
|
||||
|
||||
logKubeEnv(kube)
|
||||
|
||||
if !kube.Running() {
|
||||
t.Fatal("Not connected to kubernetes")
|
||||
}
|
||||
t.Log(kube.Version())
|
||||
|
||||
if !isHelmRunning(kube) {
|
||||
args := []string{"init"}
|
||||
if *tillerImage != "" {
|
||||
args = append(args, "-i", *tillerImage)
|
||||
}
|
||||
|
||||
helm.MustRun(args...)
|
||||
|
||||
err := wait(func() bool {
|
||||
return isHelmRunning(kube)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("could not install helm: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type conditionFunc func() bool
|
||||
|
||||
func wait(fn conditionFunc) error {
|
||||
for start := time.Now(); time.Since(start) < timeout; time.Sleep(poll) {
|
||||
if fn() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Polling timeout")
|
||||
}
|
||||
|
||||
func genName() string {
|
||||
return fmt.Sprintf("e2e-%d", rand.Uint32())
|
||||
}
|
||||
|
||||
func isHelmRunning(k *KubeContext) bool {
|
||||
return k.Run("get", "pods", "--namespace=helm").StdoutContains("Running")
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
// build +e2e
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const defaultKubectlPath = "kubectl"
|
||||
|
||||
type KubeContext struct {
|
||||
t *testing.T
|
||||
Path string
|
||||
}
|
||||
|
||||
func NewKubeContext(t *testing.T) *KubeContext {
|
||||
return &KubeContext{
|
||||
t: t,
|
||||
Path: defaultKubectlPath,
|
||||
}
|
||||
}
|
||||
|
||||
func (k *KubeContext) Run(args ...string) *Cmd {
|
||||
cmd := k.newCmd(args...)
|
||||
cmd.exec()
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (k *KubeContext) newCmd(args ...string) *Cmd {
|
||||
return &Cmd{
|
||||
t: k.t,
|
||||
path: k.Path,
|
||||
args: args,
|
||||
}
|
||||
}
|
||||
|
||||
func (k *KubeContext) getConfigValue(jsonpath string) string {
|
||||
return strings.Replace(k.Run("config", "view", "--flatten=true", "--minify=true", "-o", "jsonpath="+jsonpath).Stdout(), "'", "", -1)
|
||||
}
|
||||
|
||||
func (k *KubeContext) Cluster() string {
|
||||
return k.getConfigValue("'{.clusters[0].name}'")
|
||||
}
|
||||
|
||||
func (k *KubeContext) Server() string {
|
||||
return k.getConfigValue("'{.clusters[0].cluster.server}'")
|
||||
}
|
||||
|
||||
func (k *KubeContext) CurrentContext() string {
|
||||
return k.getConfigValue("'{.current-context}'")
|
||||
}
|
||||
|
||||
func (k *KubeContext) Running() bool {
|
||||
err := k.Run("cluster-info").exec()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (k *KubeContext) Version() string {
|
||||
return k.Run("version").Stdout()
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
// +build !e2e
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(0)
|
||||
}
|
Loading…
Reference in new issue