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"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/helm/cmd/helm/helmpath"
"k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/tiller/environment"
)
const (
localRepoIndexFilePath = "index.yaml"
homeEnvVar = "HELM_HOME"
hostEnvVar = "HELM_HOST"
tillerNamespace = "kube-system"
)
var (
@ -145,7 +145,7 @@ func main() {
func setupConnection(c *cobra.Command, args []string) error {
if tillerHost == "" {
tunnel, err := newTillerPortForwarder(tillerNamespace, kubeContext)
tunnel, err := newTillerPortForwarder(environment.TillerNamespace, kubeContext)
if err != nil {
return err
}
@ -199,12 +199,12 @@ func homePath() string {
// getKubeClient is a convenience method for creating kubernetes config and client
// 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()
if err != nil {
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 {
return nil, nil, fmt.Errorf("could not get kubernetes client: %s", err)
}

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

@ -27,7 +27,9 @@ import (
"k8s.io/kubernetes/pkg/api"
"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/helm/cmd/helm/helmpath"
@ -41,14 +43,19 @@ func TestInitCmd(t *testing.T) {
defer os.Remove(home)
var buf bytes.Buffer
fake := testclient.Fake{}
cmd := &initCmd{out: &buf, home: helmpath.Home(home), kubeClient: fake.Extensions()}
fc := fake.NewSimpleClientset()
cmd := &initCmd{
out: &buf,
home: helmpath.Home(home),
kubeClient: fc.Extensions(),
namespace: api.NamespaceDefault,
}
if err := cmd.run(); err != nil {
t.Errorf("expected error: %v", err)
}
actions := fake.Actions()
if action, ok := actions[0].(testclient.CreateAction); !ok || action.GetResource() != "deployments" {
t.Errorf("unexpected action: %v, expected create deployment", actions[0])
action := fc.Actions()[0]
if !action.Matches("create", "deployments") {
t.Errorf("unexpected action: %v, expected create deployment", action)
}
expected := "Tiller (the helm server side component) has been installed into your Kubernetes Cluster."
if !strings.Contains(buf.String(), expected) {
@ -64,11 +71,21 @@ func TestInitCmd_exsits(t *testing.T) {
defer os.Remove(home)
var buf bytes.Buffer
fake := testclient.Fake{}
fake.AddReactor("*", "*", func(action testclient.Action) (bool, runtime.Object, error) {
fc := fake.NewSimpleClientset(&extensions.Deployment{
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")
})
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 {
t.Errorf("expected error: %v", err)
}
@ -86,12 +103,18 @@ func TestInitCmd_clientOnly(t *testing.T) {
defer os.Remove(home)
var buf bytes.Buffer
fake := testclient.Fake{}
cmd := &initCmd{out: &buf, home: helmpath.Home(home), kubeClient: fake.Extensions(), clientOnly: true}
fc := fake.NewSimpleClientset()
cmd := &initCmd{
out: &buf,
home: helmpath.Home(home),
kubeClient: fc.Extensions(),
clientOnly: true,
namespace: api.NamespaceDefault,
}
if err := cmd.run(); err != nil {
t.Errorf("unexpected error: %v", err)
}
if len(fake.Actions()) != 0 {
if len(fc.Actions()) != 0 {
t.Error("expected client call")
}
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
fake := testclient.Fake{}
fc := fake.NewSimpleClientset()
cmd := &initCmd{
out: &buf,
home: helmpath.Home(home),
kubeClient: fake.Extensions(),
kubeClient: fc.Extensions(),
clientOnly: true,
dryRun: true,
namespace: api.NamespaceDefault,
}
if err := cmd.run(); err != nil {
t.Fatal(err)
}
if len(fake.Actions()) != 0 {
if len(fc.Actions()) != 0 {
t.Error("expected no server calls")
}

@ -23,7 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"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/helm/pkg/version"
@ -37,27 +37,27 @@ const defaultImage = "gcr.io/kubernetes-helm/tiller"
// command failed.
//
// If verbose is true, this will print the manifest to stdout.
func Install(client unversioned.DeploymentsNamespacer, namespace, image string, canary, verbose bool) error {
obj := deployment(image, canary)
_, err := client.Deployments(namespace).Create(obj)
func Install(client extensionsclient.DeploymentsGetter, namespace, image string, canary, verbose bool) error {
obj := deployment(namespace, image, canary)
_, err := client.Deployments(obj.Namespace).Create(obj)
return err
}
// 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 {
case canary:
image = defaultImage + ":canary"
case image == "":
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
// resource.
func DeploymentManifest(image string, canary bool) (string, error) {
obj := deployment(image, canary)
func DeploymentManifest(namespace, image string, canary bool) (string, error) {
obj := deployment(namespace, image, canary)
buf, err := yaml.Marshal(obj)
return string(buf), err
@ -68,12 +68,13 @@ func generateLabels(labels map[string]string) map[string]string {
return labels
}
func generateDeployment(image string) *extensions.Deployment {
func generateDeployment(namespace, image string) *extensions.Deployment {
labels := generateLabels(map[string]string{"name": "tiller"})
d := &extensions.Deployment{
ObjectMeta: api.ObjectMeta{
Name: "tiller-deploy",
Labels: labels,
Namespace: namespace,
Name: "tiller-deploy",
Labels: labels,
},
Spec: extensions.DeploymentSpec{
Replicas: 1,

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

@ -20,7 +20,7 @@ import (
"fmt"
"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/helm/pkg/kube"
@ -35,16 +35,16 @@ func newTillerPortForwarder(namespace, context string) (*kube.Tunnel, error) {
return nil, err
}
podName, err := getTillerPodName(client, namespace)
podName, err := getTillerPodName(client.Core(), namespace)
if err != nil {
return nil, err
}
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()
}
func getTillerPodName(client unversioned.PodsNamespacer, namespace string) (string, error) {
func getTillerPodName(client internalversion.PodsGetter, namespace string) (string, error) {
// TODO use a const for labels
selector := labels.Set{"app": "helm", "name": "tiller"}.AsSelector()
pod, err := getFirstRunningPod(client, namespace, selector)
@ -54,7 +54,7 @@ func getTillerPodName(client unversioned.PodsNamespacer, namespace string) (stri
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}
pods, err := client.Pods(namespace).List(options)
if err != nil {

@ -20,7 +20,7 @@ import (
"testing"
"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 {
@ -74,8 +74,8 @@ func TestGetFirstPod(t *testing.T) {
}
for _, tt := range tests {
client := testclient.NewSimpleFake(&api.PodList{Items: tt.pods})
name, err := getTillerPodName(client, api.NamespaceDefault)
client := fake.NewSimpleClientset(&api.PodList{Items: tt.pods})
name, err := getTillerPodName(client.Core(), api.NamespaceDefault)
if (err != nil) != tt.err {
t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err)
}

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

251
glide.lock generated

@ -1,5 +1,5 @@
hash: 8ae84a3225f6cc31f91cc42dc8cf816792a989838254964cdcaaa57c75c37cdc
updated: 2016-12-01T17:35:05.940550036-07:00
hash: 93ecfadd94d604412b346a3b988000c40e4e4414788d653cec36139481e4d157
updated: 2016-12-13T00:31:11.783543393-08:00
imports:
- name: cloud.google.com/go
version: 3b1ae45394a234c385be014e9a488f2bb6eef821
@ -17,22 +17,13 @@ imports:
- name: github.com/blang/semver
version: 31b736133b98f26d5e078ec9eb591666edfd091f
- name: github.com/coreos/go-oidc
version: 5cf2aa52da8c574d3aa4458f471ad6ae2240fe6b
version: 5644a2f50e2d2d5ba0b474bc5bc55fea1925936d
subpackages:
- http
- jose
- key
- oauth2
- oidc
- name: github.com/coreos/go-systemd
version: 4484981625c1a6a2ecb40a390fcb6a9bcfee76e3
subpackages:
- activation
- daemon
- dbus
- journal
- unit
- util
- name: github.com/coreos/pkg
version: fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8
subpackages:
@ -49,6 +40,8 @@ imports:
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
subpackages:
- spew
- name: github.com/dgrijalva/jwt-go
version: 01aeca54ebda6e0fbfafd0a524d234159c05ec20
- name: github.com/docker/distribution
version: cd27f179f2c10c5d300e6d09025b538c475b0d51
subpackages:
@ -101,10 +94,20 @@ imports:
- swagger
- name: github.com/evanphx/json-patch
version: 465937c80b3c07a7c7ad20cc934898646a91c1de
- name: github.com/exponent-io/jsonpath
version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5
- name: github.com/ghodss/yaml
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
version: 0354991b92587e2742549d3036f3b5bae5ab03f2
version: bea32b9cd2d6f55753d94a28e959b13f0244797a
subpackages:
- compiler
- match
@ -153,50 +156,6 @@ imports:
- proto
- ptypes/any
- 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
version: bbcb9da2d746f8bdbd6a936686a0a6067ada0ec5
- name: github.com/gosuri/uitable
@ -204,6 +163,8 @@ imports:
subpackages:
- util/strutil
- util/wordwrap
- name: github.com/howeyc/gopass
version: 3ca23474a7c7203e0a0a070fd33508f6efdb9b3d
- name: github.com/imdario/mergo
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
- name: github.com/inconshreveable/mousetrap
@ -212,14 +173,26 @@ imports:
version: 72f9bd7c4e0c2a40055ab3d0f09654f730cce982
- name: github.com/juju/ratelimit
version: 77ed1c8a01217656d2080ad51981f6e99adaa177
- name: github.com/mailru/easyjson
version: d5b7844b561a7bc640052f1b935f7b800330d7e0
subpackages:
- buffer
- jlexer
- jwriter
- name: github.com/Masterminds/semver
version: 52edfc04e184ecf0962489d167b511b27aeebd61
- name: github.com/Masterminds/sprig
version: 1e60e4ce482a1e2c7b9c9be667535ef152e04300
- name: github.com/mattn/go-runewidth
version: d6bea18f789704b5f83375793155289da36a3c7f
- name: github.com/mitchellh/go-wordwrap
version: ad45545899c7b13c020ea92b2072220eefad42b8
- name: github.com/pborman/uuid
version: ca53cad383cad2479bbba7f7a1a05797ec1386e4
- name: github.com/PuerkitoBio/purell
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
- name: github.com/PuerkitoBio/urlesc
version: 5bd2802263f21d8788851d5305584c82a5c75d7e
- name: github.com/russross/blackfriday
version: 300106c228d52c8941d4b3de6054a6062a86dda3
- name: github.com/satori/go.uuid
@ -229,11 +202,11 @@ imports:
- name: github.com/Sirupsen/logrus
version: 51fe59aca108dc5680109e7b2051cbdcfa5a253c
- name: github.com/spf13/cobra
version: 6a8bd97bdb1fc0d08a83459940498ea49d3e8c93
version: f62e98d28ab7ad31d707ba837a966378465c7b57
subpackages:
- doc
- name: github.com/spf13/pflag
version: 367864438f1b1a3c7db4da06a2f55b144e6784e0
version: 5ccb023bc27df288a957c5e994cd44fd19619465
- name: github.com/technosophos/moniker
version: 9f956786b91d9786ca11aa5be6104542fa911546
- name: github.com/ugorji/go
@ -254,13 +227,15 @@ imports:
- openpgp/s2k
- ssh/terminal
- name: golang.org/x/net
version: fb93926129b8ec0056f2f458b1f519654814edf0
version: e90d6d0afc4c315a0d87a568ae68577cc15149a0
subpackages:
- context
- context/ctxhttp
- http2
- http2/hpack
- idna
- internal/timeseries
- lex/httplex
- trace
- websocket
- name: golang.org/x/oauth2
@ -270,6 +245,23 @@ imports:
- internal
- jws
- 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
version: 4f7eeb5305a4ba1966344836ba4af9996b7b4e05
subpackages:
@ -297,88 +289,24 @@ imports:
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/yaml.v2
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
version: fd8fac83034df346529c6e11aabceea2db48d663
version: d47846323632bf59c729460fc7344d2df347bf46
subpackages:
- cmd/kubeadm/app/apis/kubeadm
- cmd/kubeadm/app/apis/kubeadm/install
- cmd/kubeadm/app/apis/kubeadm/v1alpha1
- federation/apis/federation
- federation/apis/federation/install
- federation/apis/federation/v1beta1
- federation/client/clientset_generated/federation_internalclientset
- federation/client/clientset_generated/federation_internalclientset/typed/core/unversioned
- federation/client/clientset_generated/federation_internalclientset/typed/extensions/unversioned
- federation/client/clientset_generated/federation_internalclientset/typed/federation/unversioned
- federation/client/clientset_generated/federation_internalclientset/typed/core/internalversion
- federation/client/clientset_generated/federation_internalclientset/typed/extensions/internalversion
- federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion
- pkg/api
- pkg/api/annotations
- pkg/api/endpoints
- pkg/api/errors
- pkg/api/events
- pkg/api/install
- pkg/api/meta
- pkg/api/meta/metatypes
@ -392,11 +320,13 @@ imports:
- pkg/api/util
- pkg/api/v1
- pkg/api/validation
- pkg/api/validation/path
- pkg/apimachinery
- pkg/apimachinery/announced
- pkg/apimachinery/registered
- pkg/apis/apps
- pkg/apis/apps/install
- pkg/apis/apps/v1alpha1
- pkg/apis/apps/v1beta1
- pkg/apis/authentication
- pkg/apis/authentication/install
- pkg/apis/authentication/v1beta1
@ -425,43 +355,60 @@ imports:
- pkg/apis/imagepolicy/v1alpha1
- pkg/apis/policy
- pkg/apis/policy/install
- pkg/apis/policy/v1alpha1
- pkg/apis/policy/v1beta1
- pkg/apis/rbac
- pkg/apis/rbac/install
- pkg/apis/rbac/v1alpha1
- pkg/apis/storage
- pkg/apis/storage/install
- pkg/apis/storage/util
- pkg/apis/storage/v1beta1
- pkg/auth/authenticator
- pkg/auth/user
- pkg/capabilities
- pkg/client/cache
- pkg/client/clientset_generated/internalclientset
- pkg/client/clientset_generated/internalclientset/typed/authentication/unversioned
- pkg/client/clientset_generated/internalclientset/typed/authorization/unversioned
- pkg/client/clientset_generated/internalclientset/typed/autoscaling/unversioned
- pkg/client/clientset_generated/internalclientset/typed/batch/unversioned
- pkg/client/clientset_generated/internalclientset/typed/certificates/unversioned
- pkg/client/clientset_generated/internalclientset/typed/core/unversioned
- pkg/client/clientset_generated/internalclientset/typed/extensions/unversioned
- pkg/client/clientset_generated/internalclientset/typed/rbac/unversioned
- pkg/client/clientset_generated/internalclientset/typed/storage/unversioned
- pkg/client/clientset_generated/internalclientset/fake
- pkg/client/clientset_generated/internalclientset/typed/apps/internalversion
- pkg/client/clientset_generated/internalclientset/typed/apps/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion
- pkg/client/clientset_generated/internalclientset/typed/authentication/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion
- pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion/fake
- pkg/client/clientset_generated/internalclientset/typed/autoscaling/internalversion
- 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/record
- pkg/client/restclient
- pkg/client/restclient/fake
- pkg/client/retry
- pkg/client/testing/core
- pkg/client/transport
- pkg/client/typed/discovery
- pkg/client/typed/discovery/fake
- pkg/client/typed/dynamic
- pkg/client/unversioned
- pkg/client/unversioned/adapters/internalclientset
- pkg/client/unversioned/auth
- pkg/client/unversioned/clientcmd
- pkg/client/unversioned/clientcmd/api
- pkg/client/unversioned/clientcmd/api/latest
- pkg/client/unversioned/clientcmd/api/v1
- pkg/client/unversioned/fake
- pkg/client/unversioned/portforward
- pkg/client/unversioned/remotecommand
- pkg/client/unversioned/testclient
- pkg/controller
- pkg/controller/deployment/util
- pkg/conversion
@ -469,8 +416,10 @@ imports:
- pkg/credentialprovider
- pkg/fieldpath
- pkg/fields
- pkg/genericapiserver/openapi/common
- pkg/httplog
- pkg/kubectl
- pkg/kubectl/cmd/testing
- pkg/kubectl/cmd/util
- pkg/kubectl/resource
- pkg/kubelet/qos
@ -479,7 +428,7 @@ imports:
- pkg/kubelet/types
- pkg/labels
- pkg/master/ports
- pkg/registry/thirdpartyresourcedata
- pkg/registry/extensions/thirdpartyresourcedata
- pkg/runtime
- pkg/runtime/serializer
- pkg/runtime/serializer/json
@ -488,15 +437,17 @@ imports:
- pkg/runtime/serializer/streaming
- pkg/runtime/serializer/versioning
- pkg/security/apparmor
- pkg/security/podsecuritypolicy/seccomp
- pkg/security/podsecuritypolicy/util
- pkg/selection
- pkg/serviceaccount
- pkg/storage
- pkg/types
- pkg/util
- pkg/util/certificates
- pkg/util/cert
- pkg/util/clock
- pkg/util/config
- pkg/util/crypto
- pkg/util/diff
- pkg/util/errors
- pkg/util/exec
- pkg/util/flag
@ -514,10 +465,10 @@ imports:
- pkg/util/labels
- pkg/util/net
- pkg/util/net/sets
- pkg/util/node
- pkg/util/parsers
- pkg/util/pod
- pkg/util/rand
- pkg/util/replicaset
- pkg/util/runtime
- pkg/util/sets
- pkg/util/slice

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

@ -22,7 +22,6 @@ import (
"fmt"
"io"
"log"
"reflect"
"strings"
"time"
@ -30,14 +29,12 @@ import (
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/strategicpatch"
"k8s.io/kubernetes/pkg/util/yaml"
"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.
type Client struct {
*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
cmdutil.Factory
// Validate idicates whether to load a schema for validation.
Validate bool
// SchemaCacheDir is the path for loading cached schema.
@ -63,10 +53,9 @@ type Client struct {
// New create a new Client
func New(config clientcmd.ClientConfig) *Client {
return &Client{
Factory: cmdutil.NewFactory(config),
IncludeThirdPartyAPIs: true,
Validate: true,
SchemaCacheDir: clientcmd.RecommendedSchemaFile,
Factory: cmdutil.NewFactory(config),
Validate: true,
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)
}
// 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
//
// Namespace will set the namespace
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 perform(c, namespace, reader, createResource)
@ -107,7 +90,7 @@ func (c *Client) newBuilder(namespace string, reader io.Reader) *resource.Builde
if err != nil {
log.Printf("warning: failed to load schema: %s", err)
}
return c.NewBuilder(c.IncludeThirdPartyAPIs).
return c.NewBuilder().
ContinueOnError().
Schema(schema).
NamespaceParam(namespace).
@ -313,33 +296,22 @@ func deleteResource(info *resource.Info) error {
}
func updateResource(target *resource.Info, currentObj runtime.Object) error {
encoder := api.Codecs.LegacyCodec(registered.EnabledVersions()...)
originalSerialization, 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)
original, err := runtime.Encode(encoder, currentObj)
if err != nil {
return err
}
editedJS, err := yaml.ToJSON(editedSerialization)
modified, err := runtime.Encode(encoder, target.Object)
if err != nil {
return err
}
if reflect.DeepEqual(originalJS, editedJS) {
if api.Semantic.DeepEqual(original, modified) {
return ErrAlreadyExists{target.Name}
}
patch, err := strategicpatch.CreateStrategicMergePatch(originalJS, editedJS, currentObj)
patch, err := strategicpatch.CreateTwoWayMergePatch(original, modified, currentObj)
if err != nil {
return err
}
@ -413,21 +385,6 @@ func waitForJob(e watch.Event, name string) (bool, error) {
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) {
for _, cInfo := range currentInfos {
if _, ok := findMatchingInfo(cInfo, targetInfos); !ok {

@ -18,51 +18,122 @@ package kube
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http"
"strings"
"testing"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/unversioned"
api "k8s.io/kubernetes/pkg/api/v1"
"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/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 {
name string
namespace string
modified *resource.Info
currentObj runtime.Object
err bool
errMessage string
}{
{
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",
func newPod(name string) api.Pod {
return api.Pod{
ObjectMeta: api.ObjectMeta{Name: name},
Spec: api.PodSpec{
Containers: []api.Container{{
Name: "app:v4",
Image: "abc/app:v4",
Ports: []api.ContainerPort{{Name: "http", ContainerPort: 80}},
}},
},
//{
//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 {
err := updateResource(tt.modified, tt.currentObj)
if err != nil && err.Error() != tt.errMessage {
t.Errorf("%q. expected error message: %v, got %v", tt.name, tt.errMessage, err)
func notFoundBody() *unversioned.Status {
return &unversioned.Status{
Code: http.StatusNotFound,
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
}
c := New(nil)
c.IncludeThirdPartyAPIs = false
c.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
return &fake.RESTClient{}, nil
}
c.Validator = func(validate bool, cacheDir string) (validation.Schema, error) {
if tt.swaggerFile == "" {
return validation.NullSchema{}, nil
}
f, tf, _, _ := cmdtesting.NewAPIFactory()
c := &Client{Factory: f}
if 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 {
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)
@ -143,14 +212,12 @@ func TestPerform(t *testing.T) {
func TestReal(t *testing.T) {
t.Skip("This is a live test, comment this line to run")
c := New(nil)
c.IncludeThirdPartyAPIs = false
if err := c.Create("test", strings.NewReader(guestbookManifest)); err != nil {
t.Fatal(err)
}
testSvcEndpointManifest := testServiceManifest + "\n---\n" + testEndpointManifest
c = New(nil)
c.IncludeThirdPartyAPIs = false
if err := c.Create("test-delete", strings.NewReader(testSvcEndpointManifest)); err != nil {
t.Fatal(err)
}
@ -322,52 +389,3 @@ spec:
ports:
- 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{}
readyChan chan struct{}
config *restclient.Config
client *restclient.RESTClient
client restclient.Interface
}
// 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{
config: config,
client: client,

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

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

@ -20,10 +20,11 @@ import (
"fmt"
"testing"
rspb "k8s.io/helm/pkg/proto/hapi/release"
"k8s.io/kubernetes/pkg/api"
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 {
@ -73,7 +74,7 @@ func newTestFixtureCfgMaps(t *testing.T, releases ...*rspb.Release) *ConfigMaps
// MockConfigMapsInterface mocks a kubernetes ConfigMapsInterface
type MockConfigMapsInterface struct {
unversioned.ConfigMapsInterface
internalversion.ConfigMapInterface
objects map[string]*api.ConfigMap
}
@ -132,7 +133,7 @@ func (mock *MockConfigMapsInterface) Update(cfgmap *api.ConfigMap) (*api.ConfigM
}
// 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 {
return kberrs.NewNotFound(api.Resource("tests"), name)
}

@ -31,8 +31,6 @@ import (
"k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/helm/pkg/storage"
"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.
@ -134,9 +132,6 @@ type KubeClient interface {
// reader must contain a YAML stream (one or more YAML documents separated
// by "\n---\n").
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
@ -145,14 +140,6 @@ type PrintingKubeClient struct {
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.
func (p *PrintingKubeClient) Create(ns string, r io.Reader) error {
_, err := io.Copy(p.Out, r)

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

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

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

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

@ -25,12 +25,13 @@ import (
"regexp"
"strings"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"github.com/technosophos/moniker"
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/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/typed/discovery"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/kube"
@ -95,13 +96,15 @@ func NewServer() *grpc.Server {
// ReleaseServer implements the server-side gRPC endpoint for the HAPI services.
type ReleaseServer struct {
env *environment.Environment
env *environment.Environment
clientset internalclientset.Interface
}
// NewReleaseServer creates a new release server.
func NewReleaseServer(env *environment.Environment) *ReleaseServer {
func NewReleaseServer(env *environment.Environment, clientset internalclientset.Interface) *ReleaseServer {
return &ReleaseServer{
env: env,
env: env,
clientset: clientset,
}
}
@ -693,15 +696,10 @@ func (s *ReleaseServer) prepareRelease(req *services.InstallReleaseRequest) (*re
return rel, nil
}
func (s *ReleaseServer) getVersionSet() (versionSet, error) {
func getVersionSet(client discovery.ServerGroupsInterface) (versionSet, error) {
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 {
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,
// as partials are not used after renderer.Render. Empty manifests are also
// removed here.
vs, err := s.getVersionSet()
vs, err := getVersionSet(s.clientset.Discovery())
if err != nil {
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 {
return nil, fmt.Errorf("Could not get apiVersions from Kubernetes: %s", err)
}

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

Loading…
Cancel
Save