mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-06-14 12:17:05 +00:00
Compare commits
12 Commits
30.0-dev20
...
30.0-dev30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
319c3c7a8d | ||
|
|
0e7704eb15 | ||
|
|
dbcb776139 | ||
|
|
a3de34f544 | ||
|
|
99667984d6 | ||
|
|
763b0e7362 | ||
|
|
e07e04377f | ||
|
|
3c8f63ed92 | ||
|
|
11a2246cb9 | ||
|
|
a2595afd5e | ||
|
|
0f4710918f | ||
|
|
4bdda920d5 |
@@ -77,8 +77,8 @@ 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 shasum -a 256 -c basenine_linux_${GOARCH}.sha256
|
||||||
RUN chmod +x ./basenine_linux_${GOARCH}
|
RUN chmod +x ./basenine_linux_${GOARCH}
|
||||||
RUN mv ./basenine_linux_${GOARCH} ./basenine
|
RUN mv ./basenine_linux_${GOARCH} ./basenine
|
||||||
|
|||||||
@@ -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=
|
||||||
|
|||||||
@@ -111,9 +111,9 @@ func checkRulesPermissions(ctx context.Context, kubernetesProvider *kubernetes.P
|
|||||||
func checkPermissionExist(group string, resource string, verb string, namespace string, exist bool, err error) bool {
|
func checkPermissionExist(group string, resource string, verb string, namespace string, exist bool, err error) bool {
|
||||||
var groupAndNamespace string
|
var groupAndNamespace string
|
||||||
if group != "" && namespace != "" {
|
if group != "" && namespace != "" {
|
||||||
groupAndNamespace = fmt.Sprintf("in group '%v' and namespace '%v'", group, namespace)
|
groupAndNamespace = fmt.Sprintf("in api group '%v' and namespace '%v'", group, namespace)
|
||||||
} else if group != "" {
|
} else if group != "" {
|
||||||
groupAndNamespace = fmt.Sprintf("in group '%v'", group)
|
groupAndNamespace = fmt.Sprintf("in api group '%v'", group)
|
||||||
} else if namespace != "" {
|
} else if namespace != "" {
|
||||||
groupAndNamespace = fmt.Sprintf("in namespace '%v'", namespace)
|
groupAndNamespace = fmt.Sprintf("in namespace '%v'", namespace)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,13 +27,21 @@ func runMizuCheck() {
|
|||||||
checkPassed = check.KubernetesVersion(kubernetesVersion)
|
checkPassed = check.KubernetesVersion(kubernetesVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Config.Check.PreTap {
|
if config.Config.Check.PreTap || config.Config.Check.PreInstall || config.Config.Check.ImagePull {
|
||||||
if checkPassed {
|
if config.Config.Check.PreTap {
|
||||||
checkPassed = check.TapKubernetesPermissions(ctx, embedFS, kubernetesProvider)
|
if checkPassed {
|
||||||
|
checkPassed = check.TapKubernetesPermissions(ctx, embedFS, kubernetesProvider)
|
||||||
|
}
|
||||||
|
} else if config.Config.Check.PreInstall {
|
||||||
|
if checkPassed {
|
||||||
|
checkPassed = check.InstallKubernetesPermissions(ctx, kubernetesProvider)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if config.Config.Check.PreInstall {
|
|
||||||
if checkPassed {
|
if config.Config.Check.ImagePull {
|
||||||
checkPassed = check.InstallKubernetesPermissions(ctx, kubernetesProvider)
|
if checkPassed {
|
||||||
|
checkPassed = check.ImagePullInCluster(ctx, kubernetesProvider)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if checkPassed {
|
if checkPassed {
|
||||||
@@ -45,12 +53,6 @@ func runMizuCheck() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Config.Check.ImagePull {
|
|
||||||
if checkPassed {
|
|
||||||
checkPassed = check.ImagePullInCluster(ctx, kubernetesProvider)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if checkPassed {
|
if checkPassed {
|
||||||
logger.Log.Infof("\nStatus check results are %v", fmt.Sprintf(uiUtils.Green, "√"))
|
logger.Log.Infof("\nStatus check results are %v", fmt.Sprintf(uiUtils.Green, "√"))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -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,4 +1,4 @@
|
|||||||
import TrafficViewer,{useWS, DEFAULT_QUERY} from '@up9/mizu-common';
|
import TrafficViewer,{useWS, DEFAULT_QUERY, OasModal} from '@up9/mizu-common';
|
||||||
import "@up9/mizu-common/dist/index.css"
|
import "@up9/mizu-common/dist/index.css"
|
||||||
import {useEffect} from 'react';
|
import {useEffect} from 'react';
|
||||||
import Api, {getWebsocketUrl} from "./api";
|
import Api, {getWebsocketUrl} from "./api";
|
||||||
@@ -17,8 +17,7 @@ const App = () => {
|
|||||||
},[])
|
},[])
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<TrafficViewer message={message} error={error} isWebSocketOpen={isOpen}
|
|
||||||
trafficViewerApiProp={trafficViewerApi} ></TrafficViewer>
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
ui-common/package-lock.json
generated
4
ui-common/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@up9/mizu-common",
|
"name": "@up9/mizu-common",
|
||||||
"version": "1.0.10",
|
"version": "1.0.135",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@up9/mizu-common",
|
"name": "@up9/mizu-common",
|
||||||
"version": "1.0.10",
|
"version": "1.0.135",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@craco/craco": "^6.4.3",
|
"@craco/craco": "^6.4.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@up9/mizu-common",
|
"name": "@up9/mizu-common",
|
||||||
"version": "1.0.133",
|
"version": "1.0.137",
|
||||||
"description": "Made with create-react-library",
|
"description": "Made with create-react-library",
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -6,23 +6,32 @@
|
|||||||
padding: 10px
|
padding: 10px
|
||||||
|
|
||||||
.selectHeader
|
.selectHeader
|
||||||
|
font-family: Source Sans Pro,Lucida Grande,Tahoma,sans-serif
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
|
font-weight: 900
|
||||||
width: 100%
|
width: 100%
|
||||||
margin-top: -1%
|
margin-top: -1%
|
||||||
|
|
||||||
.openApilogo
|
.openApilogo
|
||||||
width: 36px
|
width: 43px
|
||||||
|
|
||||||
.title
|
.title
|
||||||
color:#494677
|
color:#494677
|
||||||
font-family: Lato
|
font-family: Source Sans Pro,Lucida Grande,Tahoma,sans-serif
|
||||||
font-size: 20px
|
font-size: 28px
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
|
|
||||||
.selectContainer
|
.selectContainer
|
||||||
margin-left: 1%
|
width: 14%
|
||||||
|
margin-bottom: 1%
|
||||||
|
margin-top: 1%
|
||||||
|
|
||||||
.redoc
|
.redoc
|
||||||
height: 98%
|
height: 85%
|
||||||
overflow-y: scroll
|
overflow-y: scroll
|
||||||
|
|
||||||
|
.borderLine
|
||||||
|
border-top: 1px solid #dee6fe
|
||||||
|
margin-bottom: 1%
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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 { Select } from "../UI/Select";
|
import { UI } from "../..";
|
||||||
|
|
||||||
const modalStyle = {
|
const modalStyle = {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@@ -25,17 +25,17 @@ const modalStyle = {
|
|||||||
|
|
||||||
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 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 [resolvedServices, setResolvedServices] = useState([]);
|
||||||
const [unResolvedServices, setUnResolvedServices] = useState([]);
|
const [unResolvedServices, setUnResolvedServices] = useState([]);
|
||||||
|
|
||||||
const onSelectedOASService = useCallback( async (selectedService) => {
|
const onSelectedOASService = useCallback(async (selectedService) => {
|
||||||
if (!!selectedService){
|
if (!!selectedService) {
|
||||||
setSelectedServiceName(selectedService);
|
setSelectedServiceName(selectedService);
|
||||||
if(oasServices.length === 0){
|
if (oasServices.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -46,13 +46,13 @@ const OasModal = ({ openModal, handleCloseModal, getOasServices, getOasByService
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},[oasServices.length])
|
}, [oasServices.length])
|
||||||
|
|
||||||
const resolvedArrayBuilder = useCallback(async(services) => {
|
const resolvedArrayBuilder = useCallback(async (services) => {
|
||||||
const resServices = [];
|
const resServices = [];
|
||||||
const unResServices = [];
|
const unResServices = [];
|
||||||
services.forEach(s => {
|
services.forEach(s => {
|
||||||
if(ipAddressWithPortRegex.test(s)){
|
if (ipAddressWithPortRegex.test(s)) {
|
||||||
unResServices.push(s);
|
unResServices.push(s);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -62,10 +62,16 @@ const OasModal = ({ openModal, handleCloseModal, getOasServices, getOasByService
|
|||||||
|
|
||||||
resServices.sort();
|
resServices.sort();
|
||||||
unResServices.sort();
|
unResServices.sort();
|
||||||
onSelectedOASService(resServices[0]);
|
if (resServices.length > 0) {
|
||||||
|
onSelectedOASService(resServices[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
onSelectedOASService(unResServices[0]);
|
||||||
|
}
|
||||||
|
|
||||||
setResolvedServices(resServices);
|
setResolvedServices(resServices);
|
||||||
setUnResolvedServices(unResServices);
|
setUnResolvedServices(unResServices);
|
||||||
},[onSelectedOASService])
|
}, [onSelectedOASService])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@@ -77,8 +83,7 @@ const OasModal = ({ openModal, handleCloseModal, getOasServices, getOasByService
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, [openModal,resolvedArrayBuilder]);
|
}, [openModal, resolvedArrayBuilder]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -90,48 +95,48 @@ const OasModal = ({ openModal, handleCloseModal, getOasServices, getOasByService
|
|||||||
closeAfterTransition
|
closeAfterTransition
|
||||||
BackdropComponent={Backdrop}
|
BackdropComponent={Backdrop}
|
||||||
BackdropProps={{
|
BackdropProps={{
|
||||||
timeout: 500,
|
timeout: 500,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Fade in={openModal}>
|
<Fade in={openModal}>
|
||||||
<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 selected service: </div>
|
<div className={style.title}>OpenApi </div>
|
||||||
<div className={style.selectContainer} >
|
|
||||||
<FormControl>
|
|
||||||
<Select
|
|
||||||
labelId="service-select-label"
|
|
||||||
id="service-select"
|
|
||||||
placeholder="Show OAS"
|
|
||||||
value={selectedServiceName}
|
|
||||||
onChangeCb={onSelectedOASService}
|
|
||||||
>
|
|
||||||
<ListSubheader disableSticky={true}>Resolved</ListSubheader>
|
|
||||||
{resolvedServices.map((service) => (
|
|
||||||
<MenuItem key={service} value={service}>
|
|
||||||
{service}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
<ListSubheader disableSticky={true}>UnResolved</ListSubheader>
|
|
||||||
{unResolvedServices.map((service) => (
|
|
||||||
<MenuItem key={service} value={service}>
|
|
||||||
{service}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</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} >
|
||||||
|
<FormControl>
|
||||||
|
<UI.Select
|
||||||
|
labelId="service-select-label"
|
||||||
|
id="service-select"
|
||||||
|
value={selectedServiceName}
|
||||||
|
onChangeCb={onSelectedOASService}
|
||||||
|
>
|
||||||
|
<ListSubheader disableSticky={true}>Resolved</ListSubheader>
|
||||||
|
{resolvedServices.map((service) => (
|
||||||
|
<MenuItem key={service} value={service}>
|
||||||
|
{service}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
<ListSubheader disableSticky={true}>UnResolved</ListSubheader>
|
||||||
|
{unResolvedServices.map((service) => (
|
||||||
|
<MenuItem key={service} value={service}>
|
||||||
|
{service}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</UI.Select>
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
<div className={style.borderLine}></div>
|
||||||
<div className={style.redoc}>
|
<div className={style.redoc}>
|
||||||
{selectedServiceSpec && <RedocStandalone
|
{selectedServiceSpec && <RedocStandalone
|
||||||
spec={selectedServiceSpec}
|
spec={selectedServiceSpec}
|
||||||
options={redocThemeOptions}/>}
|
options={redocThemeOptions} />}
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
</Fade>
|
</Fade>
|
||||||
|
|||||||
@@ -1,35 +1,52 @@
|
|||||||
export const redocThemeOptions = {
|
const fontFamilyVar = "Source Sans Pro, Lucida Grande, Tahoma, sans-serif"
|
||||||
theme:{
|
|
||||||
codeBlock:{
|
export const redocThemeOptions = {
|
||||||
backgroundColor:"#11171a",
|
theme: {
|
||||||
},
|
codeBlock: {
|
||||||
colors:{
|
backgroundColor: "#14161c",
|
||||||
responses:{
|
},
|
||||||
error:{
|
components: {
|
||||||
tabTextColor:"#1b1b29"
|
buttons: {
|
||||||
},
|
fontFamily: fontFamilyVar,
|
||||||
info:{
|
},
|
||||||
tabTextColor:"#1b1b29",
|
httpBadges: {
|
||||||
},
|
fontFamily: fontFamilyVar,
|
||||||
success:{
|
}
|
||||||
tabTextColor:"#0c0b1a"
|
},
|
||||||
},
|
colors: {
|
||||||
},
|
responses: {
|
||||||
text:{
|
error: {
|
||||||
primary:"#1b1b29",
|
tabTextColor: "#1b1b29"
|
||||||
secondary:"#4d4d4d"
|
},
|
||||||
}
|
info: {
|
||||||
},
|
tabTextColor: "#1b1b29",
|
||||||
rightPanel:{
|
},
|
||||||
backgroundColor:"#253237",
|
success: {
|
||||||
},
|
tabTextColor: "#0c0b1a"
|
||||||
sidebar:{
|
},
|
||||||
backgroundColor:"#ffffff"
|
},
|
||||||
},
|
text: {
|
||||||
typography:{
|
primary: "#1b1b29",
|
||||||
code:{
|
secondary: "#4d4d4d"
|
||||||
color:"#0c0b1a"
|
}
|
||||||
}
|
},
|
||||||
}
|
rightPanel: {
|
||||||
}
|
backgroundColor: "#0D0B1D",
|
||||||
}
|
},
|
||||||
|
sidebar: {
|
||||||
|
backgroundColor: "#ffffff"
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
code: {
|
||||||
|
color: "#0c0b1a",
|
||||||
|
fontFamily: fontFamilyVar
|
||||||
|
},
|
||||||
|
fontFamily: fontFamilyVar,
|
||||||
|
fontSize: "90%",
|
||||||
|
fontWieght: "normal",
|
||||||
|
headings: {
|
||||||
|
fontFamily: fontFamilyVar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ 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";
|
||||||
|
|
||||||
const useStyles = makeStyles(() => ({
|
const useStyles = makeStyles(() => ({
|
||||||
entryTitle: {
|
entryTitle: {
|
||||||
@@ -35,15 +36,18 @@ 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 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 {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}/>
|
||||||
<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"}}
|
||||||
@@ -53,7 +57,7 @@ const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
|||||||
style={{opacity: 0.5}}
|
style={{opacity: 0.5}}
|
||||||
id="entryDetailedTitleRequestSize"
|
id="entryDetailedTitleRequestSize"
|
||||||
>
|
>
|
||||||
{`Request: ${formatSize(data.requestSize)}`}
|
{`${requestText}${formatSize(data.requestSize)}`}
|
||||||
</div>
|
</div>
|
||||||
</Queryable>}
|
</Queryable>}
|
||||||
{response && <Queryable
|
{response && <Queryable
|
||||||
@@ -65,22 +69,22 @@ const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
|||||||
style={{opacity: 0.5}}
|
style={{opacity: 0.5}}
|
||||||
id="entryDetailedTitleResponseSize"
|
id="entryDetailedTitleResponseSize"
|
||||||
>
|
>
|
||||||
{`Response: ${formatSize(data.responseSize)}`}
|
{`${responseText}${formatSize(data.responseSize)}`}
|
||||||
</div>
|
</div>
|
||||||
</Queryable>}
|
</Queryable>}
|
||||||
{response && <Queryable
|
{response && <Queryable
|
||||||
query={`elapsedTime >= ${elapsedTime}`}
|
query={`elapsedTime >= ${elapsedTime}`}
|
||||||
style={{marginRight: 18}}
|
style={{margin: "0 0 0 18px"}}
|
||||||
displayIconOnMouseOver={true}
|
displayIconOnMouseOver={true}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{opacity: 0.5}}
|
style={{opacity: 0.5}}
|
||||||
id="entryDetailedTitleElapsedTime"
|
id="entryDetailedTitleElapsedTime"
|
||||||
>
|
>
|
||||||
{`Elapsed Time: ${Math.round(elapsedTime)}ms`}
|
{`${elapsedTimeText}${Math.round(elapsedTime)}ms`}
|
||||||
</div>
|
</div>
|
||||||
</Queryable>}
|
</Queryable>}
|
||||||
</div>
|
</div>}
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -48,12 +48,13 @@ interface TrafficViewerProps {
|
|||||||
actionButtons?: JSX.Element,
|
actionButtons?: JSX.Element,
|
||||||
isShowStatusBar?: boolean,
|
isShowStatusBar?: boolean,
|
||||||
webSocketUrl : string,
|
webSocketUrl : string,
|
||||||
isCloseWebSocket : boolean
|
isCloseWebSocket : 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}) => {
|
isCloseWebSocket, isDemoBannerView}) => {
|
||||||
|
|
||||||
const classes = useLayoutStyles();
|
const classes = useLayoutStyles();
|
||||||
|
|
||||||
@@ -293,7 +294,7 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={TrafficViewerStyles.TrafficPage}>
|
<div className={TrafficViewerStyles.TrafficPage}>
|
||||||
{tappingStatus && isShowStatusBar && <StatusBar />}
|
{tappingStatus && isShowStatusBar && <StatusBar isDemoBannerView={isDemoBannerView} />}
|
||||||
<div className={TrafficViewerStyles.TrafficPageHeader}>
|
<div className={TrafficViewerStyles.TrafficPageHeader}>
|
||||||
<div className={TrafficViewerStyles.TrafficPageStreamStatus}>
|
<div className={TrafficViewerStyles.TrafficPageStreamStatus}>
|
||||||
<img className={TrafficViewerStyles.playPauseIcon} style={{ visibility: ws?.current?.readyState === WebSocket.OPEN ? "visible" : "hidden" }} alt="pause"
|
<img className={TrafficViewerStyles.playPauseIcon} style={{ visibility: ws?.current?.readyState === WebSocket.OPEN ? "visible" : "hidden" }} alt="pause"
|
||||||
@@ -356,11 +357,11 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
|||||||
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}) => {
|
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} />
|
setAnalyzeStatus={setAnalyzeStatus} isDemoBannerView={isDemoBannerView} />
|
||||||
</RecoilRoot>
|
</RecoilRoot>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +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}>
|
|
||||||
<img className="headerIcon" src={infoImg} alt="Info icon"/>
|
<img className="headerIcon" src={infoImg} alt="Info icon"/>
|
||||||
</a>
|
</a>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const menuProps: any = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// icons styles are not overwritten from the Props, only as a separate object
|
// icons styles are not overwritten from the Props, only as a separate object
|
||||||
const classes = {icon: styles.icon, selectMenu: styles.list};
|
const classes = {icon: styles.icon, selectMenu: styles.list, select: styles.oasSelect, root:styles.root};
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
MenuProps: menuProps,
|
MenuProps: menuProps,
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ const pluralize = (noun: string, amount: number) => {
|
|||||||
return `${noun}${amount !== 1 ? 's' : ''}`
|
return `${noun}${amount !== 1 ? 's' : ''}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const StatusBar = () => {
|
interface StatusBarProps {
|
||||||
|
isDemoBannerView: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const StatusBar = ({isDemoBannerView}) => {
|
||||||
const tappingStatus = useRecoilValue(tappingStatusAtom);
|
const tappingStatus = useRecoilValue(tappingStatusAtom);
|
||||||
const [expandedBar, setExpandedBar] = useState(false);
|
const [expandedBar, setExpandedBar] = useState(false);
|
||||||
const {uniqueNamespaces, amountOfPods, amountOfTappedPods, amountOfUntappedPods} = useRecoilValue(tappingStatusDetails);
|
const {uniqueNamespaces, amountOfPods, amountOfTappedPods, amountOfUntappedPods} = useRecoilValue(tappingStatusDetails);
|
||||||
|
|
||||||
return <div className={`${style.statusBar} ${(expandedBar ? `${style.expandedStatusBar}` : "")}`} onMouseOver={() => setExpandedBar(true)} onMouseLeave={() => setExpandedBar(false)} data-cy="expandedStatusBar">
|
return <div className={`${isDemoBannerView ? `${style.banner}` : ''} ${style.statusBar} ${(expandedBar ? `${style.expandedStatusBar}` : "")}`} onMouseOver={() => setExpandedBar(true)} onMouseLeave={() => setExpandedBar(false)} data-cy="expandedStatusBar">
|
||||||
<div className={style.podsCount}>
|
<div className={style.podsCount}>
|
||||||
{tappingStatus.some(pod => !pod.isTapped) && <img src={warningIcon} alt="warning"/>}
|
{tappingStatus.some(pod => !pod.isTapped) && <img src={warningIcon} alt="warning"/>}
|
||||||
<span className={style.podsCountText} data-cy="podsCountText">
|
<span className={style.podsCountText} data-cy="podsCountText">
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ const Tabs: React.FC<Props> = ({classes={}, tabs, currentTab, color, onChange, l
|
|||||||
{tabs.map(({tab, disabled, disabledMessage, highlight, badge}, index) => {
|
{tabs.map(({tab, disabled, disabledMessage, highlight, badge}, index) => {
|
||||||
const active = currentTab === tab;
|
const active = currentTab === tab;
|
||||||
const tabLink = <span
|
const tabLink = <span
|
||||||
|
data-cy={"tab-" + tab}
|
||||||
key={tab}
|
key={tab}
|
||||||
className={`${_classes.tab} ${active ? _classes.active : ''} ${disabled ? _classes.disabled : ''} ${highlight ? _classes.highlight : ''} ${dark ? 'dark' : ''}`}
|
className={`${_classes.tab} ${active ? _classes.active : ''} ${disabled ? _classes.disabled : ''} ${highlight ? _classes.highlight : ''} ${dark ? 'dark' : ''}`}
|
||||||
onClick={() => !disabled && onChange(tab)}
|
onClick={() => !disabled && onChange(tab)}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4ZM2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12Z" fill="#627EF7"/>
|
<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 fill-rule="evenodd" clip-rule="evenodd" d="M12 10.1C12.5522 10.1 13 10.5477 13 11.1V14.6H13.8C14.3522 14.6 14.8 15.0477 14.8 15.6C14.8 16.1523 14.3522 16.6 13.8 16.6H10.2C9.64767 16.6 9.19995 16.1523 9.19995 15.6C9.19995 15.0477 9.64767 14.6 10.2 14.6H11V11.1C11 10.5477 11.4477 10.1 12 10.1Z" fill="#627EF7"/>
|
</svg>
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13 11C13 11.5523 12.5523 12 12 12L10 12C9.44772 12 9 11.5523 9 11C9 10.4477 9.44772 10 10 10L12 10C12.5523 10 13 10.4477 13 11Z" fill="#627EF7"/>
|
|
||||||
<circle cx="12" cy="8" r="1" fill="#627EF7"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 471 B |
@@ -9,4 +9,4 @@ import { InformationIcon } from "./InformationIcon";
|
|||||||
|
|
||||||
|
|
||||||
export {LoadingOverlay,Select,Tabs,Tooltip,Checkbox,CustomModal,InformationIcon}
|
export {LoadingOverlay,Select,Tabs,Tooltip,Checkbox,CustomModal,InformationIcon}
|
||||||
export {StatusBar}
|
export {StatusBar}
|
||||||
@@ -3,3 +3,15 @@
|
|||||||
|
|
||||||
.list
|
.list
|
||||||
margin-top: 8px
|
margin-top: 8px
|
||||||
|
|
||||||
|
.oasSelect
|
||||||
|
font-weight: normal
|
||||||
|
padding: 8px 4px 8px 12px !important
|
||||||
|
border: 1px solid #9d9d9d !important
|
||||||
|
border-radius: 9px !important
|
||||||
|
font-family: Source Sans Pro, Lucida Grande, Tahoma, sans-serif !important
|
||||||
|
width: 216px !important
|
||||||
|
|
||||||
|
.root
|
||||||
|
font-family: Source Sans Pro, Lucida Grande, Tahoma, sans-serif !important
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
overflow: hidden
|
overflow: hidden
|
||||||
max-width: clamp(150px,50%,600px)
|
max-width: clamp(150px,50%,600px)
|
||||||
|
|
||||||
|
&.banner
|
||||||
|
top: 53px
|
||||||
|
|
||||||
.podsCount
|
.podsCount
|
||||||
display: flex
|
display: flex
|
||||||
justify-content: center
|
justify-content: center
|
||||||
|
|||||||
43
ui-common/src/hooks/WindowDimensionsHook.tsx
Normal file
43
ui-common/src/hooks/WindowDimensionsHook.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
function getWindowDimensions() {
|
||||||
|
const { innerWidth: width, innerHeight: height } = window;
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useRequestTextByWidth(windowWidth){
|
||||||
|
|
||||||
|
let requestText = "Request: "
|
||||||
|
let responseText = "Response: "
|
||||||
|
let elapsedTimeText = "Elapsed Time: "
|
||||||
|
|
||||||
|
if (windowWidth < 1078) {
|
||||||
|
requestText = ""
|
||||||
|
responseText = ""
|
||||||
|
elapsedTimeText = ""
|
||||||
|
} else if (windowWidth < 1356) {
|
||||||
|
requestText = "Req: "
|
||||||
|
responseText = "Res: "
|
||||||
|
elapsedTimeText = "ET: "
|
||||||
|
}
|
||||||
|
|
||||||
|
return {requestText, responseText, elapsedTimeText}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useWindowDimensions() {
|
||||||
|
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleResize() {
|
||||||
|
setWindowDimensions(getWindowDimensions());
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return windowDimensions;
|
||||||
|
}
|
||||||
@@ -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.133",
|
"@up9/mizu-common": "1.0.137",
|
||||||
"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",
|
||||||
|
|||||||
@@ -40,19 +40,19 @@ 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 }}
|
style={{ marginRight: 25, textTransform: 'unset' }}
|
||||||
onClick={handleOpenOasModal}>
|
onClick={handleOpenOasModal}>
|
||||||
Show OAS
|
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>}
|
||||||
size="large"
|
size="large"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||||
onClick={openServiceMapModalDebounce}>
|
onClick={openServiceMapModalDebounce}
|
||||||
|
style={{textTransform: 'unset'}}>
|
||||||
Service Map
|
Service Map
|
||||||
</Button>}
|
</Button>}
|
||||||
</div>
|
</div>
|
||||||
@@ -66,7 +66,7 @@ const trafficViewerApi = {...api}
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TrafficViewer setAnalyzeStatus={setAnalyzeStatus} webSocketUrl={getWebsocketUrl()} isCloseWebSocket={!openWebSocket}
|
<TrafficViewer setAnalyzeStatus={setAnalyzeStatus} webSocketUrl={getWebsocketUrl()} isCloseWebSocket={!openWebSocket}
|
||||||
trafficViewerApiProp={trafficViewerApi} actionButtons={actionButtons} isShowStatusBar={!openOasModal}/>
|
trafficViewerApiProp={trafficViewerApi} actionButtons={actionButtons} isShowStatusBar={!openOasModal} isDemoBannerView={false}/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user