mirror of
https://github.com/kubernetes/client-go.git
synced 2026-05-16 04:12:13 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82608c6a81 | ||
|
|
7eeeef0f16 | ||
|
|
b625a191b9 | ||
|
|
0d6350fa4e | ||
|
|
7b6e8d8480 | ||
|
|
ee23718387 | ||
|
|
8429124260 | ||
|
|
5d715fe8c7 | ||
|
|
cea5ee961b | ||
|
|
c4c506ff2e | ||
|
|
e7876b900b | ||
|
|
08d548e149 | ||
|
|
b1a83534de |
@@ -111,6 +111,8 @@ func convertAPIGroup(g apidiscovery.APIGroupDiscovery) (
|
||||
return group, gvResources, failedGVs
|
||||
}
|
||||
|
||||
var emptyKind = metav1.GroupVersionKind{}
|
||||
|
||||
// convertAPIResource tranforms a APIResourceDiscovery to an APIResource. We are
|
||||
// resilient to missing GVK, since this resource might be the parent resource
|
||||
// for a subresource. If the parent is missing a GVK, it is not returned in
|
||||
@@ -125,7 +127,7 @@ func convertAPIResource(in apidiscovery.APIResourceDiscovery) (metav1.APIResourc
|
||||
Categories: in.Categories,
|
||||
}
|
||||
var err error
|
||||
if in.ResponseKind != nil {
|
||||
if in.ResponseKind != nil && (*in.ResponseKind) != emptyKind {
|
||||
result.Group = in.ResponseKind.Group
|
||||
result.Version = in.ResponseKind.Version
|
||||
result.Kind = in.ResponseKind.Kind
|
||||
@@ -140,7 +142,7 @@ func convertAPIResource(in apidiscovery.APIResourceDiscovery) (metav1.APIResourc
|
||||
// convertAPISubresource tranforms a APISubresourceDiscovery to an APIResource.
|
||||
func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) (metav1.APIResource, error) {
|
||||
result := metav1.APIResource{}
|
||||
if in.ResponseKind == nil {
|
||||
if in.ResponseKind == nil || (*in.ResponseKind) == emptyKind {
|
||||
return result, fmt.Errorf("subresource %s/%s missing GVK", parent.Name, in.Subresource)
|
||||
}
|
||||
result.Name = fmt.Sprintf("%s/%s", parent.Name, in.Subresource)
|
||||
|
||||
@@ -610,6 +610,76 @@ func TestSplitGroupsAndResources(t *testing.T) {
|
||||
},
|
||||
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||
},
|
||||
{
|
||||
name: "Aggregated discovery with single subresource and parent empty GVK",
|
||||
agg: apidiscovery.APIGroupDiscoveryList{
|
||||
Items: []apidiscovery.APIGroupDiscovery{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "external.metrics.k8s.io",
|
||||
},
|
||||
Versions: []apidiscovery.APIVersionDiscovery{
|
||||
{
|
||||
Version: "v1beta1",
|
||||
Resources: []apidiscovery.APIResourceDiscovery{
|
||||
{
|
||||
// resilient to empty GVK for parent
|
||||
Resource: "*",
|
||||
Scope: apidiscovery.ScopeNamespace,
|
||||
SingularResource: "",
|
||||
ResponseKind: &metav1.GroupVersionKind{},
|
||||
Subresources: []apidiscovery.APISubresourceDiscovery{
|
||||
{
|
||||
Subresource: "other-external-metric",
|
||||
ResponseKind: &metav1.GroupVersionKind{
|
||||
Kind: "MetricValueList",
|
||||
},
|
||||
Verbs: []string{"get"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedGroups: metav1.APIGroupList{
|
||||
Groups: []metav1.APIGroup{
|
||||
{
|
||||
Name: "external.metrics.k8s.io",
|
||||
Versions: []metav1.GroupVersionForDiscovery{
|
||||
{
|
||||
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||
Version: "v1beta1",
|
||||
},
|
||||
},
|
||||
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||
Version: "v1beta1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||
{Group: "external.metrics.k8s.io", Version: "v1beta1"}: {
|
||||
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||
APIResources: []metav1.APIResource{
|
||||
// Since parent GVK was nil, it is NOT returned--only the subresource.
|
||||
{
|
||||
Name: "*/other-external-metric",
|
||||
SingularName: "",
|
||||
Namespaced: true,
|
||||
Group: "",
|
||||
Version: "",
|
||||
Kind: "MetricValueList",
|
||||
Verbs: []string{"get"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||
},
|
||||
{
|
||||
name: "Aggregated discovery with multiple subresources",
|
||||
agg: apidiscovery.APIGroupDiscoveryList{
|
||||
|
||||
8
go.mod
8
go.mod
@@ -24,8 +24,8 @@ require (
|
||||
golang.org/x/term v0.6.0
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
|
||||
google.golang.org/protobuf v1.28.1
|
||||
k8s.io/api v0.0.0-20230612172015-e5ccf2eb3112
|
||||
k8s.io/apimachinery v0.0.0-20230612171130-c23a82e9e261
|
||||
k8s.io/api v0.26.9
|
||||
k8s.io/apimachinery v0.26.9
|
||||
k8s.io/klog/v2 v2.80.1
|
||||
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280
|
||||
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d
|
||||
@@ -59,6 +59,6 @@ require (
|
||||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.0.0-20230612172015-e5ccf2eb3112
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20230612171130-c23a82e9e261
|
||||
k8s.io/api => k8s.io/api v0.26.9
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.26.9
|
||||
)
|
||||
|
||||
8
go.sum
8
go.sum
@@ -476,10 +476,10 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.0.0-20230612172015-e5ccf2eb3112 h1:LYwAu2/HRSHgBWkBA3RMVM2dIbIAswC9RdP+1h5JSVU=
|
||||
k8s.io/api v0.0.0-20230612172015-e5ccf2eb3112/go.mod h1:Q8EGFh0r6aLpTL7AhOHjtyGHqNgb1S4Tly2XwYg8XT0=
|
||||
k8s.io/apimachinery v0.0.0-20230612171130-c23a82e9e261 h1:e1ALI+iTI9xlG8DENWPhx4uZhrL5O5fU507otSjo9nU=
|
||||
k8s.io/apimachinery v0.0.0-20230612171130-c23a82e9e261/go.mod h1:qYzLkrQ9lhrZRh0jNKo2cfvf/R1/kQONnSiyB7NUJU0=
|
||||
k8s.io/api v0.26.9 h1:s8Y+G1u2JM55b90+Yo2RVb3PGT/hkWNVPN4idPERxJg=
|
||||
k8s.io/api v0.26.9/go.mod h1:W/W4fEWRVzPD36820LlVUQfNBiSbiq0VPWRFJKwzmUg=
|
||||
k8s.io/apimachinery v0.26.9 h1:5yAV9cFR7Z4gIorKcAjWnx4uxtxiFsERwq4Pvmx0CCg=
|
||||
k8s.io/apimachinery v0.26.9/go.mod h1:qYzLkrQ9lhrZRh0jNKo2cfvf/R1/kQONnSiyB7NUJU0=
|
||||
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
|
||||
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
|
||||
|
||||
@@ -181,22 +181,24 @@ func (e *eventBroadcasterImpl) recordToSink(event *eventsv1.Event, clock clock.C
|
||||
return nil
|
||||
}
|
||||
isomorphicEvent.Series = &eventsv1.EventSeries{
|
||||
Count: 1,
|
||||
Count: 2,
|
||||
LastObservedTime: metav1.MicroTime{Time: clock.Now()},
|
||||
}
|
||||
return isomorphicEvent
|
||||
// Make a copy of the Event to make sure that recording it
|
||||
// doesn't mess with the object stored in cache.
|
||||
return isomorphicEvent.DeepCopy()
|
||||
}
|
||||
e.eventCache[eventKey] = eventCopy
|
||||
return eventCopy
|
||||
// Make a copy of the Event to make sure that recording it doesn't
|
||||
// mess with the object stored in cache.
|
||||
return eventCopy.DeepCopy()
|
||||
}()
|
||||
if evToRecord != nil {
|
||||
recordedEvent := e.attemptRecording(evToRecord)
|
||||
if recordedEvent != nil {
|
||||
recordedEventKey := getKey(recordedEvent)
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
e.eventCache[recordedEventKey] = recordedEvent
|
||||
}
|
||||
// TODO: Add a metric counting the number of recording attempts
|
||||
e.attemptRecording(evToRecord)
|
||||
// We don't want the new recorded Event to be reflected in the
|
||||
// client's cache because server-side mutations could mess with the
|
||||
// aggregation mechanism used by the client.
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -248,6 +250,14 @@ func recordEvent(sink EventSink, event *eventsv1.Event) (*eventsv1.Event, bool)
|
||||
return nil, false
|
||||
case *errors.StatusError:
|
||||
if errors.IsAlreadyExists(err) {
|
||||
// If we tried to create an Event from an EventSerie, it means that
|
||||
// the original Patch request failed because the Event we were
|
||||
// trying to patch didn't exist. If the creation failed because the
|
||||
// Event now exists, it is safe to retry. This occurs when a new
|
||||
// Event is emitted twice in a very short period of time.
|
||||
if isEventSeries {
|
||||
return nil, true
|
||||
}
|
||||
klog.V(5).Infof("Server rejected event '%#v': '%v' (will not retry!)", event, err)
|
||||
} else {
|
||||
klog.Errorf("Server rejected event '%#v': '%v' (will not retry!)", event, err)
|
||||
|
||||
103
tools/events/event_broadcaster_test.go
Normal file
103
tools/events/event_broadcaster_test.go
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright 2022 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 events
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
eventsv1 "k8s.io/api/events/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func TestRecordEventToSink(t *testing.T) {
|
||||
nonIsomorphicEvent := eventsv1.Event{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test",
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Series: nil,
|
||||
}
|
||||
|
||||
isomorphicEvent := *nonIsomorphicEvent.DeepCopy()
|
||||
isomorphicEvent.Series = &eventsv1.EventSeries{Count: 2}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
eventsToRecord []eventsv1.Event
|
||||
expectedRecordedEvent eventsv1.Event
|
||||
}{
|
||||
{
|
||||
name: "record one Event",
|
||||
eventsToRecord: []eventsv1.Event{
|
||||
nonIsomorphicEvent,
|
||||
},
|
||||
expectedRecordedEvent: nonIsomorphicEvent,
|
||||
},
|
||||
{
|
||||
name: "record one Event followed by an isomorphic one",
|
||||
eventsToRecord: []eventsv1.Event{
|
||||
nonIsomorphicEvent,
|
||||
isomorphicEvent,
|
||||
},
|
||||
expectedRecordedEvent: isomorphicEvent,
|
||||
},
|
||||
{
|
||||
name: "record one isomorphic Event before the original",
|
||||
eventsToRecord: []eventsv1.Event{
|
||||
isomorphicEvent,
|
||||
nonIsomorphicEvent,
|
||||
},
|
||||
expectedRecordedEvent: isomorphicEvent,
|
||||
},
|
||||
{
|
||||
name: "record one isomorphic Event without one already existing",
|
||||
eventsToRecord: []eventsv1.Event{
|
||||
isomorphicEvent,
|
||||
},
|
||||
expectedRecordedEvent: isomorphicEvent,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
kubeClient := fake.NewSimpleClientset()
|
||||
eventSink := &EventSinkImpl{Interface: kubeClient.EventsV1()}
|
||||
|
||||
for _, ev := range tc.eventsToRecord {
|
||||
recordEvent(eventSink, &ev)
|
||||
}
|
||||
|
||||
recordedEvents, err := kubeClient.EventsV1().Events(metav1.NamespaceDefault).List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("expected to be able to list Events from fake client")
|
||||
}
|
||||
|
||||
if len(recordedEvents.Items) != 1 {
|
||||
t.Errorf("expected one Event to be recorded, found: %d", len(recordedEvents.Items))
|
||||
}
|
||||
|
||||
recordedEvent := recordedEvents.Items[0]
|
||||
if !reflect.DeepEqual(recordedEvent, tc.expectedRecordedEvent) {
|
||||
t.Errorf("expected to have recorded Event: %#+v, got: %#+v\n diff: %s", tc.expectedRecordedEvent, recordedEvent, diff.ObjectReflectDiff(tc.expectedRecordedEvent, recordedEvent))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package events
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -29,6 +30,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8sruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
fake "k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
ref "k8s.io/client-go/tools/reference"
|
||||
@@ -106,7 +108,7 @@ func TestEventSeriesf(t *testing.T) {
|
||||
nonIsomorphicEvent := expectedEvent.DeepCopy()
|
||||
nonIsomorphicEvent.Action = "stopped"
|
||||
|
||||
expectedEvent.Series = &eventsv1.EventSeries{Count: 1}
|
||||
expectedEvent.Series = &eventsv1.EventSeries{Count: 2}
|
||||
table := []struct {
|
||||
regarding k8sruntime.Object
|
||||
related k8sruntime.Object
|
||||
@@ -185,6 +187,44 @@ func TestEventSeriesf(t *testing.T) {
|
||||
close(stopCh)
|
||||
}
|
||||
|
||||
// TestEventSeriesWithEventSinkImplRace verifies that when Events are emitted to
|
||||
// an EventSink consecutively there is no data race. This test is meant to be
|
||||
// run with the `-race` option.
|
||||
func TestEventSeriesWithEventSinkImplRace(t *testing.T) {
|
||||
kubeClient := fake.NewSimpleClientset()
|
||||
|
||||
eventSink := &EventSinkImpl{Interface: kubeClient.EventsV1()}
|
||||
eventBroadcaster := NewBroadcaster(eventSink)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
eventBroadcaster.StartRecordingToSink(stopCh)
|
||||
|
||||
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, "test")
|
||||
|
||||
recorder.Eventf(&v1.ObjectReference{}, nil, v1.EventTypeNormal, "reason", "action", "", "")
|
||||
recorder.Eventf(&v1.ObjectReference{}, nil, v1.EventTypeNormal, "reason", "action", "", "")
|
||||
|
||||
err := wait.PollImmediate(100*time.Millisecond, 5*time.Second, func() (done bool, err error) {
|
||||
events, err := kubeClient.EventsV1().Events(metav1.NamespaceDefault).List(context.TODO(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(events.Items) != 1 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if events.Items[0].Series == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal("expected that 2 identical Eventf calls would result in the creation of an Event with a Serie")
|
||||
}
|
||||
}
|
||||
|
||||
func validateEvent(messagePrefix string, expectedUpdate bool, actualEvent *eventsv1.Event, expectedEvent *eventsv1.Event, t *testing.T) {
|
||||
recvEvent := *actualEvent
|
||||
|
||||
|
||||
@@ -344,6 +344,9 @@ func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations m
|
||||
event := recorder.makeEvent(ref, annotations, eventtype, reason, message)
|
||||
event.Source = recorder.source
|
||||
|
||||
event.ReportingInstance = recorder.source.Host
|
||||
event.ReportingController = recorder.source.Component
|
||||
|
||||
// NOTE: events should be a non-blocking operation, but we also need to not
|
||||
// put this in a goroutine, otherwise we'll race to write to a closed channel
|
||||
// when we go to shut down this broadcaster. Just drop events if we get overloaded,
|
||||
|
||||
@@ -178,11 +178,12 @@ func TestEventf(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -205,11 +206,12 @@ func TestEventf(t *testing.T) {
|
||||
UID: "bar",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
Reason: "Killed",
|
||||
Message: "some other verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Killed",
|
||||
Message: "some other verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -233,11 +235,12 @@ func TestEventf(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
@@ -261,11 +264,12 @@ func TestEventf(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -289,11 +293,12 @@ func TestEventf(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 3,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 3,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
@@ -317,11 +322,12 @@ func TestEventf(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -345,11 +351,12 @@ func TestEventf(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
@@ -697,11 +704,12 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -724,11 +732,12 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
UID: "bar",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
Reason: "Killed",
|
||||
Message: "some other verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Killed",
|
||||
Message: "some other verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -752,11 +761,12 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
@@ -780,11 +790,12 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -808,11 +819,12 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 3,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Started",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 3,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
@@ -836,11 +848,12 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
@@ -864,11 +877,12 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
Reason: "Stopped",
|
||||
Message: "some verbose message: 1",
|
||||
Source: v1.EventSource{Component: "eventTest"},
|
||||
ReportingController: "eventTest",
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
|
||||
@@ -115,6 +115,9 @@ func validateEvent(messagePrefix string, actualEvent *v1.Event, expectedEvent *v
|
||||
// Temp clear time stamps for comparison because actual values don't matter for comparison
|
||||
recvEvent.FirstTimestamp = expectedEvent.FirstTimestamp
|
||||
recvEvent.LastTimestamp = expectedEvent.LastTimestamp
|
||||
|
||||
recvEvent.ReportingController = expectedEvent.ReportingController
|
||||
|
||||
// Check that name has the right prefix.
|
||||
if n, en := recvEvent.Name, expectedEvent.Name; !strings.HasPrefix(n, en) {
|
||||
t.Errorf("%v - Name '%v' does not contain prefix '%v'", messagePrefix, n, en)
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
@@ -44,6 +45,7 @@ type Config struct {
|
||||
Organization []string
|
||||
AltNames AltNames
|
||||
Usages []x509.ExtKeyUsage
|
||||
NotBefore time.Time
|
||||
}
|
||||
|
||||
// AltNames contains the domain names and IP addresses that will be added
|
||||
@@ -57,14 +59,24 @@ type AltNames struct {
|
||||
// NewSelfSignedCACert creates a CA certificate
|
||||
func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) {
|
||||
now := time.Now()
|
||||
// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
|
||||
serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serial = new(big.Int).Add(serial, big.NewInt(1))
|
||||
notBefore := now.UTC()
|
||||
if !cfg.NotBefore.IsZero() {
|
||||
notBefore = cfg.NotBefore.UTC()
|
||||
}
|
||||
tmpl := x509.Certificate{
|
||||
SerialNumber: new(big.Int).SetInt64(0),
|
||||
SerialNumber: serial,
|
||||
Subject: pkix.Name{
|
||||
CommonName: cfg.CommonName,
|
||||
Organization: cfg.Organization,
|
||||
},
|
||||
DNSNames: []string{cfg.CommonName},
|
||||
NotBefore: now.UTC(),
|
||||
NotBefore: notBefore,
|
||||
NotAfter: now.Add(duration365d * 10).UTC(),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
BasicConstraintsValid: true,
|
||||
@@ -116,9 +128,14 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
|
||||
serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
serial = new(big.Int).Add(serial, big.NewInt(1))
|
||||
caTemplate := x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
SerialNumber: serial,
|
||||
Subject: pkix.Name{
|
||||
CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()),
|
||||
},
|
||||
@@ -144,9 +161,14 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// returns a uniform random value in [0, max-1), then add 1 to serial to make it a uniform random value in [1, max).
|
||||
serial, err = cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64-1))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
serial = new(big.Int).Add(serial, big.NewInt(1))
|
||||
template := x509.Certificate{
|
||||
SerialNumber: big.NewInt(2),
|
||||
SerialNumber: serial,
|
||||
Subject: pkix.Name{
|
||||
CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user