Merge pull request #118542 from cchapla/crd_webhook_metrics_updates

Updating names from webhookconversion to conversionwebhook for apiserver
This commit is contained in:
Kubernetes Prow Robot 2023-06-16 10:34:19 -07:00 committed by GitHub
commit 1ff1a26426
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 92 deletions

View File

@ -59,7 +59,7 @@ func (c *converterMetricFactory) addMetrics(crdName string, converter crConverte
if !exists { if !exists {
metric = metrics.NewHistogramVec( metric = metrics.NewHistogramVec(
&metrics.HistogramOpts{ &metrics.HistogramOpts{
Name: "apiserver_crd_webhook_conversion_duration_seconds", Name: "apiserver_crd_conversion_webhook_duration_seconds",
Help: "CRD webhook conversion duration in seconds", Help: "CRD webhook conversion duration in seconds",
Buckets: latencyBuckets, Buckets: latencyBuckets,
StabilityLevel: metrics.ALPHA, StabilityLevel: metrics.ALPHA,
@ -88,42 +88,42 @@ func (m *converterMetric) Convert(in runtime.Object, targetGV schema.GroupVersio
return obj, err return obj, err
} }
type WebhookConversionErrorType string type ConversionWebhookErrorType string
const ( const (
WebhookConversionCallFailure WebhookConversionErrorType = "webhook_conversion_call_failure" ConversionWebhookCallFailure ConversionWebhookErrorType = "conversion_webhook_call_failure"
WebhookConversionMalformedResponseFailure WebhookConversionErrorType = "webhook_conversion_malformed_response_failure" ConversionWebhookMalformedResponseFailure ConversionWebhookErrorType = "conversion_webhook_malformed_response_failure"
WebhookConversionPartialResponseFailure WebhookConversionErrorType = "webhook_conversion_partial_response_failure" ConversionWebhookPartialResponseFailure ConversionWebhookErrorType = "conversion_webhook_partial_response_failure"
WebhookConversionInvalidConvertedObjectFailure WebhookConversionErrorType = "webhook_conversion_invalid_converted_object_failure" ConversionWebhookInvalidConvertedObjectFailure ConversionWebhookErrorType = "conversion_webhook_invalid_converted_object_failure"
WebhookConversionNoObjectsReturnedFailure WebhookConversionErrorType = "webhook_conversion_no_objects_returned_failure" ConversionWebhookNoObjectsReturnedFailure ConversionWebhookErrorType = "conversion_webhook_no_objects_returned_failure"
) )
var ( var (
Metrics = newWebhookConversionMetrics() Metrics = newConversionWebhookMetrics()
namespace = "apiserver" namespace = "apiserver"
) )
// WebhookConversionMetrics instruments webhook conversion with prometheus metrics. // ConversionWebhookMetrics instruments webhook conversion with prometheus metrics.
type WebhookConversionMetrics struct { type ConversionWebhookMetrics struct {
webhookConversionRequest *metrics.CounterVec conversionWebhookRequest *metrics.CounterVec
webhookConversionLatency *metrics.HistogramVec conversionWebhookLatency *metrics.HistogramVec
} }
func newWebhookConversionMetrics() *WebhookConversionMetrics { func newConversionWebhookMetrics() *ConversionWebhookMetrics {
webhookConversionRequest := metrics.NewCounterVec( conversionWebhookRequest := metrics.NewCounterVec(
&metrics.CounterOpts{ &metrics.CounterOpts{
Name: "webhook_conversion_request_total", Name: "conversion_webhook_request_total",
Namespace: namespace, Namespace: namespace,
Help: "Counter for webhook conversion requests with success/failure and failure error type", Help: "Counter for conversion webhook requests with success/failure and failure error type",
StabilityLevel: metrics.ALPHA, StabilityLevel: metrics.ALPHA,
}, },
[]string{"result", "failure_type"}) []string{"result", "failure_type"})
webhookConversionLatency := metrics.NewHistogramVec( conversionWebhookLatency := metrics.NewHistogramVec(
&metrics.HistogramOpts{ &metrics.HistogramOpts{
Name: "webhook_conversion_duration_seconds", Name: "conversion_webhook_duration_seconds",
Namespace: namespace, Namespace: namespace,
Help: "Webhook conversion request latency", Help: "Conversion webhook request latency",
// Various buckets from 5 ms to 60 seconds // Various buckets from 5 ms to 60 seconds
Buckets: []float64{0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 30, 45, 60}, Buckets: []float64{0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 30, 45, 60},
StabilityLevel: metrics.ALPHA, StabilityLevel: metrics.ALPHA,
@ -131,28 +131,28 @@ func newWebhookConversionMetrics() *WebhookConversionMetrics {
[]string{"result", "failure_type"}, []string{"result", "failure_type"},
) )
legacyregistry.MustRegister(webhookConversionRequest) legacyregistry.MustRegister(conversionWebhookRequest)
legacyregistry.MustRegister(webhookConversionLatency) legacyregistry.MustRegister(conversionWebhookLatency)
return &WebhookConversionMetrics{webhookConversionRequest: webhookConversionRequest, webhookConversionLatency: webhookConversionLatency} return &ConversionWebhookMetrics{conversionWebhookRequest: conversionWebhookRequest, conversionWebhookLatency: conversionWebhookLatency}
} }
// Observe successful request // Observe successful request
func (m *WebhookConversionMetrics) ObserveWebhookConversionSuccess(ctx context.Context, elapsed time.Duration) { func (m *ConversionWebhookMetrics) ObserveConversionWebhookSuccess(ctx context.Context, elapsed time.Duration) {
result := "success" result := "success"
m.webhookConversionRequest.WithContext(ctx).WithLabelValues(result, "").Inc() m.conversionWebhookRequest.WithContext(ctx).WithLabelValues(result, "").Inc()
m.observe(ctx, elapsed, result, "") m.observe(ctx, elapsed, result, "")
} }
// Observe failure with failure type // Observe failure with failure type
func (m *WebhookConversionMetrics) ObserveWebhookConversionFailure(ctx context.Context, elapsed time.Duration, errorType WebhookConversionErrorType) { func (m *ConversionWebhookMetrics) ObserveConversionWebhookFailure(ctx context.Context, elapsed time.Duration, errorType ConversionWebhookErrorType) {
result := "failure" result := "failure"
m.webhookConversionRequest.WithContext(ctx).WithLabelValues(result, string(errorType)).Inc() m.conversionWebhookRequest.WithContext(ctx).WithLabelValues(result, string(errorType)).Inc()
m.observe(ctx, elapsed, result, errorType) m.observe(ctx, elapsed, result, errorType)
} }
// Observe latency // Observe latency
func (m *WebhookConversionMetrics) observe(ctx context.Context, elapsed time.Duration, result string, errorType WebhookConversionErrorType) { func (m *ConversionWebhookMetrics) observe(ctx context.Context, elapsed time.Duration, result string, errorType ConversionWebhookErrorType) {
elapsedSeconds := elapsed.Seconds() elapsedSeconds := elapsed.Seconds()
m.webhookConversionLatency.WithContext(ctx).WithLabelValues(result, string(errorType)).Observe(elapsedSeconds) m.conversionWebhookLatency.WithContext(ctx).WithLabelValues(result, string(errorType)).Observe(elapsedSeconds)
} }

View File

@ -26,10 +26,10 @@ import (
"k8s.io/component-base/metrics/testutil" "k8s.io/component-base/metrics/testutil"
) )
func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T) { func TestConversionWebhookMetrics_ObserveConversionWebhookSuccess(t *testing.T) {
type fields struct { type fields struct {
webhookConversionRequest *metrics.CounterVec conversionWebhookRequest *metrics.CounterVec
webhookConversionLatency *metrics.HistogramVec conversionWebhookLatency *metrics.HistogramVec
} }
type args struct { type args struct {
elapsed time.Duration elapsed time.Duration
@ -44,8 +44,8 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T)
{ {
name: "test_conversion_success", name: "test_conversion_success",
fields: fields{ fields: fields{
webhookConversionRequest: Metrics.webhookConversionRequest, conversionWebhookRequest: Metrics.conversionWebhookRequest,
webhookConversionLatency: Metrics.webhookConversionLatency, conversionWebhookLatency: Metrics.conversionWebhookLatency,
}, },
args: args{ args: args{
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
@ -58,8 +58,8 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T)
}, { }, {
name: "test_conversion_success_2", name: "test_conversion_success_2",
fields: fields{ fields: fields{
webhookConversionRequest: Metrics.webhookConversionRequest, conversionWebhookRequest: Metrics.conversionWebhookRequest,
webhookConversionLatency: Metrics.webhookConversionLatency, conversionWebhookLatency: Metrics.conversionWebhookLatency,
}, },
args: args{ args: args{
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
@ -73,25 +73,25 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionSuccess(t *testing.T)
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
m := &WebhookConversionMetrics{ m := &ConversionWebhookMetrics{
webhookConversionRequest: tt.fields.webhookConversionRequest, conversionWebhookRequest: tt.fields.conversionWebhookRequest,
webhookConversionLatency: tt.fields.webhookConversionLatency, conversionWebhookLatency: tt.fields.conversionWebhookLatency,
} }
m.ObserveWebhookConversionSuccess(context.TODO(), tt.args.elapsed) m.ObserveConversionWebhookSuccess(context.TODO(), tt.args.elapsed)
testutil.AssertVectorCount(t, fmt.Sprintf("%s_webhook_conversion_request_total", namespace), tt.wantLabels, tt.expectedRequestValue) testutil.AssertVectorCount(t, fmt.Sprintf("%s_conversion_webhook_request_total", namespace), tt.wantLabels, tt.expectedRequestValue)
testutil.AssertHistogramTotalCount(t, fmt.Sprintf("%s_webhook_conversion_duration_seconds", namespace), tt.wantLabels, tt.expectedRequestValue) testutil.AssertHistogramTotalCount(t, fmt.Sprintf("%s_conversion_webhook_duration_seconds", namespace), tt.wantLabels, tt.expectedRequestValue)
}) })
} }
} }
func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T) { func TestConversionWebhookMetrics_ObserveConversionWebhookFailure(t *testing.T) {
type fields struct { type fields struct {
webhookConversionRequest *metrics.CounterVec conversionWebhookRequest *metrics.CounterVec
webhookConversionLatency *metrics.HistogramVec conversionWebhookLatency *metrics.HistogramVec
} }
type args struct { type args struct {
elapsed time.Duration elapsed time.Duration
errorType WebhookConversionErrorType errorType ConversionWebhookErrorType
} }
tests := []struct { tests := []struct {
name string name string
@ -104,80 +104,80 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
{ {
name: "test_conversion_failure", name: "test_conversion_failure",
fields: fields{ fields: fields{
webhookConversionRequest: Metrics.webhookConversionRequest, conversionWebhookRequest: Metrics.conversionWebhookRequest,
webhookConversionLatency: Metrics.webhookConversionLatency, conversionWebhookLatency: Metrics.conversionWebhookLatency,
}, },
args: args{ args: args{
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionCallFailure, errorType: ConversionWebhookCallFailure,
}, },
wantLabels: map[string]string{ wantLabels: map[string]string{
"result": "failure", "result": "failure",
"failure_type": string(WebhookConversionCallFailure), "failure_type": string(ConversionWebhookCallFailure),
}, },
expectedRequestValue: 1, expectedRequestValue: 1,
expectedLatencyCount: 1, expectedLatencyCount: 1,
}, { }, {
name: "test_conversion_failure_2", name: "test_conversion_failure_2",
fields: fields{ fields: fields{
webhookConversionRequest: Metrics.webhookConversionRequest, conversionWebhookRequest: Metrics.conversionWebhookRequest,
webhookConversionLatency: Metrics.webhookConversionLatency, conversionWebhookLatency: Metrics.conversionWebhookLatency,
}, },
args: args{ args: args{
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionMalformedResponseFailure, errorType: ConversionWebhookMalformedResponseFailure,
}, },
wantLabels: map[string]string{ wantLabels: map[string]string{
"result": "failure", "result": "failure",
"failure_type": string(WebhookConversionMalformedResponseFailure), "failure_type": string(ConversionWebhookMalformedResponseFailure),
}, },
expectedRequestValue: 1, expectedRequestValue: 1,
expectedLatencyCount: 2, expectedLatencyCount: 2,
}, { }, {
name: "test_conversion_failure_3", name: "test_conversion_failure_3",
fields: fields{ fields: fields{
webhookConversionRequest: Metrics.webhookConversionRequest, conversionWebhookRequest: Metrics.conversionWebhookRequest,
webhookConversionLatency: Metrics.webhookConversionLatency, conversionWebhookLatency: Metrics.conversionWebhookLatency,
}, },
args: args{ args: args{
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionPartialResponseFailure, errorType: ConversionWebhookPartialResponseFailure,
}, },
wantLabels: map[string]string{ wantLabels: map[string]string{
"result": "failure", "result": "failure",
"failure_type": string(WebhookConversionPartialResponseFailure), "failure_type": string(ConversionWebhookPartialResponseFailure),
}, },
expectedRequestValue: 1, expectedRequestValue: 1,
expectedLatencyCount: 3, expectedLatencyCount: 3,
}, { }, {
name: "test_conversion_failure_4", name: "test_conversion_failure_4",
fields: fields{ fields: fields{
webhookConversionRequest: Metrics.webhookConversionRequest, conversionWebhookRequest: Metrics.conversionWebhookRequest,
webhookConversionLatency: Metrics.webhookConversionLatency, conversionWebhookLatency: Metrics.conversionWebhookLatency,
}, },
args: args{ args: args{
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionInvalidConvertedObjectFailure, errorType: ConversionWebhookInvalidConvertedObjectFailure,
}, },
wantLabels: map[string]string{ wantLabels: map[string]string{
"result": "failure", "result": "failure",
"failure_type": string(WebhookConversionInvalidConvertedObjectFailure), "failure_type": string(ConversionWebhookInvalidConvertedObjectFailure),
}, },
expectedRequestValue: 1, expectedRequestValue: 1,
expectedLatencyCount: 4, expectedLatencyCount: 4,
}, { }, {
name: "test_conversion_failure_5", name: "test_conversion_failure_5",
fields: fields{ fields: fields{
webhookConversionRequest: Metrics.webhookConversionRequest, conversionWebhookRequest: Metrics.conversionWebhookRequest,
webhookConversionLatency: Metrics.webhookConversionLatency, conversionWebhookLatency: Metrics.conversionWebhookLatency,
}, },
args: args{ args: args{
elapsed: 2 * time.Second, elapsed: 2 * time.Second,
errorType: WebhookConversionNoObjectsReturnedFailure, errorType: ConversionWebhookNoObjectsReturnedFailure,
}, },
wantLabels: map[string]string{ wantLabels: map[string]string{
"result": "failure", "result": "failure",
"failure_type": string(WebhookConversionNoObjectsReturnedFailure), "failure_type": string(ConversionWebhookNoObjectsReturnedFailure),
}, },
expectedRequestValue: 1, expectedRequestValue: 1,
expectedLatencyCount: 5, expectedLatencyCount: 5,
@ -185,13 +185,13 @@ func TestWebhookConversionMetrics_ObserveWebhookConversionFailure(t *testing.T)
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
m := &WebhookConversionMetrics{ m := &ConversionWebhookMetrics{
webhookConversionRequest: tt.fields.webhookConversionRequest, conversionWebhookRequest: tt.fields.conversionWebhookRequest,
webhookConversionLatency: tt.fields.webhookConversionLatency, conversionWebhookLatency: tt.fields.conversionWebhookLatency,
} }
m.ObserveWebhookConversionFailure(context.TODO(), tt.args.elapsed, tt.args.errorType) m.ObserveConversionWebhookFailure(context.TODO(), tt.args.elapsed, tt.args.errorType)
testutil.AssertVectorCount(t, fmt.Sprintf("%s_webhook_conversion_request_total", namespace), tt.wantLabels, tt.expectedRequestValue) testutil.AssertVectorCount(t, fmt.Sprintf("%s_conversion_webhook_request_total", namespace), tt.wantLabels, tt.expectedRequestValue)
testutil.AssertHistogramTotalCount(t, fmt.Sprintf("%s_webhook_conversion_duration_seconds", namespace), tt.wantLabels, tt.expectedRequestValue) testutil.AssertHistogramTotalCount(t, fmt.Sprintf("%s_conversion_webhook_duration_seconds", namespace), tt.wantLabels, tt.expectedRequestValue)
}) })
} }
} }

View File

@ -250,7 +250,7 @@ func (c *webhookConverter) Convert(in runtime.Object, toGV schema.GroupVersion)
objCount := len(objectsToConvert) objCount := len(objectsToConvert)
if objCount == 0 { if objCount == 0 {
Metrics.ObserveWebhookConversionSuccess(ctx, time.Since(t)) Metrics.ObserveConversionWebhookSuccess(ctx, time.Since(t))
// no objects needed conversion // no objects needed conversion
if !isList { if !isList {
// for a single item, return as-is // for a single item, return as-is
@ -276,19 +276,19 @@ func (c *webhookConverter) Convert(in runtime.Object, toGV schema.GroupVersion)
r := c.restClient.Post().Body(request).Do(ctx) r := c.restClient.Post().Body(request).Do(ctx)
if err := r.Into(response); err != nil { if err := r.Into(response); err != nil {
// TODO: Return a webhook specific error to be able to convert it to meta.Status // TODO: Return a webhook specific error to be able to convert it to meta.Status
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionCallFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookCallFailure)
return nil, fmt.Errorf("conversion webhook for %v failed: %v", in.GetObjectKind().GroupVersionKind(), err) return nil, fmt.Errorf("conversion webhook for %v failed: %v", in.GetObjectKind().GroupVersionKind(), err)
} }
span.AddEvent("Request completed") span.AddEvent("Request completed")
convertedObjects, err := getConvertedObjectsFromResponse(requestUID, response) convertedObjects, err := getConvertedObjectsFromResponse(requestUID, response)
if err != nil { if err != nil {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionMalformedResponseFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookMalformedResponseFailure)
return nil, fmt.Errorf("conversion webhook for %v failed: %v", in.GetObjectKind().GroupVersionKind(), err) return nil, fmt.Errorf("conversion webhook for %v failed: %v", in.GetObjectKind().GroupVersionKind(), err)
} }
if len(convertedObjects) != len(objectsToConvert) { if len(convertedObjects) != len(objectsToConvert) {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionPartialResponseFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookPartialResponseFailure)
return nil, fmt.Errorf("conversion webhook for %v returned %d objects, expected %d", in.GetObjectKind().GroupVersionKind(), len(convertedObjects), len(objectsToConvert)) return nil, fmt.Errorf("conversion webhook for %v returned %d objects, expected %d", in.GetObjectKind().GroupVersionKind(), len(convertedObjects), len(objectsToConvert))
} }
@ -306,78 +306,78 @@ func (c *webhookConverter) Convert(in runtime.Object, toGV schema.GroupVersion)
} }
converted, err := getRawExtensionObject(convertedObjects[convertedIndex]) converted, err := getRawExtensionObject(convertedObjects[convertedIndex])
if err != nil { if err != nil {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: %v", in.GetObjectKind().GroupVersionKind(), convertedIndex, err) return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: %v", in.GetObjectKind().GroupVersionKind(), convertedIndex, err)
} }
convertedIndex++
if expected, got := toGV, converted.GetObjectKind().GroupVersionKind().GroupVersion(); expected != got { if expected, got := toGV, converted.GetObjectKind().GroupVersionKind().GroupVersion(); expected != got {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: invalid groupVersion (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), convertedIndex, expected, got) return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: invalid groupVersion (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), convertedIndex, expected, got)
} }
if expected, got := original.GetObjectKind().GroupVersionKind().Kind, converted.GetObjectKind().GroupVersionKind().Kind; expected != got { if expected, got := original.GetObjectKind().GroupVersionKind().Kind, converted.GetObjectKind().GroupVersionKind().Kind; expected != got {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: invalid kind (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), convertedIndex, expected, got) return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: invalid kind (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), convertedIndex, expected, got)
} }
unstructConverted, ok := converted.(*unstructured.Unstructured) unstructConverted, ok := converted.(*unstructured.Unstructured)
if !ok { if !ok {
// this should not happened // this should not happened
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: invalid type, expected=Unstructured, got=%T", in.GetObjectKind().GroupVersionKind(), convertedIndex, converted) return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: invalid type, expected=Unstructured, got=%T", in.GetObjectKind().GroupVersionKind(), convertedIndex, converted)
} }
if err := validateConvertedObject(original, unstructConverted); err != nil { if err := validateConvertedObject(original, unstructConverted); err != nil {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: %v", in.GetObjectKind().GroupVersionKind(), convertedIndex, err) return nil, fmt.Errorf("conversion webhook for %v returned invalid converted object at index %v: %v", in.GetObjectKind().GroupVersionKind(), convertedIndex, err)
} }
if err := restoreObjectMeta(original, unstructConverted); err != nil { if err := restoreObjectMeta(original, unstructConverted); err != nil {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid metadata in object at index %v: %v", in.GetObjectKind().GroupVersionKind(), convertedIndex, err) return nil, fmt.Errorf("conversion webhook for %v returned invalid metadata in object at index %v: %v", in.GetObjectKind().GroupVersionKind(), convertedIndex, err)
} }
convertedIndex++
convertedList.Items[i] = *unstructConverted convertedList.Items[i] = *unstructConverted
} }
convertedList.SetAPIVersion(toGV.String()) convertedList.SetAPIVersion(toGV.String())
Metrics.ObserveWebhookConversionSuccess(ctx, time.Since(t)) Metrics.ObserveConversionWebhookSuccess(ctx, time.Since(t))
return convertedList, nil return convertedList, nil
} }
if len(convertedObjects) != 1 { if len(convertedObjects) != 1 {
// This should not happened // This should not happened
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionNoObjectsReturnedFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookNoObjectsReturnedFailure)
return nil, fmt.Errorf("conversion webhook for %v failed, no objects returned", in.GetObjectKind()) return nil, fmt.Errorf("conversion webhook for %v failed, no objects returned", in.GetObjectKind())
} }
converted, err := getRawExtensionObject(convertedObjects[0]) converted, err := getRawExtensionObject(convertedObjects[0])
if err != nil { if err != nil {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, err return nil, err
} }
if e, a := toGV, converted.GetObjectKind().GroupVersionKind().GroupVersion(); e != a { if e, a := toGV, converted.GetObjectKind().GroupVersionKind().GroupVersion(); e != a {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid object at index 0: invalid groupVersion (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), e, a) return nil, fmt.Errorf("conversion webhook for %v returned invalid object at index 0: invalid groupVersion (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), e, a)
} }
if e, a := in.GetObjectKind().GroupVersionKind().Kind, converted.GetObjectKind().GroupVersionKind().Kind; e != a { if e, a := in.GetObjectKind().GroupVersionKind().Kind, converted.GetObjectKind().GroupVersionKind().Kind; e != a {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid object at index 0: invalid kind (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), e, a) return nil, fmt.Errorf("conversion webhook for %v returned invalid object at index 0: invalid kind (expected %v, received %v)", in.GetObjectKind().GroupVersionKind(), e, a)
} }
unstructConverted, ok := converted.(*unstructured.Unstructured) unstructConverted, ok := converted.(*unstructured.Unstructured)
if !ok { if !ok {
// this should not happened // this should not happened
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v failed, unexpected type %T at index 0", in.GetObjectKind().GroupVersionKind(), converted) return nil, fmt.Errorf("conversion webhook for %v failed, unexpected type %T at index 0", in.GetObjectKind().GroupVersionKind(), converted)
} }
unstructIn, ok := in.(*unstructured.Unstructured) unstructIn, ok := in.(*unstructured.Unstructured)
if !ok { if !ok {
// this should not happened // this should not happened
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v failed unexpected input type %T", in.GetObjectKind().GroupVersionKind(), in) return nil, fmt.Errorf("conversion webhook for %v failed unexpected input type %T", in.GetObjectKind().GroupVersionKind(), in)
} }
if err := validateConvertedObject(unstructIn, unstructConverted); err != nil { if err := validateConvertedObject(unstructIn, unstructConverted); err != nil {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid object: %v", in.GetObjectKind().GroupVersionKind(), err) return nil, fmt.Errorf("conversion webhook for %v returned invalid object: %v", in.GetObjectKind().GroupVersionKind(), err)
} }
if err := restoreObjectMeta(unstructIn, unstructConverted); err != nil { if err := restoreObjectMeta(unstructIn, unstructConverted); err != nil {
Metrics.ObserveWebhookConversionFailure(ctx, time.Since(t), WebhookConversionInvalidConvertedObjectFailure) Metrics.ObserveConversionWebhookFailure(ctx, time.Since(t), ConversionWebhookInvalidConvertedObjectFailure)
return nil, fmt.Errorf("conversion webhook for %v returned invalid metadata: %v", in.GetObjectKind().GroupVersionKind(), err) return nil, fmt.Errorf("conversion webhook for %v returned invalid metadata: %v", in.GetObjectKind().GroupVersionKind(), err)
} }
Metrics.ObserveWebhookConversionSuccess(ctx, time.Since(t)) Metrics.ObserveConversionWebhookSuccess(ctx, time.Since(t))
return converted, nil return converted, nil
} }