mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	Merge pull request #24554 from ingvagabund/dhodovska-events-flag-for-describers
Automatic merge from submit-queue Introduce events flag for describers Printing events for a given object is not always needed. Thus, introducing --show-events=false to ``kubectl describe`` to skip events printing. Fixes: #24239
This commit is contained in:
		| @@ -497,6 +497,7 @@ _kubectl_describe() | |||||||
|     flags+=("-R") |     flags+=("-R") | ||||||
|     flags+=("--selector=") |     flags+=("--selector=") | ||||||
|     two_word_flags+=("-l") |     two_word_flags+=("-l") | ||||||
|  |     flags+=("--show-events") | ||||||
|     flags+=("--alsologtostderr") |     flags+=("--alsologtostderr") | ||||||
|     flags+=("--api-version=") |     flags+=("--api-version=") | ||||||
|     flags+=("--as=") |     flags+=("--as=") | ||||||
|   | |||||||
| @@ -51,6 +51,10 @@ componentstatuses (cs), endpoints (ep), and secrets. | |||||||
| \fB\-l\fP, \fB\-\-selector\fP="" | \fB\-l\fP, \fB\-\-selector\fP="" | ||||||
|     Selector (label query) to filter on |     Selector (label query) to filter on | ||||||
|  |  | ||||||
|  | .PP | ||||||
|  | \fB\-\-show\-events\fP=true | ||||||
|  |     If true, display events related to the described object. | ||||||
|  |  | ||||||
|  |  | ||||||
| .SH OPTIONS INHERITED FROM PARENT COMMANDS | .SH OPTIONS INHERITED FROM PARENT COMMANDS | ||||||
| .PP | .PP | ||||||
|   | |||||||
| @@ -89,6 +89,7 @@ kubectl describe pods frontend | |||||||
|       --include-extended-apis[=true]: If true, include definitions of new APIs via calls to the API server. [default true] |       --include-extended-apis[=true]: If true, include definitions of new APIs via calls to the API server. [default true] | ||||||
|   -R, --recursive[=false]: If true, process directory recursively. |   -R, --recursive[=false]: If true, process directory recursively. | ||||||
|   -l, --selector="": Selector (label query) to filter on |   -l, --selector="": Selector (label query) to filter on | ||||||
|  |       --show-events[=true]: If true, display events related to the described object. | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Options inherited from parent commands | ### Options inherited from parent commands | ||||||
| @@ -123,7 +124,7 @@ kubectl describe pods frontend | |||||||
|  |  | ||||||
| * [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager | * [kubectl](kubectl.md)	 - kubectl controls the Kubernetes cluster manager | ||||||
|  |  | ||||||
| ###### Auto generated by spf13/cobra on 30-Mar-2016 | ###### Auto generated by spf13/cobra on 26-Apr-2016 | ||||||
|  |  | ||||||
| <!-- BEGIN MUNGE: GENERATED_ANALYTICS --> | <!-- BEGIN MUNGE: GENERATED_ANALYTICS --> | ||||||
| []() | []() | ||||||
|   | |||||||
| @@ -33,6 +33,9 @@ options: | |||||||
| - name: selector | - name: selector | ||||||
|   shorthand: l |   shorthand: l | ||||||
|   usage: Selector (label query) to filter on |   usage: Selector (label query) to filter on | ||||||
|  | - name: show-events | ||||||
|  |   default_value: "true" | ||||||
|  |   usage: If true, display events related to the described object. | ||||||
| inherited_options: | inherited_options: | ||||||
| - name: alsologtostderr | - name: alsologtostderr | ||||||
|   default_value: "false" |   default_value: "false" | ||||||
|   | |||||||
| @@ -108,6 +108,44 @@ kube::test::describe_object_assert() { | |||||||
|   return 0 |   return 0 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | kube::test::describe_object_events_assert() { | ||||||
|  |     local resource=$1 | ||||||
|  |     local object=$2 | ||||||
|  |     local showevents=${3:-"true"} | ||||||
|  |  | ||||||
|  |     if [[ -z "${3:-}" ]]; then | ||||||
|  |         result=$(eval kubectl describe "${kube_flags[@]}" $resource $object) | ||||||
|  |     else | ||||||
|  |         result=$(eval kubectl describe "${kube_flags[@]}" "--show-events=$showevents" $resource $object) | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     if [[ -n $(echo "$result" | grep "No events.\|Events:") ]]; then | ||||||
|  |         local has_events="true" | ||||||
|  |     else | ||||||
|  |         local has_events="false" | ||||||
|  |     fi | ||||||
|  |     if [[ $showevents == $has_events ]]; then | ||||||
|  |         echo -n ${green} | ||||||
|  |         echo "Successful describe" | ||||||
|  |         echo "$result" | ||||||
|  |         echo ${reset} | ||||||
|  |         return 0 | ||||||
|  |     else | ||||||
|  |         echo ${bold}${red} | ||||||
|  |         echo "FAIL" | ||||||
|  |         if [[ $showevents == "false" ]]; then | ||||||
|  |             echo "  Events information should not be described in:" | ||||||
|  |         else | ||||||
|  |             echo "  Events information not found in:" | ||||||
|  |         fi | ||||||
|  |         echo $result | ||||||
|  |         echo ${reset}${red} | ||||||
|  |         caller | ||||||
|  |         echo ${reset} | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
| kube::test::describe_resource_assert() { | kube::test::describe_resource_assert() { | ||||||
|   local resource=$1 |   local resource=$1 | ||||||
|   local matches=${@:2} |   local matches=${@:2} | ||||||
| @@ -136,6 +174,38 @@ kube::test::describe_resource_assert() { | |||||||
|   return 0 |   return 0 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | kube::test::describe_resource_events_assert() { | ||||||
|  |     local resource=$1 | ||||||
|  |     local showevents=${2:-"true"} | ||||||
|  |  | ||||||
|  |     result=$(eval kubectl describe "${kube_flags[@]}" "--show-events=$showevents" $resource) | ||||||
|  |  | ||||||
|  |     if [[ $(echo "$result" | grep "No events.\|Events:") ]]; then | ||||||
|  |         local has_events="true" | ||||||
|  |     else | ||||||
|  |         local has_events="false" | ||||||
|  |     fi | ||||||
|  |     if [[ $showevents == $has_events ]]; then | ||||||
|  |         echo -n ${green} | ||||||
|  |         echo "Successful describe" | ||||||
|  |         echo "$result" | ||||||
|  |         echo -n ${reset} | ||||||
|  |         return 0 | ||||||
|  |     else | ||||||
|  |         echo ${bold}${red} | ||||||
|  |         echo "FAIL" | ||||||
|  |         if [[ $showevents == "false" ]]; then | ||||||
|  |             echo "  Events information should not be described in:" | ||||||
|  |         else | ||||||
|  |             echo "  Events information not found in:" | ||||||
|  |         fi | ||||||
|  |         echo $result | ||||||
|  |         caller | ||||||
|  |         echo ${reset} | ||||||
|  |         return 1 | ||||||
|  |     fi | ||||||
|  | } | ||||||
|  |  | ||||||
| kube::test::if_has_string() { | kube::test::if_has_string() { | ||||||
|   local message=$1 |   local message=$1 | ||||||
|   local match=$2 |   local match=$2 | ||||||
|   | |||||||
| @@ -392,9 +392,21 @@ runTests() { | |||||||
|   kube::test::get_object_jsonpath_assert 'pods/valid-pod' "{$id_field}" 'valid-pod' |   kube::test::get_object_jsonpath_assert 'pods/valid-pod' "{$id_field}" 'valid-pod' | ||||||
|   # Describe command should print detailed information |   # Describe command should print detailed information | ||||||
|   kube::test::describe_object_assert pods 'valid-pod' "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers" |   kube::test::describe_object_assert pods 'valid-pod' "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_object_events_assert pods 'valid-pod' | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_object_events_assert pods 'valid-pod' false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_object_events_assert pods 'valid-pod' true | ||||||
|   # Describe command (resource only) should print detailed information |   # Describe command (resource only) should print detailed information | ||||||
|   kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers" |   kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers" | ||||||
|  |  | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_resource_events_assert pods | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_resource_events_assert pods false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_resource_events_assert pods true | ||||||
|   ### Validate Export ### |   ### Validate Export ### | ||||||
|   kube::test::get_object_assert 'pods/valid-pod' "{{.metadata.namespace}} {{.metadata.name}}" '<no value> valid-pod' "--export=true" |   kube::test::get_object_assert 'pods/valid-pod' "{{.metadata.namespace}} {{.metadata.name}}" '<no value> valid-pod' "--export=true" | ||||||
|  |  | ||||||
| @@ -1244,8 +1256,20 @@ __EOF__ | |||||||
|   kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:' |   kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:' | ||||||
|   # Describe command should print detailed information |   # Describe command should print detailed information | ||||||
|   kube::test::describe_object_assert services 'redis-master' "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:" |   kube::test::describe_object_assert services 'redis-master' "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_object_events_assert services 'redis-master' | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_object_events_assert services 'redis-master' false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_object_events_assert services 'redis-master' true | ||||||
|   # Describe command (resource only) should print detailed information |   # Describe command (resource only) should print detailed information | ||||||
|   kube::test::describe_resource_assert services "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:" |   kube::test::describe_resource_assert services "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_resource_events_assert services | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_resource_events_assert services false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_resource_events_assert services true | ||||||
|  |  | ||||||
|   ### Dump current redis-master service |   ### Dump current redis-master service | ||||||
|   output_service=$(kubectl get service redis-master -o json --output-version=v1 "${kube_flags[@]}") |   output_service=$(kubectl get service redis-master -o json --output-version=v1 "${kube_flags[@]}") | ||||||
| @@ -1351,8 +1375,20 @@ __EOF__ | |||||||
|   kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:' |   kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:' | ||||||
|   # Describe command should print detailed information |   # Describe command should print detailed information | ||||||
|   kube::test::describe_object_assert rc 'frontend' "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" |   kube::test::describe_object_assert rc 'frontend' "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_object_events_assert rc 'frontend' | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_object_events_assert rc 'frontend' false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_object_events_assert rc 'frontend' true | ||||||
|   # Describe command (resource only) should print detailed information |   # Describe command (resource only) should print detailed information | ||||||
|   kube::test::describe_resource_assert rc "Name:" "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" |   kube::test::describe_resource_assert rc "Name:" "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_resource_events_assert rc | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_resource_events_assert rc false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_resource_events_assert rc true | ||||||
|  |  | ||||||
|   ### Scale replication controller frontend with current-replicas and replicas |   ### Scale replication controller frontend with current-replicas and replicas | ||||||
|   # Pre-condition: 3 replicas |   # Pre-condition: 3 replicas | ||||||
| @@ -1606,8 +1642,20 @@ __EOF__ | |||||||
|   kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" 'frontend:' |   kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" 'frontend:' | ||||||
|   # Describe command should print detailed information |   # Describe command should print detailed information | ||||||
|   kube::test::describe_object_assert rs 'frontend' "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" |   kube::test::describe_object_assert rs 'frontend' "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_object_events_assert rs 'frontend' | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_object_events_assert rs 'frontend' false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_object_events_assert rs 'frontend' true | ||||||
|   # Describe command (resource only) should print detailed information |   # Describe command (resource only) should print detailed information | ||||||
|   kube::test::describe_resource_assert rs "Name:" "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" |   kube::test::describe_resource_assert rs "Name:" "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_resource_events_assert rs | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_resource_events_assert rs false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_resource_events_assert rs true | ||||||
|  |  | ||||||
|   ### Scale replica set frontend with current-replicas and replicas |   ### Scale replica set frontend with current-replicas and replicas | ||||||
|   # Pre-condition: 3 replicas |   # Pre-condition: 3 replicas | ||||||
| @@ -1901,8 +1949,20 @@ __EOF__ | |||||||
|   kube::test::get_object_assert nodes "{{range.items}}{{$id_field}}:{{end}}" '127.0.0.1:' |   kube::test::get_object_assert nodes "{{range.items}}{{$id_field}}:{{end}}" '127.0.0.1:' | ||||||
|  |  | ||||||
|   kube::test::describe_object_assert nodes "127.0.0.1" "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:" |   kube::test::describe_object_assert nodes "127.0.0.1" "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_object_events_assert nodes "127.0.0.1" | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_object_events_assert nodes "127.0.0.1" false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_object_events_assert nodes "127.0.0.1" true | ||||||
|   # Describe command (resource only) should print detailed information |   # Describe command (resource only) should print detailed information | ||||||
|   kube::test::describe_resource_assert nodes "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:" |   kube::test::describe_resource_assert nodes "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:" | ||||||
|  |   # Describe command should print events information by default | ||||||
|  |   kube::test::describe_resource_events_assert nodes | ||||||
|  |   # Describe command should not print events information when show-events=false | ||||||
|  |   kube::test::describe_resource_events_assert nodes false | ||||||
|  |   # Describe command should print events information when show-events=true | ||||||
|  |   kube::test::describe_resource_events_assert nodes true | ||||||
|  |  | ||||||
|   ### kubectl patch update can mark node unschedulable |   ### kubectl patch update can mark node unschedulable | ||||||
|   # Pre-condition: node is schedulable |   # Pre-condition: node is schedulable | ||||||
|   | |||||||
| @@ -378,6 +378,7 @@ service-overrides | |||||||
| service-sync-period | service-sync-period | ||||||
| session-affinity | session-affinity | ||||||
| show-all | show-all | ||||||
|  | show-events | ||||||
| show-labels | show-labels | ||||||
| shutdown-fd | shutdown-fd | ||||||
| shutdown-fifo | shutdown-fifo | ||||||
|   | |||||||
| @@ -151,12 +151,14 @@ func (t *testPrinter) HandledResources() []string { | |||||||
|  |  | ||||||
| type testDescriber struct { | type testDescriber struct { | ||||||
| 	Name, Namespace string | 	Name, Namespace string | ||||||
|  | 	Settings        kubectl.DescriberSettings | ||||||
| 	Output          string | 	Output          string | ||||||
| 	Err             error | 	Err             error | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *testDescriber) Describe(namespace, name string) (output string, err error) { | func (t *testDescriber) Describe(namespace, name string, describerSettings kubectl.DescriberSettings) (output string, err error) { | ||||||
| 	t.Namespace, t.Name = namespace, name | 	t.Namespace, t.Name = namespace, name | ||||||
|  | 	t.Settings = describerSettings | ||||||
| 	return t.Output, t.Err | 	return t.Output, t.Err | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -73,6 +73,7 @@ kubectl describe pods frontend` | |||||||
|  |  | ||||||
| func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command { | func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command { | ||||||
| 	options := &DescribeOptions{} | 	options := &DescribeOptions{} | ||||||
|  | 	describerSettings := &kubectl.DescriberSettings{} | ||||||
|  |  | ||||||
| 	validArgs := kubectl.DescribableResources() | 	validArgs := kubectl.DescribableResources() | ||||||
| 	argAliases := kubectl.ResourceAliases(validArgs) | 	argAliases := kubectl.ResourceAliases(validArgs) | ||||||
| @@ -83,7 +84,7 @@ func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command { | |||||||
| 		Long:    describe_long, | 		Long:    describe_long, | ||||||
| 		Example: describe_example, | 		Example: describe_example, | ||||||
| 		Run: func(cmd *cobra.Command, args []string) { | 		Run: func(cmd *cobra.Command, args []string) { | ||||||
| 			err := RunDescribe(f, out, cmd, args, options) | 			err := RunDescribe(f, out, cmd, args, options, describerSettings) | ||||||
| 			cmdutil.CheckErr(err) | 			cmdutil.CheckErr(err) | ||||||
| 		}, | 		}, | ||||||
| 		ValidArgs:  validArgs, | 		ValidArgs:  validArgs, | ||||||
| @@ -93,11 +94,12 @@ func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command { | |||||||
| 	kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) | 	kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) | ||||||
| 	cmdutil.AddRecursiveFlag(cmd, &options.Recursive) | 	cmdutil.AddRecursiveFlag(cmd, &options.Recursive) | ||||||
| 	cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") | 	cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") | ||||||
|  | 	cmd.Flags().BoolVar(&describerSettings.ShowEvents, "show-events", true, "If true, display events related to the described object.") | ||||||
| 	cmdutil.AddInclude3rdPartyFlags(cmd) | 	cmdutil.AddInclude3rdPartyFlags(cmd) | ||||||
| 	return cmd | 	return cmd | ||||||
| } | } | ||||||
|  |  | ||||||
| func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DescribeOptions) error { | func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *DescribeOptions, describerSettings *kubectl.DescriberSettings) error { | ||||||
| 	selector := cmdutil.GetFlagString(cmd, "selector") | 	selector := cmdutil.GetFlagString(cmd, "selector") | ||||||
| 	cmdNamespace, enforceNamespace, err := f.DefaultNamespace() | 	cmdNamespace, enforceNamespace, err := f.DefaultNamespace() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -126,7 +128,7 @@ func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s | |||||||
| 	infos, err := r.Infos() | 	infos, err := r.Infos() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if apierrors.IsNotFound(err) && len(args) == 2 { | 		if apierrors.IsNotFound(err) && len(args) == 2 { | ||||||
| 			return DescribeMatchingResources(mapper, typer, f, cmdNamespace, args[0], args[1], out, err) | 			return DescribeMatchingResources(mapper, typer, f, cmdNamespace, args[0], args[1], describerSettings, out, err) | ||||||
| 		} | 		} | ||||||
| 		allErrs = append(allErrs, err) | 		allErrs = append(allErrs, err) | ||||||
| 	} | 	} | ||||||
| @@ -138,7 +140,7 @@ func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s | |||||||
| 			allErrs = append(allErrs, err) | 			allErrs = append(allErrs, err) | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		s, err := describer.Describe(info.Namespace, info.Name) | 		s, err := describer.Describe(info.Namespace, info.Name, *describerSettings) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			allErrs = append(allErrs, err) | 			allErrs = append(allErrs, err) | ||||||
| 			continue | 			continue | ||||||
| @@ -149,7 +151,7 @@ func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s | |||||||
| 	return utilerrors.NewAggregate(allErrs) | 	return utilerrors.NewAggregate(allErrs) | ||||||
| } | } | ||||||
|  |  | ||||||
| func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper, f *cmdutil.Factory, namespace, rsrc, prefix string, out io.Writer, originalError error) error { | func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper, f *cmdutil.Factory, namespace, rsrc, prefix string, describerSettings *kubectl.DescriberSettings, out io.Writer, originalError error) error { | ||||||
| 	r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). | 	r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). | ||||||
| 		NamespaceParam(namespace).DefaultNamespace(). | 		NamespaceParam(namespace).DefaultNamespace(). | ||||||
| 		ResourceTypeOrNameArgs(true, rsrc). | 		ResourceTypeOrNameArgs(true, rsrc). | ||||||
| @@ -173,7 +175,7 @@ func DescribeMatchingResources(mapper meta.RESTMapper, typer runtime.ObjectTyper | |||||||
| 		info := infos[ix] | 		info := infos[ix] | ||||||
| 		if strings.HasPrefix(info.Name, prefix) { | 		if strings.HasPrefix(info.Name, prefix) { | ||||||
| 			isFound = true | 			isFound = true | ||||||
| 			s, err := describer.Describe(info.Namespace, info.Name) | 			s, err := describer.Describe(info.Namespace, info.Name, *describerSettings) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -100,3 +100,43 @@ func TestDescribeListObjects(t *testing.T) { | |||||||
| 		t.Errorf("unexpected output: %s", buf.String()) | 		t.Errorf("unexpected output: %s", buf.String()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestDescribeObjectShowEvents(t *testing.T) { | ||||||
|  | 	pods, _, _ := testData() | ||||||
|  | 	f, tf, codec := NewAPIFactory() | ||||||
|  | 	d := &testDescriber{Output: "test output"} | ||||||
|  | 	tf.Describer = d | ||||||
|  | 	tf.Client = &fake.RESTClient{ | ||||||
|  | 		Codec: codec, | ||||||
|  | 		Resp:  &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	tf.Namespace = "test" | ||||||
|  | 	buf := bytes.NewBuffer([]byte{}) | ||||||
|  | 	cmd := NewCmdDescribe(f, buf) | ||||||
|  | 	cmd.Flags().Set("show-events", "true") | ||||||
|  | 	cmd.Run(cmd, []string{"pods"}) | ||||||
|  | 	if d.Settings.ShowEvents != true { | ||||||
|  | 		t.Errorf("ShowEvents = true expected, got ShowEvents = %v", d.Settings.ShowEvents) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func TestDescribeObjectSkipEvents(t *testing.T) { | ||||||
|  | 	pods, _, _ := testData() | ||||||
|  | 	f, tf, codec := NewAPIFactory() | ||||||
|  | 	d := &testDescriber{Output: "test output"} | ||||||
|  | 	tf.Describer = d | ||||||
|  | 	tf.Client = &fake.RESTClient{ | ||||||
|  | 		Codec: codec, | ||||||
|  | 		Resp:  &http.Response{StatusCode: 200, Body: objBody(codec, pods)}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	tf.Namespace = "test" | ||||||
|  | 	buf := bytes.NewBuffer([]byte{}) | ||||||
|  | 	cmd := NewCmdDescribe(f, buf) | ||||||
|  | 	cmd.Flags().Set("show-events", "false") | ||||||
|  | 	cmd.Run(cmd, []string{"pods"}) | ||||||
|  | 	if d.Settings.ShowEvents != false { | ||||||
|  | 		t.Errorf("ShowEvents = false expected, got ShowEvents = %v", d.Settings.ShowEvents) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -54,7 +54,13 @@ import ( | |||||||
| // if the output could not be generated. Implementers typically | // if the output could not be generated. Implementers typically | ||||||
| // abstract the retrieval of the named object from a remote server. | // abstract the retrieval of the named object from a remote server. | ||||||
| type Describer interface { | type Describer interface { | ||||||
| 	Describe(namespace, name string) (output string, err error) | 	Describe(namespace, name string, describerSettings DescriberSettings) (output string, err error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // DescriberSettings holds display configuration for each object | ||||||
|  | // describer to control what is printed. | ||||||
|  | type DescriberSettings struct { | ||||||
|  | 	ShowEvents bool | ||||||
| } | } | ||||||
|  |  | ||||||
| // ObjectDescriber is an interface for displaying arbitrary objects with extra | // ObjectDescriber is an interface for displaying arbitrary objects with extra | ||||||
| @@ -151,7 +157,7 @@ type NamespaceDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *NamespaceDescriber) Describe(namespace, name string) (string, error) { | func (d *NamespaceDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	ns, err := d.Namespaces().Get(name) | 	ns, err := d.Namespaces().Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| @@ -307,7 +313,7 @@ type LimitRangeDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *LimitRangeDescriber) Describe(namespace, name string) (string, error) { | func (d *LimitRangeDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	lr := d.LimitRanges(namespace) | 	lr := d.LimitRanges(namespace) | ||||||
|  |  | ||||||
| 	limitRange, err := lr.Get(name) | 	limitRange, err := lr.Get(name) | ||||||
| @@ -394,7 +400,7 @@ type ResourceQuotaDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *ResourceQuotaDescriber) Describe(namespace, name string) (string, error) { | func (d *ResourceQuotaDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	rq := d.ResourceQuotas(namespace) | 	rq := d.ResourceQuotas(namespace) | ||||||
|  |  | ||||||
| 	resourceQuota, err := rq.Get(name) | 	resourceQuota, err := rq.Get(name) | ||||||
| @@ -463,29 +469,33 @@ type PodDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *PodDescriber) Describe(namespace, name string) (string, error) { | func (d *PodDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	pod, err := d.Pods(namespace).Get(name) | 	pod, err := d.Pods(namespace).Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		eventsInterface := d.Events(namespace) | 		if describerSettings.ShowEvents { | ||||||
| 		selector := eventsInterface.GetFieldSelector(&name, &namespace, nil, nil) | 			eventsInterface := d.Events(namespace) | ||||||
| 		options := api.ListOptions{FieldSelector: selector} | 			selector := eventsInterface.GetFieldSelector(&name, &namespace, nil, nil) | ||||||
| 		events, err2 := eventsInterface.List(options) | 			options := api.ListOptions{FieldSelector: selector} | ||||||
| 		if err2 == nil && len(events.Items) > 0 { | 			events, err2 := eventsInterface.List(options) | ||||||
| 			return tabbedString(func(out io.Writer) error { | 			if describerSettings.ShowEvents && err2 == nil && len(events.Items) > 0 { | ||||||
| 				fmt.Fprintf(out, "Pod '%v': error '%v', but found events.\n", name, err) | 				return tabbedString(func(out io.Writer) error { | ||||||
| 				DescribeEvents(events, out) | 					fmt.Fprintf(out, "Pod '%v': error '%v', but found events.\n", name, err) | ||||||
| 				return nil | 					DescribeEvents(events, out) | ||||||
| 			}) | 					return nil | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var events *api.EventList | 	var events *api.EventList | ||||||
| 	if ref, err := api.GetReference(pod); err != nil { | 	if describerSettings.ShowEvents { | ||||||
| 		glog.Errorf("Unable to construct reference to '%#v': %v", pod, err) | 		if ref, err := api.GetReference(pod); err != nil { | ||||||
| 	} else { | 			glog.Errorf("Unable to construct reference to '%#v': %v", pod, err) | ||||||
| 		ref.Kind = "" | 		} else { | ||||||
| 		events, _ = d.Events(namespace).Search(ref) | 			ref.Kind = "" | ||||||
|  | 			events, _ = d.Events(namespace).Search(ref) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return describePod(pod, events) | 	return describePod(pod, events) | ||||||
| @@ -692,7 +702,7 @@ type PersistentVolumeDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *PersistentVolumeDescriber) Describe(namespace, name string) (string, error) { | func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := d.PersistentVolumes() | 	c := d.PersistentVolumes() | ||||||
|  |  | ||||||
| 	pv, err := c.Get(name) | 	pv, err := c.Get(name) | ||||||
| @@ -742,7 +752,7 @@ type PersistentVolumeClaimDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string) (string, error) { | func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := d.PersistentVolumeClaims(namespace) | 	c := d.PersistentVolumeClaims(namespace) | ||||||
|  |  | ||||||
| 	pvc, err := c.Get(name) | 	pvc, err := c.Get(name) | ||||||
| @@ -970,7 +980,7 @@ type ReplicationControllerDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *ReplicationControllerDescriber) Describe(namespace, name string) (string, error) { | func (d *ReplicationControllerDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	rc := d.ReplicationControllers(namespace) | 	rc := d.ReplicationControllers(namespace) | ||||||
| 	pc := d.Pods(namespace) | 	pc := d.Pods(namespace) | ||||||
|  |  | ||||||
| @@ -984,7 +994,10 @@ func (d *ReplicationControllerDescriber) Describe(namespace, name string) (strin | |||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	events, _ := d.Events(namespace).Search(controller) | 	var events *api.EventList | ||||||
|  | 	if describerSettings.ShowEvents { | ||||||
|  | 		events, _ = d.Events(namespace).Search(controller) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return describeReplicationController(controller, events, running, waiting, succeeded, failed) | 	return describeReplicationController(controller, events, running, waiting, succeeded, failed) | ||||||
| } | } | ||||||
| @@ -1033,7 +1046,7 @@ type ReplicaSetDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *ReplicaSetDescriber) Describe(namespace, name string) (string, error) { | func (d *ReplicaSetDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	rsc := d.Extensions().ReplicaSets(namespace) | 	rsc := d.Extensions().ReplicaSets(namespace) | ||||||
| 	pc := d.Pods(namespace) | 	pc := d.Pods(namespace) | ||||||
|  |  | ||||||
| @@ -1052,7 +1065,10 @@ func (d *ReplicaSetDescriber) Describe(namespace, name string) (string, error) { | |||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	events, _ := d.Events(namespace).Search(rs) | 	var events *api.EventList | ||||||
|  | 	if describerSettings.ShowEvents { | ||||||
|  | 		events, _ = d.Events(namespace).Search(rs) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return describeReplicaSet(rs, events, running, waiting, succeeded, failed) | 	return describeReplicaSet(rs, events, running, waiting, succeeded, failed) | ||||||
| } | } | ||||||
| @@ -1079,13 +1095,16 @@ type JobDescriber struct { | |||||||
| 	client *client.Client | 	client *client.Client | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *JobDescriber) Describe(namespace, name string) (string, error) { | func (d *JobDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	job, err := d.client.Extensions().Jobs(namespace).Get(name) | 	job, err := d.client.Extensions().Jobs(namespace).Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	events, _ := d.client.Events(namespace).Search(job) | 	var events *api.EventList | ||||||
|  | 	if describerSettings.ShowEvents { | ||||||
|  | 		events, _ = d.client.Events(namespace).Search(job) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return describeJob(job, events) | 	return describeJob(job, events) | ||||||
| } | } | ||||||
| @@ -1124,7 +1143,7 @@ type DaemonSetDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *DaemonSetDescriber) Describe(namespace, name string) (string, error) { | func (d *DaemonSetDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	dc := d.Extensions().DaemonSets(namespace) | 	dc := d.Extensions().DaemonSets(namespace) | ||||||
| 	pc := d.Pods(namespace) | 	pc := d.Pods(namespace) | ||||||
|  |  | ||||||
| @@ -1142,7 +1161,10 @@ func (d *DaemonSetDescriber) Describe(namespace, name string) (string, error) { | |||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	events, _ := d.Events(namespace).Search(daemon) | 	var events *api.EventList | ||||||
|  | 	if describerSettings.ShowEvents { | ||||||
|  | 		events, _ = d.Events(namespace).Search(daemon) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return describeDaemonSet(daemon, events, running, waiting, succeeded, failed) | 	return describeDaemonSet(daemon, events, running, waiting, succeeded, failed) | ||||||
| } | } | ||||||
| @@ -1175,7 +1197,7 @@ type SecretDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *SecretDescriber) Describe(namespace, name string) (string, error) { | func (d *SecretDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := d.Secrets(namespace) | 	c := d.Secrets(namespace) | ||||||
|  |  | ||||||
| 	secret, err := c.Get(name) | 	secret, err := c.Get(name) | ||||||
| @@ -1213,13 +1235,13 @@ type IngressDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (i *IngressDescriber) Describe(namespace, name string) (string, error) { | func (i *IngressDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := i.Extensions().Ingress(namespace) | 	c := i.Extensions().Ingress(namespace) | ||||||
| 	ing, err := c.Get(name) | 	ing, err := c.Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
| 	return i.describeIngress(ing) | 	return i.describeIngress(ing, describerSettings) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (i *IngressDescriber) describeBackend(ns string, backend *extensions.IngressBackend) string { | func (i *IngressDescriber) describeBackend(ns string, backend *extensions.IngressBackend) string { | ||||||
| @@ -1242,7 +1264,7 @@ func (i *IngressDescriber) describeBackend(ns string, backend *extensions.Ingres | |||||||
| 	return formatEndpoints(endpoints, sets.NewString(spName)) | 	return formatEndpoints(endpoints, sets.NewString(spName)) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (i *IngressDescriber) describeIngress(ing *extensions.Ingress) (string, error) { | func (i *IngressDescriber) describeIngress(ing *extensions.Ingress, describerSettings DescriberSettings) (string, error) { | ||||||
| 	return tabbedString(func(out io.Writer) error { | 	return tabbedString(func(out io.Writer) error { | ||||||
| 		fmt.Fprintf(out, "Name:\t%v\n", ing.Name) | 		fmt.Fprintf(out, "Name:\t%v\n", ing.Name) | ||||||
| 		fmt.Fprintf(out, "Namespace:\t%v\n", ing.Namespace) | 		fmt.Fprintf(out, "Namespace:\t%v\n", ing.Namespace) | ||||||
| @@ -1275,9 +1297,11 @@ func (i *IngressDescriber) describeIngress(ing *extensions.Ingress) (string, err | |||||||
| 		} | 		} | ||||||
| 		describeIngressAnnotations(out, ing.Annotations) | 		describeIngressAnnotations(out, ing.Annotations) | ||||||
|  |  | ||||||
| 		events, _ := i.Events(ing.Namespace).Search(ing) | 		if describerSettings.ShowEvents { | ||||||
| 		if events != nil { | 			events, _ := i.Events(ing.Namespace).Search(ing) | ||||||
| 			DescribeEvents(events, out) | 			if events != nil { | ||||||
|  | 				DescribeEvents(events, out) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	}) | 	}) | ||||||
| @@ -1314,7 +1338,7 @@ type ServiceDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *ServiceDescriber) Describe(namespace, name string) (string, error) { | func (d *ServiceDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := d.Services(namespace) | 	c := d.Services(namespace) | ||||||
|  |  | ||||||
| 	service, err := c.Get(name) | 	service, err := c.Get(name) | ||||||
| @@ -1323,8 +1347,10 @@ func (d *ServiceDescriber) Describe(namespace, name string) (string, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	endpoints, _ := d.Endpoints(namespace).Get(name) | 	endpoints, _ := d.Endpoints(namespace).Get(name) | ||||||
| 	events, _ := d.Events(namespace).Search(service) | 	var events *api.EventList | ||||||
|  | 	if describerSettings.ShowEvents { | ||||||
|  | 		events, _ = d.Events(namespace).Search(service) | ||||||
|  | 	} | ||||||
| 	return describeService(service, endpoints, events) | 	return describeService(service, endpoints, events) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1385,7 +1411,7 @@ type EndpointsDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *EndpointsDescriber) Describe(namespace, name string) (string, error) { | func (d *EndpointsDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := d.Endpoints(namespace) | 	c := d.Endpoints(namespace) | ||||||
|  |  | ||||||
| 	ep, err := c.Get(name) | 	ep, err := c.Get(name) | ||||||
| @@ -1393,7 +1419,10 @@ func (d *EndpointsDescriber) Describe(namespace, name string) (string, error) { | |||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	events, _ := d.Events(namespace).Search(ep) | 	var events *api.EventList | ||||||
|  | 	if describerSettings.ShowEvents { | ||||||
|  | 		events, _ = d.Events(namespace).Search(ep) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return describeEndpoints(ep, events) | 	return describeEndpoints(ep, events) | ||||||
| } | } | ||||||
| @@ -1455,7 +1484,7 @@ type ServiceAccountDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *ServiceAccountDescriber) Describe(namespace, name string) (string, error) { | func (d *ServiceAccountDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := d.ServiceAccounts(namespace) | 	c := d.ServiceAccounts(namespace) | ||||||
|  |  | ||||||
| 	serviceAccount, err := c.Get(name) | 	serviceAccount, err := c.Get(name) | ||||||
| @@ -1536,7 +1565,7 @@ type NodeDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *NodeDescriber) Describe(namespace, name string) (string, error) { | func (d *NodeDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	mc := d.Nodes() | 	mc := d.Nodes() | ||||||
| 	node, err := mc.Get(name) | 	node, err := mc.Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -1559,12 +1588,14 @@ func (d *NodeDescriber) Describe(namespace, name string) (string, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var events *api.EventList | 	var events *api.EventList | ||||||
| 	if ref, err := api.GetReference(node); err != nil { | 	if describerSettings.ShowEvents { | ||||||
| 		glog.Errorf("Unable to construct reference to '%#v': %v", node, err) | 		if ref, err := api.GetReference(node); err != nil { | ||||||
| 	} else { | 			glog.Errorf("Unable to construct reference to '%#v': %v", node, err) | ||||||
| 		// TODO: We haven't decided the namespace for Node object yet. | 		} else { | ||||||
| 		ref.UID = types.UID(ref.Name) | 			// TODO: We haven't decided the namespace for Node object yet. | ||||||
| 		events, _ = d.Events("").Search(ref) | 			ref.UID = types.UID(ref.Name) | ||||||
|  | 			events, _ = d.Events("").Search(ref) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return describeNode(node, nodeNonTerminatedPodsList, events, canViewPods) | 	return describeNode(node, nodeNonTerminatedPodsList, events, canViewPods) | ||||||
| @@ -1635,7 +1666,7 @@ type PetSetDescriber struct { | |||||||
| 	client *client.Client | 	client *client.Client | ||||||
| } | } | ||||||
|  |  | ||||||
| func (p *PetSetDescriber) Describe(namespace, name string) (string, error) { | func (p *PetSetDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	ps, err := p.client.Apps().PetSets(namespace).Get(name) | 	ps, err := p.client.Apps().PetSets(namespace).Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| @@ -1663,9 +1694,11 @@ func (p *PetSetDescriber) Describe(namespace, name string) (string, error) { | |||||||
| 		fmt.Fprintf(out, "CreationTimestamp:\t%s\n", ps.CreationTimestamp.Time.Format(time.RFC1123Z)) | 		fmt.Fprintf(out, "CreationTimestamp:\t%s\n", ps.CreationTimestamp.Time.Format(time.RFC1123Z)) | ||||||
| 		fmt.Fprintf(out, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed) | 		fmt.Fprintf(out, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed) | ||||||
| 		describeVolumes(ps.Spec.Template.Spec.Volumes, out, "") | 		describeVolumes(ps.Spec.Template.Spec.Volumes, out, "") | ||||||
| 		events, _ := p.client.Events(namespace).Search(ps) | 		if describerSettings.ShowEvents { | ||||||
| 		if events != nil { | 			events, _ := p.client.Events(namespace).Search(ps) | ||||||
| 			DescribeEvents(events, out) | 			if events != nil { | ||||||
|  | 				DescribeEvents(events, out) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	}) | 	}) | ||||||
| @@ -1676,7 +1709,7 @@ type HorizontalPodAutoscalerDescriber struct { | |||||||
| 	client *client.Client | 	client *client.Client | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string) (string, error) { | func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	hpa, err := d.client.Extensions().HorizontalPodAutoscalers(namespace).Get(name) | 	hpa, err := d.client.Extensions().HorizontalPodAutoscalers(namespace).Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| @@ -1718,9 +1751,11 @@ func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string) (str | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		events, _ := d.client.Events(namespace).Search(hpa) | 		if describerSettings.ShowEvents { | ||||||
| 		if events != nil { | 			events, _ := d.client.Events(namespace).Search(hpa) | ||||||
| 			DescribeEvents(events, out) | 			if events != nil { | ||||||
|  | 				DescribeEvents(events, out) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	}) | 	}) | ||||||
| @@ -1827,7 +1862,7 @@ type DeploymentDescriber struct { | |||||||
| 	clientset.Interface | 	clientset.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (dd *DeploymentDescriber) Describe(namespace, name string) (string, error) { | func (dd *DeploymentDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	d, err := dd.Extensions().Deployments(namespace).Get(name) | 	d, err := dd.Extensions().Deployments(namespace).Get(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| @@ -1861,9 +1896,11 @@ func (dd *DeploymentDescriber) Describe(namespace, name string) (string, error) | |||||||
| 			} | 			} | ||||||
| 			fmt.Fprintf(out, "NewReplicaSet:\t%s\n", printReplicaSetsByLabels(newRSs)) | 			fmt.Fprintf(out, "NewReplicaSet:\t%s\n", printReplicaSetsByLabels(newRSs)) | ||||||
| 		} | 		} | ||||||
| 		events, err := dd.Core().Events(namespace).Search(d) | 		if describerSettings.ShowEvents { | ||||||
| 		if err == nil && events != nil { | 			events, err := dd.Core().Events(namespace).Search(d) | ||||||
| 			DescribeEvents(events, out) | 			if err == nil && events != nil { | ||||||
|  | 				DescribeEvents(events, out) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		return nil | 		return nil | ||||||
| 	}) | 	}) | ||||||
| @@ -1951,7 +1988,7 @@ type ConfigMapDescriber struct { | |||||||
| 	client.Interface | 	client.Interface | ||||||
| } | } | ||||||
|  |  | ||||||
| func (d *ConfigMapDescriber) Describe(namespace, name string) (string, error) { | func (d *ConfigMapDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { | ||||||
| 	c := d.ConfigMaps(namespace) | 	c := d.ConfigMaps(namespace) | ||||||
|  |  | ||||||
| 	configMap, err := c.Get(name) | 	configMap, err := c.Get(name) | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ func TestDescribePod(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
| 	c := &describeClient{T: t, Namespace: "foo", Interface: fake} | 	c := &describeClient{T: t, Namespace: "foo", Interface: fake} | ||||||
| 	d := PodDescriber{c} | 	d := PodDescriber{c} | ||||||
| 	out, err := d.Describe("foo", "bar") | 	out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("unexpected error: %v", err) | 		t.Errorf("unexpected error: %v", err) | ||||||
| 	} | 	} | ||||||
| @@ -67,7 +67,7 @@ func TestDescribeService(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
| 	c := &describeClient{T: t, Namespace: "foo", Interface: fake} | 	c := &describeClient{T: t, Namespace: "foo", Interface: fake} | ||||||
| 	d := ServiceDescriber{c} | 	d := ServiceDescriber{c} | ||||||
| 	out, err := d.Describe("foo", "bar") | 	out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("unexpected error: %v", err) | 		t.Errorf("unexpected error: %v", err) | ||||||
| 	} | 	} | ||||||
| @@ -110,7 +110,7 @@ func TestPodDescribeResultsSorted(t *testing.T) { | |||||||
| 	d := PodDescriber{c} | 	d := PodDescriber{c} | ||||||
|  |  | ||||||
| 	// Act | 	// Act | ||||||
| 	out, err := d.Describe("foo", "bar") | 	out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) | ||||||
|  |  | ||||||
| 	// Assert | 	// Assert | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -492,7 +492,7 @@ func TestPersistentVolumeDescriber(t *testing.T) { | |||||||
| 	for name, pv := range tests { | 	for name, pv := range tests { | ||||||
| 		fake := testclient.NewSimpleFake(pv) | 		fake := testclient.NewSimpleFake(pv) | ||||||
| 		c := PersistentVolumeDescriber{fake} | 		c := PersistentVolumeDescriber{fake} | ||||||
| 		str, err := c.Describe("foo", "bar") | 		str, err := c.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Errorf("Unexpected error for test %s: %v", name, err) | 			t.Errorf("Unexpected error for test %s: %v", name, err) | ||||||
| 		} | 		} | ||||||
| @@ -513,7 +513,7 @@ func TestDescribeDeployment(t *testing.T) { | |||||||
| 		}, | 		}, | ||||||
| 	}) | 	}) | ||||||
| 	d := DeploymentDescriber{fake} | 	d := DeploymentDescriber{fake} | ||||||
| 	out, err := d.Describe("foo", "bar") | 	out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("unexpected error: %v", err) | 		t.Errorf("unexpected error: %v", err) | ||||||
| 	} | 	} | ||||||
| @@ -521,3 +521,116 @@ func TestDescribeDeployment(t *testing.T) { | |||||||
| 		t.Errorf("unexpected out: %s", out) | 		t.Errorf("unexpected out: %s", out) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestDescribeEvents(t *testing.T) { | ||||||
|  |  | ||||||
|  | 	events := &api.EventList{ | ||||||
|  | 		Items: []api.Event{ | ||||||
|  | 			{ | ||||||
|  | 				Source:         api.EventSource{Component: "kubelet"}, | ||||||
|  | 				Message:        "Item 1", | ||||||
|  | 				FirstTimestamp: unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), | ||||||
|  | 				LastTimestamp:  unversioned.NewTime(time.Date(2014, time.January, 15, 0, 0, 0, 0, time.UTC)), | ||||||
|  | 				Count:          1, | ||||||
|  | 				Type:           api.EventTypeNormal, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m := map[string]Describer{ | ||||||
|  | 		"DaemonSetDescriber": &DaemonSetDescriber{ | ||||||
|  | 			testclient.NewSimpleFake(&extensions.DaemonSet{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 		"DeploymentDescriber": &DeploymentDescriber{ | ||||||
|  | 			fake.NewSimpleClientset(&extensions.Deployment{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 		"EndpointsDescriber": &EndpointsDescriber{ | ||||||
|  | 			testclient.NewSimpleFake(&api.Endpoints{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 		// TODO(jchaloup): add tests for: | ||||||
|  | 		// - HorizontalPodAutoscalerDescriber | ||||||
|  | 		// - IngressDescriber | ||||||
|  | 		// - JobDescriber | ||||||
|  | 		"NodeDescriber": &NodeDescriber{ | ||||||
|  | 			testclient.NewSimpleFake(&api.Node{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 					SelfLink:  "url/url/url", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 		"PodDescriber": &PodDescriber{ | ||||||
|  | 			testclient.NewSimpleFake(&api.Pod{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 					SelfLink:  "url/url/url", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 		"ReplicaSetDescriber": &ReplicaSetDescriber{ | ||||||
|  | 			testclient.NewSimpleFake(&extensions.ReplicaSet{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 		"ReplicationControllerDescriber": &ReplicationControllerDescriber{ | ||||||
|  | 			testclient.NewSimpleFake(&api.ReplicationController{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 		"Service": &ServiceDescriber{ | ||||||
|  | 			testclient.NewSimpleFake(&api.Service{ | ||||||
|  | 				ObjectMeta: api.ObjectMeta{ | ||||||
|  | 					Name:      "bar", | ||||||
|  | 					Namespace: "foo", | ||||||
|  | 				}, | ||||||
|  | 			}, events), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for name, d := range m { | ||||||
|  | 		out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Errorf("unexpected error for %q: %v", name, err) | ||||||
|  | 		} | ||||||
|  | 		if !strings.Contains(out, "bar") { | ||||||
|  | 			t.Errorf("unexpected out for %q: %s", name, out) | ||||||
|  | 		} | ||||||
|  | 		if !strings.Contains(out, "Events:") { | ||||||
|  | 			t.Errorf("events not found for %q when ShowEvents=true: %s", name, out) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		out, err = d.Describe("foo", "bar", DescriberSettings{ShowEvents: false}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Errorf("unexpected error for %q: %s", name, err) | ||||||
|  | 		} | ||||||
|  | 		if !strings.Contains(out, "bar") { | ||||||
|  | 			t.Errorf("unexpected out for %q: %s", name, out) | ||||||
|  | 		} | ||||||
|  | 		if strings.Contains(out, "Events:") { | ||||||
|  | 			t.Errorf("events found for %q when ShowEvents=false: %s", name, out) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user