From 7e790724894ae4f26b4bca92c19b09465eb1156f Mon Sep 17 00:00:00 2001 From: Gyanendra Mishra Date: Wed, 21 Aug 2024 14:58:49 +0100 Subject: [PATCH] fix: check if envoy filters are updated before starting gateway (#168) there are race conditions otherwise where the gateway comes up before the filter and routing doesn't work there are also situations where there might be a bug due to which the gateway filter isn't deployed (it has bugs); but the gateway comes up anyway --- kardinal-cli/deployment/gateway.go | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/kardinal-cli/deployment/gateway.go b/kardinal-cli/deployment/gateway.go index 2b4279a7..22430e4b 100644 --- a/kardinal-cli/deployment/gateway.go +++ b/kardinal-cli/deployment/gateway.go @@ -2,6 +2,7 @@ package deployment import ( "context" + "encoding/json" "fmt" "io" "log" @@ -53,6 +54,12 @@ func StartGateway(host, flowId string) error { return fmt.Errorf("failed to find pod for service: %v", err) } + // Check for the Envoy filter before proceeding + err = checkGatewayEnvoyFilter(client.clientSet, host) + if err != nil { + return err + } + // Start port forwarding stopChan := make(chan struct{}, 1) readyChan := make(chan struct{}) @@ -190,6 +197,47 @@ func findPodForService(client *kubernetes.Clientset) (string, error) { return podName, nil } +func checkGatewayEnvoyFilter(client *kubernetes.Clientset, host string) error { + for retry := 0; retry < maxRetries; retry++ { + envoyFilterRaw, err := client.RESTClient(). + Get(). + AbsPath("/apis/networking.istio.io/v1alpha3/namespaces/istio-system/envoyfilters/kardinal-gateway-tracing"). + Do(context.Background()). + Raw() + if err != nil { + log.Printf("Error getting Envoy filter (attempt %d/%d): %v", retry+1, maxRetries, err) + time.Sleep(retryInterval) + continue + } + + var envoyFilter map[string]interface{} + err = json.Unmarshal(envoyFilterRaw, &envoyFilter) + if err != nil { + log.Printf("Error unmarshaling Envoy filter (attempt %d/%d): %v", retry+1, maxRetries, err) + time.Sleep(retryInterval) + continue + } + + luaCode, ok := envoyFilter["spec"].(map[string]interface{})["configPatches"].([]interface{})[0].(map[string]interface{})["patch"].(map[string]interface{})["value"].(map[string]interface{})["typed_config"].(map[string]interface{})["inlineCode"].(string) + if !ok { + log.Printf("Error getting Lua code from Envoy filter (attempt %d/%d)", retry+1, maxRetries) + time.Sleep(retryInterval) + continue + } + + if !strings.Contains(luaCode, host) { + log.Printf("Envoy filter 'kardinal-gateway-tracing' does not contain the expected host string: %s (attempt %d/%d)", host, retry+1, maxRetries) + time.Sleep(retryInterval) + continue + } + + log.Printf("Envoy filter 'kardinal-gateway-tracing' found and contains the expected host string: %s", host) + return nil + } + + return fmt.Errorf("failed to find Envoy filter 'kardinal-gateway-tracing' containing the expected host string after %d attempts", maxRetries) +} + func portForwardPod(config *rest.Config, podName string, stopChan <-chan struct{}, readyChan chan struct{}) error { roundTripper, upgrader, err := spdy.RoundTripperFor(config) if err != nil {