mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-04-05 10:17:50 +00:00
Compare commits
14 Commits
30.0-dev23
...
30.0-dev37
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40c745068e | ||
|
|
10dffd9331 | ||
|
|
0a800e8d8a | ||
|
|
068a4ff86e | ||
|
|
c45a869b75 | ||
|
|
0a793cd9e0 | ||
|
|
8d19080c11 | ||
|
|
319c3c7a8d | ||
|
|
0e7704eb15 | ||
|
|
dbcb776139 | ||
|
|
a3de34f544 | ||
|
|
99667984d6 | ||
|
|
763b0e7362 | ||
|
|
e07e04377f |
16
Dockerfile
16
Dockerfile
@@ -6,8 +6,7 @@ FROM node:16 AS front-end
|
|||||||
|
|
||||||
WORKDIR /app/ui-build
|
WORKDIR /app/ui-build
|
||||||
|
|
||||||
COPY ui/package.json .
|
COPY ui/package.json ui/package-lock.json ./
|
||||||
COPY ui/package-lock.json .
|
|
||||||
RUN npm i
|
RUN npm i
|
||||||
COPY ui .
|
COPY ui .
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
@@ -15,7 +14,7 @@ RUN npm run build
|
|||||||
### Base builder image for native builds architecture
|
### Base builder image for native builds architecture
|
||||||
FROM golang:1.17-alpine AS builder-native-base
|
FROM golang:1.17-alpine AS builder-native-base
|
||||||
ENV CGO_ENABLED=1 GOOS=linux
|
ENV CGO_ENABLED=1 GOOS=linux
|
||||||
RUN apk add libpcap-dev g++ perl-utils
|
RUN apk add --no-cache libpcap-dev g++ perl-utils
|
||||||
|
|
||||||
|
|
||||||
### Intermediate builder image for x86-64 to x86-64 native builds
|
### Intermediate builder image for x86-64 to x86-64 native builds
|
||||||
@@ -77,17 +76,16 @@ RUN go build -ldflags="-extldflags=-static -s -w \
|
|||||||
-X 'github.com/up9inc/mizu/agent/pkg/version.Ver=${VER}'" -o mizuagent .
|
-X 'github.com/up9inc/mizu/agent/pkg/version.Ver=${VER}'" -o mizuagent .
|
||||||
|
|
||||||
# Download Basenine executable, verify the sha1sum
|
# Download Basenine executable, verify the sha1sum
|
||||||
ADD https://github.com/up9inc/basenine/releases/download/v0.6.5/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
ADD https://github.com/up9inc/basenine/releases/download/v0.6.6/basenine_linux_${GOARCH} ./basenine_linux_${GOARCH}
|
||||||
ADD https://github.com/up9inc/basenine/releases/download/v0.6.5/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256
|
ADD https://github.com/up9inc/basenine/releases/download/v0.6.6/basenine_linux_${GOARCH}.sha256 ./basenine_linux_${GOARCH}.sha256
|
||||||
RUN shasum -a 256 -c basenine_linux_${GOARCH}.sha256
|
|
||||||
RUN chmod +x ./basenine_linux_${GOARCH}
|
|
||||||
RUN mv ./basenine_linux_${GOARCH} ./basenine
|
|
||||||
|
|
||||||
|
RUN shasum -a 256 -c basenine_linux_"${GOARCH}".sha256 && \
|
||||||
|
chmod +x ./basenine_linux_"${GOARCH}" && \
|
||||||
|
mv ./basenine_linux_"${GOARCH}" ./basenine
|
||||||
|
|
||||||
### The shipped image
|
### The shipped image
|
||||||
ARG TARGETARCH=amd64
|
ARG TARGETARCH=amd64
|
||||||
FROM ${TARGETARCH}/busybox:latest
|
FROM ${TARGETARCH}/busybox:latest
|
||||||
|
|
||||||
# gin-gonic runs in debug mode without this
|
# gin-gonic runs in debug mode without this
|
||||||
ENV GIN_MODE=release
|
ENV GIN_MODE=release
|
||||||
|
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -73,7 +73,7 @@ clean-agent: ## Clean agent.
|
|||||||
clean-cli: ## Clean CLI.
|
clean-cli: ## Clean CLI.
|
||||||
@(cd cli; make clean ; echo "CLI cleanup done" )
|
@(cd cli; make clean ; echo "CLI cleanup done" )
|
||||||
|
|
||||||
clean-docker: ## Run clen docker
|
clean-docker: ## Run clean docker
|
||||||
@(echo "DOCKER cleanup - NOT IMPLEMENTED YET " )
|
@(echo "DOCKER cleanup - NOT IMPLEMENTED YET " )
|
||||||
|
|
||||||
test-lint: ## Run lint on all modules
|
test-lint: ## Run lint on all modules
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ require (
|
|||||||
github.com/orcaman/concurrent-map v1.0.0
|
github.com/orcaman/concurrent-map v1.0.0
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220317230530-8472d80307f6
|
github.com/up9inc/basenine/client/go v0.0.0-20220326121918-785f3061c8ce
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap v0.0.0
|
github.com/up9inc/mizu/tap v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
|
|||||||
@@ -681,8 +681,8 @@ github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn
|
|||||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||||
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
|
||||||
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220317230530-8472d80307f6 h1:c0aVbLKYeFDAg246+NDgie2y484bsc20NaKLo8ODV3E=
|
github.com/up9inc/basenine/client/go v0.0.0-20220326121918-785f3061c8ce h1:vMTCpKItc9OyTLJXocNaq2NcBU5EnurJgTVOYb8W8dw=
|
||||||
github.com/up9inc/basenine/client/go v0.0.0-20220317230530-8472d80307f6/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
github.com/up9inc/basenine/client/go v0.0.0-20220326121918-785f3061c8ce/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/wI2L/jsondiff v0.1.1 h1:r2TkoEet7E4JMO5+s1RCY2R0LrNPNHY6hbDeow2hRHw=
|
github.com/wI2L/jsondiff v0.1.1 h1:r2TkoEet7E4JMO5+s1RCY2R0LrNPNHY6hbDeow2hRHw=
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ type ConfigStruct struct {
|
|||||||
HeadlessMode bool `yaml:"headless" default:"false"`
|
HeadlessMode bool `yaml:"headless" default:"false"`
|
||||||
LogLevelStr string `yaml:"log-level,omitempty" default:"INFO" readonly:""`
|
LogLevelStr string `yaml:"log-level,omitempty" default:"INFO" readonly:""`
|
||||||
ServiceMap bool `yaml:"service-map" default:"true"`
|
ServiceMap bool `yaml:"service-map" default:"true"`
|
||||||
OAS bool `yaml:"oas,omitempty" default:"false" readonly:""`
|
OAS bool `yaml:"oas" default:"true"`
|
||||||
Elastic shared.ElasticConfig `yaml:"elastic"`
|
Elastic shared.ElasticConfig `yaml:"elastic"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ require (
|
|||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/spf13/cobra v1.3.0
|
github.com/spf13/cobra v1.3.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/up9inc/basenine/server/lib v0.0.0-20220317230530-8472d80307f6
|
github.com/up9inc/basenine/server/lib v0.0.0-20220326121918-785f3061c8ce
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||||
|
|||||||
@@ -600,8 +600,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/up9inc/basenine/server/lib v0.0.0-20220317230530-8472d80307f6 h1:+RZTD+HdfIW2SMbc65yWkruTY+g5/1Av074m62A74ls=
|
github.com/up9inc/basenine/server/lib v0.0.0-20220326121918-785f3061c8ce h1:PypqybjmuxftGkX4NmP4JAUyEykZj2r6W4r9lnRZ/kE=
|
||||||
github.com/up9inc/basenine/server/lib v0.0.0-20220317230530-8472d80307f6/go.mod h1:ZIkxWiJm65jYQIso9k+OZKhR7gQ1we2jNyE2kQX9IQI=
|
github.com/up9inc/basenine/server/lib v0.0.0-20220326121918-785f3061c8ce/go.mod h1:ZIkxWiJm65jYQIso9k+OZKhR7gQ1we2jNyE2kQX9IQI=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ var filteringOptions *api.TrafficFilteringOptions // global
|
|||||||
var tapTargets []v1.Pod // global
|
var tapTargets []v1.Pod // global
|
||||||
var packetSourceManager *source.PacketSourceManager // global
|
var packetSourceManager *source.PacketSourceManager // global
|
||||||
var mainPacketInputChan chan source.TcpPacketInfo // global
|
var mainPacketInputChan chan source.TcpPacketInfo // global
|
||||||
|
var tlsTapperInstance *tlstapper.TlsTapper // global
|
||||||
|
|
||||||
func inArrayInt(arr []int, valueToCheck int) bool {
|
func inArrayInt(arr []int, valueToCheck int) bool {
|
||||||
for _, value := range arr {
|
for _, value := range arr {
|
||||||
@@ -92,7 +93,7 @@ func StartPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem,
|
|||||||
if *tls {
|
if *tls {
|
||||||
for _, e := range extensions {
|
for _, e := range extensions {
|
||||||
if e.Protocol.Name == "http" {
|
if e.Protocol.Name == "http" {
|
||||||
startTlsTapper(e, outputItems, options)
|
tlsTapperInstance = startTlsTapper(e, outputItems, options)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,24 +103,39 @@ func StartPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem,
|
|||||||
diagnose.StartMemoryProfiler(os.Getenv(MemoryProfilingDumpPath), os.Getenv(MemoryProfilingTimeIntervalSeconds))
|
diagnose.StartMemoryProfiler(os.Getenv(MemoryProfilingDumpPath), os.Getenv(MemoryProfilingTimeIntervalSeconds))
|
||||||
}
|
}
|
||||||
|
|
||||||
go startPassiveTapper(opts, outputItems)
|
streamsMap, assembler := initializePassiveTapper(opts, outputItems)
|
||||||
|
go startPassiveTapper(streamsMap, assembler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateTapTargets(newTapTargets []v1.Pod) {
|
func UpdateTapTargets(newTapTargets []v1.Pod) {
|
||||||
|
success := true
|
||||||
|
|
||||||
tapTargets = newTapTargets
|
tapTargets = newTapTargets
|
||||||
if err := initializePacketSources(); err != nil {
|
|
||||||
logger.Log.Fatal(err)
|
packetSourceManager.UpdatePods(tapTargets)
|
||||||
|
|
||||||
|
if tlsTapperInstance != nil {
|
||||||
|
if err := tlstapper.UpdateTapTargets(tlsTapperInstance, &tapTargets, *procfs); err != nil {
|
||||||
|
tlstapper.LogError(err)
|
||||||
|
success = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printNewTapTargets()
|
|
||||||
|
printNewTapTargets(success)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printNewTapTargets() {
|
func printNewTapTargets(success bool) {
|
||||||
printStr := ""
|
printStr := ""
|
||||||
for _, tapTarget := range tapTargets {
|
for _, tapTarget := range tapTargets {
|
||||||
printStr += fmt.Sprintf("%s (%s), ", tapTarget.Status.PodIP, tapTarget.Name)
|
printStr += fmt.Sprintf("%s (%s), ", tapTarget.Status.PodIP, tapTarget.Name)
|
||||||
}
|
}
|
||||||
printStr = strings.TrimRight(printStr, ", ")
|
printStr = strings.TrimRight(printStr, ", ")
|
||||||
logger.Log.Infof("Now tapping: %s", printStr)
|
|
||||||
|
if success {
|
||||||
|
logger.Log.Infof("Now tapping: %s", printStr)
|
||||||
|
} else {
|
||||||
|
logger.Log.Errorf("Failed to start tapping: %s", printStr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printPeriodicStats(cleaner *Cleaner) {
|
func printPeriodicStats(cleaner *Cleaner) {
|
||||||
@@ -190,9 +206,8 @@ func initializePacketSources() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func startPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem) {
|
func initializePassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem) (*tcpStreamMap, *tcpAssembler) {
|
||||||
streamsMap := NewTcpStreamMap()
|
streamsMap := NewTcpStreamMap()
|
||||||
go streamsMap.closeTimedoutTcpStreamChannels()
|
|
||||||
|
|
||||||
diagnose.InitializeErrorsMap(*debug, *verbose, *quiet)
|
diagnose.InitializeErrorsMap(*debug, *verbose, *quiet)
|
||||||
diagnose.InitializeTapperInternalStats()
|
diagnose.InitializeTapperInternalStats()
|
||||||
@@ -205,6 +220,12 @@ func startPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem)
|
|||||||
|
|
||||||
assembler := NewTcpAssembler(outputItems, streamsMap, opts)
|
assembler := NewTcpAssembler(outputItems, streamsMap, opts)
|
||||||
|
|
||||||
|
return streamsMap, assembler
|
||||||
|
}
|
||||||
|
|
||||||
|
func startPassiveTapper(streamsMap *tcpStreamMap, assembler *tcpAssembler) {
|
||||||
|
go streamsMap.closeTimedoutTcpStreamChannels()
|
||||||
|
|
||||||
diagnose.AppStats.SetStartTime(time.Now())
|
diagnose.AppStats.SetStartTime(time.Now())
|
||||||
|
|
||||||
staleConnectionTimeout := time.Second * time.Duration(*staleTimeoutSeconds)
|
staleConnectionTimeout := time.Second * time.Duration(*staleTimeoutSeconds)
|
||||||
@@ -236,13 +257,18 @@ func startPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem)
|
|||||||
logger.Log.Infof("AppStats: %v", diagnose.AppStats)
|
logger.Log.Infof("AppStats: %v", diagnose.AppStats)
|
||||||
}
|
}
|
||||||
|
|
||||||
func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChannelItem, options *api.TrafficFilteringOptions) {
|
func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChannelItem, options *api.TrafficFilteringOptions) *tlstapper.TlsTapper {
|
||||||
tls := tlstapper.TlsTapper{}
|
tls := tlstapper.TlsTapper{}
|
||||||
tlsPerfBufferSize := os.Getpagesize() * 100
|
tlsPerfBufferSize := os.Getpagesize() * 100
|
||||||
|
|
||||||
if err := tls.Init(tlsPerfBufferSize, *procfs, extension); err != nil {
|
if err := tls.Init(tlsPerfBufferSize, *procfs, extension); err != nil {
|
||||||
tlstapper.LogError(err)
|
tlstapper.LogError(err)
|
||||||
return
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tlstapper.UpdateTapTargets(&tls, &tapTargets, *procfs); err != nil {
|
||||||
|
tlstapper.LogError(err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// A quick way to instrument libssl.so without PID filtering - used for debuging and troubleshooting
|
// A quick way to instrument libssl.so without PID filtering - used for debuging and troubleshooting
|
||||||
@@ -250,19 +276,16 @@ func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChanne
|
|||||||
if os.Getenv("MIZU_GLOBAL_SSL_LIBRARY") != "" {
|
if os.Getenv("MIZU_GLOBAL_SSL_LIBRARY") != "" {
|
||||||
if err := tls.GlobalTap(os.Getenv("MIZU_GLOBAL_SSL_LIBRARY")); err != nil {
|
if err := tls.GlobalTap(os.Getenv("MIZU_GLOBAL_SSL_LIBRARY")); err != nil {
|
||||||
tlstapper.LogError(err)
|
tlstapper.LogError(err)
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tlstapper.UpdateTapTargets(&tls, &tapTargets, *procfs); err != nil {
|
|
||||||
tlstapper.LogError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var emitter api.Emitter = &api.Emitting{
|
var emitter api.Emitter = &api.Emitting{
|
||||||
AppStats: &diagnose.AppStats,
|
AppStats: &diagnose.AppStats,
|
||||||
OutputChannel: outputItems,
|
OutputChannel: outputItems,
|
||||||
}
|
}
|
||||||
|
|
||||||
go tls.Poll(emitter, options)
|
go tls.Poll(emitter, options)
|
||||||
|
|
||||||
|
return &tls
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,16 @@ import (
|
|||||||
const bpfFilterMaxPods = 150
|
const bpfFilterMaxPods = 150
|
||||||
const hostSourcePid = "0"
|
const hostSourcePid = "0"
|
||||||
|
|
||||||
|
type PacketSourceManagerConfig struct {
|
||||||
|
mtls bool
|
||||||
|
procfs string
|
||||||
|
interfaceName string
|
||||||
|
behaviour TcpPacketSourceBehaviour
|
||||||
|
}
|
||||||
|
|
||||||
type PacketSourceManager struct {
|
type PacketSourceManager struct {
|
||||||
sources map[string]*tcpPacketSource
|
sources map[string]*tcpPacketSource
|
||||||
|
config PacketSourceManagerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPacketSourceManager(procfs string, filename string, interfaceName string,
|
func NewPacketSourceManager(procfs string, filename string, interfaceName string,
|
||||||
@@ -28,7 +36,14 @@ func NewPacketSourceManager(procfs string, filename string, interfaceName string
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceManager.UpdatePods(mtls, procfs, pods, interfaceName, behaviour)
|
sourceManager.config = PacketSourceManagerConfig{
|
||||||
|
mtls: mtls,
|
||||||
|
procfs: procfs,
|
||||||
|
interfaceName: interfaceName,
|
||||||
|
behaviour: behaviour,
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceManager.UpdatePods(pods)
|
||||||
return sourceManager, nil
|
return sourceManager, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,10 +64,9 @@ func newHostPacketSource(filename string, interfaceName string,
|
|||||||
return source, nil
|
return source, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PacketSourceManager) UpdatePods(mtls bool, procfs string, pods []v1.Pod,
|
func (m *PacketSourceManager) UpdatePods(pods []v1.Pod) {
|
||||||
interfaceName string, behaviour TcpPacketSourceBehaviour) {
|
if m.config.mtls {
|
||||||
if mtls {
|
m.updateMtlsPods(m.config.procfs, pods, m.config.interfaceName, m.config.behaviour)
|
||||||
m.updateMtlsPods(procfs, pods, interfaceName, behaviour)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m.setBPFFilter(pods)
|
m.setBPFFilter(pods)
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ func UpdateTapTargets(tls *TlsTapper, pods *[]v1.Pod, procfs string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tls.ClearPids()
|
||||||
|
|
||||||
for _, pid := range containerPids {
|
for _, pid := range containerPids {
|
||||||
if err := tls.AddPid(procfs, pid); err != nil {
|
if err := tls.AddPid(procfs, pid); err != nil {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/up9inc/mizu/shared/logger"
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go tlsTapper bpf/tls_tapper.c -- -O2 -g -D__TARGET_ARCH_x86
|
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go tlsTapper bpf/tls_tapper.c -- -O2 -g -D__TARGET_ARCH_x86
|
||||||
@@ -14,6 +15,7 @@ type TlsTapper struct {
|
|||||||
syscallHooks syscallHooks
|
syscallHooks syscallHooks
|
||||||
sslHooksStructs []sslHooks
|
sslHooksStructs []sslHooks
|
||||||
poller *tlsPoller
|
poller *tlsPoller
|
||||||
|
registeredPids sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TlsTapper) Init(bufferSize int, procfs string, extension *api.Extension) error {
|
func (t *TlsTapper) Init(bufferSize int, procfs string, extension *api.Extension) error {
|
||||||
@@ -70,6 +72,16 @@ func (t *TlsTapper) RemovePid(pid uint32) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TlsTapper) ClearPids() {
|
||||||
|
t.registeredPids.Range(func(key, v interface{}) bool {
|
||||||
|
if err := t.RemovePid(key.(uint32)); err != nil {
|
||||||
|
LogError(err)
|
||||||
|
}
|
||||||
|
t.registeredPids.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TlsTapper) Close() []error {
|
func (t *TlsTapper) Close() []error {
|
||||||
errors := make([]error, 0)
|
errors := make([]error, 0)
|
||||||
|
|
||||||
@@ -116,6 +128,8 @@ func (t *TlsTapper) tapPid(pid uint32, sslLibrary string) error {
|
|||||||
if err := pids.Put(pid, uint32(1)); err != nil {
|
if err := pids.Put(pid, uint32(1)); err != nil {
|
||||||
return errors.Wrap(err, 0)
|
return errors.Wrap(err, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.registeredPids.Store(pid, true)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@up9/mizu-common",
|
"name": "@up9/mizu-common",
|
||||||
"version": "1.0.136",
|
"version": "1.0.142",
|
||||||
"description": "Made with create-react-library",
|
"description": "Made with create-react-library",
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||||
"node-sass": "^6.0.0",
|
"node-sass": "^6.0.0",
|
||||||
"react":"^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"recoil": "^0.5.2",
|
"recoil": "^0.5.2",
|
||||||
"react-copy-to-clipboard": "^5.0.3",
|
"react-copy-to-clipboard": "^5.0.3",
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
"rollup-plugin-postcss": "^4.0.2",
|
"rollup-plugin-postcss": "^4.0.2",
|
||||||
"rollup-plugin-sass": "^1.2.10",
|
"rollup-plugin-sass": "^1.2.10",
|
||||||
"rollup-plugin-scss": "^3.0.0",
|
"rollup-plugin-scss": "^3.0.0",
|
||||||
"react":"^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"typescript": "^4.2.4"
|
"typescript": "^4.2.4"
|
||||||
},
|
},
|
||||||
@@ -90,4 +90,4 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Box, Fade, FormControl, MenuItem, Modal, Backdrop, ListSubheader } from "@material-ui/core";
|
import { Box, Fade, FormControl, MenuItem, Modal, Backdrop } from "@material-ui/core";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { RedocStandalone } from "redoc";
|
import { RedocStandalone } from "redoc";
|
||||||
import closeIcon from "assets/closeIcon.svg";
|
import closeIcon from "assets/closeIcon.svg";
|
||||||
@@ -7,7 +7,8 @@ import style from './OasModal.module.sass';
|
|||||||
import openApiLogo from 'assets/openApiLogo.png'
|
import openApiLogo from 'assets/openApiLogo.png'
|
||||||
import { redocThemeOptions } from "./redocThemeOptions";
|
import { redocThemeOptions } from "./redocThemeOptions";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { UI } from "../..";
|
import { Select } from "../UI/Select";
|
||||||
|
|
||||||
|
|
||||||
const modalStyle = {
|
const modalStyle = {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@@ -23,68 +24,44 @@ const modalStyle = {
|
|||||||
color: '#000',
|
color: '#000',
|
||||||
};
|
};
|
||||||
|
|
||||||
const ipAddressWithPortRegex = new RegExp('([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}):([0-9]{1,5})');
|
|
||||||
|
|
||||||
const OasModal = ({ openModal, handleCloseModal, getOasServices, getOasByService }) => {
|
const OasModal = ({ openModal, handleCloseModal, getOasServices, getOasByService }) => {
|
||||||
const [oasServices, setOasServices] = useState([] as string[])
|
const [oasServices, setOasServices] = useState([] as string[])
|
||||||
const [selectedServiceName, setSelectedServiceName] = useState("");
|
const [selectedServiceName, setSelectedServiceName] = useState("");
|
||||||
const [selectedServiceSpec, setSelectedServiceSpec] = useState(null);
|
const [selectedServiceSpec, setSelectedServiceSpec] = useState(null);
|
||||||
const [resolvedServices, setResolvedServices] = useState([]);
|
|
||||||
const [unResolvedServices, setUnResolvedServices] = useState([]);
|
|
||||||
|
|
||||||
const onSelectedOASService = useCallback(async (selectedService) => {
|
const onSelectedOASService = async (selectedService) => {
|
||||||
if (!!selectedService) {
|
if (oasServices.length === 0) {
|
||||||
setSelectedServiceName(selectedService);
|
setSelectedServiceSpec(null);
|
||||||
if (oasServices.length === 0) {
|
setSelectedServiceName("");
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
else {
|
||||||
const data = await getOasByService(selectedService);
|
setSelectedServiceName(selectedService ? selectedService : oasServices[0]);
|
||||||
setSelectedServiceSpec(data);
|
}
|
||||||
|
try {
|
||||||
|
const data = await getOasByService(selectedService ? selectedService : oasServices[0]);
|
||||||
|
setSelectedServiceSpec(data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast.error("Error occurred while fetching service OAS spec");
|
toast.error("Error occurred while fetching service OAS spec");
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, [oasServices.length])
|
|
||||||
|
|
||||||
const resolvedArrayBuilder = useCallback(async (services) => {
|
|
||||||
const resServices = [];
|
|
||||||
const unResServices = [];
|
|
||||||
services.forEach(s => {
|
|
||||||
if (ipAddressWithPortRegex.test(s)) {
|
|
||||||
unResServices.push(s);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resServices.push(s);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
resServices.sort();
|
|
||||||
unResServices.sort();
|
|
||||||
if (resServices.length > 0) {
|
|
||||||
onSelectedOASService(resServices[0]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
onSelectedOASService(unResServices[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
setResolvedServices(resServices);
|
|
||||||
setUnResolvedServices(unResServices);
|
|
||||||
}, [onSelectedOASService])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const services = await getOasServices();
|
const services = await getOasServices();
|
||||||
resolvedArrayBuilder(services);
|
|
||||||
setOasServices(services);
|
setOasServices(services);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, [openModal, resolvedArrayBuilder]);
|
}, [openModal]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onSelectedOASService(null);
|
||||||
|
},[oasServices])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@@ -102,34 +79,27 @@ const OasModal = ({ openModal, handleCloseModal, getOasServices, getOasByService
|
|||||||
<Box sx={modalStyle}>
|
<Box sx={modalStyle}>
|
||||||
<div className={style.boxContainer}>
|
<div className={style.boxContainer}>
|
||||||
<div className={style.selectHeader}>
|
<div className={style.selectHeader}>
|
||||||
<div><img src={openApiLogo} alt="openApi" className={style.openApilogo} /></div>
|
<div><img src={openApiLogo} alt="openAPI" className={style.openApilogo} /></div>
|
||||||
<div className={style.title}>OpenApi </div>
|
<div className={style.title}>OpenAPI</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ cursor: "pointer" }}>
|
<div style={{ cursor: "pointer" }}>
|
||||||
<img src={closeIcon} alt="close" onClick={handleCloseModal} />
|
<img src={closeIcon} alt="close" onClick={handleCloseModal} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={style.selectContainer} >
|
<div className={style.selectContainer} >
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<UI.Select
|
<Select
|
||||||
labelId="service-select-label"
|
labelId="service-select-label"
|
||||||
id="service-select"
|
id="service-select"
|
||||||
value={selectedServiceName}
|
value={selectedServiceName}
|
||||||
onChangeCb={onSelectedOASService}
|
onChangeCb={onSelectedOASService}
|
||||||
>
|
>
|
||||||
<ListSubheader disableSticky={true}>Resolved</ListSubheader>
|
{oasServices.map((service) => (
|
||||||
{resolvedServices.map((service) => (
|
|
||||||
<MenuItem key={service} value={service}>
|
<MenuItem key={service} value={service}>
|
||||||
{service}
|
{service}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
<ListSubheader disableSticky={true}>UnResolved</ListSubheader>
|
</Select>
|
||||||
{unResolvedServices.map((service) => (
|
|
||||||
<MenuItem key={service} value={service}>
|
|
||||||
{service}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</UI.Select>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
<div className={style.borderLine}></div>
|
<div className={style.borderLine}></div>
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import React, {useEffect, useState} from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import EntryViewer from "./EntryDetailed/EntryViewer";
|
import EntryViewer from "./EntryDetailed/EntryViewer";
|
||||||
import {EntryItem} from "./EntryListItem/EntryListItem";
|
import { EntryItem } from "./EntryListItem/EntryListItem";
|
||||||
import {makeStyles} from "@material-ui/core";
|
import { makeStyles } from "@material-ui/core";
|
||||||
import Protocol from "../UI/Protocol"
|
import Protocol from "../UI/Protocol"
|
||||||
import Queryable from "../UI/Queryable";
|
import Queryable from "../UI/Queryable";
|
||||||
import {toast} from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import {RecoilState, useRecoilState, useRecoilValue} from "recoil";
|
import { RecoilState, useRecoilState, useRecoilValue } from "recoil";
|
||||||
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
|
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
|
||||||
import trafficViewerApi from "../../recoil/TrafficViewerApi";
|
import trafficViewerApi from "../../recoil/TrafficViewerApi";
|
||||||
import TrafficViewerApi from "./TrafficViewerApi";
|
import TrafficViewerApi from "./TrafficViewerApi";
|
||||||
import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi/atom";
|
import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi/atom";
|
||||||
import queryAtom from "../../recoil/query/atom";
|
import queryAtom from "../../recoil/query/atom";
|
||||||
import useWindowDimensions, { useRequestTextByWidth } from "../../hooks/WindowDimensionsHook";
|
import useWindowDimensions, { useRequestTextByWidth } from "../../hooks/WindowDimensionsHook";
|
||||||
|
import { TOAST_CONTAINER_ID } from "../../configs/Consts";
|
||||||
|
|
||||||
const useStyles = makeStyles(() => ({
|
const useStyles = makeStyles(() => ({
|
||||||
entryTitle: {
|
entryTitle: {
|
||||||
@@ -37,24 +38,24 @@ const useStyles = makeStyles(() => ({
|
|||||||
|
|
||||||
export const formatSize = (n: number) => n > 1000 ? `${Math.round(n / 1000)}KB` : `${n} B`;
|
export const formatSize = (n: number) => n > 1000 ? `${Math.round(n / 1000)}KB` : `${n} B`;
|
||||||
const minSizeDisplayRequestSize = 880;
|
const minSizeDisplayRequestSize = 880;
|
||||||
const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
const EntryTitle: React.FC<any> = ({ protocol, data, elapsedTime }) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const request = data.request;
|
const request = data.request;
|
||||||
const response = data.response;
|
const response = data.response;
|
||||||
|
|
||||||
const { width } = useWindowDimensions();
|
const { width } = useWindowDimensions();
|
||||||
const {requestText, responseText, elapsedTimeText} = useRequestTextByWidth(width)
|
const { requestText, responseText, elapsedTimeText } = useRequestTextByWidth(width)
|
||||||
|
|
||||||
return <div className={classes.entryTitle}>
|
return <div className={classes.entryTitle}>
|
||||||
<Protocol protocol={protocol} horizontal={true}/>
|
<Protocol protocol={protocol} horizontal={true} />
|
||||||
{(width > minSizeDisplayRequestSize) && <div style={{right: "30px", position: "absolute", display: "flex"}}>
|
{(width > minSizeDisplayRequestSize) && <div style={{ right: "30px", position: "absolute", display: "flex" }}>
|
||||||
{request && <Queryable
|
{request && <Queryable
|
||||||
query={`requestSize == ${data.requestSize}`}
|
query={`requestSize == ${data.requestSize}`}
|
||||||
style={{margin: "0 18px"}}
|
style={{ margin: "0 18px" }}
|
||||||
displayIconOnMouseOver={true}
|
displayIconOnMouseOver={true}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{opacity: 0.5}}
|
style={{ opacity: 0.5 }}
|
||||||
id="entryDetailedTitleRequestSize"
|
id="entryDetailedTitleRequestSize"
|
||||||
>
|
>
|
||||||
{`${requestText}${formatSize(data.requestSize)}`}
|
{`${requestText}${formatSize(data.requestSize)}`}
|
||||||
@@ -62,11 +63,11 @@ const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
|||||||
</Queryable>}
|
</Queryable>}
|
||||||
{response && <Queryable
|
{response && <Queryable
|
||||||
query={`responseSize == ${data.responseSize}`}
|
query={`responseSize == ${data.responseSize}`}
|
||||||
style={{margin: "0 18px"}}
|
style={{ margin: "0 18px" }}
|
||||||
displayIconOnMouseOver={true}
|
displayIconOnMouseOver={true}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{opacity: 0.5}}
|
style={{ opacity: 0.5 }}
|
||||||
id="entryDetailedTitleResponseSize"
|
id="entryDetailedTitleResponseSize"
|
||||||
>
|
>
|
||||||
{`${responseText}${formatSize(data.responseSize)}`}
|
{`${responseText}${formatSize(data.responseSize)}`}
|
||||||
@@ -74,11 +75,11 @@ const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
|||||||
</Queryable>}
|
</Queryable>}
|
||||||
{response && <Queryable
|
{response && <Queryable
|
||||||
query={`elapsedTime >= ${elapsedTime}`}
|
query={`elapsedTime >= ${elapsedTime}`}
|
||||||
style={{margin: "0 0 0 18px"}}
|
style={{ margin: "0 0 0 18px" }}
|
||||||
displayIconOnMouseOver={true}
|
displayIconOnMouseOver={true}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{opacity: 0.5}}
|
style={{ opacity: 0.5 }}
|
||||||
id="entryDetailedTitleElapsedTime"
|
id="entryDetailedTitleElapsedTime"
|
||||||
>
|
>
|
||||||
{`${elapsedTimeText}${Math.round(elapsedTime)}ms`}
|
{`${elapsedTimeText}${Math.round(elapsedTime)}ms`}
|
||||||
@@ -88,7 +89,7 @@ const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
|||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const EntrySummary: React.FC<any> = ({entry}) => {
|
const EntrySummary: React.FC<any> = ({ entry }) => {
|
||||||
return <EntryItem
|
return <EntryItem
|
||||||
key={`entry-${entry.id}`}
|
key={`entry-${entry.id}`}
|
||||||
entry={entry}
|
entry={entry}
|
||||||
@@ -117,14 +118,10 @@ export const EntryDetailed = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response?.data?.type) {
|
if (error.response?.data?.type) {
|
||||||
toast[error.response.data.type](`Entry[${focusedEntryId}]: ${error.response.data.msg}`, {
|
toast[error.response.data.type](`Entry[${focusedEntryId}]: ${error.response.data.msg}`, {
|
||||||
position: "bottom-right",
|
|
||||||
theme: "colored",
|
theme: "colored",
|
||||||
autoClose: error.response.data.autoClose,
|
autoClose: error.response.data.autoClose,
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true,
|
|
||||||
progress: undefined,
|
progress: undefined,
|
||||||
|
containerId: TOAST_CONTAINER_ID
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@@ -139,7 +136,7 @@ export const EntryDetailed = () => {
|
|||||||
data={entryData.data}
|
data={entryData.data}
|
||||||
elapsedTime={entryData.data.elapsedTime}
|
elapsedTime={entryData.data.elapsedTime}
|
||||||
/>}
|
/>}
|
||||||
{entryData && <EntrySummary entry={entryData.base}/>}
|
{entryData && <EntrySummary entry={entryData.base} />}
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{entryData && <EntryViewer
|
{entryData && <EntryViewer
|
||||||
representation={entryData.representation}
|
representation={entryData.representation}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import SwapHorizIcon from '@material-ui/icons/SwapHoriz';
|
|||||||
import styles from './EntryListItem.module.sass';
|
import styles from './EntryListItem.module.sass';
|
||||||
import StatusCode, {getClassification, StatusCodeClassification} from "../../UI/StatusCode";
|
import StatusCode, {getClassification, StatusCodeClassification} from "../../UI/StatusCode";
|
||||||
import Protocol, {ProtocolInterface} from "../../UI/Protocol"
|
import Protocol, {ProtocolInterface} from "../../UI/Protocol"
|
||||||
import eBPFLogo from '../../assets/ebpf.png';
|
import eBPFLogo from 'assets/lock.svg';
|
||||||
import {Summary} from "../../UI/Summary";
|
import {Summary} from "../../UI/Summary";
|
||||||
import Queryable from "../../UI/Queryable";
|
import Queryable from "../../UI/Queryable";
|
||||||
import ingoingIconSuccess from "assets/ingoing-traffic-success.svg"
|
import ingoingIconSuccess from "assets/ingoing-traffic-success.svg"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -8,8 +8,7 @@ import { EntryDetailed } from "./EntryDetailed";
|
|||||||
import playIcon from 'assets/run.svg';
|
import playIcon from 'assets/run.svg';
|
||||||
import pauseIcon from 'assets/pause.svg';
|
import pauseIcon from 'assets/pause.svg';
|
||||||
import variables from '../../variables.module.scss';
|
import variables from '../../variables.module.scss';
|
||||||
import { toast,ToastContainer } from 'react-toastify';
|
import { toast, ToastContainer } from 'react-toastify';
|
||||||
import 'react-toastify/dist/ReactToastify.css';
|
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { RecoilRoot, RecoilState, useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
|
import { RecoilRoot, RecoilState, useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
|
||||||
import entriesAtom from "../../recoil/entries";
|
import entriesAtom from "../../recoil/entries";
|
||||||
@@ -20,6 +19,7 @@ import trafficViewerApiAtom from "../../recoil/TrafficViewerApi"
|
|||||||
import TrafficViewerApi from "./TrafficViewerApi";
|
import TrafficViewerApi from "./TrafficViewerApi";
|
||||||
import { StatusBar } from "../UI/StatusBar";
|
import { StatusBar } from "../UI/StatusBar";
|
||||||
import tappingStatusAtom from "../../recoil/tappingStatus/atom";
|
import tappingStatusAtom from "../../recoil/tappingStatus/atom";
|
||||||
|
import { TOAST_CONTAINER_ID } from "../../configs/Consts";
|
||||||
|
|
||||||
const useLayoutStyles = makeStyles(() => ({
|
const useLayoutStyles = makeStyles(() => ({
|
||||||
details: {
|
details: {
|
||||||
@@ -47,14 +47,14 @@ interface TrafficViewerProps {
|
|||||||
trafficViewerApiProp: TrafficViewerApi,
|
trafficViewerApiProp: TrafficViewerApi,
|
||||||
actionButtons?: JSX.Element,
|
actionButtons?: JSX.Element,
|
||||||
isShowStatusBar?: boolean,
|
isShowStatusBar?: boolean,
|
||||||
webSocketUrl : string,
|
webSocketUrl: string,
|
||||||
isCloseWebSocket : boolean,
|
isCloseWebSocket: boolean,
|
||||||
isDemoBannerView : boolean
|
isDemoBannerView: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus, trafficViewerApiProp,
|
export const TrafficViewer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus, trafficViewerApiProp,
|
||||||
actionButtons,isShowStatusBar,webSocketUrl,
|
actionButtons, isShowStatusBar, webSocketUrl,
|
||||||
isCloseWebSocket, isDemoBannerView}) => {
|
isCloseWebSocket, isDemoBannerView }) => {
|
||||||
|
|
||||||
const classes = useLayoutStyles();
|
const classes = useLayoutStyles();
|
||||||
|
|
||||||
@@ -106,9 +106,9 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
handleQueryChange(query);
|
handleQueryChange(query);
|
||||||
}, [query, handleQueryChange]);
|
}, [query, handleQueryChange]);
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(() => {
|
||||||
isCloseWebSocket && closeWebSocket()
|
isCloseWebSocket && closeWebSocket()
|
||||||
},[isCloseWebSocket])
|
}, [isCloseWebSocket])
|
||||||
|
|
||||||
const ws = useRef(null);
|
const ws = useRef(null);
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
sendQueryWhenWsOpen(query);
|
sendQueryWhenWsOpen(query);
|
||||||
|
|
||||||
ws.current.onclose = () => {
|
ws.current.onclose = () => {
|
||||||
if(window.location.pathname === "/")
|
if (window.location.pathname === "/")
|
||||||
setForceRender(forceRender + 1);
|
setForceRender(forceRender + 1);
|
||||||
}
|
}
|
||||||
ws.current.onerror = (event) => {
|
ws.current.onerror = (event) => {
|
||||||
@@ -140,13 +140,13 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
openWebSocket(`leftOff(${leftOffBottom})`, false);
|
openWebSocket(`leftOff(${leftOffBottom})`, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendQueryWhenWsOpen = (query) => {
|
const sendQueryWhenWsOpen = (query) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (ws?.current?.readyState === WebSocket.OPEN) {
|
if (ws?.current?.readyState === WebSocket.OPEN) {
|
||||||
ws.current.send(JSON.stringify({"query": query, "enableFullEntries": false}));
|
ws.current.send(JSON.stringify({ "query": query, "enableFullEntries": false }));
|
||||||
} else {
|
} else {
|
||||||
sendQueryWhenWsOpen(query);
|
sendQueryWhenWsOpen(query);
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const closeWebSocket = () => {
|
const closeWebSocket = () => {
|
||||||
if(ws?.current?.readyState === WebSocket.OPEN) {
|
if (ws?.current?.readyState === WebSocket.OPEN) {
|
||||||
ws.current.close();
|
ws.current.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,14 +186,11 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
break;
|
break;
|
||||||
case "toast":
|
case "toast":
|
||||||
toast[message.data.type](message.data.text, {
|
toast[message.data.type](message.data.text, {
|
||||||
position: "bottom-right",
|
|
||||||
theme: "colored",
|
theme: "colored",
|
||||||
autoClose: message.data.autoClose,
|
autoClose: message.data.autoClose,
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
pauseOnHover: true,
|
||||||
draggable: true,
|
|
||||||
progress: undefined,
|
progress: undefined,
|
||||||
|
containerId: TOAST_CONTAINER_ID
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "queryMetadata":
|
case "queryMetadata":
|
||||||
@@ -217,13 +214,13 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTrafficViewerApiState({...trafficViewerApiProp, webSocket : {close : closeWebSocket}});
|
setTrafficViewerApiState({ ...trafficViewerApiProp, webSocket: { close: closeWebSocket } });
|
||||||
(async () => {
|
(async () => {
|
||||||
openWebSocket("leftOff(-1)", true);
|
openWebSocket("leftOff(-1)", true);
|
||||||
try{
|
try {
|
||||||
const tapStatusResponse = await trafficViewerApiProp.tapStatus();
|
const tapStatusResponse = await trafficViewerApiProp.tapStatus();
|
||||||
setTappingStatus(tapStatusResponse);
|
setTappingStatus(tapStatusResponse);
|
||||||
if(setAnalyzeStatus) {
|
if (setAnalyzeStatus) {
|
||||||
const analyzeStatusResponse = await trafficViewerApiProp.analyzeStatus();
|
const analyzeStatusResponse = await trafficViewerApiProp.analyzeStatus();
|
||||||
setAnalyzeStatus(analyzeStatusResponse);
|
setAnalyzeStatus(analyzeStatusResponse);
|
||||||
}
|
}
|
||||||
@@ -235,7 +232,7 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleConnection = () => {
|
const toggleConnection = () => {
|
||||||
if(ws?.current?.readyState === WebSocket.OPEN) {
|
if (ws?.current?.readyState === WebSocket.OPEN) {
|
||||||
ws?.current?.close();
|
ws?.current?.close();
|
||||||
} else {
|
} else {
|
||||||
if (query) {
|
if (query) {
|
||||||
@@ -349,19 +346,28 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
setAddressesWithTLS={setAddressesWithTLS}
|
setAddressesWithTLS={setAddressesWithTLS}
|
||||||
userDismissedTLSWarning={userDismissedTLSWarning}
|
userDismissedTLSWarning={userDismissedTLSWarning}
|
||||||
setUserDismissedTLSWarning={setUserDismissedTLSWarning} />
|
setUserDismissedTLSWarning={setUserDismissedTLSWarning} />
|
||||||
<ToastContainer/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const MemoiedTrafficViewer = React.memo(TrafficViewer)
|
const MemoiedTrafficViewer = React.memo(TrafficViewer)
|
||||||
const TrafficViewerContainer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus, trafficViewerApiProp,
|
const TrafficViewerContainer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus, trafficViewerApiProp,
|
||||||
actionButtons, isShowStatusBar = true ,
|
actionButtons, isShowStatusBar = true,
|
||||||
webSocketUrl, isCloseWebSocket, isDemoBannerView}) => {
|
webSocketUrl, isCloseWebSocket, isDemoBannerView }) => {
|
||||||
return <RecoilRoot>
|
return <RecoilRoot>
|
||||||
<MemoiedTrafficViewer actionButtons={actionButtons} isShowStatusBar={isShowStatusBar} webSocketUrl={webSocketUrl}
|
<MemoiedTrafficViewer actionButtons={actionButtons} isShowStatusBar={isShowStatusBar} webSocketUrl={webSocketUrl}
|
||||||
isCloseWebSocket={isCloseWebSocket} trafficViewerApiProp={trafficViewerApiProp}
|
isCloseWebSocket={isCloseWebSocket} trafficViewerApiProp={trafficViewerApiProp}
|
||||||
setAnalyzeStatus={setAnalyzeStatus} isDemoBannerView={isDemoBannerView} />
|
setAnalyzeStatus={setAnalyzeStatus} isDemoBannerView={isDemoBannerView} />
|
||||||
|
<ToastContainer enableMultiContainer containerId={TOAST_CONTAINER_ID}
|
||||||
|
position="bottom-right"
|
||||||
|
autoClose={5000}
|
||||||
|
hideProgressBar={false}
|
||||||
|
newestOnTop={false}
|
||||||
|
closeOnClick
|
||||||
|
rtl={false}
|
||||||
|
pauseOnFocusLoss
|
||||||
|
draggable
|
||||||
|
pauseOnHover />
|
||||||
</RecoilRoot>
|
</RecoilRoot>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
ui-common/src/components/TrafficViewer/assets/lock.svg
Normal file
3
ui-common/src/components/TrafficViewer/assets/lock.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="12" height="14" viewBox="0 0 12 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.33333 6.36364H8.66667V6.36011H10.6667V6.36364H11C11.2778 6.36364 11.5139 6.45644 11.7083 6.64205C11.9028 6.82765 12 7.05303 12 7.31818V13.0455C12 13.3106 11.9028 13.536 11.7083 13.7216C11.5139 13.9072 11.2778 14 11 14H1C0.722222 14 0.486111 13.9072 0.291666 13.7216C0.0972223 13.536 0 13.3106 0 13.0455V7.31818C0 7.05303 0.0972223 6.82765 0.291666 6.64205C0.486111 6.45644 0.722222 6.36364 1 6.36364H1.33333V4.45455C1.33333 3.23485 1.79167 2.1875 2.70833 1.3125C3.625 0.4375 4.72222 0 6 0C7.27778 0 8.375 0.4375 9.29167 1.3125C9.92325 1.91538 10.3373 2.60007 10.5337 3.36658L8.59659 3.85085C8.48731 3.40176 8.25026 3.00309 7.88542 2.65483C7.36458 2.15767 6.73611 1.90909 6 1.90909C5.26389 1.90909 4.63542 2.15767 4.11458 2.65483C3.59375 3.15199 3.33333 3.75189 3.33333 4.45455V6.36364Z" fill="#BCCEFD"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 959 B |
@@ -6,11 +6,11 @@ export interface Props {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Checkbox: React.FC<Props> = ({checked, onToggle, disabled}) => {
|
const Checkbox: React.FC<Props> = ({checked, onToggle, disabled, ...props}) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input style={!disabled ? {cursor: "pointer"}: {}} type="checkbox" checked={checked} disabled={disabled} onChange={(event) => onToggle(event.target.checked)}/>
|
<input style={!disabled ? {cursor: "pointer"}: {}} type="checkbox" checked={checked} disabled={disabled} onChange={(event) => onToggle(event.target.checked)} {...props}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export interface InformationIconProps{
|
|||||||
|
|
||||||
export const InformationIcon: React.FC<InformationIconProps> = ({link,style}) => {
|
export const InformationIcon: React.FC<InformationIconProps> = ({link,style}) => {
|
||||||
return <React.Fragment>
|
return <React.Fragment>
|
||||||
<a href={DEFUALT_LINK ? DEFUALT_LINK : link} style={style} className={styles.flex} title="documentation">
|
<a href={DEFUALT_LINK ? DEFUALT_LINK : link} style={style} className={styles.flex} title="documentation" target="_blank">
|
||||||
<img className="headerIcon" src={infoImg} alt="Info icon"/>
|
<img className="headerIcon" src={infoImg} alt="Info icon"/>
|
||||||
</a>
|
</a>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
.highlighterContainer
|
||||||
|
&.fitScreen
|
||||||
|
pre
|
||||||
|
max-height: 90vh
|
||||||
|
overflow: auto
|
||||||
|
|
||||||
|
pre
|
||||||
|
code
|
||||||
|
font-size: 0.75rem
|
||||||
|
|
||||||
|
&:first-child
|
||||||
|
margin-right: 0.75rem
|
||||||
|
background: #F7F9FC
|
||||||
|
|
||||||
|
.react-syntax-highlighter-line-number
|
||||||
|
color: rgb(98, 126, 247)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
&:last-child
|
||||||
|
display: block
|
||||||
|
|
||||||
|
code.hljs
|
||||||
|
white-space: pre-wrap
|
||||||
|
|
||||||
|
code.hljs:before
|
||||||
|
counter-reset: listing
|
||||||
|
|
||||||
|
.hljsMarkerLine
|
||||||
|
counter-increment: listing
|
||||||
|
|
||||||
|
.hljsMarkerLine:before
|
||||||
|
content: counter(listing) " "
|
||||||
|
display: inline-block
|
||||||
|
width: 3rem
|
||||||
|
padding-left: auto
|
||||||
|
margin-left: auto
|
||||||
|
text-align: right
|
||||||
|
opacity: .5
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
.highlighterContainer {
|
|
||||||
&.fitScreen {
|
|
||||||
pre {
|
|
||||||
max-height: 90vh;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
code {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-right: 0.75rem;
|
|
||||||
background: #F7F9FC;
|
|
||||||
|
|
||||||
.react-syntax-highlighter-line-number {
|
|
||||||
color: rgb(98, 126, 247);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code.hljs {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
code.hljs:before {
|
|
||||||
counter-reset: listing;
|
|
||||||
}
|
|
||||||
|
|
||||||
code.hljs .hljs-marker-line {
|
|
||||||
counter-increment: listing;
|
|
||||||
}
|
|
||||||
|
|
||||||
code.hljs .hljs-marker-line:before {
|
|
||||||
content: counter(listing) " ";
|
|
||||||
display: inline-block;
|
|
||||||
width: 3rem;
|
|
||||||
padding-left: auto;
|
|
||||||
margin-left: auto;
|
|
||||||
text-align: right;
|
|
||||||
opacity: .5;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Lowlight from 'react-lowlight'
|
import Lowlight from 'react-lowlight'
|
||||||
import 'highlight.js/styles/atom-one-light.css'
|
import 'highlight.js/styles/atom-one-light.css'
|
||||||
import './index.scss';
|
import styles from './index.module.sass';
|
||||||
|
|
||||||
import xml from 'highlight.js/lib/languages/xml'
|
import xml from 'highlight.js/lib/languages/xml'
|
||||||
import json from 'highlight.js/lib/languages/json'
|
import json from 'highlight.js/lib/languages/json'
|
||||||
@@ -37,11 +37,11 @@ export const SyntaxHighlighter: React.FC<Props> = ({
|
|||||||
const markers = showLineNumbers ? code.split("\n").map((item, i) => {
|
const markers = showLineNumbers ? code.split("\n").map((item, i) => {
|
||||||
return {
|
return {
|
||||||
line: i + 1,
|
line: i + 1,
|
||||||
className: 'hljs-marker-line'
|
className: styles.hljsMarkerLine
|
||||||
}
|
}
|
||||||
}) : [];
|
}) : [];
|
||||||
|
|
||||||
return <div style={{fontSize: ".75rem"}}><Lowlight language={language ? language : ""} value={code} markers={markers}/></div>;
|
return <div style={{fontSize: ".75rem"}} className={styles.highlighterContainer}><Lowlight language={language ? language : ""} value={code} markers={markers}/></div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SyntaxHighlighter;
|
export default SyntaxHighlighter;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path fill="#627EF7" d="M12 4.707c-2.938-1.83-7.416-2.567-12-2.707v17.714c3.937.12 7.795.681 10.667 1.995.846.388 1.817.388 2.667 0 2.872-1.314 6.729-1.875 10.666-1.995v-17.714c-4.584.14-9.062.877-12 2.707zm-10 13.104v-13.704c5.157.389 7.527 1.463 9 2.334v13.168c-1.525-.546-4.716-1.505-9-1.798zm20 0c-4.283.293-7.475 1.252-9 1.799v-13.171c1.453-.861 3.83-1.942 9-2.332v13.704z"/>
|
<path d="M19 21H6.14286C5.07143 21 4 20.32 4 18.96C4 17.6 5.07143 16.92 6.14286 16.92H19V4H6.14286C5.07143 4 4 5.02 4 6.04V18.96M16.8571 17.6V20.32V17.6Z" stroke="#627EF7" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
</svg>
|
<rect x="8" y="7" width="7" height="2" fill="#627EF7"/>
|
||||||
|
<rect x="8" y="11" width="4" height="2" fill="#627EF7"/>
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 471 B After Width: | Height: | Size: 454 B |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
1
ui-common/src/configs/Consts.ts
Normal file
1
ui-common/src/configs/Consts.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const TOAST_CONTAINER_ID = "Common";
|
||||||
4657
ui/package-lock.json
generated
4657
ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
|||||||
"@types/jest": "^26.0.22",
|
"@types/jest": "^26.0.22",
|
||||||
"@types/node": "^12.20.10",
|
"@types/node": "^12.20.10",
|
||||||
"@uiw/react-textarea-code-editor": "^1.4.12",
|
"@uiw/react-textarea-code-editor": "^1.4.12",
|
||||||
"@up9/mizu-common": "1.0.136",
|
"@up9/mizu-common": "1.0.142",
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
"core-js": "^3.20.2",
|
"core-js": "^3.20.2",
|
||||||
"craco-babel-loader": "^1.0.3",
|
"craco-babel-loader": "^1.0.3",
|
||||||
@@ -75,4 +75,4 @@
|
|||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,12 +40,11 @@ const trafficViewerApi = {...api}
|
|||||||
{window["isOasEnabled"] && <Button
|
{window["isOasEnabled"] && <Button
|
||||||
startIcon={<img className="custom" src={services} alt="services"></img>}
|
startIcon={<img className="custom" src={services} alt="services"></img>}
|
||||||
size="large"
|
size="large"
|
||||||
type="submit"
|
|
||||||
variant="contained"
|
variant="contained"
|
||||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||||
style={{ marginRight: 25, textTransform: 'unset' }}
|
style={{ marginRight: 25, textTransform: 'unset' }}
|
||||||
onClick={handleOpenOasModal}>
|
onClick={handleOpenOasModal}>
|
||||||
OpenApi Specs
|
OpenAPI Specs
|
||||||
</Button>}
|
</Button>}
|
||||||
{window["isServiceMapEnabled"] && <Button
|
{window["isServiceMapEnabled"] && <Button
|
||||||
startIcon={<img src={serviceMap} className="custom" alt="service-map" style={{marginRight:"8%"}}></img>}
|
startIcon={<img src={serviceMap} className="custom" alt="service-map" style={{marginRight:"8%"}}></img>}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import ServiceMapOptions from './ServiceMapOptions'
|
|||||||
import { useCommonStyles } from "../../helpers/commonStyle";
|
import { useCommonStyles } from "../../helpers/commonStyle";
|
||||||
import refresh from "../assets/refresh.svg";
|
import refresh from "../assets/refresh.svg";
|
||||||
import close from "../assets/close.svg";
|
import close from "../assets/close.svg";
|
||||||
|
import { TOAST_CONTAINER_ID } from "../../consts";
|
||||||
|
|
||||||
interface GraphData {
|
interface GraphData {
|
||||||
nodes: Node[];
|
nodes: Node[];
|
||||||
@@ -140,7 +141,7 @@ export const ServiceMapModal: React.FC<ServiceMapModalProps> = ({ isOpen, onOpen
|
|||||||
setGraphData(newGraphData)
|
setGraphData(newGraphData)
|
||||||
|
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
toast.error("An error occurred while loading Mizu Service Map, see console for mode details");
|
toast.error("An error occurred while loading Mizu Service Map, see console for mode details", { containerId: TOAST_CONTAINER_ID });
|
||||||
console.error(ex);
|
console.error(ex);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
@@ -176,20 +177,20 @@ export const ServiceMapModal: React.FC<ServiceMapModalProps> = ({ isOpen, onOpen
|
|||||||
<img alt="spinner" src={spinnerImg} style={{ height: 50 }} />
|
<img alt="spinner" src={spinnerImg} style={{ height: 50 }} />
|
||||||
</div>}
|
</div>}
|
||||||
{!isLoading && <div style={{ height: "100%", width: "100%" }}>
|
{!isLoading && <div style={{ height: "100%", width: "100%" }}>
|
||||||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
startIcon={<img src={refresh} className="custom" alt="refresh" style={{ marginRight:"8%"}}></img>}
|
startIcon={<img src={refresh} className="custom" alt="refresh" style={{ marginRight: "8%" }}></img>}
|
||||||
size="medium"
|
size="medium"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||||
onClick={refreshServiceMap}
|
onClick={refreshServiceMap}
|
||||||
>
|
>
|
||||||
Refresh
|
Refresh
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
|
<img src={close} alt="close" onClick={() => onClose()} style={{ cursor: "pointer" }}></img>
|
||||||
</div>
|
</div>
|
||||||
<img src={close} alt="close" onClick={() => onClose()} style={{cursor:"pointer"}}></img>
|
|
||||||
</div>
|
|
||||||
<Graph
|
<Graph
|
||||||
graph={graphData}
|
graph={graphData}
|
||||||
options={ServiceMapOptions}
|
options={ServiceMapOptions}
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export const adminUsername = "admin";
|
export const adminUsername = "admin";
|
||||||
|
export const TOAST_CONTAINER_ID = "Community";
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import './index.sass';
|
import './index.sass';
|
||||||
import {ToastContainer} from "react-toastify";
|
import {ToastContainer} from "react-toastify";
|
||||||
import 'react-toastify/dist/ReactToastify.css';
|
import 'react-toastify/dist/ReactToastify.min.css';
|
||||||
import {RecoilRoot} from "recoil";
|
import {RecoilRoot} from "recoil";
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
import { TOAST_CONTAINER_ID } from './consts';
|
||||||
|
|
||||||
ReactDOM.render( <>
|
ReactDOM.render( <>
|
||||||
<RecoilRoot>
|
<RecoilRoot>
|
||||||
<App/>
|
<App/>
|
||||||
<ToastContainer
|
<ToastContainer enableMultiContainer containerId={TOAST_CONTAINER_ID}
|
||||||
position="bottom-right"
|
position="bottom-right"
|
||||||
autoClose={5000}
|
autoClose={5000}
|
||||||
hideProgressBar={false}
|
hideProgressBar={false}
|
||||||
|
|||||||
Reference in New Issue
Block a user