-
Couldn't load subscription status.
- Fork 2.8k
fix(aws): support aws_ca_bundle #5665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| /* | ||
| Copyright 2025 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 aws | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
| "time" | ||
|
|
||
| "github.com/aws/smithy-go/middleware" | ||
| smithyhttp "github.com/aws/smithy-go/transport/http" | ||
|
|
||
| extdnshttp "sigs.k8s.io/external-dns/pkg/http" | ||
|
||
| "sigs.k8s.io/external-dns/pkg/metrics" | ||
| ) | ||
|
|
||
| type requestMetrics struct { | ||
| StartTime time.Time | ||
| } | ||
|
|
||
| type requestMetricsKey struct{} | ||
|
|
||
| func getRequestMetric(ctx context.Context) requestMetrics { | ||
| requestMetrics, _ := middleware.GetStackValue(ctx, requestMetricsKey{}).(requestMetrics) | ||
| return requestMetrics | ||
| } | ||
|
|
||
| func setRequestMetric(ctx context.Context, requestMetrics requestMetrics) context.Context { | ||
| return middleware.WithStackValue(ctx, requestMetricsKey{}, requestMetrics) | ||
| } | ||
|
|
||
| var initializeTimedOperationMiddleware = middleware.InitializeMiddlewareFunc("timedOperation", func( | ||
| ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler, | ||
| ) (middleware.InitializeOutput, middleware.Metadata, error) { | ||
| requestMetrics := requestMetrics{} | ||
| requestMetrics.StartTime = time.Now() | ||
| ctx = setRequestMetric(ctx, requestMetrics) | ||
|
|
||
| return next.HandleInitialize(ctx, in) | ||
| }) | ||
|
|
||
| var extractAWSRequestParameters = middleware.DeserializeMiddlewareFunc("extractAWSRequestParameters", func( | ||
| ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler, | ||
| ) (middleware.DeserializeOutput, middleware.Metadata, error) { | ||
| // Call the next middleware first to get the response | ||
| out, metadata, err := next.HandleDeserialize(ctx, in) | ||
|
|
||
| requestMetrics := getRequestMetric(ctx) | ||
|
|
||
| if req, ok := in.Request.(*smithyhttp.Request); ok && req != nil { | ||
| extdnshttp.RequestDurationLabels.WithOptions( | ||
| metrics.WithLabel("scheme", req.URL.Scheme), | ||
| metrics.WithLabel("host", req.URL.Host), | ||
| metrics.WithLabel("path", metrics.PathProcessor(req.URL.Path)), | ||
| metrics.WithLabel("method", req.Method), | ||
| ) | ||
| } | ||
|
|
||
| // Try to access HTTP response and status code | ||
| if resp, ok := out.RawResponse.(*smithyhttp.Response); ok && resp != nil { | ||
| extdnshttp.RequestDurationLabels.WithOptions( | ||
| metrics.WithLabel("status", fmt.Sprintf("%d", resp.StatusCode)), | ||
| ) | ||
| } | ||
|
|
||
| extdnshttp.RequestDurationMetric.SetWithLabels(time.Since(requestMetrics.StartTime).Seconds(), extdnshttp.RequestDurationLabels) | ||
|
|
||
| return out, metadata, err | ||
| }) | ||
|
|
||
| func GetInstrumentationMiddlewares() []func(*middleware.Stack) error { | ||
| return []func(s *middleware.Stack) error{ | ||
| func(s *middleware.Stack) error { | ||
| if err := s.Initialize.Add(initializeTimedOperationMiddleware, middleware.Before); err != nil { | ||
|
||
| return fmt.Errorf("error adding timedOperationMiddleware: %w", err) | ||
| } | ||
|
|
||
| if err := s.Deserialize.Add(extractAWSRequestParameters, middleware.After); err != nil { | ||
| return fmt.Errorf("error adding extractAWSRequestParameters: %w", err) | ||
| } | ||
|
|
||
| return nil | ||
| }, | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| /* | ||
| Copyright 2025 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 aws | ||
|
|
||
| import ( | ||
| "context" | ||
| "net/http" | ||
| "net/url" | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/aws/smithy-go/middleware" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
|
|
||
| smithyhttp "github.com/aws/smithy-go/transport/http" | ||
| ) | ||
|
|
||
| func Test_GetInstrumentationMiddlewares(t *testing.T) { | ||
| t.Run("adds expected middlewares", func(t *testing.T) { | ||
| stack := middleware.NewStack("test-stack", nil) | ||
|
|
||
| for _, mw := range GetInstrumentationMiddlewares() { | ||
| err := mw(stack) | ||
| require.NoError(t, err) | ||
| } | ||
|
|
||
| // Check Initialize stage | ||
| timedOperationMiddleware, found := stack.Initialize.Get("timedOperation") | ||
| assert.True(t, found, "timedOperation middleware should be present in Initialize stage") | ||
| assert.NotNil(t, timedOperationMiddleware) | ||
|
|
||
| // Check Deserialize stage | ||
| extractAWSRequestParametersMiddleware, found := stack.Deserialize.Get("extractAWSRequestParameters") | ||
| assert.True(t, found, "extractAWSRequestParameters middleware should be present in Deserialize stage") | ||
| assert.NotNil(t, extractAWSRequestParametersMiddleware) | ||
| }) | ||
| } | ||
|
|
||
| type MockInitializeHandler struct { | ||
| CapturedContext context.Context | ||
| } | ||
|
|
||
| func (mock *MockInitializeHandler) HandleInitialize(ctx context.Context, in middleware.InitializeInput) (middleware.InitializeOutput, middleware.Metadata, error) { | ||
| mock.CapturedContext = ctx | ||
|
|
||
| return middleware.InitializeOutput{}, middleware.Metadata{}, nil | ||
| } | ||
|
|
||
| func Test_InitializedTimedOperationMiddleware(t *testing.T) { | ||
| testContext := context.Background() | ||
| mockInitializeHandler := &MockInitializeHandler{} | ||
|
|
||
| _, _, err := initializeTimedOperationMiddleware.HandleInitialize(testContext, middleware.InitializeInput{}, mockInitializeHandler) | ||
| require.NoError(t, err) | ||
|
|
||
| requestMetrics := middleware.GetStackValue(mockInitializeHandler.CapturedContext, requestMetricsKey{}).(requestMetrics) | ||
| assert.NotNil(t, requestMetrics.StartTime) | ||
| } | ||
|
|
||
| type MockDeserializeHandler struct { | ||
| } | ||
|
|
||
| func (mock *MockDeserializeHandler) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput) (middleware.DeserializeOutput, middleware.Metadata, error) { | ||
| return middleware.DeserializeOutput{}, middleware.Metadata{}, nil | ||
| } | ||
|
|
||
| func Test_ExtractAWSRequestParameters(t *testing.T) { | ||
| testContext := context.Background() | ||
| middleware.WithStackValue(testContext, requestMetricsKey{}, requestMetrics{StartTime: time.Now()}) | ||
|
|
||
| mockDeserializeHandler := &MockDeserializeHandler{} | ||
|
|
||
| deserializeInput := middleware.DeserializeInput{ | ||
| Request: &smithyhttp.Request{ | ||
| Request: &http.Request{ | ||
| Method: http.MethodGet, | ||
| URL: &url.URL{ | ||
| Host: "example.com", | ||
| Scheme: "HTTPS", | ||
| Path: "/testPath", | ||
| }, | ||
| }, | ||
| }, | ||
| } | ||
| _, _, err := extractAWSRequestParameters.HandleDeserialize(testContext, deserializeInput, mockDeserializeHandler) | ||
| require.NoError(t, err) | ||
| } |

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Configuring metrics per provider not a great idea. Please avoid that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you, I've been struggling to find a better implementation. Any insights would be appreciated.