Skip to content
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
4 changes: 0 additions & 4 deletions api/core/v1alpha2/proxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,6 @@ func getProxyTelemetryInfo(proxy *Proxy) string {
features = append(features, "Tracing")
}

if proxy.Spec.Telemetry.ThirdPartySinks != nil {
features = append(features, "3rdParty")
}

if len(features) == 0 {
return "Default"
}
Expand Down
17 changes: 2 additions & 15 deletions api/core/v1alpha2/proxy_types_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,17 +353,7 @@ func TestGetProxyTelemetryInfo(t *testing.T) {
}},
expected: "[Tracing]",
},
{
name: "third party sinks",
proxy: &Proxy{Spec: ProxySpec{
Telemetry: &ProxyTelementry{
ThirdPartySinks: &ThirdPartySinks{
DatadogLogs: &APIKey{Key: "key"},
},
},
}},
expected: "[3rdParty]",
},

{
name: "multiple features",
proxy: &Proxy{Spec: ProxySpec{
Expand All @@ -374,12 +364,9 @@ func TestGetProxyTelemetryInfo(t *testing.T) {
Tracing: &ProxyTracing{
Enabled: true,
},
ThirdPartySinks: &ThirdPartySinks{
AxiomLogs: &APIKey{Key: "key"},
},
},
}},
expected: "[AccessLogs Tracing 3rdParty]",
expected: "[AccessLogs Tracing]",
},
}

Expand Down
26 changes: 26 additions & 0 deletions api/core/v1alpha2/proxy_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ func (r *Proxy) Default() {
var _ resourcestrategy.Validater = &Proxy{}
var _ resourcestrategy.ValidateUpdater = &Proxy{}

// isCloudProvider returns true if the proxy uses the cloud infrastructure provider.
func isCloudProvider(p InfraProvider) bool {
return p == InfraProviderCloud || p == ""
}

func (r *Proxy) validate() field.ErrorList {
errs := field.ErrorList{}
spec := r.Spec
Expand All @@ -38,6 +43,27 @@ func (r *Proxy) validate() field.ErrorList {
"minimumDrainTime must be less than or equal to drainTimeout"))
}

// Telemetry settings are managed by CloudMonitoringIntegration for cloud proxies.
if isCloudProvider(spec.Provider) && spec.Telemetry != nil {
telPath := field.NewPath("spec", "telemetry")
msg := "telemetry settings are not configurable for cloud proxies; use CloudMonitoringIntegration instead"
if spec.Telemetry.AccessLogs != nil {
errs = append(errs, field.Forbidden(telPath.Child("accessLogs"), msg))
}
if spec.Telemetry.ContentLogs != nil {
errs = append(errs, field.Forbidden(telPath.Child("contentLogs"), msg))
}
if spec.Telemetry.Tracing != nil {
errs = append(errs, field.Forbidden(telPath.Child("tracing"), msg))
}
if spec.Telemetry.OtelCollectorConfig != nil {
errs = append(errs, field.Forbidden(telPath.Child("otelCollectorConfig"), msg))
}
if spec.Telemetry.ThirdPartySinks != nil {
errs = append(errs, field.Forbidden(telPath.Child("thirdPartySinks"), msg))
}
}

return errs
}

Expand Down
183 changes: 183 additions & 0 deletions api/core/v1alpha2/proxy_validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package v1alpha2

import (
"context"
"testing"
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func defaultedProxy(provider InfraProvider, tel *ProxyTelementry) *Proxy {
p := &Proxy{
Spec: ProxySpec{
Provider: provider,
Telemetry: tel,
},
}
p.Default()
return p
}

func TestValidate_CloudTelemetryRejected(t *testing.T) {
msg := "telemetry settings are not configurable for cloud proxies; use CloudMonitoringIntegration instead"

tests := []struct {
name string
provider InfraProvider
telemetry *ProxyTelementry
wantErrs int
wantField string
}{
{
name: "cloud provider with nil telemetry is valid",
provider: InfraProviderCloud,
wantErrs: 0,
},
{
name: "empty provider (defaults to cloud) with nil telemetry is valid",
provider: "",
wantErrs: 0,
},
{
name: "cloud provider with empty telemetry is valid",
provider: InfraProviderCloud,
telemetry: &ProxyTelementry{},
wantErrs: 0,
},
{
name: "cloud provider with accessLogs rejected",
provider: InfraProviderCloud,
telemetry: &ProxyTelementry{
AccessLogs: &ProxyAccessLogs{
JSON: map[string]string{"key": "value"},
},
},
wantErrs: 1,
wantField: "spec.telemetry.accessLogs",
},
{
name: "cloud provider with contentLogs rejected",
provider: InfraProviderCloud,
telemetry: &ProxyTelementry{
ContentLogs: &ProxyContentLogs{RequestBodyEnabled: true},
},
wantErrs: 1,
wantField: "spec.telemetry.contentLogs",
},
{
name: "cloud provider with tracing rejected",
provider: InfraProviderCloud,
telemetry: &ProxyTelementry{
Tracing: &ProxyTracing{Enabled: true},
},
wantErrs: 1,
wantField: "spec.telemetry.tracing",
},
{
name: "cloud provider with otelCollectorConfig rejected",
provider: InfraProviderCloud,
telemetry: &ProxyTelementry{
OtelCollectorConfig: &LocalObjectReference{Name: "cfg"},
},
wantErrs: 1,
wantField: "spec.telemetry.otelCollectorConfig",
},
{
name: "cloud provider with thirdPartySinks rejected",
provider: InfraProviderCloud,
telemetry: &ProxyTelementry{
ThirdPartySinks: &ThirdPartySinks{
DatadogLogs: &APIKey{Key: "key"},
},
},
wantErrs: 1,
wantField: "spec.telemetry.thirdPartySinks",
},
{
name: "cloud provider with multiple telemetry fields rejected",
provider: "",
telemetry: &ProxyTelementry{
AccessLogs: &ProxyAccessLogs{JSON: map[string]string{"k": "v"}},
Tracing: &ProxyTracing{Enabled: true},
ContentLogs: &ProxyContentLogs{RequestBodyEnabled: true},
},
wantErrs: 3,
},
{
name: "kubernetes provider with telemetry is valid",
provider: InfraProviderKubernetes,
telemetry: &ProxyTelementry{
Tracing: &ProxyTracing{Enabled: true},
},
wantErrs: 0,
},
{
name: "unmanaged provider with telemetry is valid",
provider: InfraProviderUnmanaged,
telemetry: &ProxyTelementry{
AccessLogs: &ProxyAccessLogs{JSON: map[string]string{"k": "v"}},
OtelCollectorConfig: &LocalObjectReference{Name: "cfg"},
},
wantErrs: 0,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := defaultedProxy(tt.provider, tt.telemetry)
errs := p.Validate(context.Background())
if len(errs) != tt.wantErrs {
t.Errorf("Validate() returned %d errors, want %d: %v", len(errs), tt.wantErrs, errs)
}
if tt.wantField != "" && len(errs) > 0 {
if errs[0].Field != tt.wantField {
t.Errorf("Validate() error field = %q, want %q", errs[0].Field, tt.wantField)
}
}
if tt.wantErrs > 0 {
for _, e := range errs {
if e.Detail != msg {
t.Errorf("Validate() error detail = %q, want %q", e.Detail, msg)
}
}
}
})
}
}

func TestValidateUpdate_CloudTelemetryRejected(t *testing.T) {
old := defaultedProxy(InfraProviderCloud, nil)
updated := defaultedProxy(InfraProviderCloud, &ProxyTelementry{
Tracing: &ProxyTracing{Enabled: true},
})

errs := old.ValidateUpdate(context.Background(), updated)
if len(errs) != 1 {
t.Fatalf("ValidateUpdate() returned %d errors, want 1: %v", len(errs), errs)
}
if errs[0].Field != "spec.telemetry.tracing" {
t.Errorf("ValidateUpdate() error field = %q, want %q", errs[0].Field, "spec.telemetry.tracing")
}
}

func TestValidate_DrainTimeout(t *testing.T) {
p := &Proxy{
Spec: ProxySpec{
Provider: InfraProviderKubernetes,
Shutdown: &ShutdownConfig{
DrainTimeout: &metav1.Duration{Duration: 10 * time.Second},
MinimumDrainTime: &metav1.Duration{Duration: 30 * time.Second},
},
},
}
p.Default()

errs := p.Validate(context.Background())
if len(errs) != 1 {
t.Fatalf("Validate() returned %d errors, want 1: %v", len(errs), errs)
}
if errs[0].Field != "spec.shutdown.minimumDrainTime" {
t.Errorf("Validate() error field = %q, want %q", errs[0].Field, "spec.shutdown.minimumDrainTime")
}
}