Skip to content

Commit 8d1addc

Browse files
heanlancursoragent
andcommitted
Address comments
- Remove Follow field from FlowStreamFilter: the SSE endpoint always streams in follow mode; exposing a non-functional field on the API was misleading. - Move FlowStreamFilter and FlowFilterDirection out of apis/v1 and into the flowstream handler package, as the filter is parsed from URL query parameters (not a JSON body) and does not belong in the public JSON API types. - Copy FlowStreamService proto stubs locally under pkg/flowpb instead of depending on antrea.io/antrea/v2, which pulls in the entire Antrea module and its transitive dependencies. - Merge DroppedCount and Flows into a single FlowStreamEvent per gRPC response, matching how the gRPC layer itself works. - Expose flowAggregator.serverName as a Helm chart value and config field instead of hardcoding the TLS ServerName override. - Use {{ .Release.Name }} in the flow-aggregator RoleBinding name to avoid collisions when multiple antrea-ui releases share the same flow-aggregator namespace. - Move flow-store and use-flow-stream out of src/api/ into src/store/ and src/hooks/ respectively, as they are not network client modules. - Restore .env.development to VITE_API_SERVER=http://localhost:8080 and remove the Vite dev proxy; the backend already configures CORS for localhost:3000 in dev mode so the proxy is unnecessary. Signed-off-by: Anlan He <anlan.he@broadcom.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 55d119c commit 8d1addc

29 files changed

Lines changed: 2500 additions & 215 deletions

apis/v1/flow.go

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -161,30 +161,3 @@ type FlowStreamDroppedEvent struct {
161161
type FlowStreamErrorEvent struct {
162162
Message string `json:"message"`
163163
}
164-
165-
// FlowFilterDirection matches antrea FlowFilter.direction (service.proto, FlowStreamService).
166-
// It is distinct from per-flow FlowDirection in flow.proto (ingress/egress), which is not
167-
// exposed on this JSON API yet.
168-
type FlowFilterDirection int
169-
170-
const (
171-
FlowFilterDirectionBoth FlowFilterDirection = 0
172-
FlowFilterDirectionFrom FlowFilterDirection = 1
173-
FlowFilterDirectionTo FlowFilterDirection = 2
174-
)
175-
176-
// FlowStreamFilter represents the query parameters for the flow stream endpoint.
177-
// All specified filters are AND-ed. Within each filter, values are OR-ed.
178-
type FlowStreamFilter struct {
179-
Namespaces []string `json:"namespaces,omitempty"`
180-
PodNames []string `json:"podNames,omitempty"`
181-
PodLabelSelector string `json:"podLabelSelector,omitempty"`
182-
ServiceNames []string `json:"serviceNames,omitempty"`
183-
FlowTypes []FlowType `json:"flowTypes,omitempty"`
184-
IPs []string `json:"ips,omitempty"`
185-
Direction FlowFilterDirection `json:"direction,omitempty"`
186-
// Follow is accepted from the client for completeness but is always overridden to true
187-
// in the backend SSE handler. The FlowStreamService gRPC stream requires follow mode to
188-
// keep the connection open; non-follow (one-shot) mode is not supported over SSE.
189-
Follow bool `json:"follow"`
190-
}

build/charts/antrea-ui/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Kubernetes: `>= 1.16.0-0`
4545
| flowAggregator.caConfigMap | string | `"flow-aggregator-ca"` | Name of the ConfigMap (in namespace below) containing the CA certificate (key: ca.crt) used to verify the FlowStreamService server certificate. The FlowStreamService uses server-side TLS only (no client authentication). Leave empty to skip server certificate verification (dev/test only). |
4646
| flowAggregator.enabled | bool | `false` | When true, the backend connects to Flow Aggregator's FlowStreamService over gRPC. |
4747
| flowAggregator.namespace | string | `"flow-aggregator"` | Namespace where the Flow Aggregator is installed. |
48+
| flowAggregator.serverName | string | `""` | Override the TLS server name used for certificate verification. Useful when dialing via kubectl port-forward (loopback address) while the server cert is issued for the in-cluster Service DNS name (e.g. flow-aggregator.flow-aggregator.svc). Leave empty to use the hostname from the address field. |
4849
| frontend.extraVolumeMounts | list | `[]` | Additional volumeMounts. |
4950
| frontend.image | object | `{"pullPolicy":"IfNotPresent","repository":"antrea/antrea-ui-frontend","tag":""}` | Container image to use for the Antrea UI frontend. |
5051
| frontend.port | int | `3000` | Container port on which the frontend will listen. |

build/charts/antrea-ui/templates/_backend_conf.tpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ flowAggregator:
2020
{{- if .Values.flowAggregator.enabled }}
2121
caConfigMap: {{ .Values.flowAggregator.caConfigMap | quote }}
2222
namespace: {{ .Values.flowAggregator.namespace | default "flow-aggregator" | quote }}
23+
serverName: {{ .Values.flowAggregator.serverName | quote }}
2324
{{- end }}
2425
{{- end }}

build/charts/antrea-ui/templates/flow-aggregator-rolebinding.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ apiVersion: rbac.authorization.k8s.io/v1
44
metadata:
55
labels:
66
app: antrea-ui
7-
name: antrea-ui-flow-aggregator-ca-reader
7+
name: {{ .Release.Name }}-flow-aggregator-ca-reader
88
# This RoleBinding is in the flow-aggregator namespace so the antrea-ui
99
# ServiceAccount can read the flow-aggregator-ca ConfigMap across namespaces.
1010
# It references flow-aggregator-exporter-role which is created by the

build/charts/antrea-ui/values.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ flowAggregator:
4747
caConfigMap: flow-aggregator-ca
4848
# -- Namespace where the Flow Aggregator is installed.
4949
namespace: flow-aggregator
50+
# -- Override the TLS server name used for certificate verification. Useful when dialing
51+
# via kubectl port-forward (loopback address) while the server cert is issued for the
52+
# in-cluster Service DNS name (e.g. flow-aggregator.flow-aggregator.svc).
53+
# Leave empty to use the hostname from the address field.
54+
serverName: ""
5055

5156
security:
5257
# -- (bool) Set the Secure attribute for Antrea UI cookies. The attribute is set by default when HTTPS is
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
# VITE_API_SERVER is intentionally empty in development. API requests (/api, /auth)
2-
# are proxied to http://localhost:8080 by the Vite dev server (see vite.config.ts),
3-
# matching the production nginx proxy setup.
4-
VITE_API_SERVER=
1+
VITE_API_SERVER=http://localhost:8080

client/web/antrea-ui/src/api/flow-stream.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@
1515
*/
1616

1717
import { describe, expect, it } from 'vitest';
18-
import { streamFilterKey } from './flow-stream';
18+
import { streamFilterKey, FlowStreamFilter } from './flow-stream';
1919

2020
describe('streamFilterKey', () => {
2121
it('matches for different object instances with the same filter', () => {
22-
const a = { follow: true as const };
23-
const b = { follow: true as const };
22+
const a: FlowStreamFilter = {};
23+
const b: FlowStreamFilter = {};
2424
expect(streamFilterKey(a)).toBe(streamFilterKey(b));
2525
});
2626

2727
it('normalizes array field order', () => {
28-
const a = { follow: true as const, namespaces: ['z', 'a'] };
29-
const b = { follow: true as const, namespaces: ['a', 'z'] };
28+
const a: FlowStreamFilter = { namespaces: ['z', 'a'] };
29+
const b: FlowStreamFilter = { namespaces: ['a', 'z'] };
3030
expect(streamFilterKey(a)).toBe(streamFilterKey(b));
3131
});
3232

3333
it('changes when a filter field changes', () => {
34-
const empty = { follow: true as const };
35-
const withNs = { follow: true as const, namespaces: ['default'] };
34+
const empty: FlowStreamFilter = {};
35+
const withNs: FlowStreamFilter = { namespaces: ['default'] };
3636
expect(streamFilterKey(empty)).not.toBe(streamFilterKey(withNs));
3737
});
3838
});

client/web/antrea-ui/src/api/flow-stream.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export interface FlowStreamFilter {
3232
flowTypes?: number[];
3333
ips?: string[];
3434
direction?: FlowFilterDirection;
35-
follow?: boolean;
3635
}
3736

3837
/**
@@ -48,7 +47,6 @@ export function streamFilterKey(f: FlowStreamFilter): string {
4847
const direction =
4948
f.direction && f.direction !== 'both' ? f.direction : 'both';
5049
return JSON.stringify({
51-
follow: f.follow !== false,
5250
namespaces,
5351
pods,
5452
podLabelSelector: f.podLabelSelector ?? '',
@@ -102,7 +100,6 @@ function buildStreamURL(filter: FlowStreamFilter): string {
102100
if (filter.direction && filter.direction !== 'both') {
103101
params.set('direction', filter.direction);
104102
}
105-
params.set('follow', filter.follow !== false ? 'true' : 'false');
106103
return `${apiUri}/flows/stream?${params.toString()}`;
107104
}
108105

client/web/antrea-ui/src/components/flow-filters.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { CdsButton } from '@cds/react/button';
1919
import { CdsSelect } from '@cds/react/select';
2020
import { FlowType, flowTypeLabel, destinationK8sServiceFilterKey } from '../api/flow-types';
2121
import { FlowStreamFilter, FlowFilterDirection } from '../api/flow-stream';
22-
import { FlowEntry } from '../api/flow-store';
22+
import { FlowEntry } from '../store/flow-store';
2323

2424
interface FlowFiltersProps {
2525
onFilterChange: (filter: FlowStreamFilter) => void;
@@ -235,12 +235,12 @@ export default function FlowFilters({
235235
setIpsText('');
236236
setPodLabelSelector('');
237237
setMenusCloseNonce(n => n + 1);
238-
onFilterChange({ follow: true });
238+
onFilterChange({});
239239
}, [onFilterChange]);
240240

241241
const applyFilters = useCallback(() => {
242242
setMenusCloseNonce(n => n + 1);
243-
const filter: FlowStreamFilter = { follow: true };
243+
const filter: FlowStreamFilter = {};
244244
if (selectedNamespaces.length > 0) {
245245
filter.namespaces = selectedNamespaces;
246246
}

client/web/antrea-ui/src/api/use-flow-stream.ts renamed to client/web/antrea-ui/src/hooks/use-flow-stream.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
*/
1616

1717
import { useEffect, useRef, useState, useCallback, useMemo, useContext } from 'react';
18-
import { Flow } from './flow-types';
19-
import { FlowStore, FlowEntry } from './flow-store';
20-
import { FlowStreamClient, FlowStreamFilter, streamFilterKey } from './flow-stream';
18+
import { Flow } from '../api/flow-types';
19+
import { FlowStore, FlowEntry } from '../store/flow-store';
20+
import { FlowStreamClient, FlowStreamFilter, streamFilterKey } from '../api/flow-stream';
2121
import SettingsContext from '../components/settings';
2222

2323
export interface UseFlowStreamResult {

0 commit comments

Comments
 (0)