Skip to content

Commit

Permalink
Promote new Event API to v1
Browse files Browse the repository at this point in the history
  • Loading branch information
chelseychen committed Jul 1, 2020
1 parent 1cbda24 commit 75612c1
Show file tree
Hide file tree
Showing 23 changed files with 1,458 additions and 41 deletions.
1 change: 1 addition & 0 deletions cmd/kube-apiserver/app/aggregator.go
Expand Up @@ -252,6 +252,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{
{Group: "extensions", Version: "v1beta1"}: {group: 17900, version: 1},
// to my knowledge, nothing below here collides
{Group: "apps", Version: "v1"}: {group: 17800, version: 15},
{Group: "events.k8s.io", Version: "v1"}: {group: 17750, version: 15},
{Group: "events.k8s.io", Version: "v1beta1"}: {group: 17750, version: 5},
{Group: "authentication.k8s.io", Version: "v1"}: {group: 17700, version: 15},
{Group: "authentication.k8s.io", Version: "v1beta1"}: {group: 17700, version: 9},
Expand Down
2 changes: 2 additions & 0 deletions hack/.golint_failures
Expand Up @@ -28,6 +28,7 @@ pkg/apis/core/v1/helper/qos
pkg/apis/core/validation
pkg/apis/discovery/v1alpha1
pkg/apis/discovery/v1beta1
pkg/apis/events/v1
pkg/apis/events/v1beta1
pkg/apis/extensions/v1beta1
pkg/apis/flowcontrol/v1alpha1
Expand Down Expand Up @@ -228,6 +229,7 @@ staging/src/k8s.io/api/certificates/v1beta1
staging/src/k8s.io/api/coordination/v1
staging/src/k8s.io/api/coordination/v1beta1
staging/src/k8s.io/api/core/v1
staging/src/k8s.io/api/events/v1
staging/src/k8s.io/api/events/v1beta1
staging/src/k8s.io/api/extensions/v1beta1
staging/src/k8s.io/api/imagepolicy/v1alpha1
Expand Down
1 change: 1 addition & 0 deletions hack/.import-aliases
Expand Up @@ -19,6 +19,7 @@
"k8s.io/api/core/v1": "v1",
"k8s.io/api/discovery/v1alpha1": "discoveryv1alpha1",
"k8s.io/api/discovery/v1beta1": "discoveryv1beta1",
"k8s.io/api/events/v1": "eventsv1",
"k8s.io/api/events/v1beta1": "eventsv1beta1",
"k8s.io/api/extensions/v1beta1": "extensionsv1beta1",
"k8s.io/api/imagepolicy/v1alpha1": "imagepolicyv1alpha1",
Expand Down
1 change: 1 addition & 0 deletions hack/lib/init.sh
Expand Up @@ -87,6 +87,7 @@ coordination.k8s.io/v1 \
discovery.k8s.io/v1alpha1 \
discovery.k8s.io/v1beta1 \
extensions/v1beta1 \
events.k8s.io/v1 \
events.k8s.io/v1beta1 \
imagepolicy.k8s.io/v1alpha1 \
networking.k8s.io/v1 \
Expand Down
89 changes: 87 additions & 2 deletions pkg/apis/core/validation/events.go
Expand Up @@ -18,9 +18,14 @@ package validation

import (
"fmt"
"reflect"
"time"

"k8s.io/api/core/v1"
eventsv1beta1 "k8s.io/api/events/v1beta1"
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/apis/core"
Expand All @@ -33,8 +38,88 @@ const (
NoteLengthLimit = 1024
)

// ValidateEvent makes sure that the event makes sense.
func ValidateEvent(event *core.Event) field.ErrorList {
func ValidateEventCreate(event *core.Event, requestVersion schema.GroupVersion) field.ErrorList {
// Make sure events always pass legacy validation.
allErrs := legacyValidateEvent(event)
if requestVersion == v1.SchemeGroupVersion || requestVersion == eventsv1beta1.SchemeGroupVersion {
// No further validation for backwards compatibility.
return allErrs
}

// Strict validation applies to creation via events.k8s.io/v1 API and newer.
allErrs = append(allErrs, ValidateObjectMeta(&event.ObjectMeta, true, apimachineryvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))...)
allErrs = append(allErrs, validateV1EventSeries(event)...)
zeroTime := time.Time{}
if event.EventTime.Time == zeroTime {
allErrs = append(allErrs, field.Required(field.NewPath("eventTime"), ""))
}
if event.Type != v1.EventTypeNormal && event.Type != v1.EventTypeWarning {
allErrs = append(allErrs, field.Invalid(field.NewPath("type"), "", fmt.Sprintf("has invalid value: %v", event.Type)))
}
if event.FirstTimestamp.Time != zeroTime {
allErrs = append(allErrs, field.Invalid(field.NewPath("firstTimestamp"), "", "needs to be unset"))
}
if event.LastTimestamp.Time != zeroTime {
allErrs = append(allErrs, field.Invalid(field.NewPath("lastTimestamp"), "", "needs to be unset"))
}
if event.Count != 0 {
allErrs = append(allErrs, field.Invalid(field.NewPath("count"), "", "needs to be unset"))
}
if event.Source.Component != "" || event.Source.Host != "" {
allErrs = append(allErrs, field.Invalid(field.NewPath("source"), "", "needs to be unset"))
}
return allErrs
}

func ValidateEventUpdate(newEvent, oldEvent *core.Event, requestVersion schema.GroupVersion) field.ErrorList {
// Make sure the new event always passes legacy validation.
allErrs := legacyValidateEvent(newEvent)
if requestVersion == v1.SchemeGroupVersion || requestVersion == eventsv1beta1.SchemeGroupVersion {
// No further validation for backwards compatibility.
return allErrs
}

// Strict validation applies to update via events.k8s.io/v1 API and newer.
allErrs = append(allErrs, ValidateObjectMetaUpdate(&newEvent.ObjectMeta, &oldEvent.ObjectMeta, field.NewPath("metadata"))...)
// if the series was modified, validate the new data
if !reflect.DeepEqual(newEvent.Series, oldEvent.Series) {
allErrs = append(allErrs, validateV1EventSeries(newEvent)...)
}

allErrs = append(allErrs, ValidateImmutableField(newEvent.InvolvedObject, oldEvent.InvolvedObject, field.NewPath("involvedObject"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Reason, oldEvent.Reason, field.NewPath("reason"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Message, oldEvent.Message, field.NewPath("message"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Source, oldEvent.Source, field.NewPath("source"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.FirstTimestamp, oldEvent.FirstTimestamp, field.NewPath("firstTimestamp"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.LastTimestamp, oldEvent.LastTimestamp, field.NewPath("lastTimestamp"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Count, oldEvent.Count, field.NewPath("count"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Reason, oldEvent.Reason, field.NewPath("reason"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Type, oldEvent.Type, field.NewPath("type"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.EventTime, oldEvent.EventTime, field.NewPath("eventTime"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Action, oldEvent.Action, field.NewPath("action"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.Related, oldEvent.Related, field.NewPath("related"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.ReportingController, oldEvent.ReportingController, field.NewPath("reportingController"))...)
allErrs = append(allErrs, ValidateImmutableField(newEvent.ReportingInstance, oldEvent.ReportingInstance, field.NewPath("reportingInstance"))...)

return allErrs
}

func validateV1EventSeries(event *core.Event) field.ErrorList {
allErrs := field.ErrorList{}
zeroTime := time.Time{}
if event.Series != nil {
if event.Series.Count < 2 {
allErrs = append(allErrs, field.Invalid(field.NewPath("series.count"), "", fmt.Sprintf("should be at least 2")))
}
if event.Series.LastObservedTime.Time == zeroTime {
allErrs = append(allErrs, field.Required(field.NewPath("series.lastObservedTime"), ""))
}
}
return allErrs
}

// legacyValidateEvent makes sure that the event makes sense.
func legacyValidateEvent(event *core.Event) field.ErrorList {
allErrs := field.ErrorList{}
// Because go
zeroTime := time.Time{}
Expand Down

0 comments on commit 75612c1

Please sign in to comment.