Skip to content
This repository was archived by the owner on Aug 5, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/krateoplatformops/plumbing v1.7.3
github.com/krateoplatformops/unstructured-runtime v1.1.0
github.com/stretchr/testify v1.11.1
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0
go.opentelemetry.io/otel v1.44.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0
go.opentelemetry.io/otel/metric v1.44.0
Expand Down Expand Up @@ -46,6 +47,7 @@ require (
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-errors/errors v1.5.1 // indirect
Expand Down
23 changes: 18 additions & 5 deletions internal/chartinspector/chartinspector.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package chartinspector

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"

"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)

type Resource struct {
Expand All @@ -31,7 +34,7 @@ type Parameters struct {
}

type ChartInspectorInterface interface {
Resources(Parameters) ([]Resource, error)
Resources(ctx context.Context, params Parameters) ([]Resource, error)
}

type ChartInspector struct {
Expand All @@ -42,8 +45,16 @@ type ChartInspector struct {
var _ ChartInspectorInterface = &ChartInspector{}

func NewChartInspector(server string) ChartInspector {
httpcli := http.DefaultClient
httpcli.Timeout = 60 * time.Second
// Wrap the default transport with otelhttp so the outbound request to
// chart-inspector injects the W3C traceparent header (continuing the active
// reconcile span) and emits a client span. When no global tracer provider /
// propagator is registered this transport is a cheap pass-through, so the
// off-path stays byte-identical; the unstructured-runtime installs the W3C
// propagator unconditionally, so the active reconcile span always propagates.
httpcli := &http.Client{
Timeout: 60 * time.Second,
Transport: otelhttp.NewTransport(http.DefaultTransport),
}

return ChartInspector{server: server, httpClient: httpcli}
}
Expand Down Expand Up @@ -78,15 +89,17 @@ func (c *ChartInspector) Validate(params Parameters) error {
return nil
}

func (c *ChartInspector) Resources(params Parameters) ([]Resource, error) {
func (c *ChartInspector) Resources(ctx context.Context, params Parameters) ([]Resource, error) {
if err := c.Validate(params); err != nil {
return nil, fmt.Errorf("validating parameters: %w", err)
}
u, err := url.JoinPath(c.server, "/resources")
if err != nil {
return nil, fmt.Errorf("joining server url: %w", err)
}
req, err := http.NewRequest(http.MethodGet, u, nil)
// Use the reconcile ctx so the otelhttp transport injects the traceparent
// header from the active span, linking the chart-inspector server span.
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
if err != nil {
return nil, fmt.Errorf("creating request: %w", err)
}
Expand Down
16 changes: 12 additions & 4 deletions internal/chartinspector/chartinspector_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package chartinspector

import (
"context"
"net/http"
"net/http/httptest"
"net/url"
"testing"

"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)

func TestNewChartInspector(t *testing.T) {
Expand All @@ -14,8 +17,13 @@ func TestNewChartInspector(t *testing.T) {
if inspector.server != server {
t.Errorf("expected server %s, got %s", server, inspector.server)
}
if inspector.httpClient != http.DefaultClient {
t.Error("expected default http client")
if inspector.httpClient == nil {
t.Error("expected non-nil http client")
}
// The client must carry an otelhttp transport so the outbound request to
// chart-inspector injects the W3C traceparent header from the active span.
if _, ok := inspector.httpClient.Transport.(*otelhttp.Transport); !ok {
t.Errorf("expected otelhttp transport, got %T", inspector.httpClient.Transport)
}
}

Expand Down Expand Up @@ -206,7 +214,7 @@ func TestChartInspector_Resources(t *testing.T) {
defer server.Close()

inspector := NewChartInspector(server.URL)
resources, err := inspector.Resources(tt.params)
resources, err := inspector.Resources(context.Background(), tt.params)

if tt.wantErr {
if err == nil {
Expand Down Expand Up @@ -297,7 +305,7 @@ func TestChartInspector_ResourcesQueryParameters(t *testing.T) {
CompositionGroup: "custom.group",
}

_, err := inspector.Resources(params)
_, err := inspector.Resources(context.Background(), params)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/composition/composition.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func (h *handler) Observe(ctx context.Context, mg *unstructured.Unstructured) (c
// Get Resources and generate RBAC
generated, err := rbgen.
WithBaseName(releaseName).
Generate(rbacgen.Parameters{
Generate(ctx, rbacgen.Parameters{
CompositionName: mg.GetName(),
CompositionNamespace: mg.GetNamespace(),
CompositionGVR: compositionGVR,
Expand Down Expand Up @@ -451,7 +451,7 @@ func (h *handler) Create(ctx context.Context, mg *unstructured.Unstructured) err
// Get Resources and generate RBAC
generated, err := rbgen.
WithBaseName(releaseName).
Generate(rbacgen.Parameters{
Generate(ctx, rbacgen.Parameters{
CompositionName: mg.GetName(),
CompositionNamespace: mg.GetNamespace(),
CompositionGVR: compositionGVR,
Expand Down Expand Up @@ -780,7 +780,7 @@ func (h *handler) Delete(ctx context.Context, mg *unstructured.Unstructured) err
// Get Resources and generate RBAC
generated, err := rbgen.
WithBaseName(compositionMeta.GetReleaseName(mg)).
Generate(rbacgen.Parameters{
Generate(ctx, rbacgen.Parameters{
CompositionName: mg.GetName(),
CompositionNamespace: mg.GetNamespace(),
CompositionGVR: compositionGVR,
Expand Down
10 changes: 4 additions & 6 deletions internal/metrics/wrappers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ type metricChartInspector struct {
wrapped chartinspector.ChartInspectorInterface
}

func (m *metricChartInspector) Resources(params chartinspector.Parameters) ([]chartinspector.Resource, error) {
ctx := context.Background() // Use background context for metrics
func (m *metricChartInspector) Resources(ctx context.Context, params chartinspector.Parameters) ([]chartinspector.Resource, error) {
timer := NewTimer()

resources, err := m.wrapped.Resources(params)
resources, err := m.wrapped.Resources(ctx, params)

metrics := GetInstance()
if metrics != nil {
Expand Down Expand Up @@ -54,11 +53,10 @@ func (m *metricRBACGen) WithBaseName(name string) rbacgen.RBACGenInterface {
return m
}

func (m *metricRBACGen) Generate(params rbacgen.Parameters) (*rbac.RBAC, error) {
ctx := context.Background() // Use background context for metrics
func (m *metricRBACGen) Generate(ctx context.Context, params rbacgen.Parameters) (*rbac.RBAC, error) {
timer := NewTimer()

result, err := m.wrapped.Generate(params)
result, err := m.wrapped.Generate(ctx, params)

metrics := GetInstance()
if metrics != nil {
Expand Down
7 changes: 4 additions & 3 deletions internal/rbacgen/rbacgen.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rbacgen

import (
"context"
"fmt"

corev1 "k8s.io/api/core/v1"
Expand All @@ -14,7 +15,7 @@ import (
)

type RBACGenInterface interface {
Generate(Parameters) (*rbac.RBAC, error)
Generate(ctx context.Context, params Parameters) (*rbac.RBAC, error)
WithBaseName(string) RBACGenInterface
}

Expand Down Expand Up @@ -49,8 +50,8 @@ func (r *RBACGen) WithBaseName(baseName string) RBACGenInterface {
return r
}

func (r *RBACGen) Generate(params Parameters) (*rbac.RBAC, error) {
resources, err := r.chartInspector.Resources(chartinspector.Parameters{
func (r *RBACGen) Generate(ctx context.Context, params Parameters) (*rbac.RBAC, error) {
resources, err := r.chartInspector.Resources(ctx, chartinspector.Parameters{
CompositionName: params.CompositionName,
CompositionNamespace: params.CompositionNamespace,
CompositionGroup: params.CompositionGVR.Group,
Expand Down
29 changes: 15 additions & 14 deletions internal/rbacgen/rbacgen_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rbacgen

import (
"context"
"errors"
"testing"

Expand All @@ -14,8 +15,8 @@ type MockChartInspector struct {
mock.Mock
}

func (m *MockChartInspector) Resources(params chartinspector.Parameters) ([]chartinspector.Resource, error) {
args := m.Called(params)
func (m *MockChartInspector) Resources(ctx context.Context, params chartinspector.Parameters) ([]chartinspector.Resource, error) {
args := m.Called(ctx, params)
if args.Get(0) == nil {
return nil, args.Error(1)
}
Expand Down Expand Up @@ -80,9 +81,9 @@ func TestRBACGen_Generate(t *testing.T) {
CompositionDefinitionResource: params.CompositionDefintionGVR.Resource,
}

mockInspector.On("Resources", expectedParams).Return(mockResources, nil)
mockInspector.On("Resources", mock.Anything, expectedParams).Return(mockResources, nil)

policy, err := rbacGen.Generate(params)
policy, err := rbacGen.Generate(context.Background(), params)

assert.NoError(t, err)
assert.NotNil(t, policy)
Expand Down Expand Up @@ -124,9 +125,9 @@ func TestRBACGen_Generate(t *testing.T) {
CompositionResource: params.CompositionGVR.Resource,
}

mockInspector.On("Resources", expectedParams).Return(mockResources, nil)
mockInspector.On("Resources", mock.Anything, expectedParams).Return(mockResources, nil)

policy, err := rbacGen.Generate(params)
policy, err := rbacGen.Generate(context.Background(), params)

assert.NoError(t, err)
assert.NotNil(t, policy)
Expand Down Expand Up @@ -157,9 +158,9 @@ func TestRBACGen_Generate(t *testing.T) {
CompositionNamespace: params.CompositionNamespace,
}

mockInspector.On("Resources", expectedParams).Return(mockResources, nil)
mockInspector.On("Resources", mock.Anything, expectedParams).Return(mockResources, nil)

policy, err := rbacGen.Generate(params)
policy, err := rbacGen.Generate(context.Background(), params)

assert.NoError(t, err)
assert.NotNil(t, policy)
Expand Down Expand Up @@ -188,9 +189,9 @@ func TestRBACGen_Generate(t *testing.T) {
CompositionNamespace: params.CompositionNamespace,
}

mockInspector.On("Resources", expectedParams).Return(mockResources, nil)
mockInspector.On("Resources", mock.Anything, expectedParams).Return(mockResources, nil)

policy, err := rbacGen.Generate(params)
policy, err := rbacGen.Generate(context.Background(), params)

assert.NoError(t, err)
assert.NotNil(t, policy)
Expand All @@ -215,9 +216,9 @@ func TestRBACGen_Generate(t *testing.T) {
CompositionNamespace: params.CompositionNamespace,
}

mockInspector.On("Resources", expectedParams).Return(nil, errors.New("some error"))
mockInspector.On("Resources", mock.Anything, expectedParams).Return(nil, errors.New("some error"))

policy, err := rbacGen.Generate(params)
policy, err := rbacGen.Generate(context.Background(), params)

assert.Error(t, err)
assert.Nil(t, policy)
Expand All @@ -244,9 +245,9 @@ func TestRBACGen_Generate(t *testing.T) {
CompositionNamespace: params.CompositionNamespace,
}

mockInspector.On("Resources", expectedParams).Return(mockResources, nil)
mockInspector.On("Resources", mock.Anything, expectedParams).Return(mockResources, nil)

policy, err := rbacGen.Generate(params)
policy, err := rbacGen.Generate(context.Background(), params)

assert.NoError(t, err)
assert.NotNil(t, policy)
Expand Down