From b47a5b6508c51e2dd61e90a8010ecc35fae45943 Mon Sep 17 00:00:00 2001 From: Ewout Prangsma Date: Mon, 18 Jun 2018 11:55:42 +0200 Subject: [PATCH] Use standard EventRecord to use event compression --- main.go | 2 +- pkg/deployment/deployment.go | 14 ++-- pkg/deployment/members.go | 3 +- pkg/deployment/reconcile/context.go | 2 +- pkg/deployment/resources/context.go | 2 +- pkg/deployment/resources/pod_inspector.go | 3 +- pkg/operator/operator_deployment.go | 1 + .../operator_deployment_relication.go | 5 +- pkg/operator/operator_local_storage.go | 5 +- pkg/replication/deployment_replication.go | 19 ++---- pkg/storage/local_storage.go | 16 ++--- pkg/util/k8sutil/events.go | 68 ++++++++----------- 12 files changed, 57 insertions(+), 83 deletions(-) diff --git a/main.go b/main.go index aee46c36b..d93bb5d62 100644 --- a/main.go +++ b/main.go @@ -39,11 +39,11 @@ import ( "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/kubernetes/scheme" v1core "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/record" "github.com/arangodb/kube-arangodb/pkg/client" + scheme "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned/scheme" "github.com/arangodb/kube-arangodb/pkg/logging" "github.com/arangodb/kube-arangodb/pkg/operator" "github.com/arangodb/kube-arangodb/pkg/server" diff --git a/pkg/deployment/deployment.go b/pkg/deployment/deployment.go index 90adab81d..918c97a32 100644 --- a/pkg/deployment/deployment.go +++ b/pkg/deployment/deployment.go @@ -32,10 +32,9 @@ import ( "github.com/arangodb/arangosync/client" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/record" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha" "github.com/arangodb/kube-arangodb/pkg/deployment/chaos" @@ -60,6 +59,7 @@ type Dependencies struct { Log zerolog.Logger KubeCli kubernetes.Interface DatabaseCRCli versioned.Interface + EventRecorder record.EventRecorder } // deploymentEventType strongly typed type of event @@ -96,8 +96,6 @@ type Deployment struct { stopCh chan struct{} stopped int32 - eventsCli corev1.EventInterface - inspectTrigger trigger.Trigger updateDeploymentTrigger trigger.Trigger clientCache *clientCache @@ -121,7 +119,6 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De deps: deps, eventCh: make(chan *deploymentEvent, deploymentEventQueueSize), stopCh: make(chan struct{}), - eventsCli: deps.KubeCli.Core().Events(apiObject.GetNamespace()), clientCache: newClientCache(deps.KubeCli, apiObject), } d.status.last = *(apiObject.Status.DeepCopy()) @@ -337,11 +334,8 @@ func (d *Deployment) handleArangoDeploymentUpdatedEvent() error { // CreateEvent creates a given event. // On error, the error is logged. -func (d *Deployment) CreateEvent(evt *v1.Event) { - _, err := d.eventsCli.Create(evt) - if err != nil { - d.deps.Log.Error().Err(err).Interface("event", *evt).Msg("Failed to record event") - } +func (d *Deployment) CreateEvent(evt *k8sutil.Event) { + d.deps.EventRecorder.Event(evt.InvolvedObject, evt.Type, evt.Reason, evt.Message) } // Update the status of the API object from the internal status diff --git a/pkg/deployment/members.go b/pkg/deployment/members.go index 6e115a933..37ed06a98 100644 --- a/pkg/deployment/members.go +++ b/pkg/deployment/members.go @@ -28,7 +28,6 @@ import ( "github.com/dchest/uniuri" "github.com/rs/zerolog" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha" @@ -42,7 +41,7 @@ func (d *Deployment) createInitialMembers(apiObject *api.ArangoDeployment) error log.Debug().Msg("creating initial members...") // Go over all groups and create members - var events []*v1.Event + var events []*k8sutil.Event status, lastVersion := d.GetStatus() if err := apiObject.ForeachServerGroup(func(group api.ServerGroup, spec api.ServerGroupSpec, members *api.MemberStatusList) error { for len(*members) < spec.GetCount() { diff --git a/pkg/deployment/reconcile/context.go b/pkg/deployment/reconcile/context.go index 0e6cb7681..10018570e 100644 --- a/pkg/deployment/reconcile/context.go +++ b/pkg/deployment/reconcile/context.go @@ -59,7 +59,7 @@ type Context interface { GetSyncServerClient(ctx context.Context, group api.ServerGroup, id string) (client.API, error) // CreateEvent creates a given event. // On error, the error is logged. - CreateEvent(evt *v1.Event) + CreateEvent(evt *k8sutil.Event) // CreateMember adds a new member to the given group. // If ID is non-empty, it will be used, otherwise a new ID is created. CreateMember(group api.ServerGroup, id string) error diff --git a/pkg/deployment/resources/context.go b/pkg/deployment/resources/context.go index e5f614500..9e4db969f 100644 --- a/pkg/deployment/resources/context.go +++ b/pkg/deployment/resources/context.go @@ -64,7 +64,7 @@ type Context interface { GetNamespace() string // CreateEvent creates a given event. // On error, the error is logged. - CreateEvent(evt *v1.Event) + CreateEvent(evt *k8sutil.Event) // GetOwnedPods returns a list of all pods owned by the deployment. GetOwnedPods() ([]v1.Pod, error) // GetOwnedPVCs returns a list of all PVCs owned by the deployment. diff --git a/pkg/deployment/resources/pod_inspector.go b/pkg/deployment/resources/pod_inspector.go index 1ccaecc6d..ebad40ec1 100644 --- a/pkg/deployment/resources/pod_inspector.go +++ b/pkg/deployment/resources/pod_inspector.go @@ -27,7 +27,6 @@ import ( "fmt" "time" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1alpha" @@ -47,7 +46,7 @@ const ( // the member status of the deployment accordingly. func (r *Resources) InspectPods(ctx context.Context) error { log := r.log - var events []*v1.Event + var events []*k8sutil.Event pods, err := r.context.GetOwnedPods() if err != nil { diff --git a/pkg/operator/operator_deployment.go b/pkg/operator/operator_deployment.go index 62cd54182..63524c7f4 100644 --- a/pkg/operator/operator_deployment.go +++ b/pkg/operator/operator_deployment.go @@ -212,6 +212,7 @@ func (o *Operator) makeDeploymentConfigAndDeps(apiObject *api.ArangoDeployment) Logger(), KubeCli: o.Dependencies.KubeCli, DatabaseCRCli: o.Dependencies.CRCli, + EventRecorder: o.Dependencies.EventRecorder, } return cfg, deps } diff --git a/pkg/operator/operator_deployment_relication.go b/pkg/operator/operator_deployment_relication.go index bff0d9d61..013e7ce34 100644 --- a/pkg/operator/operator_deployment_relication.go +++ b/pkg/operator/operator_deployment_relication.go @@ -208,8 +208,9 @@ func (o *Operator) makeDeploymentReplicationConfigAndDeps(apiObject *api.ArangoD Log: o.Dependencies.LogService.MustGetLogger("deployment-replication").With(). Str("deployment-replication", apiObject.GetName()). Logger(), - KubeCli: o.Dependencies.KubeCli, - CRCli: o.Dependencies.CRCli, + KubeCli: o.Dependencies.KubeCli, + CRCli: o.Dependencies.CRCli, + EventRecorder: o.Dependencies.EventRecorder, } return cfg, deps } diff --git a/pkg/operator/operator_local_storage.go b/pkg/operator/operator_local_storage.go index 008df5098..5d0b3b5ac 100644 --- a/pkg/operator/operator_local_storage.go +++ b/pkg/operator/operator_local_storage.go @@ -210,8 +210,9 @@ func (o *Operator) makeLocalStorageConfigAndDeps(apiObject *api.ArangoLocalStora Log: o.Dependencies.LogService.MustGetLogger("storage").With(). Str("localStorage", apiObject.GetName()). Logger(), - KubeCli: o.Dependencies.KubeCli, - StorageCRCli: o.Dependencies.CRCli, + KubeCli: o.Dependencies.KubeCli, + StorageCRCli: o.Dependencies.CRCli, + EventRecorder: o.Dependencies.EventRecorder, } return cfg, deps } diff --git a/pkg/replication/deployment_replication.go b/pkg/replication/deployment_replication.go index 4a44dd1c8..0275dc8c7 100644 --- a/pkg/replication/deployment_replication.go +++ b/pkg/replication/deployment_replication.go @@ -29,10 +29,9 @@ import ( "time" "github.com/rs/zerolog" - "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/record" "github.com/arangodb/arangosync/client" api "github.com/arangodb/kube-arangodb/pkg/apis/replication/v1alpha" @@ -49,9 +48,10 @@ type Config struct { // Dependencies holds dependent services for a DeploymentReplication type Dependencies struct { - Log zerolog.Logger - KubeCli kubernetes.Interface - CRCli versioned.Interface + Log zerolog.Logger + KubeCli kubernetes.Interface + CRCli versioned.Interface + EventRecorder record.EventRecorder } // deploymentReplicationEvent strongly typed type of event @@ -84,8 +84,6 @@ type DeploymentReplication struct { stopCh chan struct{} stopped int32 - eventsCli corev1.EventInterface - inspectTrigger trigger.Trigger recentInspectionErrors int clientCache client.ClientCache @@ -103,7 +101,6 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeploymentReplic deps: deps, eventCh: make(chan *deploymentReplicationEvent, deploymentReplicationEventQueueSize), stopCh: make(chan struct{}), - eventsCli: deps.KubeCli.Core().Events(apiObject.GetNamespace()), } go dr.run() @@ -241,10 +238,8 @@ func (dr *DeploymentReplication) handleArangoDeploymentReplicationUpdatedEvent(e // createEvent creates a given event. // On error, the error is logged. -func (dr *DeploymentReplication) createEvent(evt *v1.Event) { - if _, err := dr.eventsCli.Create(evt); err != nil { - dr.deps.Log.Error().Err(err).Interface("event", *evt).Msg("Failed to record event") - } +func (dr *DeploymentReplication) createEvent(evt *k8sutil.Event) { + dr.deps.EventRecorder.Event(evt.InvolvedObject, evt.Type, evt.Reason, evt.Message) } // Update the status of the API object from the internal status diff --git a/pkg/storage/local_storage.go b/pkg/storage/local_storage.go index 2591bda6d..b1dfeca9c 100644 --- a/pkg/storage/local_storage.go +++ b/pkg/storage/local_storage.go @@ -35,6 +35,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/record" api "github.com/arangodb/kube-arangodb/pkg/apis/storage/v1alpha" "github.com/arangodb/kube-arangodb/pkg/generated/clientset/versioned" @@ -52,9 +53,10 @@ type Config struct { // Dependencies holds dependent services for a LocalStorage type Dependencies struct { - Log zerolog.Logger - KubeCli kubernetes.Interface - StorageCRCli versioned.Interface + Log zerolog.Logger + KubeCli kubernetes.Interface + StorageCRCli versioned.Interface + EventRecorder record.EventRecorder } // localStorageEvent strongly typed type of event @@ -112,7 +114,6 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoLocalStorage) (* deps: deps, eventCh: make(chan *localStorageEvent, localStorageEventQueueSize), stopCh: make(chan struct{}), - eventsCli: deps.KubeCli.Core().Events(apiObject.GetNamespace()), } ls.pvCleaner = newPVCleaner(deps.Log, deps.KubeCli, ls.GetClientByNodeName) @@ -324,11 +325,8 @@ func (ls *LocalStorage) handleArangoLocalStorageUpdatedEvent(event *localStorage // createEvent creates a given event. // On error, the error is logged. -func (ls *LocalStorage) createEvent(evt *v1.Event) { - _, err := ls.eventsCli.Create(evt) - if err != nil { - ls.deps.Log.Error().Err(err).Interface("event", *evt).Msg("Failed to record event") - } +func (ls *LocalStorage) createEvent(evt *k8sutil.Event) { + ls.deps.EventRecorder.Event(evt.InvolvedObject, evt.Type, evt.Reason, evt.Message) } // Update the status of the API object from the internal status diff --git a/pkg/util/k8sutil/events.go b/pkg/util/k8sutil/events.go index 599257fad..602a77508 100644 --- a/pkg/util/k8sutil/events.go +++ b/pkg/util/k8sutil/events.go @@ -24,25 +24,31 @@ package k8sutil import ( "fmt" - "os" "strings" - "time" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/arangodb/kube-arangodb/pkg/util/constants" + "k8s.io/apimachinery/pkg/runtime" ) +// Event is used to create events using an EventRecorder. +type Event struct { + InvolvedObject runtime.Object + Type string + Reason string + Message string +} + // APIObject helps to abstract an object from our custom API. type APIObject interface { + runtime.Object metav1.Object // AsOwner creates an OwnerReference for the given deployment AsOwner() metav1.OwnerReference } // NewMemberAddEvent creates an event indicating that a member was added. -func NewMemberAddEvent(memberName, role string, apiObject APIObject) *v1.Event { +func NewMemberAddEvent(memberName, role string, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = fmt.Sprintf("New %s Added", strings.Title(role)) @@ -51,7 +57,7 @@ func NewMemberAddEvent(memberName, role string, apiObject APIObject) *v1.Event { } // NewMemberRemoveEvent creates an event indicating that an existing member was removed. -func NewMemberRemoveEvent(memberName, role string, apiObject APIObject) *v1.Event { +func NewMemberRemoveEvent(memberName, role string, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = fmt.Sprintf("%s Removed", strings.Title(role)) @@ -60,7 +66,7 @@ func NewMemberRemoveEvent(memberName, role string, apiObject APIObject) *v1.Even } // NewPodCreatedEvent creates an event indicating that a pod has been created -func NewPodCreatedEvent(podName, role string, apiObject APIObject) *v1.Event { +func NewPodCreatedEvent(podName, role string, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = fmt.Sprintf("Pod Of %s Created", strings.Title(role)) @@ -69,7 +75,7 @@ func NewPodCreatedEvent(podName, role string, apiObject APIObject) *v1.Event { } // NewPodGoneEvent creates an event indicating that a pod is missing -func NewPodGoneEvent(podName, role string, apiObject APIObject) *v1.Event { +func NewPodGoneEvent(podName, role string, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = fmt.Sprintf("Pod Of %s Gone", strings.Title(role)) @@ -79,7 +85,7 @@ func NewPodGoneEvent(podName, role string, apiObject APIObject) *v1.Event { // NewImmutableFieldEvent creates an event indicating that an attempt was made to change a field // that is immutable. -func NewImmutableFieldEvent(fieldName string, apiObject APIObject) *v1.Event { +func NewImmutableFieldEvent(fieldName string, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Immutable Field Change" @@ -88,7 +94,7 @@ func NewImmutableFieldEvent(fieldName string, apiObject APIObject) *v1.Event { } // NewPodsSchedulingFailureEvent creates an event indicating that one of more cannot be scheduled. -func NewPodsSchedulingFailureEvent(unscheduledPodNames []string, apiObject APIObject) *v1.Event { +func NewPodsSchedulingFailureEvent(unscheduledPodNames []string, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Pods Scheduling Failure" @@ -98,7 +104,7 @@ func NewPodsSchedulingFailureEvent(unscheduledPodNames []string, apiObject APIOb // NewPodsSchedulingResolvedEvent creates an event indicating that an earlier problem with // pod scheduling has been resolved. -func NewPodsSchedulingResolvedEvent(apiObject APIObject) *v1.Event { +func NewPodsSchedulingResolvedEvent(apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Pods Scheduling Resolved" @@ -107,7 +113,7 @@ func NewPodsSchedulingResolvedEvent(apiObject APIObject) *v1.Event { } // NewSecretsChangedEvent creates an event indicating that one of more secrets have changed. -func NewSecretsChangedEvent(changedSecretNames []string, apiObject APIObject) *v1.Event { +func NewSecretsChangedEvent(changedSecretNames []string, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Secrets changed" @@ -117,7 +123,7 @@ func NewSecretsChangedEvent(changedSecretNames []string, apiObject APIObject) *v // NewSecretsRestoredEvent creates an event indicating that all secrets have been restored // to their original values. -func NewSecretsRestoredEvent(apiObject APIObject) *v1.Event { +func NewSecretsRestoredEvent(apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Secrets restored" @@ -127,7 +133,7 @@ func NewSecretsRestoredEvent(apiObject APIObject) *v1.Event { // NewAccessPackageCreatedEvent creates an event indicating that a secret containing an access package // has been created. -func NewAccessPackageCreatedEvent(apiObject APIObject, apSecretName string) *v1.Event { +func NewAccessPackageCreatedEvent(apiObject APIObject, apSecretName string) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Access package created" @@ -137,7 +143,7 @@ func NewAccessPackageCreatedEvent(apiObject APIObject, apSecretName string) *v1. // NewAccessPackageDeletedEvent creates an event indicating that a secret containing an access package // has been deleted. -func NewAccessPackageDeletedEvent(apiObject APIObject, apSecretName string) *v1.Event { +func NewAccessPackageDeletedEvent(apiObject APIObject, apSecretName string) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Access package deleted" @@ -147,7 +153,7 @@ func NewAccessPackageDeletedEvent(apiObject APIObject, apSecretName string) *v1. // NewPlanTimeoutEvent creates an event indicating that an item on a reconciliation plan did not // finish before its deadline. -func NewPlanTimeoutEvent(apiObject APIObject, itemType, memberID, role string) *v1.Event { +func NewPlanTimeoutEvent(apiObject APIObject, itemType, memberID, role string) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Reconciliation Plan Timeout" @@ -157,7 +163,7 @@ func NewPlanTimeoutEvent(apiObject APIObject, itemType, memberID, role string) * // NewPlanAbortedEvent creates an event indicating that an item on a reconciliation plan wants to abort // the entire plan. -func NewPlanAbortedEvent(apiObject APIObject, itemType, memberID, role string) *v1.Event { +func NewPlanAbortedEvent(apiObject APIObject, itemType, memberID, role string) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeNormal event.Reason = "Reconciliation Plan Aborted" @@ -166,7 +172,7 @@ func NewPlanAbortedEvent(apiObject APIObject, itemType, memberID, role string) * } // NewErrorEvent creates an even of type error. -func NewErrorEvent(reason string, err error, apiObject APIObject) *v1.Event { +func NewErrorEvent(reason string, err error, apiObject APIObject) *Event { event := newDeploymentEvent(apiObject) event.Type = v1.EventTypeWarning event.Reason = strings.Title(reason) @@ -175,28 +181,8 @@ func NewErrorEvent(reason string, err error, apiObject APIObject) *v1.Event { } // newDeploymentEvent creates a new event for the given api object & owner. -func newDeploymentEvent(apiObject APIObject) *v1.Event { - t := time.Now() - owner := apiObject.AsOwner() - return &v1.Event{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: apiObject.GetName() + "-", - Namespace: apiObject.GetNamespace(), - }, - InvolvedObject: v1.ObjectReference{ - APIVersion: owner.APIVersion, - Kind: owner.Kind, - Name: owner.Name, - Namespace: apiObject.GetNamespace(), - UID: owner.UID, - ResourceVersion: apiObject.GetResourceVersion(), - }, - Source: v1.EventSource{ - Component: os.Getenv(constants.EnvOperatorPodName), - }, - // Each deployment event is unique so it should not be collapsed with other events - FirstTimestamp: metav1.Time{Time: t}, - LastTimestamp: metav1.Time{Time: t}, - Count: int32(1), +func newDeploymentEvent(apiObject runtime.Object) *Event { + return &Event{ + InvolvedObject: apiObject, } }