From 7fa80ac37468ff251ef9aa9d99c847995e5e0135 Mon Sep 17 00:00:00 2001 From: Matt Jenkinson <75292329+mattdjenkinson@users.noreply.github.com> Date: Tue, 24 Feb 2026 20:29:36 +0000 Subject: [PATCH 1/3] feat: add device info from clients to the connector --- api/v1alpha/httpproxy_types.go | 14 ++ api/v1alpha1/connector_types.go | 21 +++ api/v1alpha1/zz_generated.deepcopy.go | 20 +++ .../networking.datumapis.com_connectors.yaml | 17 +++ .../networking.datumapis.com_httpproxies.yaml | 12 ++ internal/controller/httpproxy_controller.go | 44 ++++++ .../controller/httpproxy_controller_test.go | 129 ++++++++++++++++++ 7 files changed, 257 insertions(+) diff --git a/api/v1alpha/httpproxy_types.go b/api/v1alpha/httpproxy_types.go index 72f7fa90..2feab44c 100644 --- a/api/v1alpha/httpproxy_types.go +++ b/api/v1alpha/httpproxy_types.go @@ -175,6 +175,20 @@ type ConnectorReference struct { // // +kubebuilder:validation:Required Name string `json:"name"` + + // DeviceName is the human-readable name of the device running the + // referenced connector (e.g. "Matt's Macbook Pro"). + // + // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxLength=253 + DeviceName string `json:"deviceName,omitempty"` + + // DeviceOS is the operating system of the device running the referenced + // connector (e.g. "macOS"). + // + // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxLength=253 + DeviceOS string `json:"deviceOS,omitempty"` } // HostnameStatus captures the per-hostname verification and DNS programming status. diff --git a/api/v1alpha1/connector_types.go b/api/v1alpha1/connector_types.go index b4559db9..f62aa132 100644 --- a/api/v1alpha1/connector_types.go +++ b/api/v1alpha1/connector_types.go @@ -49,6 +49,11 @@ type ConnectorSpec struct { // +listMapKey=type // +kubebuilder:validation:MaxItems=16 Capabilities []ConnectorCapability `json:"capabilities,omitempty"` + + // Device describes the device running the connector. + // + // +kubebuilder:validation:Optional + Device *ConnectorDeviceInfo `json:"device,omitempty"` } type PublicKeyDiscoveryMode string @@ -105,6 +110,22 @@ const ( PublicKeyConnectorConnectionType ConnectorConnectionType = "PublicKey" ) +type ConnectorDeviceInfo struct { + // Human-readable name of the device running the connector. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + Name string `json:"name"` + + // Operating system of the device running the connector. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + OS string `json:"os"` +} + // ConnectorConnectionDetails provides details on how to connect to the connector. // // +kubebuilder:validation:XValidation:message="publicKey field must be nil if the type is not PublicKey",rule="!(self.type != 'PublicKey' && has(self.publicKey))" diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index ecf6ff24..bdde75e1 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -387,6 +387,21 @@ func (in *ConnectorConnectionDetailsPublicKey) DeepCopy() *ConnectorConnectionDe return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConnectorDeviceInfo) DeepCopyInto(out *ConnectorDeviceInfo) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectorDeviceInfo. +func (in *ConnectorDeviceInfo) DeepCopy() *ConnectorDeviceInfo { + if in == nil { + return nil + } + out := new(ConnectorDeviceInfo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConnectorList) DeepCopyInto(out *ConnectorList) { *out = *in @@ -429,6 +444,11 @@ func (in *ConnectorSpec) DeepCopyInto(out *ConnectorSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Device != nil { + in, out := &in.Device, &out.Device + *out = new(ConnectorDeviceInfo) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectorSpec. diff --git a/config/crd/bases/networking.datumapis.com_connectors.yaml b/config/crd/bases/networking.datumapis.com_connectors.yaml index 6648f065..2db1ea6b 100644 --- a/config/crd/bases/networking.datumapis.com_connectors.yaml +++ b/config/crd/bases/networking.datumapis.com_connectors.yaml @@ -70,6 +70,23 @@ spec: connectorClassName: minLength: 1 type: string + device: + description: Device describes the device running the connector. + properties: + name: + description: Human-readable name of the device running the connector. + maxLength: 253 + minLength: 1 + type: string + os: + description: Operating system of the device running the connector. + maxLength: 253 + minLength: 1 + type: string + required: + - name + - os + type: object required: - connectorClassName type: object diff --git a/config/crd/bases/networking.datumapis.com_httpproxies.yaml b/config/crd/bases/networking.datumapis.com_httpproxies.yaml index 582bb6df..28cbce24 100644 --- a/config/crd/bases/networking.datumapis.com_httpproxies.yaml +++ b/config/crd/bases/networking.datumapis.com_httpproxies.yaml @@ -134,6 +134,18 @@ spec: For now, only a name reference is supported. In the future this can be extended to selector-based matching to allow multiple connectors. properties: + deviceName: + description: |- + DeviceName is the human-readable name of the device running the + referenced connector (e.g. "Matt's Macbook Pro"). + maxLength: 253 + type: string + deviceOS: + description: |- + DeviceOS is the operating system of the device running the referenced + connector (e.g. "macOS"). + maxLength: 253 + type: string name: description: Name of the referenced Connector. type: string diff --git a/internal/controller/httpproxy_controller.go b/internal/controller/httpproxy_controller.go index 7894bc43..f9bb8358 100644 --- a/internal/controller/httpproxy_controller.go +++ b/internal/controller/httpproxy_controller.go @@ -117,6 +117,15 @@ func (r *HTTPProxyReconciler) Reconcile(ctx context.Context, req mcreconcile.Req return ctrl.Result{}, nil } + if updated, err := enrichConnectorDeviceInfo(ctx, cl.GetClient(), &httpProxy); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to enrich connector device info: %w", err) + } else if updated { + if err := cl.GetClient().Update(ctx, &httpProxy); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + } + httpProxyCopy := httpProxy.DeepCopy() acceptedCondition := &metav1.Condition{ @@ -1275,6 +1284,41 @@ func buildConnectorOfflineHTTPRouteFilter(httpProxy *networkingv1alpha.HTTPProxy } } +func enrichConnectorDeviceInfo(ctx context.Context, cl client.Client, httpProxy *networkingv1alpha.HTTPProxy) (bool, error) { + updated := false + for i, rule := range httpProxy.Spec.Rules { + for j, backend := range rule.Backends { + if backend.Connector == nil { + continue + } + + var connector networkingv1alpha1.Connector + if err := cl.Get(ctx, client.ObjectKey{ + Namespace: httpProxy.Namespace, + Name: backend.Connector.Name, + }, &connector); err != nil { + return false, err + } + + ref := &httpProxy.Spec.Rules[i].Backends[j].Connector + if connector.Spec.Device != nil { + if (*ref).DeviceName != connector.Spec.Device.Name || (*ref).DeviceOS != connector.Spec.Device.OS { + (*ref).DeviceName = connector.Spec.Device.Name + (*ref).DeviceOS = connector.Spec.Device.OS + updated = true + } + } else { + if (*ref).DeviceName != "" || (*ref).DeviceOS != "" { + (*ref).DeviceName = "" + (*ref).DeviceOS = "" + updated = true + } + } + } + } + return updated, nil +} + func connectorReady(ctx context.Context, cl client.Client, namespace, name string) (bool, error) { var connector networkingv1alpha1.Connector if err := cl.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &connector); err != nil { diff --git a/internal/controller/httpproxy_controller_test.go b/internal/controller/httpproxy_controller_test.go index 01d80fdd..ee4fc152 100644 --- a/internal/controller/httpproxy_controller_test.go +++ b/internal/controller/httpproxy_controller_test.go @@ -436,6 +436,12 @@ func TestHTTPProxyReconcile(t *testing.T) { Name: "connector-1", Namespace: "test", }, + Spec: networkingv1alpha1.ConnectorSpec{ + Device: &networkingv1alpha1.ConnectorDeviceInfo{ + Name: "Matt's Macbook Pro", + OS: "macOS", + }, + }, Status: networkingv1alpha1.ConnectorStatus{ Conditions: []metav1.Condition{ { @@ -483,6 +489,12 @@ func TestHTTPProxyReconcile(t *testing.T) { assert.NoError(t, err) assert.Len(t, patchList.Items, 1) assert.Equal(t, fmt.Sprintf("connector-%s", httpProxy.Name), patchList.Items[0].Name) + + connRef := httpProxy.Spec.Rules[0].Backends[0].Connector + if assert.NotNil(t, connRef, "connector reference should be present") { + assert.Equal(t, "Matt's Macbook Pro", connRef.DeviceName, "device name should be enriched from connector spec") + assert.Equal(t, "macOS", connRef.DeviceOS, "device OS should be enriched from connector spec") + } }, }, { @@ -1480,6 +1492,123 @@ func TestBuildConnectorEnvoyPatchesScopesRouteConfigBySectionName(t *testing.T) assert.NotContains(t, routeConfigPatchCounts, "ns-test/gw/default-https") } +func TestEnrichConnectorDeviceInfo(t *testing.T) { + testScheme := runtime.NewScheme() + assert.NoError(t, scheme.AddToScheme(testScheme)) + assert.NoError(t, networkingv1alpha.AddToScheme(testScheme)) + assert.NoError(t, networkingv1alpha1.AddToScheme(testScheme)) + + tests := []struct { + name string + httpProxy *networkingv1alpha.HTTPProxy + connector *networkingv1alpha1.Connector + expectUpdated bool + expectDeviceName string + expectDeviceOS string + }{ + { + name: "populates device info from connector spec", + httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { + h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ + Name: "connector-1", + } + }), + connector: &networkingv1alpha1.Connector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "connector-1", + Namespace: "test", + }, + Spec: networkingv1alpha1.ConnectorSpec{ + Device: &networkingv1alpha1.ConnectorDeviceInfo{ + Name: "Matt's Macbook Pro", + OS: "macOS", + }, + }, + }, + expectUpdated: true, + expectDeviceName: "Matt's Macbook Pro", + expectDeviceOS: "macOS", + }, + { + name: "clears device info when connector has no device", + httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { + h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ + Name: "connector-1", + DeviceName: "old-device", + DeviceOS: "old-os", + } + }), + connector: &networkingv1alpha1.Connector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "connector-1", + Namespace: "test", + }, + }, + expectUpdated: true, + expectDeviceName: "", + expectDeviceOS: "", + }, + { + name: "no update when device info already matches", + httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { + h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ + Name: "connector-1", + DeviceName: "Matt's Macbook Pro", + DeviceOS: "macOS", + } + }), + connector: &networkingv1alpha1.Connector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "connector-1", + Namespace: "test", + }, + Spec: networkingv1alpha1.ConnectorSpec{ + Device: &networkingv1alpha1.ConnectorDeviceInfo{ + Name: "Matt's Macbook Pro", + OS: "macOS", + }, + }, + }, + expectUpdated: false, + expectDeviceName: "Matt's Macbook Pro", + expectDeviceOS: "macOS", + }, + { + name: "no connector reference is a no-op", + httpProxy: newHTTPProxy(), + connector: &networkingv1alpha1.Connector{ + ObjectMeta: metav1.ObjectMeta{ + Name: "connector-1", + Namespace: "test", + }, + }, + expectUpdated: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cl := fake.NewClientBuilder(). + WithScheme(testScheme). + WithObjects(tt.connector). + Build() + + updated, err := enrichConnectorDeviceInfo(context.Background(), cl, tt.httpProxy) + assert.NoError(t, err) + assert.Equal(t, tt.expectUpdated, updated) + + for _, rule := range tt.httpProxy.Spec.Rules { + for _, backend := range rule.Backends { + if backend.Connector != nil { + assert.Equal(t, tt.expectDeviceName, backend.Connector.DeviceName) + assert.Equal(t, tt.expectDeviceOS, backend.Connector.DeviceOS) + } + } + } + }) + } +} + func TestHTTPProxyFinalizerCleanup(t *testing.T) { logger := zap.New(zap.UseFlagOptions(&zap.Options{Development: true})) ctx := log.IntoContext(context.Background(), logger) From 139e2420f56d40cba24f6a6a0581814a5df87879 Mon Sep 17 00:00:00 2001 From: Matt Jenkinson <75292329+mattdjenkinson@users.noreply.github.com> Date: Tue, 24 Feb 2026 20:40:02 +0000 Subject: [PATCH 2/3] move to status --- api/v1alpha1/connector_types.go | 11 +++--- api/v1alpha1/zz_generated.deepcopy.go | 10 +++--- .../networking.datumapis.com_connectors.yaml | 36 ++++++++++--------- internal/controller/httpproxy_controller.go | 8 ++--- .../controller/httpproxy_controller_test.go | 22 ++++++------ 5 files changed, 44 insertions(+), 43 deletions(-) diff --git a/api/v1alpha1/connector_types.go b/api/v1alpha1/connector_types.go index f62aa132..f75b2599 100644 --- a/api/v1alpha1/connector_types.go +++ b/api/v1alpha1/connector_types.go @@ -49,11 +49,6 @@ type ConnectorSpec struct { // +listMapKey=type // +kubebuilder:validation:MaxItems=16 Capabilities []ConnectorCapability `json:"capabilities,omitempty"` - - // Device describes the device running the connector. - // - // +kubebuilder:validation:Optional - Device *ConnectorDeviceInfo `json:"device,omitempty"` } type PublicKeyDiscoveryMode string @@ -181,6 +176,12 @@ type ConnectorStatus struct { // // +kubebuilder:validation:Optional LeaseRef *corev1.LocalObjectReference `json:"leaseRef,omitempty"` + + // Device describes the device running the connector, as reported by the + // connector agent. + // + // +kubebuilder:validation:Optional + Device *ConnectorDeviceInfo `json:"device,omitempty"` } const ( diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index bdde75e1..238ffb62 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -444,11 +444,6 @@ func (in *ConnectorSpec) DeepCopyInto(out *ConnectorSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Device != nil { - in, out := &in.Device, &out.Device - *out = new(ConnectorDeviceInfo) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectorSpec. @@ -488,6 +483,11 @@ func (in *ConnectorStatus) DeepCopyInto(out *ConnectorStatus) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.Device != nil { + in, out := &in.Device, &out.Device + *out = new(ConnectorDeviceInfo) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectorStatus. diff --git a/config/crd/bases/networking.datumapis.com_connectors.yaml b/config/crd/bases/networking.datumapis.com_connectors.yaml index 2db1ea6b..1227d184 100644 --- a/config/crd/bases/networking.datumapis.com_connectors.yaml +++ b/config/crd/bases/networking.datumapis.com_connectors.yaml @@ -70,23 +70,6 @@ spec: connectorClassName: minLength: 1 type: string - device: - description: Device describes the device running the connector. - properties: - name: - description: Human-readable name of the device running the connector. - maxLength: 253 - minLength: 1 - type: string - os: - description: Operating system of the device running the connector. - maxLength: 253 - minLength: 1 - type: string - required: - - name - - os - type: object required: - connectorClassName type: object @@ -306,6 +289,25 @@ spec: rule: '!(self.type != ''PublicKey'' && has(self.publicKey))' - message: publicKey field must be specified if the type is PublicKey rule: self.type == 'PublicKey' && has(self.publicKey) + device: + description: |- + Device describes the device running the connector, as reported by the + connector agent. + properties: + name: + description: Human-readable name of the device running the connector. + maxLength: 253 + minLength: 1 + type: string + os: + description: Operating system of the device running the connector. + maxLength: 253 + minLength: 1 + type: string + required: + - name + - os + type: object leaseRef: description: |- LeaseRef references the Lease used to report connector liveness. diff --git a/internal/controller/httpproxy_controller.go b/internal/controller/httpproxy_controller.go index f9bb8358..bdbe9d3a 100644 --- a/internal/controller/httpproxy_controller.go +++ b/internal/controller/httpproxy_controller.go @@ -1301,10 +1301,10 @@ func enrichConnectorDeviceInfo(ctx context.Context, cl client.Client, httpProxy } ref := &httpProxy.Spec.Rules[i].Backends[j].Connector - if connector.Spec.Device != nil { - if (*ref).DeviceName != connector.Spec.Device.Name || (*ref).DeviceOS != connector.Spec.Device.OS { - (*ref).DeviceName = connector.Spec.Device.Name - (*ref).DeviceOS = connector.Spec.Device.OS + if connector.Status.Device != nil { + if (*ref).DeviceName != connector.Status.Device.Name || (*ref).DeviceOS != connector.Status.Device.OS { + (*ref).DeviceName = connector.Status.Device.Name + (*ref).DeviceOS = connector.Status.Device.OS updated = true } } else { diff --git a/internal/controller/httpproxy_controller_test.go b/internal/controller/httpproxy_controller_test.go index ee4fc152..4a2ed4e3 100644 --- a/internal/controller/httpproxy_controller_test.go +++ b/internal/controller/httpproxy_controller_test.go @@ -436,12 +436,6 @@ func TestHTTPProxyReconcile(t *testing.T) { Name: "connector-1", Namespace: "test", }, - Spec: networkingv1alpha1.ConnectorSpec{ - Device: &networkingv1alpha1.ConnectorDeviceInfo{ - Name: "Matt's Macbook Pro", - OS: "macOS", - }, - }, Status: networkingv1alpha1.ConnectorStatus{ Conditions: []metav1.Condition{ { @@ -464,6 +458,10 @@ func TestHTTPProxyReconcile(t *testing.T) { }, }, }, + Device: &networkingv1alpha1.ConnectorDeviceInfo{ + Name: "Matt's Macbook Pro", + OS: "macOS", + }, }, }, }, @@ -492,8 +490,8 @@ func TestHTTPProxyReconcile(t *testing.T) { connRef := httpProxy.Spec.Rules[0].Backends[0].Connector if assert.NotNil(t, connRef, "connector reference should be present") { - assert.Equal(t, "Matt's Macbook Pro", connRef.DeviceName, "device name should be enriched from connector spec") - assert.Equal(t, "macOS", connRef.DeviceOS, "device OS should be enriched from connector spec") + assert.Equal(t, "Matt's Macbook Pro", connRef.DeviceName, "device name should be enriched from connector status") + assert.Equal(t, "macOS", connRef.DeviceOS, "device OS should be enriched from connector status") } }, }, @@ -1507,7 +1505,7 @@ func TestEnrichConnectorDeviceInfo(t *testing.T) { expectDeviceOS string }{ { - name: "populates device info from connector spec", + name: "populates device info from connector status", httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ Name: "connector-1", @@ -1518,7 +1516,7 @@ func TestEnrichConnectorDeviceInfo(t *testing.T) { Name: "connector-1", Namespace: "test", }, - Spec: networkingv1alpha1.ConnectorSpec{ + Status: networkingv1alpha1.ConnectorStatus{ Device: &networkingv1alpha1.ConnectorDeviceInfo{ Name: "Matt's Macbook Pro", OS: "macOS", @@ -1530,7 +1528,7 @@ func TestEnrichConnectorDeviceInfo(t *testing.T) { expectDeviceOS: "macOS", }, { - name: "clears device info when connector has no device", + name: "clears device info when connector status has no device", httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ Name: "connector-1", @@ -1562,7 +1560,7 @@ func TestEnrichConnectorDeviceInfo(t *testing.T) { Name: "connector-1", Namespace: "test", }, - Spec: networkingv1alpha1.ConnectorSpec{ + Status: networkingv1alpha1.ConnectorStatus{ Device: &networkingv1alpha1.ConnectorDeviceInfo{ Name: "Matt's Macbook Pro", OS: "macOS", From 4527bf4dd9e165bbe7cee6964a590cbf37a84017 Mon Sep 17 00:00:00 2001 From: Matt Jenkinson <75292329+mattdjenkinson@users.noreply.github.com> Date: Tue, 24 Feb 2026 21:01:46 +0000 Subject: [PATCH 3/3] remove proxy ref to device info --- api/v1alpha/httpproxy_types.go | 14 -- .../networking.datumapis.com_httpproxies.yaml | 12 -- internal/controller/httpproxy_controller.go | 44 ------ .../controller/httpproxy_controller_test.go | 127 ------------------ 4 files changed, 197 deletions(-) diff --git a/api/v1alpha/httpproxy_types.go b/api/v1alpha/httpproxy_types.go index 2feab44c..72f7fa90 100644 --- a/api/v1alpha/httpproxy_types.go +++ b/api/v1alpha/httpproxy_types.go @@ -175,20 +175,6 @@ type ConnectorReference struct { // // +kubebuilder:validation:Required Name string `json:"name"` - - // DeviceName is the human-readable name of the device running the - // referenced connector (e.g. "Matt's Macbook Pro"). - // - // +kubebuilder:validation:Optional - // +kubebuilder:validation:MaxLength=253 - DeviceName string `json:"deviceName,omitempty"` - - // DeviceOS is the operating system of the device running the referenced - // connector (e.g. "macOS"). - // - // +kubebuilder:validation:Optional - // +kubebuilder:validation:MaxLength=253 - DeviceOS string `json:"deviceOS,omitempty"` } // HostnameStatus captures the per-hostname verification and DNS programming status. diff --git a/config/crd/bases/networking.datumapis.com_httpproxies.yaml b/config/crd/bases/networking.datumapis.com_httpproxies.yaml index 28cbce24..582bb6df 100644 --- a/config/crd/bases/networking.datumapis.com_httpproxies.yaml +++ b/config/crd/bases/networking.datumapis.com_httpproxies.yaml @@ -134,18 +134,6 @@ spec: For now, only a name reference is supported. In the future this can be extended to selector-based matching to allow multiple connectors. properties: - deviceName: - description: |- - DeviceName is the human-readable name of the device running the - referenced connector (e.g. "Matt's Macbook Pro"). - maxLength: 253 - type: string - deviceOS: - description: |- - DeviceOS is the operating system of the device running the referenced - connector (e.g. "macOS"). - maxLength: 253 - type: string name: description: Name of the referenced Connector. type: string diff --git a/internal/controller/httpproxy_controller.go b/internal/controller/httpproxy_controller.go index bdbe9d3a..7894bc43 100644 --- a/internal/controller/httpproxy_controller.go +++ b/internal/controller/httpproxy_controller.go @@ -117,15 +117,6 @@ func (r *HTTPProxyReconciler) Reconcile(ctx context.Context, req mcreconcile.Req return ctrl.Result{}, nil } - if updated, err := enrichConnectorDeviceInfo(ctx, cl.GetClient(), &httpProxy); err != nil { - return ctrl.Result{}, fmt.Errorf("failed to enrich connector device info: %w", err) - } else if updated { - if err := cl.GetClient().Update(ctx, &httpProxy); err != nil { - return ctrl.Result{}, err - } - return ctrl.Result{}, nil - } - httpProxyCopy := httpProxy.DeepCopy() acceptedCondition := &metav1.Condition{ @@ -1284,41 +1275,6 @@ func buildConnectorOfflineHTTPRouteFilter(httpProxy *networkingv1alpha.HTTPProxy } } -func enrichConnectorDeviceInfo(ctx context.Context, cl client.Client, httpProxy *networkingv1alpha.HTTPProxy) (bool, error) { - updated := false - for i, rule := range httpProxy.Spec.Rules { - for j, backend := range rule.Backends { - if backend.Connector == nil { - continue - } - - var connector networkingv1alpha1.Connector - if err := cl.Get(ctx, client.ObjectKey{ - Namespace: httpProxy.Namespace, - Name: backend.Connector.Name, - }, &connector); err != nil { - return false, err - } - - ref := &httpProxy.Spec.Rules[i].Backends[j].Connector - if connector.Status.Device != nil { - if (*ref).DeviceName != connector.Status.Device.Name || (*ref).DeviceOS != connector.Status.Device.OS { - (*ref).DeviceName = connector.Status.Device.Name - (*ref).DeviceOS = connector.Status.Device.OS - updated = true - } - } else { - if (*ref).DeviceName != "" || (*ref).DeviceOS != "" { - (*ref).DeviceName = "" - (*ref).DeviceOS = "" - updated = true - } - } - } - } - return updated, nil -} - func connectorReady(ctx context.Context, cl client.Client, namespace, name string) (bool, error) { var connector networkingv1alpha1.Connector if err := cl.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, &connector); err != nil { diff --git a/internal/controller/httpproxy_controller_test.go b/internal/controller/httpproxy_controller_test.go index 4a2ed4e3..01d80fdd 100644 --- a/internal/controller/httpproxy_controller_test.go +++ b/internal/controller/httpproxy_controller_test.go @@ -458,10 +458,6 @@ func TestHTTPProxyReconcile(t *testing.T) { }, }, }, - Device: &networkingv1alpha1.ConnectorDeviceInfo{ - Name: "Matt's Macbook Pro", - OS: "macOS", - }, }, }, }, @@ -487,12 +483,6 @@ func TestHTTPProxyReconcile(t *testing.T) { assert.NoError(t, err) assert.Len(t, patchList.Items, 1) assert.Equal(t, fmt.Sprintf("connector-%s", httpProxy.Name), patchList.Items[0].Name) - - connRef := httpProxy.Spec.Rules[0].Backends[0].Connector - if assert.NotNil(t, connRef, "connector reference should be present") { - assert.Equal(t, "Matt's Macbook Pro", connRef.DeviceName, "device name should be enriched from connector status") - assert.Equal(t, "macOS", connRef.DeviceOS, "device OS should be enriched from connector status") - } }, }, { @@ -1490,123 +1480,6 @@ func TestBuildConnectorEnvoyPatchesScopesRouteConfigBySectionName(t *testing.T) assert.NotContains(t, routeConfigPatchCounts, "ns-test/gw/default-https") } -func TestEnrichConnectorDeviceInfo(t *testing.T) { - testScheme := runtime.NewScheme() - assert.NoError(t, scheme.AddToScheme(testScheme)) - assert.NoError(t, networkingv1alpha.AddToScheme(testScheme)) - assert.NoError(t, networkingv1alpha1.AddToScheme(testScheme)) - - tests := []struct { - name string - httpProxy *networkingv1alpha.HTTPProxy - connector *networkingv1alpha1.Connector - expectUpdated bool - expectDeviceName string - expectDeviceOS string - }{ - { - name: "populates device info from connector status", - httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { - h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ - Name: "connector-1", - } - }), - connector: &networkingv1alpha1.Connector{ - ObjectMeta: metav1.ObjectMeta{ - Name: "connector-1", - Namespace: "test", - }, - Status: networkingv1alpha1.ConnectorStatus{ - Device: &networkingv1alpha1.ConnectorDeviceInfo{ - Name: "Matt's Macbook Pro", - OS: "macOS", - }, - }, - }, - expectUpdated: true, - expectDeviceName: "Matt's Macbook Pro", - expectDeviceOS: "macOS", - }, - { - name: "clears device info when connector status has no device", - httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { - h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ - Name: "connector-1", - DeviceName: "old-device", - DeviceOS: "old-os", - } - }), - connector: &networkingv1alpha1.Connector{ - ObjectMeta: metav1.ObjectMeta{ - Name: "connector-1", - Namespace: "test", - }, - }, - expectUpdated: true, - expectDeviceName: "", - expectDeviceOS: "", - }, - { - name: "no update when device info already matches", - httpProxy: newHTTPProxy(func(h *networkingv1alpha.HTTPProxy) { - h.Spec.Rules[0].Backends[0].Connector = &networkingv1alpha.ConnectorReference{ - Name: "connector-1", - DeviceName: "Matt's Macbook Pro", - DeviceOS: "macOS", - } - }), - connector: &networkingv1alpha1.Connector{ - ObjectMeta: metav1.ObjectMeta{ - Name: "connector-1", - Namespace: "test", - }, - Status: networkingv1alpha1.ConnectorStatus{ - Device: &networkingv1alpha1.ConnectorDeviceInfo{ - Name: "Matt's Macbook Pro", - OS: "macOS", - }, - }, - }, - expectUpdated: false, - expectDeviceName: "Matt's Macbook Pro", - expectDeviceOS: "macOS", - }, - { - name: "no connector reference is a no-op", - httpProxy: newHTTPProxy(), - connector: &networkingv1alpha1.Connector{ - ObjectMeta: metav1.ObjectMeta{ - Name: "connector-1", - Namespace: "test", - }, - }, - expectUpdated: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cl := fake.NewClientBuilder(). - WithScheme(testScheme). - WithObjects(tt.connector). - Build() - - updated, err := enrichConnectorDeviceInfo(context.Background(), cl, tt.httpProxy) - assert.NoError(t, err) - assert.Equal(t, tt.expectUpdated, updated) - - for _, rule := range tt.httpProxy.Spec.Rules { - for _, backend := range rule.Backends { - if backend.Connector != nil { - assert.Equal(t, tt.expectDeviceName, backend.Connector.DeviceName) - assert.Equal(t, tt.expectDeviceOS, backend.Connector.DeviceOS) - } - } - } - }) - } -} - func TestHTTPProxyFinalizerCleanup(t *testing.T) { logger := zap.New(zap.UseFlagOptions(&zap.Options{Development: true})) ctx := log.IntoContext(context.Background(), logger)