Compare commits

..

5 Commits

Author SHA1 Message Date
Igor Gov
bfbbc27e62 Adding experimental feature flags (#627) 2022-01-12 09:33:41 +02:00
Igor Gov
e2df973fe6 Adding make file debug functionalities (#626) 2022-01-12 09:16:38 +02:00
Igor Gov
656809512b Adding make file debug functionalities (#624) 2022-01-12 09:04:13 +02:00
RoyUP9
b96542a8ed Refactor to agent status (#622) 2022-01-11 20:01:39 +02:00
RoyUP9
a55f51f0e7 Extracted tap config to consistent volume (#617) 2022-01-11 13:44:41 +02:00
18 changed files with 213 additions and 87 deletions

View File

@@ -8,7 +8,7 @@ SHELL=/bin/bash
# HELP
# This will output the help for each task
# thanks to https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
.PHONY: help ui agent cli tap docker
.PHONY: help ui extensions extensions-debug agent agent-debug cli tap docker
help: ## This help.
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
@@ -28,6 +28,9 @@ ui: ## Build UI.
cli: ## Build CLI.
@echo "building cli"; cd cli && $(MAKE) build
cli-debug: ## Build CLI.
@echo "building cli"; cd cli && $(MAKE) build-debug
build-cli-ci: ## Build CLI for CI.
@echo "building cli for ci"; cd cli && $(MAKE) build GIT_BRANCH=ci SUFFIX=ci
@@ -37,6 +40,12 @@ agent: ## Build agent.
${MAKE} extensions
@ls -l agent/build
agent-debug: ## Build agent for debug.
@(echo "building mizu agent for debug.." )
@(cd agent; go build -gcflags="all=-N -l" -o build/mizuagent main.go)
${MAKE} extensions-debug
@ls -l agent/build
docker: ## Build and publish agent docker image.
$(MAKE) push-docker
@@ -62,7 +71,7 @@ push-cli: ## Build and publish CLI.
gsutil cp -r ./cli/bin/* gs://${BUCKET_PATH}/
gsutil setmeta -r -h "Cache-Control:public, max-age=30" gs://${BUCKET_PATH}/\*
clean: clean-ui clean-agent clean-cli clean-docker ## Clean all build artifacts.
clean: clean-ui clean-agent clean-cli clean-docker clean-extensions ## Clean all build artifacts.
clean-ui: ## Clean UI.
@(rm -rf ui/build ; echo "UI cleanup done" )
@@ -73,9 +82,15 @@ clean-agent: ## Clean agent.
clean-cli: ## Clean CLI.
@(cd cli; make clean ; echo "CLI cleanup done" )
clean-extensions: ## Clean extensions
@(rm -rf tap/extensions/*.so ; echo "Extensions cleanup done" )
clean-docker:
@(echo "DOCKER cleanup - NOT IMPLEMENTED YET " )
extensions-debug:
devops/build_extensions_debug.sh
extensions:
devops/build_extensions.sh

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"mizuserver/pkg/models"
"mizuserver/pkg/providers"
"mizuserver/pkg/providers/tappersCount"
"mizuserver/pkg/up9"
"sync"
@@ -29,7 +30,7 @@ func init() {
func (h *RoutesEventHandlers) WebSocketConnect(socketId int, isTapper bool) {
if isTapper {
logger.Log.Infof("Websocket event - Tapper connected, socket ID: %d", socketId)
providers.TapperAdded()
tappersCount.Add()
} else {
logger.Log.Infof("Websocket event - Browser socket connected, socket ID: %d", socketId)
socketListLock.Lock()
@@ -41,7 +42,7 @@ func (h *RoutesEventHandlers) WebSocketConnect(socketId int, isTapper bool) {
func (h *RoutesEventHandlers) WebSocketDisconnect(socketId int, isTapper bool) {
if isTapper {
logger.Log.Infof("Websocket event - Tapper disconnected, socket ID: %d", socketId)
providers.TapperRemoved()
tappersCount.Remove()
} else {
logger.Log.Infof("Websocket event - Browser socket disconnected, socket ID: %d", socketId)
socketListLock.Lock()

View File

@@ -11,18 +11,20 @@ import (
"mizuserver/pkg/config"
"mizuserver/pkg/models"
"mizuserver/pkg/providers"
"mizuserver/pkg/providers/tapConfig"
"mizuserver/pkg/providers/tappedPods"
"mizuserver/pkg/providers/tappersStatus"
"net/http"
"regexp"
"time"
)
var globalTapConfig = &models.TapConfig{TappedNamespaces: make(map[string]bool)}
var cancelTapperSyncer context.CancelFunc
func PostTapConfig(c *gin.Context) {
tapConfig := &models.TapConfig{}
requestTapConfig := &models.TapConfig{}
if err := c.Bind(tapConfig); err != nil {
if err := c.Bind(requestTapConfig); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
@@ -30,14 +32,14 @@ func PostTapConfig(c *gin.Context) {
if cancelTapperSyncer != nil {
cancelTapperSyncer()
providers.TapStatus = shared.TapStatus{}
providers.TappersStatus = make(map[string]shared.TapperStatus)
tappedPods.Set([]*shared.PodInfo{})
tappersStatus.Reset()
broadcastTappedPodsStatus()
}
var tappedNamespaces []string
for namespace, tapped := range tapConfig.TappedNamespaces {
for namespace, tapped := range requestTapConfig.TappedNamespaces {
if tapped {
tappedNamespaces = append(tappedNamespaces, namespace)
}
@@ -60,7 +62,7 @@ func PostTapConfig(c *gin.Context) {
}
cancelTapperSyncer = cancel
globalTapConfig = tapConfig
tapConfig.Save(requestTapConfig)
c.JSON(http.StatusOK, "OK")
}
@@ -81,17 +83,19 @@ func GetTapConfig(c *gin.Context) {
return
}
savedTapConfig := tapConfig.Get()
tappedNamespaces := make(map[string]bool)
for _, namespace := range namespaces {
if namespace.Name == config.Config.MizuResourcesNamespace {
continue
}
tappedNamespaces[namespace.Name] = globalTapConfig.TappedNamespaces[namespace.Name]
tappedNamespaces[namespace.Name] = savedTapConfig.TappedNamespaces[namespace.Name]
}
tapConfig := models.TapConfig{TappedNamespaces: tappedNamespaces}
c.JSON(http.StatusOK, tapConfig)
tapConfigToReturn := models.TapConfig{TappedNamespaces: tappedNamespaces}
c.JSON(http.StatusOK, tapConfigToReturn)
}
func startMizuTapperSyncer(ctx context.Context, provider *kubernetes.Provider, targetNamespaces []string, podFilterRegex regexp.Regexp, ignoredUserAgents []string, mizuApiFilteringOptions tapApi.TrafficFilteringOptions, serviceMesh bool) (*kubernetes.MizuTapperSyncer, error) {
@@ -129,7 +133,7 @@ func startMizuTapperSyncer(ctx context.Context, provider *kubernetes.Provider, t
return
}
providers.TapStatus = shared.TapStatus{Pods: kubernetes.GetPodInfosForPods(tapperSyncer.CurrentlyTappedPods)}
tappedPods.Set(kubernetes.GetPodInfosForPods(tapperSyncer.CurrentlyTappedPods))
broadcastTappedPodsStatus()
case tapperStatus, ok := <-tapperSyncer.TapperStatusChangedOut:
if !ok {
@@ -137,7 +141,7 @@ func startMizuTapperSyncer(ctx context.Context, provider *kubernetes.Provider, t
return
}
addTapperStatus(tapperStatus)
tappersStatus.Set(&tapperStatus)
broadcastTappedPodsStatus()
case <-ctx.Done():
logger.Log.Debug("mizuTapperSyncer event listener loop exiting due to context done")

View File

@@ -8,43 +8,42 @@ import (
"mizuserver/pkg/api"
"mizuserver/pkg/holder"
"mizuserver/pkg/providers"
"mizuserver/pkg/providers/tappedPods"
"mizuserver/pkg/providers/tappersCount"
"mizuserver/pkg/providers/tappersStatus"
"mizuserver/pkg/up9"
"mizuserver/pkg/utils"
"mizuserver/pkg/validation"
"net/http"
)
func HealthCheck(c *gin.Context) {
tappers := make([]shared.TapperStatus, 0)
for _, value := range providers.TappersStatus {
tappers := make([]*shared.TapperStatus, 0)
for _, value := range tappersStatus.Get() {
tappers = append(tappers, value)
}
response := shared.HealthResponse{
TapStatus: providers.TapStatus,
TappersCount: providers.TappersCount,
TappedPods: tappedPods.Get(),
TappersCount: tappersCount.Get(),
TappersStatus: tappers,
}
c.JSON(http.StatusOK, response)
}
func PostTappedPods(c *gin.Context) {
tapStatus := &shared.TapStatus{}
if err := c.Bind(tapStatus); err != nil {
var requestTappedPods []*shared.PodInfo
if err := c.Bind(&requestTappedPods); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
if err := validation.Validate(tapStatus); err != nil {
c.JSON(http.StatusBadRequest, err)
return
}
logger.Log.Infof("[Status] POST request: %d tapped pods", len(tapStatus.Pods))
providers.TapStatus.Pods = tapStatus.Pods
logger.Log.Infof("[Status] POST request: %d tapped pods", len(requestTappedPods))
tappedPods.Set(requestTappedPods)
broadcastTappedPodsStatus()
}
func broadcastTappedPodsStatus() {
tappedPodsStatus := utils.GetTappedPodsStatus()
tappedPodsStatus := tappedPods.GetTappedPodsStatus()
message := shared.CreateWebSocketStatusMessage(tappedPodsStatus)
if jsonBytes, err := json.Marshal(message); err != nil {
@@ -54,14 +53,6 @@ func broadcastTappedPodsStatus() {
}
}
func addTapperStatus(tapperStatus shared.TapperStatus) {
if providers.TappersStatus == nil {
providers.TappersStatus = make(map[string]shared.TapperStatus)
}
providers.TappersStatus[tapperStatus.NodeName] = tapperStatus
}
func PostTapperStatus(c *gin.Context) {
tapperStatus := &shared.TapperStatus{}
if err := c.Bind(tapperStatus); err != nil {
@@ -75,12 +66,12 @@ func PostTapperStatus(c *gin.Context) {
}
logger.Log.Infof("[Status] POST request, tapper status: %v", tapperStatus)
addTapperStatus(*tapperStatus)
tappersStatus.Set(tapperStatus)
broadcastTappedPodsStatus()
}
func GetTappersCount(c *gin.Context) {
c.JSON(http.StatusOK, providers.TappersCount)
c.JSON(http.StatusOK, tappersCount.Get())
}
func GetAuthStatus(c *gin.Context) {
@@ -94,7 +85,7 @@ func GetAuthStatus(c *gin.Context) {
}
func GetTappingStatus(c *gin.Context) {
tappedPodsStatus := utils.GetTappedPodsStatus()
tappedPodsStatus := tappedPods.GetTappedPodsStatus()
c.JSON(http.StatusOK, tappedPodsStatus)
}

View File

@@ -8,19 +8,14 @@ import (
"github.com/up9inc/mizu/tap"
"mizuserver/pkg/models"
"os"
"sync"
"time"
)
const tlsLinkRetainmentTime = time.Minute * 15
var (
TappersCount int
TapStatus shared.TapStatus
TappersStatus map[string]shared.TapperStatus
authStatus *models.AuthStatus
RecentTLSLinks = cache.New(tlsLinkRetainmentTime, tlsLinkRetainmentTime)
tappersCountLock = sync.Mutex{}
authStatus *models.AuthStatus
RecentTLSLinks = cache.New(tlsLinkRetainmentTime, tlsLinkRetainmentTime)
)
func GetAuthStatus() (*models.AuthStatus, error) {
@@ -68,15 +63,3 @@ func GetAllRecentTLSAddresses() []string {
return recentTLSLinks
}
func TapperAdded() {
tappersCountLock.Lock()
TappersCount++
tappersCountLock.Unlock()
}
func TapperRemoved() {
tappersCountLock.Lock()
TappersCount--
tappersCountLock.Unlock()
}

View File

@@ -0,0 +1,54 @@
package tapConfig
import (
"encoding/json"
"github.com/up9inc/mizu/shared"
"github.com/up9inc/mizu/shared/logger"
"io/ioutil"
"mizuserver/pkg/models"
"os"
"sync"
)
const FilePath = shared.DataDirPath + "tap-config.json"
var lock = &sync.Mutex{}
var config *models.TapConfig
func Get() *models.TapConfig {
if config == nil {
lock.Lock()
defer lock.Unlock()
if config == nil {
if content, err := ioutil.ReadFile(FilePath); err != nil {
config = &models.TapConfig{TappedNamespaces: make(map[string]bool)}
if !os.IsNotExist(err) {
logger.Log.Errorf("Error loading tap config from file, err: %v", err)
}
} else {
if err = json.Unmarshal(content, &config); err != nil {
config = &models.TapConfig{TappedNamespaces: make(map[string]bool)}
logger.Log.Errorf("Error while unmarshal tap config, err: %v", err)
}
}
}
}
return config
}
func Save(tapConfigToSave *models.TapConfig) {
lock.Lock()
defer lock.Unlock()
config = tapConfigToSave
if data, err := json.Marshal(config); err != nil {
logger.Log.Errorf("Error while marshal tap config, err: %v", err)
} else {
if err := ioutil.WriteFile(FilePath, data, 0644); err != nil {
logger.Log.Errorf("Error writing tap config to file, err: %v", err)
}
}
}

View File

@@ -0,0 +1,32 @@
package tappedPods
import (
"github.com/up9inc/mizu/shared"
"mizuserver/pkg/providers/tappersStatus"
"strings"
)
var tappedPods []*shared.PodInfo
func Get() []*shared.PodInfo {
return tappedPods
}
func Set(tappedPodsToSet []*shared.PodInfo) {
tappedPods = tappedPodsToSet
}
func GetTappedPodsStatus() []shared.TappedPodStatus {
tappedPodsStatus := make([]shared.TappedPodStatus, 0)
for _, pod := range Get() {
var status string
if tapperStatus, ok := tappersStatus.Get()[pod.NodeName]; ok {
status = strings.ToLower(tapperStatus.Status)
}
isTapped := status == "running"
tappedPodsStatus = append(tappedPodsStatus, shared.TappedPodStatus{Name: pod.Name, Namespace: pod.Namespace, IsTapped: isTapped})
}
return tappedPodsStatus
}

View File

@@ -0,0 +1,25 @@
package tappersCount
import "sync"
var lock = &sync.Mutex{}
var tappersCount int
func Add() {
lock.Lock()
defer lock.Unlock()
tappersCount++
}
func Remove() {
lock.Lock()
defer lock.Unlock()
tappersCount--
}
func Get() int {
return tappersCount
}

View File

@@ -0,0 +1,25 @@
package tappersStatus
import "github.com/up9inc/mizu/shared"
var tappersStatus map[string]*shared.TapperStatus
func Get() map[string]*shared.TapperStatus {
if tappersStatus == nil {
tappersStatus = make(map[string]*shared.TapperStatus)
}
return tappersStatus
}
func Set(tapperStatus *shared.TapperStatus) {
if tappersStatus == nil {
tappersStatus = make(map[string]*shared.TapperStatus)
}
tappersStatus[tapperStatus.NodeName] = tapperStatus
}
func Reset() {
tappersStatus = make(map[string]*shared.TapperStatus)
}

View File

@@ -3,12 +3,10 @@ package utils
import (
"context"
"fmt"
"mizuserver/pkg/providers"
"net/http"
"net/url"
"os"
"os/signal"
"strings"
"syscall"
"time"
@@ -45,16 +43,6 @@ func StartServer(app *gin.Engine) {
}
}
func GetTappedPodsStatus() []shared.TappedPodStatus {
tappedPodsStatus := make([]shared.TappedPodStatus, 0)
for _, pod := range providers.TapStatus.Pods {
status := strings.ToLower(providers.TappersStatus[pod.NodeName].Status)
isTapped := status == "running"
tappedPodsStatus = append(tappedPodsStatus, shared.TappedPodStatus{Name: pod.Name, Namespace: pod.Namespace, IsTapped: isTapped})
}
return tappedPodsStatus
}
func CheckErr(e error) {
if e != nil {
logger.Log.Errorf("%v", e)

View File

@@ -14,8 +14,12 @@ help: ## This help.
install:
go install mizu.go
build-debug:
export GCLFAGS='-gcflags="all=-N -l"'
${MAKE} build
build: ## Build mizu CLI binary (select platform via GOOS / GOARCH env variables).
go build -ldflags="-X 'github.com/up9inc/mizu/cli/mizu.GitCommitHash=$(COMMIT_HASH)' \
go build ${GCLFAGS} -ldflags="-X 'github.com/up9inc/mizu/cli/mizu.GitCommitHash=$(COMMIT_HASH)' \
-X 'github.com/up9inc/mizu/cli/mizu.Branch=$(GIT_BRANCH)' \
-X 'github.com/up9inc/mizu/cli/mizu.BuildTimestamp=$(BUILD_TIMESTAMP)' \
-X 'github.com/up9inc/mizu/cli/mizu.Platform=$(SUFFIX)' \

View File

@@ -87,9 +87,8 @@ func (provider *Provider) ReportTappedPods(pods []core.Pod) error {
tappedPodsUrl := fmt.Sprintf("%s/status/tappedPods", provider.url)
podInfos := kubernetes.GetPodInfosForPods(pods)
tapStatus := shared.TapStatus{Pods: podInfos}
if jsonValue, err := json.Marshal(tapStatus); err != nil {
if jsonValue, err := json.Marshal(podInfos); err != nil {
return fmt.Errorf("failed Marshal the tapped pods %w", err)
} else {
if response, err := provider.client.Post(tappedPodsUrl, "application/json", bytes.NewBuffer(jsonValue)); err != nil {

View File

@@ -89,6 +89,8 @@ func getInstallMizuAgentConfig(maxDBSizeBytes int64, tapperResources shared.Reso
MizuResourcesNamespace: config.Config.MizuResourcesNamespace,
AgentDatabasePath: shared.DataDirPath,
StandaloneMode: true,
ServiceMap: config.Config.ServiceMap,
OAS: config.Config.OAS,
}
return &mizuAgentConfig
@@ -99,7 +101,7 @@ func watchApiServerPodReady(ctx context.Context, kubernetesProvider *kubernetes.
podWatchHelper := kubernetes.NewPodWatchHelper(kubernetesProvider, podExactRegex)
eventChan, errorChan := kubernetes.FilteredWatch(ctx, podWatchHelper, []string{config.Config.MizuResourcesNamespace}, podWatchHelper)
timeAfter := time.After(30 * time.Second)
timeAfter := time.After(1 * time.Minute)
for {
select {
case wEvent, ok := <-eventChan:

View File

@@ -156,6 +156,8 @@ func getTapMizuAgentConfig() *shared.MizuAgentConfig {
TapperResources: config.Config.Tap.TapperResources,
MizuResourcesNamespace: config.Config.MizuResourcesNamespace,
AgentDatabasePath: shared.DataDirPath,
ServiceMap: config.Config.ServiceMap,
OAS: config.Config.OAS,
}
return &mizuAgentConfig

View File

@@ -34,9 +34,11 @@ type ConfigStruct struct {
ConfigFilePath string `yaml:"config-path,omitempty" readonly:""`
HeadlessMode bool `yaml:"headless" default:"false"`
LogLevelStr string `yaml:"log-level,omitempty" default:"INFO" readonly:""`
ServiceMap bool `yaml:"service-map" default:"false" readonly:""`
OAS bool `yaml:"oas" default:"false" readonly:""`
}
func(config *ConfigStruct) validate() error {
func (config *ConfigStruct) validate() error {
if _, err := logging.LogLevel(config.LogLevelStr); err != nil {
return fmt.Errorf("%s is not a valid log level, err: %v", config.LogLevelStr, err)
}

View File

@@ -2,6 +2,7 @@
for f in tap/extensions/*; do
if [ -d "$f" ]; then
echo Building extension: $f
extension=$(basename $f) && \
cd tap/extensions/${extension} && \
go build -buildmode=plugin -o ../${extension}.so . && \

View File

@@ -73,10 +73,10 @@ func getMissingPods(pods1 []core.Pod, pods2 []core.Pod) []core.Pod {
return missingPods
}
func GetPodInfosForPods(pods []core.Pod) []shared.PodInfo {
podInfos := make([]shared.PodInfo, 0)
func GetPodInfosForPods(pods []core.Pod) []*shared.PodInfo {
podInfos := make([]*shared.PodInfo, 0)
for _, pod := range pods {
podInfos = append(podInfos, shared.PodInfo{Name: pod.Name, Namespace: pod.Namespace, NodeName: pod.Spec.NodeName})
podInfos = append(podInfos, &shared.PodInfo{Name: pod.Name, Namespace: pod.Namespace, NodeName: pod.Spec.NodeName})
}
return podInfos
}

View File

@@ -41,6 +41,8 @@ type MizuAgentConfig struct {
MizuResourcesNamespace string `json:"mizuResourceNamespace"`
AgentDatabasePath string `json:"agentDatabasePath"`
StandaloneMode bool `json:"standaloneMode"`
ServiceMap bool `json:"serviceMap"`
OAS bool `json:"oas"`
}
type WebSocketMessageMetadata struct {
@@ -81,10 +83,6 @@ type TappedPodStatus struct {
IsTapped bool `json:"isTapped"`
}
type TapStatus struct {
Pods []PodInfo `json:"pods"`
}
type PodInfo struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
@@ -124,9 +122,9 @@ func CreateWebSocketMessageTypeAnalyzeStatus(analyzeStatus AnalyzeStatus) WebSoc
}
type HealthResponse struct {
TapStatus TapStatus `json:"tapStatus"`
TappersCount int `json:"tappersCount"`
TappersStatus []TapperStatus `json:"tappersStatus"`
TappedPods []*PodInfo `json:"tappedPods"`
TappersCount int `json:"tappersCount"`
TappersStatus []*TapperStatus `json:"tappersStatus"`
}
type VersionResponse struct {