Merge pull request #1657 from adamreese/feat/kube-1.5

feat(*): migrate to kubernetes 1.5
pull/1676/head
Adam Reese 8 years ago committed by GitHub
commit 0d436e5c3a

@ -28,18 +28,18 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/helm/cmd/helm/helmpath" "k8s.io/helm/cmd/helm/helmpath"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/tiller/environment"
) )
const ( const (
localRepoIndexFilePath = "index.yaml" localRepoIndexFilePath = "index.yaml"
homeEnvVar = "HELM_HOME" homeEnvVar = "HELM_HOME"
hostEnvVar = "HELM_HOST" hostEnvVar = "HELM_HOST"
tillerNamespace = "kube-system"
) )
var ( var (
@ -145,7 +145,7 @@ func main() {
func setupConnection(c *cobra.Command, args []string) error { func setupConnection(c *cobra.Command, args []string) error {
if tillerHost == "" { if tillerHost == "" {
tunnel, err := newTillerPortForwarder(tillerNamespace, kubeContext) tunnel, err := newTillerPortForwarder(environment.TillerNamespace, kubeContext)
if err != nil { if err != nil {
return err return err
} }
@ -199,12 +199,12 @@ func homePath() string {
// getKubeClient is a convenience method for creating kubernetes config and client // getKubeClient is a convenience method for creating kubernetes config and client
// for a given kubeconfig context // for a given kubeconfig context
func getKubeClient(context string) (*restclient.Config, *unversioned.Client, error) { func getKubeClient(context string) (*restclient.Config, *internalclientset.Clientset, error) {
config, err := kube.GetConfig(context).ClientConfig() config, err := kube.GetConfig(context).ClientConfig()
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("could not get kubernetes config for context '%s': %s", context, err) return nil, nil, fmt.Errorf("could not get kubernetes config for context '%s': %s", context, err)
} }
client, err := unversioned.New(config) client, err := internalclientset.NewForConfig(config)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("could not get kubernetes client: %s", err) return nil, nil, fmt.Errorf("could not get kubernetes client: %s", err)
} }

@ -24,11 +24,12 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
kerrors "k8s.io/kubernetes/pkg/api/errors" kerrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/unversioned" extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
"k8s.io/helm/cmd/helm/helmpath" "k8s.io/helm/cmd/helm/helmpath"
"k8s.io/helm/cmd/helm/installer" "k8s.io/helm/cmd/helm/installer"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
"k8s.io/helm/pkg/tiller/environment"
) )
const initDesc = ` const initDesc = `
@ -65,15 +66,17 @@ type initCmd struct {
image string image string
clientOnly bool clientOnly bool
canary bool canary bool
namespace string
dryRun bool dryRun bool
out io.Writer out io.Writer
home helmpath.Home home helmpath.Home
kubeClient unversioned.DeploymentsNamespacer kubeClient extensionsclient.DeploymentsGetter
} }
func newInitCmd(out io.Writer) *cobra.Command { func newInitCmd(out io.Writer) *cobra.Command {
i := &initCmd{ i := &initCmd{
out: out, out: out,
namespace: environment.TillerNamespace,
} }
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -102,7 +105,7 @@ func newInitCmd(out io.Writer) *cobra.Command {
func (i *initCmd) run() error { func (i *initCmd) run() error {
if flagDebug { if flagDebug {
m, err := installer.DeploymentManifest(i.image, i.canary) m, err := installer.DeploymentManifest(i.namespace, i.image, i.canary)
if err != nil { if err != nil {
return err return err
} }
@ -124,7 +127,7 @@ func (i *initCmd) run() error {
} }
i.kubeClient = c i.kubeClient = c
} }
if err := installer.Install(i.kubeClient, tillerNamespace, i.image, i.canary, flagDebug); err != nil { if err := installer.Install(i.kubeClient, i.namespace, i.image, i.canary, flagDebug); err != nil {
if !kerrors.IsAlreadyExists(err) { if !kerrors.IsAlreadyExists(err) {
return fmt.Errorf("error installing: %s", err) return fmt.Errorf("error installing: %s", err)
} }

@ -27,7 +27,9 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
testcore "k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/helm/cmd/helm/helmpath" "k8s.io/helm/cmd/helm/helmpath"
@ -41,14 +43,19 @@ func TestInitCmd(t *testing.T) {
defer os.Remove(home) defer os.Remove(home)
var buf bytes.Buffer var buf bytes.Buffer
fake := testclient.Fake{} fc := fake.NewSimpleClientset()
cmd := &initCmd{out: &buf, home: helmpath.Home(home), kubeClient: fake.Extensions()} cmd := &initCmd{
out: &buf,
home: helmpath.Home(home),
kubeClient: fc.Extensions(),
namespace: api.NamespaceDefault,
}
if err := cmd.run(); err != nil { if err := cmd.run(); err != nil {
t.Errorf("expected error: %v", err) t.Errorf("expected error: %v", err)
} }
actions := fake.Actions() action := fc.Actions()[0]
if action, ok := actions[0].(testclient.CreateAction); !ok || action.GetResource() != "deployments" { if !action.Matches("create", "deployments") {
t.Errorf("unexpected action: %v, expected create deployment", actions[0]) t.Errorf("unexpected action: %v, expected create deployment", action)
} }
expected := "Tiller (the helm server side component) has been installed into your Kubernetes Cluster." expected := "Tiller (the helm server side component) has been installed into your Kubernetes Cluster."
if !strings.Contains(buf.String(), expected) { if !strings.Contains(buf.String(), expected) {
@ -64,11 +71,21 @@ func TestInitCmd_exsits(t *testing.T) {
defer os.Remove(home) defer os.Remove(home)
var buf bytes.Buffer var buf bytes.Buffer
fake := testclient.Fake{} fc := fake.NewSimpleClientset(&extensions.Deployment{
fake.AddReactor("*", "*", func(action testclient.Action) (bool, runtime.Object, error) { ObjectMeta: api.ObjectMeta{
Namespace: api.NamespaceDefault,
Name: "tiller-deploy",
},
})
fc.AddReactor("*", "*", func(action testcore.Action) (bool, runtime.Object, error) {
return true, nil, errors.NewAlreadyExists(api.Resource("deployments"), "1") return true, nil, errors.NewAlreadyExists(api.Resource("deployments"), "1")
}) })
cmd := &initCmd{out: &buf, home: helmpath.Home(home), kubeClient: fake.Extensions()} cmd := &initCmd{
out: &buf,
home: helmpath.Home(home),
kubeClient: fc.Extensions(),
namespace: api.NamespaceDefault,
}
if err := cmd.run(); err != nil { if err := cmd.run(); err != nil {
t.Errorf("expected error: %v", err) t.Errorf("expected error: %v", err)
} }
@ -86,12 +103,18 @@ func TestInitCmd_clientOnly(t *testing.T) {
defer os.Remove(home) defer os.Remove(home)
var buf bytes.Buffer var buf bytes.Buffer
fake := testclient.Fake{} fc := fake.NewSimpleClientset()
cmd := &initCmd{out: &buf, home: helmpath.Home(home), kubeClient: fake.Extensions(), clientOnly: true} cmd := &initCmd{
out: &buf,
home: helmpath.Home(home),
kubeClient: fc.Extensions(),
clientOnly: true,
namespace: api.NamespaceDefault,
}
if err := cmd.run(); err != nil { if err := cmd.run(); err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
if len(fake.Actions()) != 0 { if len(fc.Actions()) != 0 {
t.Error("expected client call") t.Error("expected client call")
} }
expected := "Not installing tiller due to 'client-only' flag having been set" expected := "Not installing tiller due to 'client-only' flag having been set"
@ -114,18 +137,19 @@ func TestInitCmd_dryRun(t *testing.T) {
}() }()
var buf bytes.Buffer var buf bytes.Buffer
fake := testclient.Fake{} fc := fake.NewSimpleClientset()
cmd := &initCmd{ cmd := &initCmd{
out: &buf, out: &buf,
home: helmpath.Home(home), home: helmpath.Home(home),
kubeClient: fake.Extensions(), kubeClient: fc.Extensions(),
clientOnly: true, clientOnly: true,
dryRun: true, dryRun: true,
namespace: api.NamespaceDefault,
} }
if err := cmd.run(); err != nil { if err := cmd.run(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if len(fake.Actions()) != 0 { if len(fc.Actions()) != 0 {
t.Error("expected no server calls") t.Error("expected no server calls")
} }

@ -23,7 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/unversioned" extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/helm/pkg/version" "k8s.io/helm/pkg/version"
@ -37,27 +37,27 @@ const defaultImage = "gcr.io/kubernetes-helm/tiller"
// command failed. // command failed.
// //
// If verbose is true, this will print the manifest to stdout. // If verbose is true, this will print the manifest to stdout.
func Install(client unversioned.DeploymentsNamespacer, namespace, image string, canary, verbose bool) error { func Install(client extensionsclient.DeploymentsGetter, namespace, image string, canary, verbose bool) error {
obj := deployment(image, canary) obj := deployment(namespace, image, canary)
_, err := client.Deployments(namespace).Create(obj) _, err := client.Deployments(obj.Namespace).Create(obj)
return err return err
} }
// deployment gets the deployment object that installs Tiller. // deployment gets the deployment object that installs Tiller.
func deployment(image string, canary bool) *extensions.Deployment { func deployment(namespace, image string, canary bool) *extensions.Deployment {
switch { switch {
case canary: case canary:
image = defaultImage + ":canary" image = defaultImage + ":canary"
case image == "": case image == "":
image = fmt.Sprintf("%s:%s", defaultImage, version.Version) image = fmt.Sprintf("%s:%s", defaultImage, version.Version)
} }
return generateDeployment(image) return generateDeployment(namespace, image)
} }
// DeploymentManifest gets the manifest (as a string) that describes the Tiller Deployment // DeploymentManifest gets the manifest (as a string) that describes the Tiller Deployment
// resource. // resource.
func DeploymentManifest(image string, canary bool) (string, error) { func DeploymentManifest(namespace, image string, canary bool) (string, error) {
obj := deployment(image, canary) obj := deployment(namespace, image, canary)
buf, err := yaml.Marshal(obj) buf, err := yaml.Marshal(obj)
return string(buf), err return string(buf), err
@ -68,12 +68,13 @@ func generateLabels(labels map[string]string) map[string]string {
return labels return labels
} }
func generateDeployment(image string) *extensions.Deployment { func generateDeployment(namespace, image string) *extensions.Deployment {
labels := generateLabels(map[string]string{"name": "tiller"}) labels := generateLabels(map[string]string{"name": "tiller"})
d := &extensions.Deployment{ d := &extensions.Deployment{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
Name: "tiller-deploy", Namespace: namespace,
Labels: labels, Name: "tiller-deploy",
Labels: labels,
}, },
Spec: extensions.DeploymentSpec{ Spec: extensions.DeploymentSpec{
Replicas: 1, Replicas: 1,

@ -21,12 +21,13 @@ import (
"testing" "testing"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"k8s.io/kubernetes/pkg/api"
"k8s.io/helm/pkg/version"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
testcore "k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/helm/pkg/version"
) )
func TestDeploymentManifest(t *testing.T) { func TestDeploymentManifest(t *testing.T) {
@ -44,7 +45,7 @@ func TestDeploymentManifest(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
o, err := DeploymentManifest(tt.image, tt.canary) o, err := DeploymentManifest(api.NamespaceDefault, tt.image, tt.canary)
if err != nil { if err != nil {
t.Fatalf("%s: error %q", tt.name, err) t.Fatalf("%s: error %q", tt.name, err)
} }
@ -62,9 +63,9 @@ func TestDeploymentManifest(t *testing.T) {
func TestInstall(t *testing.T) { func TestInstall(t *testing.T) {
image := "gcr.io/kubernetes-helm/tiller:v2.0.0" image := "gcr.io/kubernetes-helm/tiller:v2.0.0"
fake := testclient.Fake{} fake := fake.NewSimpleClientset()
fake.AddReactor("create", "deployments", func(action testclient.Action) (bool, runtime.Object, error) { fake.AddReactor("create", "deployments", func(action testcore.Action) (bool, runtime.Object, error) {
obj := action.(testclient.CreateAction).GetObject().(*extensions.Deployment) obj := action.(testcore.CreateAction).GetObject().(*extensions.Deployment)
l := obj.GetLabels() l := obj.GetLabels()
if reflect.DeepEqual(l, map[string]string{"app": "helm"}) { if reflect.DeepEqual(l, map[string]string{"app": "helm"}) {
t.Errorf("expected labels = '', got '%s'", l) t.Errorf("expected labels = '', got '%s'", l)
@ -76,16 +77,16 @@ func TestInstall(t *testing.T) {
return true, obj, nil return true, obj, nil
}) })
err := Install(fake.Extensions(), "default", image, false, false) err := Install(fake.Extensions(), api.NamespaceDefault, image, false, false)
if err != nil { if err != nil {
t.Errorf("unexpected error: %#+v", err) t.Errorf("unexpected error: %#+v", err)
} }
} }
func TestInstall_canary(t *testing.T) { func TestInstall_canary(t *testing.T) {
fake := testclient.Fake{} fake := fake.NewSimpleClientset()
fake.AddReactor("create", "deployments", func(action testclient.Action) (bool, runtime.Object, error) { fake.AddReactor("create", "deployments", func(action testcore.Action) (bool, runtime.Object, error) {
obj := action.(testclient.CreateAction).GetObject().(*extensions.Deployment) obj := action.(testcore.CreateAction).GetObject().(*extensions.Deployment)
i := obj.Spec.Template.Spec.Containers[0].Image i := obj.Spec.Template.Spec.Containers[0].Image
if i != "gcr.io/kubernetes-helm/tiller:canary" { if i != "gcr.io/kubernetes-helm/tiller:canary" {
t.Errorf("expected canary image, got '%s'", i) t.Errorf("expected canary image, got '%s'", i)
@ -93,7 +94,7 @@ func TestInstall_canary(t *testing.T) {
return true, obj, nil return true, obj, nil
}) })
err := Install(fake.Extensions(), "default", "", true, false) err := Install(fake.Extensions(), api.NamespaceDefault, "", true, false)
if err != nil { if err != nil {
t.Errorf("unexpected error: %#+v", err) t.Errorf("unexpected error: %#+v", err)
} }

@ -20,7 +20,7 @@ import (
"fmt" "fmt"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
"k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/labels"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"
@ -35,16 +35,16 @@ func newTillerPortForwarder(namespace, context string) (*kube.Tunnel, error) {
return nil, err return nil, err
} }
podName, err := getTillerPodName(client, namespace) podName, err := getTillerPodName(client.Core(), namespace)
if err != nil { if err != nil {
return nil, err return nil, err
} }
const tillerPort = 44134 const tillerPort = 44134
t := kube.NewTunnel(client.RESTClient, config, namespace, podName, tillerPort) t := kube.NewTunnel(client.Core().RESTClient(), config, namespace, podName, tillerPort)
return t, t.ForwardPort() return t, t.ForwardPort()
} }
func getTillerPodName(client unversioned.PodsNamespacer, namespace string) (string, error) { func getTillerPodName(client internalversion.PodsGetter, namespace string) (string, error) {
// TODO use a const for labels // TODO use a const for labels
selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector() selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector()
pod, err := getFirstRunningPod(client, namespace, selector) pod, err := getFirstRunningPod(client, namespace, selector)
@ -54,7 +54,7 @@ func getTillerPodName(client unversioned.PodsNamespacer, namespace string) (stri
return pod.ObjectMeta.GetName(), nil return pod.ObjectMeta.GetName(), nil
} }
func getFirstRunningPod(client unversioned.PodsNamespacer, namespace string, selector labels.Selector) (*api.Pod, error) { func getFirstRunningPod(client internalversion.PodsGetter, namespace string, selector labels.Selector) (*api.Pod, error) {
options := api.ListOptions{LabelSelector: selector} options := api.ListOptions{LabelSelector: selector}
pods, err := client.Pods(namespace).List(options) pods, err := client.Pods(namespace).List(options)
if err != nil { if err != nil {

@ -20,7 +20,7 @@ import (
"testing" "testing"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned/testclient" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
) )
func mockTillerPod() api.Pod { func mockTillerPod() api.Pod {
@ -74,8 +74,8 @@ func TestGetFirstPod(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
client := testclient.NewSimpleFake(&api.PodList{Items: tt.pods}) client := fake.NewSimpleClientset(&api.PodList{Items: tt.pods})
name, err := getTillerPodName(client, api.NamespaceDefault) name, err := getTillerPodName(client.Core(), api.NamespaceDefault)
if (err != nil) != tt.err { if (err != nil) != tt.err {
t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err) t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err)
} }

@ -25,6 +25,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/proto/hapi/services" "k8s.io/helm/pkg/proto/hapi/services"
"k8s.io/helm/pkg/storage" "k8s.io/helm/pkg/storage"
"k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/storage/driver"
@ -80,15 +81,16 @@ func main() {
} }
func start(c *cobra.Command, args []string) { func start(c *cobra.Command, args []string) {
clientset, err := kube.New(nil).ClientSet()
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot initialize Kubernetes connection: %s", err)
}
switch store { switch store {
case storageMemory: case storageMemory:
env.Releases = storage.Init(driver.NewMemory()) env.Releases = storage.Init(driver.NewMemory())
case storageConfigMap: case storageConfigMap:
c, err := env.KubeClient.APIClient() env.Releases = storage.Init(driver.NewConfigMaps(clientset.Core().ConfigMaps(environment.TillerNamespace)))
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot initialize Kubernetes connection: %s", err)
}
env.Releases = storage.Init(driver.NewConfigMaps(c.ConfigMaps(environment.TillerNamespace)))
} }
lstn, err := net.Listen("tcp", grpcAddr) lstn, err := net.Listen("tcp", grpcAddr)
@ -108,7 +110,7 @@ func start(c *cobra.Command, args []string) {
srvErrCh := make(chan error) srvErrCh := make(chan error)
probeErrCh := make(chan error) probeErrCh := make(chan error)
go func() { go func() {
svc := tiller.NewReleaseServer(env) svc := tiller.NewReleaseServer(env, clientset)
services.RegisterReleaseServiceServer(rootServer, svc) services.RegisterReleaseServiceServer(rootServer, svc)
if err := rootServer.Serve(lstn); err != nil { if err := rootServer.Serve(lstn); err != nil {
srvErrCh <- err srvErrCh <- err

251
glide.lock generated

@ -1,5 +1,5 @@
hash: 8ae84a3225f6cc31f91cc42dc8cf816792a989838254964cdcaaa57c75c37cdc hash: 93ecfadd94d604412b346a3b988000c40e4e4414788d653cec36139481e4d157
updated: 2016-12-01T17:35:05.940550036-07:00 updated: 2016-12-13T00:31:11.783543393-08:00
imports: imports:
- name: cloud.google.com/go - name: cloud.google.com/go
version: 3b1ae45394a234c385be014e9a488f2bb6eef821 version: 3b1ae45394a234c385be014e9a488f2bb6eef821
@ -17,22 +17,13 @@ imports:
- name: github.com/blang/semver - name: github.com/blang/semver
version: 31b736133b98f26d5e078ec9eb591666edfd091f version: 31b736133b98f26d5e078ec9eb591666edfd091f
- name: github.com/coreos/go-oidc - name: github.com/coreos/go-oidc
version: 5cf2aa52da8c574d3aa4458f471ad6ae2240fe6b version: 5644a2f50e2d2d5ba0b474bc5bc55fea1925936d
subpackages: subpackages:
- http - http
- jose - jose
- key - key
- oauth2 - oauth2
- oidc - oidc
- name: github.com/coreos/go-systemd
version: 4484981625c1a6a2ecb40a390fcb6a9bcfee76e3
subpackages:
- activation
- daemon
- dbus
- journal
- unit
- util
- name: github.com/coreos/pkg - name: github.com/coreos/pkg
version: fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8 version: fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8
subpackages: subpackages:
@ -49,6 +40,8 @@ imports:
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
subpackages: subpackages:
- spew - spew
- name: github.com/dgrijalva/jwt-go
version: 01aeca54ebda6e0fbfafd0a524d234159c05ec20
- name: github.com/docker/distribution - name: github.com/docker/distribution
version: cd27f179f2c10c5d300e6d09025b538c475b0d51 version: cd27f179f2c10c5d300e6d09025b538c475b0d51
subpackages: subpackages:
@ -101,10 +94,20 @@ imports:
- swagger - swagger
- name: github.com/evanphx/json-patch - name: github.com/evanphx/json-patch
version: 465937c80b3c07a7c7ad20cc934898646a91c1de version: 465937c80b3c07a7c7ad20cc934898646a91c1de
- name: github.com/exponent-io/jsonpath
version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5
- name: github.com/ghodss/yaml - name: github.com/ghodss/yaml
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
- name: github.com/go-openapi/jsonpointer
version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
- name: github.com/go-openapi/jsonreference
version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272
- name: github.com/go-openapi/spec
version: 6aced65f8501fe1217321abf0749d354824ba2ff
- name: github.com/go-openapi/swag
version: 1d0bd113de87027671077d3c71eb3ac5d7dbba72
- name: github.com/gobwas/glob - name: github.com/gobwas/glob
version: 0354991b92587e2742549d3036f3b5bae5ab03f2 version: bea32b9cd2d6f55753d94a28e959b13f0244797a
subpackages: subpackages:
- compiler - compiler
- match - match
@ -153,50 +156,6 @@ imports:
- proto - proto
- ptypes/any - ptypes/any
- ptypes/timestamp - ptypes/timestamp
- name: github.com/google/cadvisor
version: a726d13de8cb32860e73d72a78dc8e0124267709
subpackages:
- api
- cache/memory
- client/v2
- collector
- container
- container/common
- container/docker
- container/libcontainer
- container/raw
- container/rkt
- container/systemd
- devicemapper
- events
- fs
- healthz
- http
- http/mux
- info/v1
- info/v1/test
- info/v2
- machine
- manager
- manager/watcher
- manager/watcher/raw
- manager/watcher/rkt
- metrics
- pages
- pages/static
- storage
- summary
- utils
- utils/cloudinfo
- utils/cpuload
- utils/cpuload/netlink
- utils/docker
- utils/oomparser
- utils/sysfs
- utils/sysinfo
- utils/tail
- validate
- version
- name: github.com/google/gofuzz - name: github.com/google/gofuzz
version: bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5 version: bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5
- name: github.com/gosuri/uitable - name: github.com/gosuri/uitable
@ -204,6 +163,8 @@ imports:
subpackages: subpackages:
- util/strutil - util/strutil
- util/wordwrap - util/wordwrap
- name: github.com/howeyc/gopass
version: 3ca23474a7c7203e0a0a070fd33508f6efdb9b3d
- name: github.com/imdario/mergo - name: github.com/imdario/mergo
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
- name: github.com/inconshreveable/mousetrap - name: github.com/inconshreveable/mousetrap
@ -212,14 +173,26 @@ imports:
version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982 version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982
- name: github.com/juju/ratelimit - name: github.com/juju/ratelimit
version: 77ed1c8a01217656d2080ad51981f6e99adaa177 version: 77ed1c8a01217656d2080ad51981f6e99adaa177
- name: github.com/mailru/easyjson
version: d5b7844b561a7bc640052f1b935f7b800330d7e0
subpackages:
- buffer
- jlexer
- jwriter
- name: github.com/Masterminds/semver - name: github.com/Masterminds/semver
version: 52edfc04e184ecf0962489d167b511b27aeebd61 version: 52edfc04e184ecf0962489d167b511b27aeebd61
- name: github.com/Masterminds/sprig - name: github.com/Masterminds/sprig
version: 1e60e4ce482a1e2c7b9c9be667535ef152e04300 version: 1e60e4ce482a1e2c7b9c9be667535ef152e04300
- name: github.com/mattn/go-runewidth - name: github.com/mattn/go-runewidth
version: d6bea18f789704b5f83375793155289da36a3c7f version: d6bea18f789704b5f83375793155289da36a3c7f
- name: github.com/mitchellh/go-wordwrap
version: ad45545899c7b13c020ea92b2072220eefad42b8
- name: github.com/pborman/uuid - name: github.com/pborman/uuid
version: ca53cad383cad2479bbba7f7a1a05797ec1386e4 version: ca53cad383cad2479bbba7f7a1a05797ec1386e4
- name: github.com/PuerkitoBio/purell
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
- name: github.com/PuerkitoBio/urlesc
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
- name: github.com/russross/blackfriday - name: github.com/russross/blackfriday
version: 300106c228d52c8941d4b3de6054a6062a86dda3 version: 300106c228d52c8941d4b3de6054a6062a86dda3
- name: github.com/satori/go.uuid - name: github.com/satori/go.uuid
@ -229,11 +202,11 @@ imports:
- name: github.com/Sirupsen/logrus - name: github.com/Sirupsen/logrus
version: 51fe59aca108dc5680109e7b2051cbdcfa5a253c version: 51fe59aca108dc5680109e7b2051cbdcfa5a253c
- name: github.com/spf13/cobra - name: github.com/spf13/cobra
version: 6a8bd97bdb1fc0d08a83459940498ea49d3e8c93 version: f62e98d28ab7ad31d707ba837a966378465c7b57
subpackages: subpackages:
- doc - doc
- name: github.com/spf13/pflag - name: github.com/spf13/pflag
version: 367864438f1b1a3c7db4da06a2f55b144e6784e0 version: 5ccb023bc27df288a957c5e994cd44fd19619465
- name: github.com/technosophos/moniker - name: github.com/technosophos/moniker
version: 9f956786b91d9786ca11aa5be6104542fa911546 version: 9f956786b91d9786ca11aa5be6104542fa911546
- name: github.com/ugorji/go - name: github.com/ugorji/go
@ -254,13 +227,15 @@ imports:
- openpgp/s2k - openpgp/s2k
- ssh/terminal - ssh/terminal
- name: golang.org/x/net - name: golang.org/x/net
version: fb93926129b8ec0056f2f458b1f519654814edf0 version: e90d6d0afc4c315a0d87a568ae68577cc15149a0
subpackages: subpackages:
- context - context
- context/ctxhttp - context/ctxhttp
- http2 - http2
- http2/hpack - http2/hpack
- idna
- internal/timeseries - internal/timeseries
- lex/httplex
- trace - trace
- websocket - websocket
- name: golang.org/x/oauth2 - name: golang.org/x/oauth2
@ -270,6 +245,23 @@ imports:
- internal - internal
- jws - jws
- jwt - jwt
- name: golang.org/x/sys
version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
subpackages:
- unix
- name: golang.org/x/text
version: 2910a502d2bf9e43193af9d68ca516529614eed3
subpackages:
- cases
- internal/tag
- language
- runes
- secure/bidirule
- secure/precis
- transform
- unicode/bidi
- unicode/norm
- width
- name: google.golang.org/appengine - name: google.golang.org/appengine
version: 4f7eeb5305a4ba1966344836ba4af9996b7b4e05 version: 4f7eeb5305a4ba1966344836ba4af9996b7b4e05
subpackages: subpackages:
@ -297,88 +289,24 @@ imports:
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2
version: a83829b6f1293c91addabc89d0571c246397bbf4 version: a83829b6f1293c91addabc89d0571c246397bbf4
- name: k8s.io/client-go
version: 0b62e254fe853d89b1d8d3445bbdab11bcc11bc3
subpackages:
- 1.4/pkg/api
- 1.4/pkg/api/endpoints
- 1.4/pkg/api/errors
- 1.4/pkg/api/meta
- 1.4/pkg/api/meta/metatypes
- 1.4/pkg/api/pod
- 1.4/pkg/api/resource
- 1.4/pkg/api/service
- 1.4/pkg/api/unversioned
- 1.4/pkg/api/unversioned/validation
- 1.4/pkg/api/util
- 1.4/pkg/api/v1
- 1.4/pkg/api/validation
- 1.4/pkg/apimachinery
- 1.4/pkg/apimachinery/registered
- 1.4/pkg/apis/autoscaling
- 1.4/pkg/apis/batch
- 1.4/pkg/apis/extensions
- 1.4/pkg/auth/user
- 1.4/pkg/capabilities
- 1.4/pkg/conversion
- 1.4/pkg/conversion/queryparams
- 1.4/pkg/fields
- 1.4/pkg/labels
- 1.4/pkg/runtime
- 1.4/pkg/runtime/serializer
- 1.4/pkg/runtime/serializer/json
- 1.4/pkg/runtime/serializer/protobuf
- 1.4/pkg/runtime/serializer/recognizer
- 1.4/pkg/runtime/serializer/streaming
- 1.4/pkg/runtime/serializer/versioning
- 1.4/pkg/security/apparmor
- 1.4/pkg/selection
- 1.4/pkg/third_party/forked/golang/reflect
- 1.4/pkg/types
- 1.4/pkg/util
- 1.4/pkg/util/clock
- 1.4/pkg/util/config
- 1.4/pkg/util/crypto
- 1.4/pkg/util/errors
- 1.4/pkg/util/flowcontrol
- 1.4/pkg/util/framer
- 1.4/pkg/util/hash
- 1.4/pkg/util/integer
- 1.4/pkg/util/intstr
- 1.4/pkg/util/json
- 1.4/pkg/util/labels
- 1.4/pkg/util/net
- 1.4/pkg/util/net/sets
- 1.4/pkg/util/parsers
- 1.4/pkg/util/rand
- 1.4/pkg/util/runtime
- 1.4/pkg/util/sets
- 1.4/pkg/util/uuid
- 1.4/pkg/util/validation
- 1.4/pkg/util/validation/field
- 1.4/pkg/util/wait
- 1.4/pkg/util/yaml
- 1.4/pkg/version
- 1.4/pkg/watch
- 1.4/pkg/watch/versioned
- 1.4/rest
- 1.4/tools/clientcmd/api
- 1.4/tools/metrics
- 1.4/transport
- name: k8s.io/kubernetes - name: k8s.io/kubernetes
version: fd8fac83034df346529c6e11aabceea2db48d663 version: d47846323632bf59c729460fc7344d2df347bf46
subpackages: subpackages:
- cmd/kubeadm/app/apis/kubeadm
- cmd/kubeadm/app/apis/kubeadm/install
- cmd/kubeadm/app/apis/kubeadm/v1alpha1
- federation/apis/federation - federation/apis/federation
- federation/apis/federation/install - federation/apis/federation/install
- federation/apis/federation/v1beta1 - federation/apis/federation/v1beta1
- federation/client/clientset_generated/federation_internalclientset - federation/client/clientset_generated/federation_internalclientset
- federation/client/clientset_generated/federation_internalclientset/typed/core/unversioned - federation/client/clientset_generated/federation_internalclientset/typed/core/internalversion
- federation/client/clientset_generated/federation_internalclientset/typed/extensions/unversioned - federation/client/clientset_generated/federation_internalclientset/typed/extensions/internalversion
- federation/client/clientset_generated/federation_internalclientset/typed/federation/unversioned - federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion
- pkg/api - pkg/api
- pkg/api/annotations - pkg/api/annotations
- pkg/api/endpoints - pkg/api/endpoints
- pkg/api/errors - pkg/api/errors
- pkg/api/events
- pkg/api/install - pkg/api/install
- pkg/api/meta - pkg/api/meta
- pkg/api/meta/metatypes - pkg/api/meta/metatypes
@ -392,11 +320,13 @@ imports:
- pkg/api/util - pkg/api/util
- pkg/api/v1 - pkg/api/v1
- pkg/api/validation - pkg/api/validation
- pkg/api/validation/path
- pkg/apimachinery - pkg/apimachinery
- pkg/apimachinery/announced
- pkg/apimachinery/registered - pkg/apimachinery/registered
- pkg/apis/apps - pkg/apis/apps
- pkg/apis/apps/install - pkg/apis/apps/install
- pkg/apis/apps/v1alpha1 - pkg/apis/apps/v1beta1
- pkg/apis/authentication - pkg/apis/authentication
- pkg/apis/authentication/install - pkg/apis/authentication/install
- pkg/apis/authentication/v1beta1 - pkg/apis/authentication/v1beta1
@ -425,43 +355,60 @@ imports:
- pkg/apis/imagepolicy/v1alpha1 - pkg/apis/imagepolicy/v1alpha1
- pkg/apis/policy - pkg/apis/policy
- pkg/apis/policy/install - pkg/apis/policy/install
- pkg/apis/policy/v1alpha1 - pkg/apis/policy/v1beta1
- pkg/apis/rbac - pkg/apis/rbac
- pkg/apis/rbac/install - pkg/apis/rbac/install
- pkg/apis/rbac/v1alpha1 - pkg/apis/rbac/v1alpha1
- pkg/apis/storage - pkg/apis/storage
- pkg/apis/storage/install - pkg/apis/storage/install
- pkg/apis/storage/util
- pkg/apis/storage/v1beta1 - pkg/apis/storage/v1beta1
- pkg/auth/authenticator
- pkg/auth/user - pkg/auth/user
- pkg/capabilities - pkg/capabilities
- pkg/client/cache - pkg/client/cache
- pkg/client/clientset_generated/internalclientset - pkg/client/clientset_generated/internalclientset
- pkg/client/clientset_generated/internalclientset/typed/authentication/unversioned - pkg/client/clientset_generated/internalclientset/fake
- pkg/client/clientset_generated/internalclientset/typed/authorization/unversioned - pkg/client/clientset_generated/internalclientset/typed/apps/internalversion
- pkg/client/clientset_generated/internalclientset/typed/autoscaling/unversioned - pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/batch/unversioned - pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion
- pkg/client/clientset_generated/internalclientset/typed/certificates/unversioned - pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/core/unversioned - pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion
- pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned - pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/rbac/unversioned - pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion
- pkg/client/clientset_generated/internalclientset/typed/storage/unversioned - pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/batch/internalversion
- pkg/client/clientset_generated/internalclientset/typed/batch/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion
- pkg/client/clientset_generated/internalclientset/typed/certificates/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/core/internalversion
- pkg/client/clientset_generated/internalclientset/typed/core/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion
- pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/policy/internalversion
- pkg/client/clientset_generated/internalclientset/typed/policy/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion
- pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/storage/internalversion
- pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake
- pkg/client/metrics - pkg/client/metrics
- pkg/client/record - pkg/client/record
- pkg/client/restclient - pkg/client/restclient
- pkg/client/restclient/fake
- pkg/client/retry
- pkg/client/testing/core
- pkg/client/transport - pkg/client/transport
- pkg/client/typed/discovery - pkg/client/typed/discovery
- pkg/client/typed/discovery/fake
- pkg/client/typed/dynamic - pkg/client/typed/dynamic
- pkg/client/unversioned - pkg/client/unversioned
- pkg/client/unversioned/adapters/internalclientset
- pkg/client/unversioned/auth - pkg/client/unversioned/auth
- pkg/client/unversioned/clientcmd - pkg/client/unversioned/clientcmd
- pkg/client/unversioned/clientcmd/api - pkg/client/unversioned/clientcmd/api
- pkg/client/unversioned/clientcmd/api/latest - pkg/client/unversioned/clientcmd/api/latest
- pkg/client/unversioned/clientcmd/api/v1 - pkg/client/unversioned/clientcmd/api/v1
- pkg/client/unversioned/fake
- pkg/client/unversioned/portforward - pkg/client/unversioned/portforward
- pkg/client/unversioned/remotecommand - pkg/client/unversioned/remotecommand
- pkg/client/unversioned/testclient
- pkg/controller - pkg/controller
- pkg/controller/deployment/util - pkg/controller/deployment/util
- pkg/conversion - pkg/conversion
@ -469,8 +416,10 @@ imports:
- pkg/credentialprovider - pkg/credentialprovider
- pkg/fieldpath - pkg/fieldpath
- pkg/fields - pkg/fields
- pkg/genericapiserver/openapi/common
- pkg/httplog - pkg/httplog
- pkg/kubectl - pkg/kubectl
- pkg/kubectl/cmd/testing
- pkg/kubectl/cmd/util - pkg/kubectl/cmd/util
- pkg/kubectl/resource - pkg/kubectl/resource
- pkg/kubelet/qos - pkg/kubelet/qos
@ -479,7 +428,7 @@ imports:
- pkg/kubelet/types - pkg/kubelet/types
- pkg/labels - pkg/labels
- pkg/master/ports - pkg/master/ports
- pkg/registry/thirdpartyresourcedata - pkg/registry/extensions/thirdpartyresourcedata
- pkg/runtime - pkg/runtime
- pkg/runtime/serializer - pkg/runtime/serializer
- pkg/runtime/serializer/json - pkg/runtime/serializer/json
@ -488,15 +437,17 @@ imports:
- pkg/runtime/serializer/streaming - pkg/runtime/serializer/streaming
- pkg/runtime/serializer/versioning - pkg/runtime/serializer/versioning
- pkg/security/apparmor - pkg/security/apparmor
- pkg/security/podsecuritypolicy/seccomp
- pkg/security/podsecuritypolicy/util - pkg/security/podsecuritypolicy/util
- pkg/selection - pkg/selection
- pkg/serviceaccount
- pkg/storage - pkg/storage
- pkg/types - pkg/types
- pkg/util - pkg/util
- pkg/util/certificates - pkg/util/cert
- pkg/util/clock - pkg/util/clock
- pkg/util/config - pkg/util/config
- pkg/util/crypto - pkg/util/diff
- pkg/util/errors - pkg/util/errors
- pkg/util/exec - pkg/util/exec
- pkg/util/flag - pkg/util/flag
@ -514,10 +465,10 @@ imports:
- pkg/util/labels - pkg/util/labels
- pkg/util/net - pkg/util/net
- pkg/util/net/sets - pkg/util/net/sets
- pkg/util/node
- pkg/util/parsers - pkg/util/parsers
- pkg/util/pod - pkg/util/pod
- pkg/util/rand - pkg/util/rand
- pkg/util/replicaset
- pkg/util/runtime - pkg/util/runtime
- pkg/util/sets - pkg/util/sets
- pkg/util/slice - pkg/util/slice

@ -1,10 +1,13 @@
package: k8s.io/helm package: k8s.io/helm
import: import:
- package: golang.org/x/net - package: golang.org/x/net
version: fb93926129b8ec0056f2f458b1f519654814edf0 version: e90d6d0afc4c315a0d87a568ae68577cc15149a0
subpackages: subpackages:
- context - context
- package: github.com/spf13/cobra - package: github.com/spf13/cobra
version: f62e98d28ab7ad31d707ba837a966378465c7b57
- package: github.com/spf13/pflag
version: 5ccb023bc27df288a957c5e994cd44fd19619465
- package: github.com/Masterminds/sprig - package: github.com/Masterminds/sprig
version: ^2.7 version: ^2.7
- package: github.com/ghodss/yaml - package: github.com/ghodss/yaml
@ -20,7 +23,7 @@ import:
- package: google.golang.org/grpc - package: google.golang.org/grpc
version: 1.0.3 version: 1.0.3
- package: k8s.io/kubernetes - package: k8s.io/kubernetes
version: ~1.4.1 version: ~1.5.0
subpackages: subpackages:
- pkg/api - pkg/api
- pkg/api/errors - pkg/api/errors
@ -28,12 +31,14 @@ import:
- pkg/apimachinery/registered - pkg/apimachinery/registered
- pkg/apis/batch - pkg/apis/batch
- pkg/apis/extensions - pkg/apis/extensions
- pkg/client/clientset_generated/internalclientset
- pkg/client/clientset_generated/internalclientset/typed/core/internalversion
- pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion
- pkg/client/restclient - pkg/client/restclient
- pkg/client/unversioned - pkg/client/typed/discovery
- pkg/client/unversioned/clientcmd - pkg/client/unversioned/clientcmd
- pkg/client/unversioned/portforward - pkg/client/unversioned/portforward
- pkg/client/unversioned/remotecommand - pkg/client/unversioned/remotecommand
- pkg/client/unversioned/testclient
- pkg/kubectl - pkg/kubectl
- pkg/kubectl/cmd/util - pkg/kubectl/cmd/util
- pkg/kubectl/resource - pkg/kubectl/resource
@ -41,7 +46,6 @@ import:
- pkg/runtime - pkg/runtime
- pkg/util/intstr - pkg/util/intstr
- pkg/util/strategicpatch - pkg/util/strategicpatch
- pkg/util/yaml
- pkg/watch - pkg/watch
- package: github.com/gosuri/uitable - package: github.com/gosuri/uitable
- package: github.com/asaskevich/govalidator - package: github.com/asaskevich/govalidator

@ -22,7 +22,6 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"reflect"
"strings" "strings"
"time" "time"
@ -30,14 +29,12 @@ import (
"k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/strategicpatch" "k8s.io/kubernetes/pkg/util/strategicpatch"
"k8s.io/kubernetes/pkg/util/yaml"
"k8s.io/kubernetes/pkg/watch" "k8s.io/kubernetes/pkg/watch"
) )
@ -46,14 +43,7 @@ var ErrNoObjectsVisited = goerrors.New("no objects visited")
// Client represents a client capable of communicating with the Kubernetes API. // Client represents a client capable of communicating with the Kubernetes API.
type Client struct { type Client struct {
*cmdutil.Factory cmdutil.Factory
// IncludeThirdPartyAPIs indicates whether to load "dynamic" APIs.
//
// This requires additional calls to the Kubernetes API server, and these calls
// are not supported by all versions. Additionally, during testing, initializing
// a client will still attempt to contact a live server. In these situations,
// this flag may need to be disabled.
IncludeThirdPartyAPIs bool
// Validate idicates whether to load a schema for validation. // Validate idicates whether to load a schema for validation.
Validate bool Validate bool
// SchemaCacheDir is the path for loading cached schema. // SchemaCacheDir is the path for loading cached schema.
@ -63,10 +53,9 @@ type Client struct {
// New create a new Client // New create a new Client
func New(config clientcmd.ClientConfig) *Client { func New(config clientcmd.ClientConfig) *Client {
return &Client{ return &Client{
Factory: cmdutil.NewFactory(config), Factory: cmdutil.NewFactory(config),
IncludeThirdPartyAPIs: true, Validate: true,
Validate: true, SchemaCacheDir: clientcmd.RecommendedSchemaFile,
SchemaCacheDir: clientcmd.RecommendedSchemaFile,
} }
} }
@ -82,21 +71,15 @@ func (e ErrAlreadyExists) Error() string {
return fmt.Sprintf("Looks like there are no changes for %s", e.errorMsg) return fmt.Sprintf("Looks like there are no changes for %s", e.errorMsg)
} }
// APIClient returns a Kubernetes API client.
//
// This is necessary because cmdutil.Client is a field, not a method, which
// means it can't satisfy an interface's method requirement. In order to ensure
// that an implementation of environment.KubeClient can access the raw API client,
// it is necessary to add this method.
func (c *Client) APIClient() (unversioned.Interface, error) {
return c.Client()
}
// Create creates kubernetes resources from an io.reader // Create creates kubernetes resources from an io.reader
// //
// Namespace will set the namespace // Namespace will set the namespace
func (c *Client) Create(namespace string, reader io.Reader) error { func (c *Client) Create(namespace string, reader io.Reader) error {
if err := c.ensureNamespace(namespace); err != nil { client, err := c.ClientSet()
if err != nil {
return err
}
if err := ensureNamespace(client, namespace); err != nil {
return err return err
} }
return perform(c, namespace, reader, createResource) return perform(c, namespace, reader, createResource)
@ -107,7 +90,7 @@ func (c *Client) newBuilder(namespace string, reader io.Reader) *resource.Builde
if err != nil { if err != nil {
log.Printf("warning: failed to load schema: %s", err) log.Printf("warning: failed to load schema: %s", err)
} }
return c.NewBuilder(c.IncludeThirdPartyAPIs). return c.NewBuilder().
ContinueOnError(). ContinueOnError().
Schema(schema). Schema(schema).
NamespaceParam(namespace). NamespaceParam(namespace).
@ -313,33 +296,22 @@ func deleteResource(info *resource.Info) error {
} }
func updateResource(target *resource.Info, currentObj runtime.Object) error { func updateResource(target *resource.Info, currentObj runtime.Object) error {
encoder := api.Codecs.LegacyCodec(registered.EnabledVersions()...) encoder := api.Codecs.LegacyCodec(registered.EnabledVersions()...)
originalSerialization, err := runtime.Encode(encoder, currentObj) original, err := runtime.Encode(encoder, currentObj)
if err != nil {
return err
}
editedSerialization, err := runtime.Encode(encoder, target.Object)
if err != nil {
return err
}
originalJS, err := yaml.ToJSON(originalSerialization)
if err != nil { if err != nil {
return err return err
} }
editedJS, err := yaml.ToJSON(editedSerialization) modified, err := runtime.Encode(encoder, target.Object)
if err != nil { if err != nil {
return err return err
} }
if reflect.DeepEqual(originalJS, editedJS) { if api.Semantic.DeepEqual(original, modified) {
return ErrAlreadyExists{target.Name} return ErrAlreadyExists{target.Name}
} }
patch, err := strategicpatch.CreateStrategicMergePatch(originalJS, editedJS, currentObj) patch, err := strategicpatch.CreateTwoWayMergePatch(original, modified, currentObj)
if err != nil { if err != nil {
return err return err
} }
@ -413,21 +385,6 @@ func waitForJob(e watch.Event, name string) (bool, error) {
return false, nil return false, nil
} }
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
}
func deleteUnwantedResources(currentInfos, targetInfos []*resource.Info) { func deleteUnwantedResources(currentInfos, targetInfos []*resource.Info) {
for _, cInfo := range currentInfos { for _, cInfo := range currentInfos {
if _, ok := findMatchingInfo(cInfo, targetInfos); !ok { if _, ok := findMatchingInfo(cInfo, targetInfos); !ok {

@ -18,51 +18,122 @@ package kube
import ( import (
"bytes" "bytes"
"encoding/json"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
"k8s.io/kubernetes/pkg/api/meta" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
api "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/client/restclient/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
) )
func TestUpdateResource(t *testing.T) { func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
}
tests := []struct { func newPod(name string) api.Pod {
name string return api.Pod{
namespace string ObjectMeta: api.ObjectMeta{Name: name},
modified *resource.Info Spec: api.PodSpec{
currentObj runtime.Object Containers: []api.Container{{
err bool Name: "app:v4",
errMessage string Image: "abc/app:v4",
}{ Ports: []api.ContainerPort{{Name: "http", ContainerPort: 80}},
{ }},
name: "no changes when updating resources",
modified: createFakeInfo("nginx", nil),
currentObj: createFakePod("nginx", nil),
err: true,
errMessage: "Looks like there are no changes for nginx",
}, },
//{
//name: "valid update input",
//modified: createFakeInfo("nginx", map[string]string{"app": "nginx"}),
//currentObj: createFakePod("nginx", nil),
//},
} }
}
func newPodList(names ...string) api.PodList {
var list api.PodList
for _, name := range names {
list.Items = append(list.Items, newPod(name))
}
return list
}
for _, tt := range tests { func notFoundBody() *unversioned.Status {
err := updateResource(tt.modified, tt.currentObj) return &unversioned.Status{
if err != nil && err.Error() != tt.errMessage { Code: http.StatusNotFound,
t.Errorf("%q. expected error message: %v, got %v", tt.name, tt.errMessage, err) Status: unversioned.StatusFailure,
Reason: unversioned.StatusReasonNotFound,
Message: " \"\" not found",
Details: &unversioned.StatusDetails{},
}
}
func newResponse(code int, obj runtime.Object) (*http.Response, error) {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
body := ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(testapi.Default.Codec(), obj))))
return &http.Response{StatusCode: code, Header: header, Body: body}, nil
}
func TestUpdate(t *testing.T) {
listA := newPodList("starfish", "otter", "squid")
listB := newPodList("starfish", "otter", "dolphin")
listB.Items[0].Spec.Containers[0].Ports = []api.ContainerPort{{Name: "https", ContainerPort: 443}}
actions := make(map[string]string)
f, tf, codec, ns := cmdtesting.NewAPIFactory()
tf.Client = &fake.RESTClient{
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
actions[p] = m
switch {
case p == "/namespaces/test/pods/starfish" && m == "GET":
return newResponse(200, &listA.Items[0])
case p == "/namespaces/test/pods/otter" && m == "GET":
return newResponse(200, &listA.Items[1])
case p == "/namespaces/test/pods/dolphin" && m == "GET":
return newResponse(404, notFoundBody())
case p == "/namespaces/test/pods/starfish" && m == "PATCH":
data, err := ioutil.ReadAll(req.Body)
if err != nil {
t.Fatalf("could not dump request: %s", err)
}
req.Body.Close()
expected := `{"spec":{"containers":[{"name":"app:v4","ports":[{"containerPort":443,"name":"https","protocol":"TCP"},{"$patch":"delete","containerPort":80}]}]}}`
if string(data) != expected {
t.Errorf("expected patch %s, got %s", expected, string(data))
}
return newResponse(200, &listB.Items[0])
case p == "/namespaces/test/pods" && m == "POST":
return newResponse(200, &listB.Items[1])
case p == "/namespaces/test/pods/squid" && m == "DELETE":
return newResponse(200, &listB.Items[1])
default:
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
return nil, nil
}
}),
}
c := &Client{Factory: f}
if err := c.Update("test", objBody(codec, &listA), objBody(codec, &listB)); err != nil {
t.Fatal(err)
}
expectedActions := map[string]string{
"/namespaces/test/pods/dolphin": "GET",
"/namespaces/test/pods/otter": "GET",
"/namespaces/test/pods/starfish": "PATCH",
"/namespaces/test/pods": "POST",
"/namespaces/test/pods/squid": "DELETE",
}
for k, v := range expectedActions {
if m, ok := actions[k]; !ok || m != v {
t.Errorf("expected a %s request to %s", k, v)
} }
} }
} }
@ -110,20 +181,18 @@ func TestPerform(t *testing.T) {
return nil return nil
} }
c := New(nil) f, tf, _, _ := cmdtesting.NewAPIFactory()
c.IncludeThirdPartyAPIs = false c := &Client{Factory: f}
c.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { if tt.swaggerFile != "" {
return &fake.RESTClient{}, nil
}
c.Validator = func(validate bool, cacheDir string) (validation.Schema, error) {
if tt.swaggerFile == "" {
return validation.NullSchema{}, nil
}
data, err := ioutil.ReadFile(tt.swaggerFile) data, err := ioutil.ReadFile(tt.swaggerFile)
if err != nil {
t.Fatalf("could not read swagger spec: %s", err)
}
validator, err := validation.NewSwaggerSchemaFromBytes(data, nil)
if err != nil { if err != nil {
t.Fatalf("could not load swagger spec: %s", err) t.Fatalf("could not load swagger spec: %s", err)
} }
return validation.NewSwaggerSchemaFromBytes(data, nil) tf.Validator = validator
} }
err := perform(c, tt.namespace, tt.reader, fn) err := perform(c, tt.namespace, tt.reader, fn)
@ -143,14 +212,12 @@ func TestPerform(t *testing.T) {
func TestReal(t *testing.T) { func TestReal(t *testing.T) {
t.Skip("This is a live test, comment this line to run") t.Skip("This is a live test, comment this line to run")
c := New(nil) c := New(nil)
c.IncludeThirdPartyAPIs = false
if err := c.Create("test", strings.NewReader(guestbookManifest)); err != nil { if err := c.Create("test", strings.NewReader(guestbookManifest)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
testSvcEndpointManifest := testServiceManifest + "\n---\n" + testEndpointManifest testSvcEndpointManifest := testServiceManifest + "\n---\n" + testEndpointManifest
c = New(nil) c = New(nil)
c.IncludeThirdPartyAPIs = false
if err := c.Create("test-delete", strings.NewReader(testSvcEndpointManifest)); err != nil { if err := c.Create("test-delete", strings.NewReader(testSvcEndpointManifest)); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -322,52 +389,3 @@ spec:
ports: ports:
- containerPort: 80 - containerPort: 80
` `
func createFakePod(name string, labels map[string]string) runtime.Object {
objectMeta := createObjectMeta(name, labels)
object := &api.Pod{
ObjectMeta: objectMeta,
}
return object
}
func createFakeInfo(name string, labels map[string]string) *resource.Info {
pod := createFakePod(name, labels)
marshaledObj, _ := json.Marshal(pod)
mapping := &meta.RESTMapping{
Resource: name,
Scope: meta.RESTScopeNamespace,
GroupVersionKind: unversioned.GroupVersionKind{
Kind: "Pod",
Version: "v1",
}}
client := &fake.RESTClient{
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return &http.Response{
StatusCode: 200,
Header: header,
Body: ioutil.NopCloser(bytes.NewReader(marshaledObj)),
}, nil
})}
info := resource.NewInfo(client, mapping, "default", "nginx", false)
info.Object = pod
return info
}
func createObjectMeta(name string, labels map[string]string) api.ObjectMeta {
objectMeta := api.ObjectMeta{Name: name, Namespace: "default"}
if labels != nil {
objectMeta.Labels = labels
}
return objectMeta
}

@ -0,0 +1,41 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kube // import "k8s.io/helm/pkg/kube"
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
)
func createNamespace(client internalclientset.Interface, namespace string) error {
ns := &api.Namespace{
ObjectMeta: api.ObjectMeta{
Name: namespace,
},
}
_, err := client.Core().Namespaces().Create(ns)
return err
}
func ensureNamespace(client internalclientset.Interface, namespace string) error {
err := createNamespace(client, namespace)
if err != nil && !errors.IsAlreadyExists(err) {
return err
}
return nil
}

@ -0,0 +1,36 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kube // import "k8s.io/helm/pkg/kube"
import (
"testing"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
)
func TestEnsureNamespace(t *testing.T) {
client := fake.NewSimpleClientset()
if err := ensureNamespace(client, "foo"); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if err := ensureNamespace(client, "foo"); err != nil {
t.Fatalf("unexpected error: %s", err)
}
if _, err := client.Core().Namespaces().Get("foo"); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}

@ -38,11 +38,11 @@ type Tunnel struct {
stopChan chan struct{} stopChan chan struct{}
readyChan chan struct{} readyChan chan struct{}
config *restclient.Config config *restclient.Config
client *restclient.RESTClient client restclient.Interface
} }
// NewTunnel creates a new tunnel // NewTunnel creates a new tunnel
func NewTunnel(client *restclient.RESTClient, config *restclient.Config, namespace, podName string, remote int) *Tunnel { func NewTunnel(client restclient.Interface, config *restclient.Config, namespace, podName string, remote int) *Tunnel {
return &Tunnel{ return &Tunnel{
config: config, config: config,
client: client, client: client,

@ -27,13 +27,12 @@ import (
"time" "time"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
rspb "k8s.io/helm/pkg/proto/hapi/release"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kberrs "k8s.io/kubernetes/pkg/api/errors" kberrs "k8s.io/kubernetes/pkg/api/errors"
client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
kblabels "k8s.io/kubernetes/pkg/labels" kblabels "k8s.io/kubernetes/pkg/labels"
rspb "k8s.io/helm/pkg/proto/hapi/release"
) )
var _ Driver = (*ConfigMaps)(nil) var _ Driver = (*ConfigMaps)(nil)
@ -48,12 +47,12 @@ var magicGzip = []byte{0x1f, 0x8b, 0x08}
// ConfigMaps is a wrapper around an implementation of a kubernetes // ConfigMaps is a wrapper around an implementation of a kubernetes
// ConfigMapsInterface. // ConfigMapsInterface.
type ConfigMaps struct { type ConfigMaps struct {
impl client.ConfigMapsInterface impl internalversion.ConfigMapInterface
} }
// NewConfigMaps initializes a new ConfigMaps wrapping an implmenetation of // NewConfigMaps initializes a new ConfigMaps wrapping an implmenetation of
// the kubernetes ConfigMapsInterface. // the kubernetes ConfigMapsInterface.
func NewConfigMaps(impl client.ConfigMapsInterface) *ConfigMaps { func NewConfigMaps(impl internalversion.ConfigMapInterface) *ConfigMaps {
return &ConfigMaps{impl: impl} return &ConfigMaps{impl: impl}
} }
@ -210,7 +209,7 @@ func (cfgmaps *ConfigMaps) Delete(key string) (rls *rspb.Release, err error) {
return nil, err return nil, err
} }
// delete the release // delete the release
if err = cfgmaps.impl.Delete(key); err != nil { if err = cfgmaps.impl.Delete(key, &api.DeleteOptions{}); err != nil {
return rls, err return rls, err
} }
return rls, nil return rls, nil

@ -19,9 +19,9 @@ import (
"testing" "testing"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
"k8s.io/kubernetes/pkg/api"
rspb "k8s.io/helm/pkg/proto/hapi/release" rspb "k8s.io/helm/pkg/proto/hapi/release"
"k8s.io/kubernetes/pkg/api"
) )
func TestConfigMapName(t *testing.T) { func TestConfigMapName(t *testing.T) {

@ -20,10 +20,11 @@ import (
"fmt" "fmt"
"testing" "testing"
rspb "k8s.io/helm/pkg/proto/hapi/release"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
kberrs "k8s.io/kubernetes/pkg/api/errors" kberrs "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
rspb "k8s.io/helm/pkg/proto/hapi/release"
) )
func releaseStub(name string, vers int32, code rspb.Status_Code) *rspb.Release { func releaseStub(name string, vers int32, code rspb.Status_Code) *rspb.Release {
@ -73,7 +74,7 @@ func newTestFixtureCfgMaps(t *testing.T, releases ...*rspb.Release) *ConfigMaps
// MockConfigMapsInterface mocks a kubernetes ConfigMapsInterface // MockConfigMapsInterface mocks a kubernetes ConfigMapsInterface
type MockConfigMapsInterface struct { type MockConfigMapsInterface struct {
unversioned.ConfigMapsInterface internalversion.ConfigMapInterface
objects map[string]*api.ConfigMap objects map[string]*api.ConfigMap
} }
@ -132,7 +133,7 @@ func (mock *MockConfigMapsInterface) Update(cfgmap *api.ConfigMap) (*api.ConfigM
} }
// Delete deletes a ConfigMap by name. // Delete deletes a ConfigMap by name.
func (mock *MockConfigMapsInterface) Delete(name string) error { func (mock *MockConfigMapsInterface) Delete(name string, opts *api.DeleteOptions) error {
if _, ok := mock.objects[name]; !ok { if _, ok := mock.objects[name]; !ok {
return kberrs.NewNotFound(api.Resource("tests"), name) return kberrs.NewNotFound(api.Resource("tests"), name)
} }

@ -31,8 +31,6 @@ import (
"k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/helm/pkg/storage" "k8s.io/helm/pkg/storage"
"k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/storage/driver"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
) )
// TillerNamespace is the namespace tiller is running in. // TillerNamespace is the namespace tiller is running in.
@ -134,9 +132,6 @@ type KubeClient interface {
// reader must contain a YAML stream (one or more YAML documents separated // reader must contain a YAML stream (one or more YAML documents separated
// by "\n---\n"). // by "\n---\n").
Update(namespace string, originalReader, modifiedReader io.Reader) error Update(namespace string, originalReader, modifiedReader io.Reader) error
// APIClient gets a raw API client for Kubernetes.
APIClient() (unversioned.Interface, error)
} }
// PrintingKubeClient implements KubeClient, but simply prints the reader to // PrintingKubeClient implements KubeClient, but simply prints the reader to
@ -145,14 +140,6 @@ type PrintingKubeClient struct {
Out io.Writer Out io.Writer
} }
// APIClient always returns an error.
//
// The printing client does not have access to a Kubernetes client at all. So it
// will always return an error if the client is accessed.
func (p *PrintingKubeClient) APIClient() (unversioned.Interface, error) {
return testclient.NewSimpleFake(), nil
}
// Create prints the values of what would be created with a real KubeClient. // Create prints the values of what would be created with a real KubeClient.
func (p *PrintingKubeClient) Create(ns string, r io.Reader) error { func (p *PrintingKubeClient) Create(ns string, r io.Reader) error {
_, err := io.Copy(p.Out, r) _, err := io.Copy(p.Out, r)

@ -23,8 +23,6 @@ import (
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/chart"
unversionedclient "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/testclient"
) )
type mockEngine struct { type mockEngine struct {
@ -35,12 +33,7 @@ func (e *mockEngine) Render(chrt *chart.Chart, v chartutil.Values) (map[string]s
return e.out, nil return e.out, nil
} }
type mockKubeClient struct { type mockKubeClient struct{}
}
func (k *mockKubeClient) APIClient() (unversionedclient.Interface, error) {
return testclient.NewSimpleFake(), nil
}
func (k *mockKubeClient) Create(ns string, r io.Reader) error { func (k *mockKubeClient) Create(ns string, r io.Reader) error {
return nil return nil

@ -23,6 +23,7 @@ import (
"strings" "strings"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/proto/hapi/release"
) )

@ -18,6 +18,7 @@ package tiller
import ( import (
"golang.org/x/net/context" "golang.org/x/net/context"
tpb "k8s.io/helm/pkg/proto/hapi/services" tpb "k8s.io/helm/pkg/proto/hapi/services"
relutil "k8s.io/helm/pkg/releaseutil" relutil "k8s.io/helm/pkg/releaseutil"
) )

@ -21,7 +21,6 @@ import (
"testing" "testing"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
rpb "k8s.io/helm/pkg/proto/hapi/release" rpb "k8s.io/helm/pkg/proto/hapi/release"
tpb "k8s.io/helm/pkg/proto/hapi/services" tpb "k8s.io/helm/pkg/proto/hapi/services"
) )

@ -25,12 +25,13 @@ import (
"regexp" "regexp"
"strings" "strings"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"github.com/technosophos/moniker" "github.com/technosophos/moniker"
ctx "golang.org/x/net/context" ctx "golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/typed/discovery"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"
@ -95,13 +96,15 @@ func NewServer() *grpc.Server {
// ReleaseServer implements the server-side gRPC endpoint for the HAPI services. // ReleaseServer implements the server-side gRPC endpoint for the HAPI services.
type ReleaseServer struct { type ReleaseServer struct {
env *environment.Environment env *environment.Environment
clientset internalclientset.Interface
} }
// NewReleaseServer creates a new release server. // NewReleaseServer creates a new release server.
func NewReleaseServer(env *environment.Environment) *ReleaseServer { func NewReleaseServer(env *environment.Environment, clientset internalclientset.Interface) *ReleaseServer {
return &ReleaseServer{ return &ReleaseServer{
env: env, env: env,
clientset: clientset,
} }
} }
@ -693,15 +696,10 @@ func (s *ReleaseServer) prepareRelease(req *services.InstallReleaseRequest) (*re
return rel, nil return rel, nil
} }
func (s *ReleaseServer) getVersionSet() (versionSet, error) { func getVersionSet(client discovery.ServerGroupsInterface) (versionSet, error) {
defVersions := newVersionSet("v1") defVersions := newVersionSet("v1")
cli, err := s.env.KubeClient.APIClient()
if err != nil {
log.Printf("API Client for Kubernetes is missing: %s.", err)
return defVersions, err
}
groups, err := cli.Discovery().ServerGroups() groups, err := client.ServerGroups()
if err != nil { if err != nil {
return defVersions, err return defVersions, err
} }
@ -745,7 +743,7 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values
// Sort hooks, manifests, and partials. Only hooks and manifests are returned, // Sort hooks, manifests, and partials. Only hooks and manifests are returned,
// as partials are not used after renderer.Render. Empty manifests are also // as partials are not used after renderer.Render. Empty manifests are also
// removed here. // removed here.
vs, err := s.getVersionSet() vs, err := getVersionSet(s.clientset.Discovery())
if err != nil { if err != nil {
return nil, nil, "", fmt.Errorf("Could not get apiVersions from Kubernetes: %s", err) return nil, nil, "", fmt.Errorf("Could not get apiVersions from Kubernetes: %s", err)
} }
@ -958,7 +956,7 @@ func (s *ReleaseServer) UninstallRelease(c ctx.Context, req *services.UninstallR
} }
} }
vs, err := s.getVersionSet() vs, err := getVersionSet(s.clientset.Discovery())
if err != nil { if err != nil {
return nil, fmt.Errorf("Could not get apiVersions from Kubernetes: %s", err) return nil, fmt.Errorf("Could not get apiVersions from Kubernetes: %s", err)
} }

@ -28,6 +28,7 @@ import (
"github.com/golang/protobuf/ptypes/timestamp" "github.com/golang/protobuf/ptypes/timestamp"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/chart"
@ -82,7 +83,8 @@ data:
func rsFixture() *ReleaseServer { func rsFixture() *ReleaseServer {
return &ReleaseServer{ return &ReleaseServer{
env: mockEnvironment(), env: mockEnvironment(),
clientset: fake.NewSimpleClientset(),
} }
} }
@ -178,7 +180,7 @@ func TestValidName(t *testing.T) {
func TestGetVersionSet(t *testing.T) { func TestGetVersionSet(t *testing.T) {
rs := rsFixture() rs := rsFixture()
vs, err := rs.getVersionSet() vs, err := getVersionSet(rs.clientset.Discovery())
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

Loading…
Cancel
Save