Merge pull request #92874 from chelseychen/event-api
Fix a few places where source field is empty when creating events via events/v1
This commit is contained in:
commit
c23a4b08d7
@ -435,6 +435,7 @@ func AddFieldLabelConversionsForEvent(scheme *runtime.Scheme) error {
|
|||||||
"involvedObject.resourceVersion",
|
"involvedObject.resourceVersion",
|
||||||
"involvedObject.fieldPath",
|
"involvedObject.fieldPath",
|
||||||
"reason",
|
"reason",
|
||||||
|
"reportingComponent",
|
||||||
"source",
|
"source",
|
||||||
"type",
|
"type",
|
||||||
"metadata.namespace",
|
"metadata.namespace",
|
||||||
|
@ -17,8 +17,11 @@ limitations under the License.
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
v1 "k8s.io/api/events/v1"
|
v1 "k8s.io/api/events/v1"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
k8s_api "k8s.io/kubernetes/pkg/apis/core"
|
k8s_api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||||
)
|
)
|
||||||
@ -56,3 +59,29 @@ func Convert_core_Event_To_v1_Event(in *k8s_api.Event, out *v1.Event, s conversi
|
|||||||
out.DeprecatedCount = in.Count
|
out.DeprecatedCount = in.Count
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddFieldLabelConversionsForEvent(scheme *runtime.Scheme) error {
|
||||||
|
mapping := map[string]string{
|
||||||
|
"reason": "reason",
|
||||||
|
"regarding.kind": "involvedObject.kind", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.namespace": "involvedObject.namespace", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.name": "involvedObject.name", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.uid": "involvedObject.uid", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.apiVersion": "involvedObject.apiVersion", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.resourceVersion": "involvedObject.resourceVersion", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.fieldPath": "involvedObject.fieldPath", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"reportingController": "reportingComponent", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"type": "type",
|
||||||
|
"metadata.namespace": "metadata.namespace",
|
||||||
|
"metadata.name": "metadata.name",
|
||||||
|
}
|
||||||
|
return scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("Event"),
|
||||||
|
func(label, value string) (string, string, error) {
|
||||||
|
mappedLabel, ok := mapping[label]
|
||||||
|
if !ok {
|
||||||
|
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||||
|
}
|
||||||
|
return mappedLabel, value, nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -41,5 +41,5 @@ func init() {
|
|||||||
// We only register manually written functions here. The registration of the
|
// We only register manually written functions here. The registration of the
|
||||||
// generated functions takes place in the generated files. The separation
|
// generated functions takes place in the generated files. The separation
|
||||||
// makes the code compile even when the generated files are missing.
|
// makes the code compile even when the generated files are missing.
|
||||||
localSchemeBuilder.Register(RegisterDefaults)
|
localSchemeBuilder.Register(RegisterDefaults, AddFieldLabelConversionsForEvent)
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,11 @@ limitations under the License.
|
|||||||
package v1beta1
|
package v1beta1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
v1beta1 "k8s.io/api/events/v1beta1"
|
v1beta1 "k8s.io/api/events/v1beta1"
|
||||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
k8s_api "k8s.io/kubernetes/pkg/apis/core"
|
k8s_api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||||
)
|
)
|
||||||
@ -56,3 +59,29 @@ func Convert_core_Event_To_v1beta1_Event(in *k8s_api.Event, out *v1beta1.Event,
|
|||||||
out.DeprecatedCount = in.Count
|
out.DeprecatedCount = in.Count
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddFieldLabelConversionsForEvent(scheme *runtime.Scheme) error {
|
||||||
|
mapping := map[string]string{
|
||||||
|
"reason": "reason",
|
||||||
|
"regarding.kind": "involvedObject.kind", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.namespace": "involvedObject.namespace", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.name": "involvedObject.name", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.uid": "involvedObject.uid", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.apiVersion": "involvedObject.apiVersion", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.resourceVersion": "involvedObject.resourceVersion", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"regarding.fieldPath": "involvedObject.fieldPath", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"reportingController": "reportingComponent", // map events.k8s.io field to fieldset returned by ToSelectableFields
|
||||||
|
"type": "type",
|
||||||
|
"metadata.namespace": "metadata.namespace",
|
||||||
|
"metadata.name": "metadata.name",
|
||||||
|
}
|
||||||
|
return scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("Event"),
|
||||||
|
func(label, value string) (string, string, error) {
|
||||||
|
mappedLabel, ok := mapping[label]
|
||||||
|
if !ok {
|
||||||
|
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||||
|
}
|
||||||
|
return mappedLabel, value, nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -41,5 +41,5 @@ func init() {
|
|||||||
// We only register manually written functions here. The registration of the
|
// We only register manually written functions here. The registration of the
|
||||||
// generated functions takes place in the generated files. The separation
|
// generated functions takes place in the generated files. The separation
|
||||||
// makes the code compile even when the generated files are missing.
|
// makes the code compile even when the generated files are missing.
|
||||||
localSchemeBuilder.Register(RegisterDefaults)
|
localSchemeBuilder.Register(RegisterDefaults, AddFieldLabelConversionsForEvent)
|
||||||
}
|
}
|
||||||
|
@ -1757,7 +1757,7 @@ func printEvent(obj *api.Event, options printers.GenerateOptions) ([]metav1.Tabl
|
|||||||
obj.Reason,
|
obj.Reason,
|
||||||
target,
|
target,
|
||||||
obj.InvolvedObject.FieldPath,
|
obj.InvolvedObject.FieldPath,
|
||||||
formatEventSource(obj.Source),
|
formatEventSource(obj.Source, obj.ReportingController, obj.ReportingInstance),
|
||||||
strings.TrimSpace(obj.Message),
|
strings.TrimSpace(obj.Message),
|
||||||
firstTimestamp,
|
firstTimestamp,
|
||||||
int64(count),
|
int64(count),
|
||||||
@ -2247,13 +2247,29 @@ func layoutContainerCells(containers []api.Container) (names string, images stri
|
|||||||
return namesBuffer.String(), imagesBuffer.String()
|
return namesBuffer.String(), imagesBuffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatEventSource formats EventSource as a comma separated string excluding Host when empty
|
// formatEventSource formats EventSource as a comma separated string excluding Host when empty.
|
||||||
func formatEventSource(es api.EventSource) string {
|
// It uses reportingController when Source.Component is empty and reportingInstance when Source.Host is empty
|
||||||
EventSourceString := []string{es.Component}
|
func formatEventSource(es api.EventSource, reportingController, reportingInstance string) string {
|
||||||
if len(es.Host) > 0 {
|
return formatEventSourceComponentInstance(
|
||||||
EventSourceString = append(EventSourceString, es.Host)
|
firstNonEmpty(es.Component, reportingController),
|
||||||
|
firstNonEmpty(es.Host, reportingInstance),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func firstNonEmpty(ss ...string) string {
|
||||||
|
for _, s := range ss {
|
||||||
|
if len(s) > 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(EventSourceString, ", ")
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatEventSourceComponentInstance(component, instance string) string {
|
||||||
|
if len(instance) == 0 {
|
||||||
|
return component
|
||||||
|
}
|
||||||
|
return component + ", " + instance
|
||||||
}
|
}
|
||||||
|
|
||||||
func printControllerRevision(obj *apps.ControllerRevision, options printers.GenerateOptions) ([]metav1.TableRow, error) {
|
func printControllerRevision(obj *apps.ControllerRevision, options printers.GenerateOptions) ([]metav1.TableRow, error) {
|
||||||
|
@ -255,6 +255,28 @@ func TestPrintEvent(t *testing.T) {
|
|||||||
// Columns: Last Seen, Type, Reason, Object, Subobject, Message, First Seen, Count, Name
|
// Columns: Last Seen, Type, Reason, Object, Subobject, Message, First Seen, Count, Name
|
||||||
expected: []metav1.TableRow{{Cells: []interface{}{"3d", "Warning", "Event Reason", "deployment/Deployment Name", "spec.containers{foo}", "kubelet, Node1", "Message Data", "3d", int64(1), "event7"}}},
|
expected: []metav1.TableRow{{Cells: []interface{}{"3d", "Warning", "Event Reason", "deployment/Deployment Name", "spec.containers{foo}", "kubelet, Node1", "Message Data", "3d", int64(1), "event7"}}},
|
||||||
},
|
},
|
||||||
|
// Basic event, with empty Source; generate options=Wide
|
||||||
|
{
|
||||||
|
event: api.Event{
|
||||||
|
ReportingController: "kubelet",
|
||||||
|
ReportingInstance: "test",
|
||||||
|
InvolvedObject: api.ObjectReference{
|
||||||
|
Kind: "Deployment",
|
||||||
|
Name: "Deployment Name",
|
||||||
|
FieldPath: "spec.containers{foo}",
|
||||||
|
},
|
||||||
|
Reason: "Event Reason",
|
||||||
|
Message: "Message Data",
|
||||||
|
FirstTimestamp: metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -3)},
|
||||||
|
LastTimestamp: metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -2)},
|
||||||
|
Count: 6,
|
||||||
|
Type: api.EventTypeWarning,
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "event2"},
|
||||||
|
},
|
||||||
|
options: printers.GenerateOptions{Wide: true},
|
||||||
|
// Columns: Last Seen, Type, Reason, Object, Subobject, Source, Message, First Seen, Count, Name
|
||||||
|
expected: []metav1.TableRow{{Cells: []interface{}{"2d", "Warning", "Event Reason", "deployment/Deployment Name", "spec.containers{foo}", "kubelet, test", "Message Data", "3d", int64(6), "event2"}}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
@ -68,7 +68,6 @@ filegroup(
|
|||||||
"//pkg/registry/core/serviceaccount:all-srcs",
|
"//pkg/registry/core/serviceaccount:all-srcs",
|
||||||
"//pkg/registry/discovery/endpointslice:all-srcs",
|
"//pkg/registry/discovery/endpointslice:all-srcs",
|
||||||
"//pkg/registry/discovery/rest:all-srcs",
|
"//pkg/registry/discovery/rest:all-srcs",
|
||||||
"//pkg/registry/events/event:all-srcs",
|
|
||||||
"//pkg/registry/events/rest:all-srcs",
|
"//pkg/registry/events/rest:all-srcs",
|
||||||
"//pkg/registry/extensions/rest:all-srcs",
|
"//pkg/registry/extensions/rest:all-srcs",
|
||||||
"//pkg/registry/flowcontrol/flowschema:all-srcs",
|
"//pkg/registry/flowcontrol/flowschema:all-srcs",
|
||||||
|
@ -104,6 +104,10 @@ func Matcher(label labels.Selector, field fields.Selector) storage.SelectionPred
|
|||||||
// ToSelectableFields returns a field set that represents the object.
|
// ToSelectableFields returns a field set that represents the object.
|
||||||
func ToSelectableFields(event *api.Event) fields.Set {
|
func ToSelectableFields(event *api.Event) fields.Set {
|
||||||
objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&event.ObjectMeta, true)
|
objectMetaFieldsSet := generic.ObjectMetaFieldsSet(&event.ObjectMeta, true)
|
||||||
|
source := event.Source.Component
|
||||||
|
if source == "" {
|
||||||
|
source = event.ReportingController
|
||||||
|
}
|
||||||
specificFieldsSet := fields.Set{
|
specificFieldsSet := fields.Set{
|
||||||
"involvedObject.kind": event.InvolvedObject.Kind,
|
"involvedObject.kind": event.InvolvedObject.Kind,
|
||||||
"involvedObject.namespace": event.InvolvedObject.Namespace,
|
"involvedObject.namespace": event.InvolvedObject.Namespace,
|
||||||
@ -113,7 +117,8 @@ func ToSelectableFields(event *api.Event) fields.Set {
|
|||||||
"involvedObject.resourceVersion": event.InvolvedObject.ResourceVersion,
|
"involvedObject.resourceVersion": event.InvolvedObject.ResourceVersion,
|
||||||
"involvedObject.fieldPath": event.InvolvedObject.FieldPath,
|
"involvedObject.fieldPath": event.InvolvedObject.FieldPath,
|
||||||
"reason": event.Reason,
|
"reason": event.Reason,
|
||||||
"source": event.Source.Component,
|
"reportingComponent": event.ReportingController, // use the core/v1 field name
|
||||||
|
"source": source,
|
||||||
"type": event.Type,
|
"type": event.Type,
|
||||||
}
|
}
|
||||||
return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
|
return generic.MergeFieldsSets(objectMetaFieldsSet, specificFieldsSet)
|
||||||
|
@ -50,7 +50,7 @@ func TestGetAttrs(t *testing.T) {
|
|||||||
Type: api.EventTypeNormal,
|
Type: api.EventTypeNormal,
|
||||||
}
|
}
|
||||||
field := ToSelectableFields(eventA)
|
field := ToSelectableFields(eventA)
|
||||||
expect := fields.Set{
|
expectA := fields.Set{
|
||||||
"metadata.name": "f0118",
|
"metadata.name": "f0118",
|
||||||
"metadata.namespace": "default",
|
"metadata.namespace": "default",
|
||||||
"involvedObject.kind": "Pod",
|
"involvedObject.kind": "Pod",
|
||||||
@ -61,10 +61,49 @@ func TestGetAttrs(t *testing.T) {
|
|||||||
"involvedObject.resourceVersion": "0",
|
"involvedObject.resourceVersion": "0",
|
||||||
"involvedObject.fieldPath": "",
|
"involvedObject.fieldPath": "",
|
||||||
"reason": "ForTesting",
|
"reason": "ForTesting",
|
||||||
|
"reportingComponent": "",
|
||||||
"source": "test",
|
"source": "test",
|
||||||
"type": api.EventTypeNormal,
|
"type": api.EventTypeNormal,
|
||||||
}
|
}
|
||||||
if e, a := expect, field; !reflect.DeepEqual(e, a) {
|
if e, a := expectA, field; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("diff: %s", diff.ObjectDiff(e, a))
|
||||||
|
}
|
||||||
|
|
||||||
|
eventB := &api.Event{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "f0118",
|
||||||
|
Namespace: "default",
|
||||||
|
},
|
||||||
|
InvolvedObject: api.ObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "baz",
|
||||||
|
UID: "long uid string",
|
||||||
|
APIVersion: "v1",
|
||||||
|
ResourceVersion: "0",
|
||||||
|
FieldPath: "",
|
||||||
|
},
|
||||||
|
Reason: "ForTesting",
|
||||||
|
ReportingController: "test",
|
||||||
|
Type: api.EventTypeNormal,
|
||||||
|
}
|
||||||
|
field = ToSelectableFields(eventB)
|
||||||
|
expectB := fields.Set{
|
||||||
|
"metadata.name": "f0118",
|
||||||
|
"metadata.namespace": "default",
|
||||||
|
"involvedObject.kind": "Pod",
|
||||||
|
"involvedObject.name": "foo",
|
||||||
|
"involvedObject.namespace": "baz",
|
||||||
|
"involvedObject.uid": "long uid string",
|
||||||
|
"involvedObject.apiVersion": "v1",
|
||||||
|
"involvedObject.resourceVersion": "0",
|
||||||
|
"involvedObject.fieldPath": "",
|
||||||
|
"reason": "ForTesting",
|
||||||
|
"reportingComponent": "test",
|
||||||
|
"source": "test",
|
||||||
|
"type": api.EventTypeNormal,
|
||||||
|
}
|
||||||
|
if e, a := expectB, field; !reflect.DeepEqual(e, a) {
|
||||||
t.Errorf("diff: %s", diff.ObjectDiff(e, a))
|
t.Errorf("diff: %s", diff.ObjectDiff(e, a))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = [
|
|
||||||
"doc.go",
|
|
||||||
"strategy.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/kubernetes/pkg/registry/events/event",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
|
||||||
"//pkg/apis/core:go_default_library",
|
|
||||||
"//pkg/apis/core/validation:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apiserver/pkg/storage:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2017 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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 event // import "k8s.io/kubernetes/pkg/registry/events/event"
|
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2017 The Kubernetes Authors.
|
|
||||||
|
|
||||||
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 event
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
|
||||||
"k8s.io/apiserver/pkg/registry/generic"
|
|
||||||
apistorage "k8s.io/apiserver/pkg/storage"
|
|
||||||
"k8s.io/apiserver/pkg/storage/names"
|
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
|
||||||
coreapi "k8s.io/kubernetes/pkg/apis/core"
|
|
||||||
corevalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
|
||||||
)
|
|
||||||
|
|
||||||
// eventStrategy implements verification logic for Pod Presets.
|
|
||||||
type eventStrategy struct {
|
|
||||||
runtime.ObjectTyper
|
|
||||||
names.NameGenerator
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strategy is the default logic that applies when creating and updating Pod Preset objects.
|
|
||||||
var Strategy = eventStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
|
|
||||||
|
|
||||||
// NamespaceScoped returns true because all Events need to be within a namespace.
|
|
||||||
func (eventStrategy) NamespaceScoped() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareForCreate clears the status of a Pod Preset before creation.
|
|
||||||
func (eventStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
|
||||||
func (eventStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate validates a new Event.
|
|
||||||
func (eventStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
|
||||||
groupVersion := requestGroupVersion(ctx)
|
|
||||||
event := obj.(*coreapi.Event)
|
|
||||||
return corevalidation.ValidateEventCreate(event, groupVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Canonicalize normalizes the object after validation.
|
|
||||||
// AllowCreateOnUpdate is false for Event; this means POST is needed to create one.
|
|
||||||
func (eventStrategy) AllowCreateOnUpdate() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (eventStrategy) Canonicalize(obj runtime.Object) {}
|
|
||||||
|
|
||||||
// ValidateUpdate is the default update validation for an end user.
|
|
||||||
func (eventStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
|
||||||
groupVersion := requestGroupVersion(ctx)
|
|
||||||
event := obj.(*coreapi.Event)
|
|
||||||
oldEvent := old.(*coreapi.Event)
|
|
||||||
return corevalidation.ValidateEventUpdate(event, oldEvent, groupVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AllowUnconditionalUpdate is the default update policy for Event objects.
|
|
||||||
func (eventStrategy) AllowUnconditionalUpdate() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectableFields returns a field set that represents the object.
|
|
||||||
func SelectableFields(pip *coreapi.Event) fields.Set {
|
|
||||||
return generic.ObjectMetaFieldsSet(&pip.ObjectMeta, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
|
||||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
|
||||||
pip, ok := obj.(*coreapi.Event)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("given object is not a Event")
|
|
||||||
}
|
|
||||||
return labels.Set(pip.ObjectMeta.Labels), SelectableFields(pip), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matcher is the filter used by the generic etcd backend to watch events
|
|
||||||
// from etcd to clients of the apiserver only interested in specific labels/fields.
|
|
||||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
|
||||||
return apistorage.SelectionPredicate{
|
|
||||||
Label: label,
|
|
||||||
Field: field,
|
|
||||||
GetAttrs: GetAttrs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// requestGroupVersion returns the group/version associated with the given context, or a zero-value group/version.
|
|
||||||
func requestGroupVersion(ctx context.Context) schema.GroupVersion {
|
|
||||||
if requestInfo, found := genericapirequest.RequestInfoFrom(ctx); found {
|
|
||||||
return schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion}
|
|
||||||
}
|
|
||||||
return schema.GroupVersion{}
|
|
||||||
}
|
|
@ -153,7 +153,8 @@ func (f *EventSourceObjectSpamFilter) Filter(event *v1.Event) bool {
|
|||||||
// localKey - key that makes this event in the local group
|
// localKey - key that makes this event in the local group
|
||||||
type EventAggregatorKeyFunc func(event *v1.Event) (aggregateKey string, localKey string)
|
type EventAggregatorKeyFunc func(event *v1.Event) (aggregateKey string, localKey string)
|
||||||
|
|
||||||
// EventAggregatorByReasonFunc aggregates events by exact match on event.Source, event.InvolvedObject, event.Type and event.Reason
|
// EventAggregatorByReasonFunc aggregates events by exact match on event.Source, event.InvolvedObject, event.Type,
|
||||||
|
// event.Reason, event.ReportingController and event.ReportingInstance
|
||||||
func EventAggregatorByReasonFunc(event *v1.Event) (string, string) {
|
func EventAggregatorByReasonFunc(event *v1.Event) (string, string) {
|
||||||
return strings.Join([]string{
|
return strings.Join([]string{
|
||||||
event.Source.Component,
|
event.Source.Component,
|
||||||
@ -165,6 +166,8 @@ func EventAggregatorByReasonFunc(event *v1.Event) (string, string) {
|
|||||||
event.InvolvedObject.APIVersion,
|
event.InvolvedObject.APIVersion,
|
||||||
event.Type,
|
event.Type,
|
||||||
event.Reason,
|
event.Reason,
|
||||||
|
event.ReportingController,
|
||||||
|
event.ReportingInstance,
|
||||||
},
|
},
|
||||||
""), event.Message
|
""), event.Message
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||||
|
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/typed/events/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/typed/events/v1:go_default_library",
|
||||||
"//test/e2e/framework:go_default_library",
|
"//test/e2e/framework:go_default_library",
|
||||||
"//test/e2e/instrumentation/common:go_default_library",
|
"//test/e2e/instrumentation/common:go_default_library",
|
||||||
|
@ -22,11 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
eventsv1 "k8s.io/api/events/v1"
|
eventsv1 "k8s.io/api/events/v1"
|
||||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
|
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
typedeventsv1 "k8s.io/client-go/kubernetes/typed/events/v1"
|
typedeventsv1 "k8s.io/client-go/kubernetes/typed/events/v1"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
"k8s.io/kubernetes/test/e2e/instrumentation/common"
|
"k8s.io/kubernetes/test/e2e/instrumentation/common"
|
||||||
@ -73,10 +74,12 @@ func eventExistsInList(client typedeventsv1.EventInterface, namespace, name stri
|
|||||||
|
|
||||||
var _ = common.SIGDescribe("Events API", func() {
|
var _ = common.SIGDescribe("Events API", func() {
|
||||||
f := framework.NewDefaultFramework("events")
|
f := framework.NewDefaultFramework("events")
|
||||||
|
var coreClient corev1.EventInterface
|
||||||
var client typedeventsv1.EventInterface
|
var client typedeventsv1.EventInterface
|
||||||
var clientAllNamespaces typedeventsv1.EventInterface
|
var clientAllNamespaces typedeventsv1.EventInterface
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
|
coreClient = f.ClientSet.CoreV1().Events(f.Namespace.Name)
|
||||||
client = f.ClientSet.EventsV1().Events(f.Namespace.Name)
|
client = f.ClientSet.EventsV1().Events(f.Namespace.Name)
|
||||||
clientAllNamespaces = f.ClientSet.EventsV1().Events(metav1.NamespaceAll)
|
clientAllNamespaces = f.ClientSet.EventsV1().Events(metav1.NamespaceAll)
|
||||||
})
|
})
|
||||||
@ -103,6 +106,20 @@ var _ = common.SIGDescribe("Events API", func() {
|
|||||||
foundCreatedEvent = eventExistsInList(client, f.Namespace.Name, eventName)
|
foundCreatedEvent = eventExistsInList(client, f.Namespace.Name, eventName)
|
||||||
framework.ExpectEqual(foundCreatedEvent, true, "failed to find test event in list with namespace scope")
|
framework.ExpectEqual(foundCreatedEvent, true, "failed to find test event in list with namespace scope")
|
||||||
|
|
||||||
|
ginkgo.By("listing events with field selection filtering on source")
|
||||||
|
filteredCoreV1List, err := coreClient.List(context.TODO(), metav1.ListOptions{FieldSelector: "source=test-controller"})
|
||||||
|
framework.ExpectNoError(err, "failed to get filtered list")
|
||||||
|
if len(filteredCoreV1List.Items) != 1 || filteredCoreV1List.Items[0].Name != eventName {
|
||||||
|
framework.Failf("expected single event, got %#v", filteredCoreV1List.Items)
|
||||||
|
}
|
||||||
|
|
||||||
|
ginkgo.By("listing events with field selection filtering on reportingController")
|
||||||
|
filteredEventsV1List, err := client.List(context.TODO(), metav1.ListOptions{FieldSelector: "reportingController=test-controller"})
|
||||||
|
framework.ExpectNoError(err, "failed to get filtered list")
|
||||||
|
if len(filteredEventsV1List.Items) != 1 || filteredEventsV1List.Items[0].Name != eventName {
|
||||||
|
framework.Failf("expected single event, got %#v", filteredEventsV1List.Items)
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.By("getting the test event")
|
ginkgo.By("getting the test event")
|
||||||
testEvent, err := client.Get(context.TODO(), eventName, metav1.GetOptions{})
|
testEvent, err := client.Get(context.TODO(), eventName, metav1.GetOptions{})
|
||||||
framework.ExpectNoError(err, "failed to get test event")
|
framework.ExpectNoError(err, "failed to get test event")
|
||||||
|
Loading…
Reference in New Issue
Block a user