Merge pull request #4509 from adamreese/dev-v3-kube-v1.11

ref(*): kubernetes v1.11 support
pull/4518/head
Adam Reese 6 years ago committed by GitHub
commit 56c4b9b48d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

493
Gopkg.lock generated

File diff suppressed because it is too large Load Diff

@ -33,19 +33,27 @@
[[constraint]]
name = "k8s.io/api"
branch = "release-1.10"
branch = "release-1.11"
[[constraint]]
name = "k8s.io/apimachinery"
branch = "release-1.10"
branch = "release-1.11"
[[constraint]]
version = "kubernetes-1.10.0"
version = "kubernetes-1.11.2"
name = "k8s.io/client-go"
[[constraint]]
name = "k8s.io/kubernetes"
branch = "release-1.10"
branch = "release-1.11"
[[override]]
name = "github.com/json-iterator/go"
revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682"
[[override]]
name = "github.com/Azure/go-autorest"
revision = "1ff28809256a84bb6966640ff3d0371af82ccba4"
[prune]
go-tests = true

@ -24,7 +24,7 @@ import (
// Import to initialize client auth plugins.
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/helm/environment"
@ -34,7 +34,7 @@ import (
var (
settings environment.EnvSettings
config clientcmd.ClientConfig
config genericclioptions.RESTClientGetter
configOnce sync.Once
)
@ -89,7 +89,7 @@ func newClient(allNamespaces bool) helm.Interface {
)
}
func kubeConfig() clientcmd.ClientConfig {
func kubeConfig() genericclioptions.RESTClientGetter {
configOnce.Do(func() {
config = kube.GetConfig(settings.KubeConfig, settings.KubeContext, settings.Namespace)
})
@ -97,7 +97,7 @@ func kubeConfig() clientcmd.ClientConfig {
}
func getNamespace() string {
if ns, _, err := kubeConfig().Namespace(); err == nil {
if ns, _, err := kubeConfig().ToRawKubeConfigLoader().Namespace(); err == nil {
return ns
}
return "default"

@ -43,14 +43,14 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubernetes/pkg/api/legacyscheme"
batchinternal "k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/get"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/validation"
"k8s.io/kubernetes/pkg/printers"
)
const (
@ -68,9 +68,12 @@ type Client struct {
}
// New creates a new Client.
func New(config clientcmd.ClientConfig) *Client {
func New(getter genericclioptions.RESTClientGetter) *Client {
if getter == nil {
getter = genericclioptions.NewConfigFlags()
}
return &Client{
Factory: cmdutil.NewFactory(config),
Factory: cmdutil.NewFactory(getter),
Log: nopLogger,
}
}
@ -100,7 +103,7 @@ func (c *Client) Create(namespace string, reader io.Reader, timeout int64, shoul
}
func (c *Client) namespace() string {
if ns, _, err := c.DefaultNamespace(); err == nil {
if ns, _, err := c.ToRawKubeConfigLoader().Namespace(); err == nil {
return ns
}
return v1.NamespaceDefault
@ -108,8 +111,8 @@ func (c *Client) namespace() string {
func (c *Client) newBuilder(namespace string, reader io.Reader) *resource.Result {
return c.NewBuilder().
Internal().
ContinueOnError().
WithScheme(legacyscheme.Scheme).
Schema(c.validator()).
NamespaceParam(c.namespace()).
DefaultNamespace().
@ -177,7 +180,7 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// versions per cluster, but this certainly won't hurt anything, so let's be safe.
gvk := info.ResourceMapping().GroupVersionKind
vk := gvk.Version + "/" + gvk.Kind
objs[vk] = append(objs[vk], info.AsInternal())
objs[vk] = append(objs[vk], asVersioned(info))
//Get the relation pods
objPods, err = c.getSelectRelationPod(info, objPods)
@ -203,10 +206,7 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// an object type changes, so we can just rely on that. Problem is it doesn't seem to keep
// track of tab widths.
buf := new(bytes.Buffer)
p, err := cmdutil.PrinterForOptions(&printers.PrintOptions{})
if err != nil {
return "", err
}
p, _ := get.NewHumanPrintFlags().ToPrinter("")
for t, ot := range objs {
if _, err = buf.WriteString("==> " + t + "\n"); err != nil {
return "", err
@ -294,7 +294,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader
for _, info := range original.Difference(target) {
c.Log("Deleting %q in %s...", info.Name, info.Namespace)
if err := deleteResource(c, info); err != nil {
if err := deleteResource(info); err != nil {
c.Log("Failed to delete %q, err: %s", info.Name, err)
}
}
@ -314,7 +314,7 @@ func (c *Client) Delete(namespace string, reader io.Reader) error {
}
return perform(infos, func(info *resource.Info) error {
c.Log("Starting delete for %q %s", info.Name, info.Mapping.GroupVersionKind.Kind)
err := deleteResource(c, info)
err := deleteResource(info)
return c.skipIfNotFound(err)
})
}
@ -376,17 +376,11 @@ func createResource(info *resource.Info) error {
return info.Refresh(obj, true)
}
func deleteResource(c *Client, info *resource.Info) error {
reaper, err := c.Reaper(info.Mapping)
if err != nil {
// If there is no reaper for this resources, delete it.
if kubectl.IsNoSuchReaperError(err) {
return resource.NewHelper(info.Client, info.Mapping).Delete(info.Namespace, info.Name)
}
return err
}
c.Log("Using reaper for deleting %q", info.Name)
return reaper.Stop(info.Namespace, info.Name, 0, nil)
func deleteResource(info *resource.Info) error {
policy := metav1.DeletePropagationBackground
opts := &metav1.DeleteOptions{PropagationPolicy: &policy}
_, err := resource.NewHelper(info.Client, info.Mapping).DeleteWithOptions(info.Namespace, info.Name, opts)
return err
}
func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) {
@ -408,7 +402,7 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P
}
// Get a versioned object
versionedObject, err := target.Versioned()
versionedObject := asVersioned(target)
// Unstructured objects, such as CRDs, may not have an not registered error
// returned from ConvertToVersion. Anything that's unstructured should
@ -452,7 +446,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
if force {
// Attempt to delete...
if err := deleteResource(c, target); err != nil {
if err := deleteResource(target); err != nil {
return err
}
log.Printf("Deleted %s: %q", kind, target.Name)
@ -480,14 +474,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
return nil
}
versioned, err := target.Versioned()
if runtime.IsNotRegisteredError(err) {
return nil
}
if err != nil {
return err
}
versioned := asVersioned(target)
selector, err := getSelectorFromObject(versioned)
if err != nil {
return nil
@ -695,13 +682,7 @@ func (c *Client) getSelectRelationPod(info *resource.Info, objPods map[string][]
c.Log("get relation pod of object: %s/%s/%s", info.Namespace, info.Mapping.GroupVersionKind.Kind, info.Name)
versioned, err := info.Versioned()
if runtime.IsNotRegisteredError(err) {
return objPods, nil
}
if err != nil {
return objPods, err
}
versioned := asVersioned(info)
// We can ignore this error because it will only error if it isn't a type that doesn't
// have pods. In that case, we don't care
@ -749,3 +730,7 @@ func isFoundPod(podItem []core.Pod, pod core.Pod) bool {
}
return false
}
func asVersioned(info *resource.Info) runtime.Object {
return cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
}

@ -23,25 +23,20 @@ import (
"net/http"
"strings"
"testing"
"time"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/scheme"
)
var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer
var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer
func objBody(codec runtime.Codec, obj runtime.Object) io.ReadCloser {
return ioutil.NopCloser(bytes.NewReader([]byte(runtime.EncodeOrDie(codec, obj))))
@ -98,24 +93,6 @@ func newResponse(code int, obj runtime.Object) (*http.Response, error) {
return &http.Response{StatusCode: code, Header: header, Body: body}, nil
}
type fakeReaper struct {
name string
}
func (r *fakeReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error {
r.name = name
return nil
}
type fakeReaperFactory struct {
cmdutil.Factory
reaper kubectl.Reaper
}
func (f *fakeReaperFactory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error) {
return f.reaper, nil
}
type testClient struct {
*Client
*cmdtesting.TestFactory
@ -123,8 +100,6 @@ type testClient struct {
func newTestClient() *testClient {
tf := cmdtesting.NewTestFactory()
tf.Namespace = core.NamespaceDefault
c := &Client{Factory: tf, Log: nopLogger}
return &testClient{Client: c, TestFactory: tf}
}
@ -141,7 +116,6 @@ func TestUpdate(t *testing.T) {
tf := cmdtesting.NewTestFactory()
defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
@ -176,12 +150,11 @@ func TestUpdate(t *testing.T) {
}),
}
c := newTestClient()
tf.Namespace = core.NamespaceDefault
reaper := &fakeReaper{}
rf := &fakeReaperFactory{Factory: tf, reaper: reaper}
c.Client.Factory = rf
codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...)
c := &Client{
Factory: tf,
Log: nopLogger,
}
codec := legacyscheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
if err := c.Update(core.NamespaceDefault, objBody(codec, &listA), objBody(codec, &listB), false, false, 0, false); err != nil {
t.Fatal(err)
}
@ -202,6 +175,7 @@ func TestUpdate(t *testing.T) {
"/namespaces/default/pods/otter:GET",
"/namespaces/default/pods/dolphin:GET",
"/namespaces/default/pods:POST",
"/namespaces/default/pods/squid:DELETE",
}
if len(expectedActions) != len(actions) {
t.Errorf("unexpected number of requests, expected %d, got %d", len(expectedActions), len(actions))
@ -212,11 +186,6 @@ func TestUpdate(t *testing.T) {
t.Errorf("expected %s request got %s", v, actions[k])
}
}
if reaper.name != "squid" {
t.Errorf("unexpected reaper: %#v", reaper)
}
}
func TestBuild(t *testing.T) {

@ -16,17 +16,15 @@ limitations under the License.
package kube // import "k8s.io/helm/pkg/kube"
import "k8s.io/client-go/tools/clientcmd"
import (
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
)
// GetConfig returns a Kubernetes client config.
func GetConfig(kubeconfig, context, namespace string) clientcmd.ClientConfig {
rules := clientcmd.NewDefaultClientConfigLoadingRules()
rules.DefaultClientConfig = &clientcmd.DefaultClientConfig
rules.ExplicitPath = kubeconfig
overrides := &clientcmd.ConfigOverrides{ClusterDefaults: clientcmd.ClusterDefaults}
overrides.CurrentContext = context
overrides.Context.Namespace = namespace
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides)
func GetConfig(kubeconfig, context, namespace string) *genericclioptions.ConfigFlags {
cf := genericclioptions.NewConfigFlags()
cf.Namespace = &namespace
cf.Context = &context
cf.KubeConfig = &kubeconfig
return cf
}

@ -16,7 +16,7 @@ limitations under the License.
package kube // import "k8s.io/helm/pkg/kube"
import "k8s.io/kubernetes/pkg/kubectl/resource"
import "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
// Result provides convenience methods for comparing collections of Infos.
type Result []*resource.Info

@ -19,15 +19,14 @@ package kube // import "k8s.io/helm/pkg/kube"
import (
"testing"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
)
func TestResult(t *testing.T) {
mapping, err := testapi.Default.RESTMapper().RESTMapping(schema.GroupKind{Kind: "Pod"})
if err != nil {
t.Fatal(err)
mapping := &meta.RESTMapping{
Resource: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "pod"},
}
info := func(name string) *resource.Info {

@ -27,7 +27,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
@ -37,8 +36,8 @@ import (
// deployment holds associated replicaSets for a deployment
type deployment struct {
replicaSets *extensions.ReplicaSet
deployment *extensions.Deployment
replicaSets *appsv1.ReplicaSet
deployment *appsv1.Deployment
}
// waitForResources polls to get the current status of all pods, PVCs, and Services
@ -56,11 +55,7 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
pvc := []v1.PersistentVolumeClaim{}
deployments := []deployment{}
for _, v := range created {
obj, err := v.Versioned()
if err != nil && !runtime.IsNotRegisteredError(err) {
return false, err
}
switch value := obj.(type) {
switch value := asVersioned(v).(type) {
case *v1.ReplicationController:
list, err := getPods(kcs, value.Namespace, value.Spec.Selector)
if err != nil {
@ -74,12 +69,12 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
}
pods = append(pods, *pod)
case *appsv1.Deployment:
currentDeployment, err := kcs.ExtensionsV1beta1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
currentDeployment, err := kcs.AppsV1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
// Find RS associated with deployment
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.ExtensionsV1beta1())
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.AppsV1())
if err != nil || newReplicaSet == nil {
return false, err
}
@ -89,12 +84,12 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
}
deployments = append(deployments, newDeployment)
case *appsv1beta1.Deployment:
currentDeployment, err := kcs.ExtensionsV1beta1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
currentDeployment, err := kcs.AppsV1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
// Find RS associated with deployment
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.ExtensionsV1beta1())
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.AppsV1())
if err != nil || newReplicaSet == nil {
return false, err
}
@ -104,12 +99,12 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
}
deployments = append(deployments, newDeployment)
case *appsv1beta2.Deployment:
currentDeployment, err := kcs.ExtensionsV1beta1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
currentDeployment, err := kcs.AppsV1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
// Find RS associated with deployment
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.ExtensionsV1beta1())
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.AppsV1())
if err != nil || newReplicaSet == nil {
return false, err
}
@ -119,12 +114,12 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
}
deployments = append(deployments, newDeployment)
case *extensions.Deployment:
currentDeployment, err := kcs.ExtensionsV1beta1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
currentDeployment, err := kcs.AppsV1().Deployments(value.Namespace).Get(value.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
// Find RS associated with deployment
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.ExtensionsV1beta1())
newReplicaSet, err := deploymentutil.GetNewReplicaSet(currentDeployment, kcs.AppsV1())
if err != nil || newReplicaSet == nil {
return false, err
}

@ -27,7 +27,7 @@ import (
"time"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/engine"

@ -23,7 +23,7 @@ import (
"time"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi/chart"

@ -30,7 +30,7 @@ import (
"github.com/pkg/errors"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/chart"

Loading…
Cancel
Save