Merge pull request #62744 from liggitt/describe-cronjob

Automatic merge from submit-queue (batch tested with PRs 60201, 62744). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Fix kubectl describe cronjob

CronJob describer was attempting to use the internal batch clientset, which speaks to the batch/v1 API group. CronJobs do not exist in that API group.
pull/8/head
Kubernetes Submit Queue 2018-04-18 07:58:19 -07:00 committed by GitHub
commit 87caa938b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 31 deletions

View File

@ -4034,6 +4034,8 @@ run_job_tests() {
kubectl run pi --schedule="59 23 31 2 *" --namespace=test-jobs --generator=cronjob/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}"
# Post-Condition: assertion object exists
kube::test::get_object_assert 'cronjob/pi --namespace=test-jobs' "{{$id_field}}" 'pi'
kubectl get cronjob/pi --namespace=test-jobs
kubectl describe cronjob/pi --namespace=test-jobs
### Create a job in dry-run mode
output_message=$(kubectl create job test-job --from=cronjob/pi --dry-run=true --namespace=test-jobs -o name)
@ -4046,6 +4048,8 @@ run_job_tests() {
kubectl create job test-job --from=cronjob/pi --namespace=test-jobs
# Post-Condition: assertion object exists
kube::test::get_object_assert 'job/test-job --namespace=test-jobs' "{{$id_field}}" 'test-job'
kubectl get job/test-job --namespace=test-jobs
kubectl describe job/test-job --namespace=test-jobs
#Clean up
kubectl delete job test-job --namespace=test-jobs
kubectl delete cronjob pi --namespace=test-jobs

View File

@ -166,16 +166,14 @@ func (f *ring1Factory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (
func (f *ring1Factory) Describer(mapping *meta.RESTMapping) (printers.Describer, error) {
clientset, err := f.clientAccessFactory.ClientSet()
if err != nil {
// if we can't make a client for this group/version, go generic if possible
if genericDescriber, genericErr := genericDescriber(f.clientAccessFactory, mapping); genericErr == nil {
return genericDescriber, nil
}
// otherwise return the original error
return nil, err
}
externalclientset, err := f.clientAccessFactory.KubernetesClientSet()
if err != nil {
return nil, err
}
// try to get a describer
if describer, ok := printersinternal.DescriberFor(mapping.GroupVersionKind.GroupKind(), clientset); ok {
if describer, ok := printersinternal.DescriberFor(mapping.GroupVersionKind.GroupKind(), clientset, externalclientset); ok {
return describer, nil
}
// if this is a kind we don't have a describer for yet, go generic if possible

View File

@ -106,7 +106,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/client-go/dynamic:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
],
)

View File

@ -33,6 +33,7 @@ import (
"github.com/golang/glog"
"github.com/fatih/camelcase"
versionedextension "k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
@ -45,7 +46,7 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/dynamic"
clientextensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
externalclient "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/api/events"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/ref"
@ -122,7 +123,7 @@ func (pw *prefixWriter) Flush() {
}
}
func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer {
func describerMap(c clientset.Interface, externalclient externalclient.Interface) map[schema.GroupKind]printers.Describer {
m := map[schema.GroupKind]printers.Describer{
api.Kind("Pod"): &PodDescriber{c},
api.Kind("ReplicationController"): &ReplicationControllerDescriber{c},
@ -144,12 +145,12 @@ func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer
extensions.Kind("PodSecurityPolicy"): &PodSecurityPolicyDescriber{c},
autoscaling.Kind("HorizontalPodAutoscaler"): &HorizontalPodAutoscalerDescriber{c},
extensions.Kind("DaemonSet"): &DaemonSetDescriber{c},
extensions.Kind("Deployment"): &DeploymentDescriber{c, versionedExtensionsClientV1beta1(c)},
extensions.Kind("Deployment"): &DeploymentDescriber{c, externalclient},
extensions.Kind("Ingress"): &IngressDescriber{c},
batch.Kind("Job"): &JobDescriber{c},
batch.Kind("CronJob"): &CronJobDescriber{c},
batch.Kind("CronJob"): &CronJobDescriber{c, externalclient},
apps.Kind("StatefulSet"): &StatefulSetDescriber{c},
apps.Kind("Deployment"): &DeploymentDescriber{c, versionedExtensionsClientV1beta1(c)},
apps.Kind("Deployment"): &DeploymentDescriber{c, externalclient},
apps.Kind("DaemonSet"): &DaemonSetDescriber{c},
apps.Kind("ReplicaSet"): &ReplicaSetDescriber{c},
certificates.Kind("CertificateSigningRequest"): &CertificateSigningRequestDescriber{c},
@ -170,7 +171,7 @@ func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer
func DescribableResources() []string {
keys := make([]string, 0)
for k := range describerMap(nil) {
for k := range describerMap(nil, nil) {
resource := strings.ToLower(k.Kind)
keys = append(keys, resource)
}
@ -179,8 +180,8 @@ func DescribableResources() []string {
// DescriberFor returns the default describe functions for each of the standard
// Kubernetes types.
func DescriberFor(kind schema.GroupKind, c clientset.Interface) (printers.Describer, bool) {
f, ok := describerMap(c)[kind]
func DescriberFor(kind schema.GroupKind, c clientset.Interface, externalclient externalclient.Interface) (printers.Describer, bool) {
f, ok := describerMap(c, externalclient)[kind]
return f, ok
}
@ -1854,10 +1855,11 @@ func describeJob(job *batch.Job, events *api.EventList) (string, error) {
// CronJobDescriber generates information about a cron job and the jobs it has created.
type CronJobDescriber struct {
clientset.Interface
external externalclient.Interface
}
func (d *CronJobDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
cronJob, err := d.Batch().CronJobs(namespace).Get(name, metav1.GetOptions{})
cronJob, err := d.external.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return "", err
}
@ -1867,7 +1869,12 @@ func (d *CronJobDescriber) Describe(namespace, name string, describerSettings pr
events, _ = d.Core().Events(namespace).Search(legacyscheme.Scheme, cronJob)
}
return describeCronJob(cronJob, events)
internalCronJob := &batch.CronJob{}
if err := legacyscheme.Scheme.Convert(cronJob, internalCronJob, nil); err != nil {
return "", err
}
return describeCronJob(internalCronJob, events)
}
func describeCronJob(cronJob *batch.CronJob, events *api.EventList) (string, error) {
@ -3066,11 +3073,11 @@ func DescribeEvents(el *api.EventList, w PrefixWriter) {
// DeploymentDescriber generates information about a deployment.
type DeploymentDescriber struct {
clientset.Interface
extensionV1beta1Client clientextensionsv1beta1.ExtensionsV1beta1Interface
external externalclient.Interface
}
func (dd *DeploymentDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
d, err := dd.extensionV1beta1Client.Deployments(namespace).Get(name, metav1.GetOptions{})
d, err := dd.external.ExtensionsV1beta1().Deployments(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return "", err
}
@ -3115,7 +3122,7 @@ func describeDeployment(d *versionedextension.Deployment, selector labels.Select
w.Write(LEVEL_1, "%v \t%v\t%v\n", c.Type, c.Status, c.Reason)
}
}
oldRSs, _, newRS, err := deploymentutil.GetAllReplicaSets(d, dd.extensionV1beta1Client)
oldRSs, _, newRS, err := deploymentutil.GetAllReplicaSets(d, dd.external.ExtensionsV1beta1())
if err == nil {
w.Write(LEVEL_0, "OldReplicaSets:\t%s\n", printReplicaSetsByLabels(oldRSs))
var newRSs []*versionedextension.ReplicaSet
@ -3952,14 +3959,6 @@ func (list SortableVolumeDevices) Less(i, j int) bool {
return list[i].DevicePath < list[j].DevicePath
}
// TODO: get rid of this and plumb the caller correctly
func versionedExtensionsClientV1beta1(internalClient clientset.Interface) clientextensionsv1beta1.ExtensionsV1beta1Interface {
if internalClient == nil {
return &clientextensionsv1beta1.ExtensionsV1beta1Client{}
}
return clientextensionsv1beta1.New(internalClient.Extensions().RESTClient())
}
var maxAnnotationLen = 200
// printAnnotationsMultilineWithFilter prints filtered multiple annotations with a proper alignment.

View File

@ -1312,7 +1312,7 @@ func TestDescribeDeployment(t *testing.T) {
},
},
})
d := DeploymentDescriber{fake, versionedFake.ExtensionsV1beta1()}
d := DeploymentDescriber{fake, versionedFake}
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error: %v", err)
@ -1934,7 +1934,7 @@ func TestDescribeEvents(t *testing.T) {
Replicas: utilpointer.Int32Ptr(1),
Selector: &metav1.LabelSelector{},
},
}).ExtensionsV1beta1(),
}),
},
"EndpointsDescriber": &EndpointsDescriber{
fake.NewSimpleClientset(&api.Endpoints{