Skip to content

Commit 05b7b62

Browse files
committed
query UDNs from K8S API
1 parent 7b4d18a commit 05b7b62

File tree

8 files changed

+146
-4
lines changed

8 files changed

+146
-4
lines changed

pkg/handler/k8s.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/auth"
9+
"github.com/netobserv/network-observability-console-plugin/pkg/kubernetes/resources"
10+
"github.com/netobserv/network-observability-console-plugin/pkg/utils"
11+
12+
"k8s.io/apimachinery/pkg/runtime/schema"
13+
)
14+
15+
func (h *Handlers) GetUDNIdss(ctx context.Context) func(w http.ResponseWriter, r *http.Request) {
16+
return func(w http.ResponseWriter, r *http.Request) {
17+
token, err := auth.GetUserToken(r.Header)
18+
if err != nil {
19+
writeError(w, http.StatusInternalServerError, err.Error())
20+
}
21+
22+
cudns, err := resources.List(ctx, token, schema.GroupVersionResource{
23+
Group: "k8s.ovn.org",
24+
Version: "v1",
25+
Resource: "clusteruserdefinednetworks",
26+
})
27+
if err != nil {
28+
writeError(w, http.StatusInternalServerError, err.Error())
29+
}
30+
31+
udns, err := resources.List(ctx, token, schema.GroupVersionResource{
32+
Group: "k8s.ovn.org",
33+
Version: "v1",
34+
Resource: "userdefinednetworks",
35+
})
36+
if err != nil {
37+
writeError(w, http.StatusInternalServerError, err.Error())
38+
}
39+
40+
values := []string{}
41+
for _, cudn := range cudns {
42+
md := cudn.Object["metadata"].(map[string]interface{})
43+
values = append(values, fmt.Sprintf("%s", md["name"]))
44+
}
45+
for _, udn := range udns {
46+
md := udn.Object["metadata"].(map[string]interface{})
47+
values = append(values, fmt.Sprintf("%s.%s", md["namespace"], md["name"]))
48+
}
49+
writeJSON(w, http.StatusOK, utils.NonEmpty(utils.Dedup(values)))
50+
}
51+
}

pkg/kubernetes/auth/check_auth.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (b *DenyAllChecker) CheckAdmin(_ context.Context, _ http.Header) error {
7373
return errors.New("deny all auth mode selected")
7474
}
7575

76-
func getUserToken(header http.Header) (string, error) {
76+
func GetUserToken(header http.Header) (string, error) {
7777
authValue := header.Get(AuthHeader)
7878
if authValue != "" {
7979
parts := strings.Split(authValue, "Bearer ")
@@ -130,7 +130,7 @@ type BearerTokenChecker struct {
130130

131131
func (c *BearerTokenChecker) CheckAuth(ctx context.Context, header http.Header) error {
132132
hlog.Debug("Checking authenticated user")
133-
token, err := getUserToken(header)
133+
token, err := GetUserToken(header)
134134
if err != nil {
135135
return err
136136
}
@@ -145,7 +145,7 @@ func (c *BearerTokenChecker) CheckAuth(ctx context.Context, header http.Header)
145145

146146
func (c *BearerTokenChecker) CheckAdmin(ctx context.Context, header http.Header) error {
147147
hlog.Debug("Checking admin user")
148-
token, err := getUserToken(header)
148+
token, err := GetUserToken(header)
149149
if err != nil {
150150
return err
151151
}

pkg/kubernetes/client/client.go

+31
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import (
55

66
authv1 "k8s.io/api/authentication/v1"
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
10+
"k8s.io/apimachinery/pkg/runtime/schema"
11+
"k8s.io/client-go/dynamic"
812
"k8s.io/client-go/kubernetes"
913
"k8s.io/client-go/rest"
1014
)
@@ -53,3 +57,30 @@ func NewInCluster() (KubeAPI, error) {
5357
}
5458
return &InCluster{client: client}, nil
5559
}
60+
61+
func (c *InCluster) GetResources(ctx context.Context, token string) ([]unstructured.Unstructured, error) {
62+
config, err := rest.InClusterConfig()
63+
if err != nil {
64+
return nil, err
65+
}
66+
config.BearerToken = token
67+
config.BearerTokenFile = ""
68+
69+
dynamicClient, err := dynamic.NewForConfig(config)
70+
if err != nil {
71+
panic(err)
72+
}
73+
74+
gvr := schema.GroupVersionResource{
75+
Group: "k8s.ovn.org",
76+
Version: "v1",
77+
Resource: "userdefinednetworks",
78+
}
79+
80+
// Retrieve the custom resource
81+
list, err := dynamicClient.Resource(gvr).List(context.TODO(), v1.ListOptions{})
82+
if err != nil {
83+
return nil, err
84+
}
85+
return list.Items, err
86+
}

pkg/kubernetes/resources/resources.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package resources
2+
3+
import (
4+
"context"
5+
6+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
8+
"k8s.io/apimachinery/pkg/runtime/schema"
9+
"k8s.io/client-go/dynamic"
10+
"k8s.io/client-go/rest"
11+
)
12+
13+
func List(ctx context.Context, token string, gvr schema.GroupVersionResource) ([]unstructured.Unstructured, error) {
14+
config, err := rest.InClusterConfig()
15+
if err != nil {
16+
return nil, err
17+
}
18+
config.BearerToken = token
19+
config.BearerTokenFile = ""
20+
21+
dynamicClient, err := dynamic.NewForConfig(config)
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
// Retrieve the custom resource
27+
list, err := dynamicClient.Resource(gvr).List(context.TODO(), v1.ListOptions{})
28+
if err != nil {
29+
return nil, err
30+
}
31+
return list.Items, err
32+
}

pkg/server/routes.go

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ func setupRoutes(ctx context.Context, cfg *config.Config, authChecker auth.Check
5555
api.HandleFunc("/resources/namespaces", h.GetNamespaces(ctx))
5656
api.HandleFunc("/resources/names", h.GetNames(ctx))
5757

58+
// K8S endpoints
59+
api.HandleFunc("/k8s/resources/udnIds", h.GetUDNIdss(ctx))
60+
5861
// Frontend files
5962
api.HandleFunc("/frontend-config", h.GetFrontendConfig())
6063
r.PathPrefix("/").Handler(http.FileServer(http.Dir("./web/dist/")))

web/src/api/routes.ts

+9
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ export const getResources = (namespace: string, kind: string, forcedNamespace?:
108108
});
109109
};
110110

111+
export const getK8SUDNIds = (): Promise<string[]> => {
112+
return axios.get(ContextSingleton.getHost() + '/api/k8s/resources/udnIds').then(r => {
113+
if (r.status >= 400) {
114+
throw new Error(`${r.statusText} [code=${r.status}]`);
115+
}
116+
return r.data;
117+
});
118+
};
119+
111120
export const getFlowMetrics = (params: FlowQuery, range: number | TimeRange): Promise<FlowMetricsResult> => {
112121
return getFlowMetricsGeneric(params, res => {
113122
return parseTopologyMetrics(

web/src/components/netflow-traffic.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,9 @@ export const NetflowTraffic: React.FC<NetflowTrafficProps> = ({
437437
model.setWarning,
438438
clearFlows
439439
);
440+
441+
// TODO: do something with UDN Ids to highlight empty / unused
442+
drawerRef.current?.getTopologyHandle()?.fetchUDNs();
440443
break;
441444
default:
442445
console.error('tick called on not implemented view Id', model.selectedViewId);

web/src/components/tabs/netflow-topology/netflow-topology.tsx

+14-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
Stats,
1515
TopologyMetrics
1616
} from '../../../api/loki';
17+
import { getK8SUDNIds } from '../../../api/routes';
1718
import { Config, Feature } from '../../../model/config';
1819
import { Filter, FilterDefinition, Filters } from '../../../model/filters';
1920
import {
@@ -52,6 +53,7 @@ export type NetflowTopologyHandle = {
5253
setWarning: (v?: Warning) => void,
5354
initFunction: () => void
5455
) => Promise<Stats[]> | undefined;
56+
fetchUDNs: () => void;
5557
};
5658

5759
export interface NetflowTopologyProps {
@@ -182,8 +184,19 @@ export const NetflowTopology: React.FC<NetflowTopologyProps> = React.forwardRef(
182184
[t]
183185
);
184186

187+
const fetchUDNs = React.useCallback(() => {
188+
getK8SUDNIds()
189+
.then(ids => {
190+
console.log('fetchUDNs', ids);
191+
})
192+
.catch(err => {
193+
console.error('fetchUDNs', err);
194+
});
195+
}, []);
196+
185197
React.useImperativeHandle(ref, () => ({
186-
fetch
198+
fetch,
199+
fetchUDNs
187200
}));
188201

189202
const getContent = React.useCallback(() => {

0 commit comments

Comments
 (0)