Skip to content

Commit

Permalink
fix: using dynamic namespace for the gateway cmd (#239)
Browse files Browse the repository at this point in the history
  • Loading branch information
leoporoli authored Sep 20, 2024
1 parent 1073cb5 commit 7615ce3
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 13 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,4 @@ kardinal flow telepresence-intercept {{flow-id}} {{service-name}} {{local-port}}
- Explore our [docs](https://kardinal.dev/docs) to learn more about how Kardinal works.
- Ask questions and get help in our community [forum](https://discuss.kardinal.dev).
- Read our [blog](https://blog.kardinal.dev/) for tips from developers and creators.

2 changes: 1 addition & 1 deletion kardinal-cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ var gatewayCmd = &cobra.Command{
}
}

if err := deployment.StartGateway(hostFlowIdMap); err != nil {
if err := deployment.StartGateway(ctx, hostFlowIdMap); err != nil {
log.Fatal("An error occurred while creating a gateway", err)
}
},
Expand Down
39 changes: 28 additions & 11 deletions kardinal-cli/deployment/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const (
proxyPortRangeEnd = 60000
maxRetries = 10
retryInterval = 10 * time.Second
prodNamespace = "prod"
)

func hashStringToRange(s string, maxRange int) int {
Expand Down Expand Up @@ -67,7 +66,7 @@ func findAvailablePortInRange(host string, portsInUse *[]int) (int, error) {
return port, nil
}

func StartGateway(hostFlowIdMap map[string]string) error {
func StartGateway(ctx context.Context, hostFlowIdMap map[string]string) error {
client, err := kubernetes_pack.CreateKubernetesClient()
if err != nil {
return fmt.Errorf("an error occurred while creating a kubernetes client:\n %v", err)
Expand All @@ -76,10 +75,27 @@ func StartGateway(hostFlowIdMap map[string]string) error {
for host, flowId := range hostFlowIdMap {
logrus.Printf("Starting gateway for host: %s", host)

// Check for pods in the prod namespace
err = assertProdNamespaceReady(client.GetClientSet(), flowId)
// TODO move these values to a shared library between Kardinal Manager, Kontrol and Kardinal CLI
kardinalLabelKey := "kardinal.dev"
enabledKardinal := "enabled"

namespaceLabels := map[string]string{
kardinalLabelKey: enabledKardinal,
}

namespaceList, err := client.GetNamespacesByLabels(ctx, namespaceLabels)
if err != nil {
return fmt.Errorf("failed to list namespaces from Kubernetes: %v", err)
}
if len(namespaceList.Items) > 1 {
return fmt.Errorf("cannot start gateway because more than one Kardinal namespace was found")
}
baselineNamespace := namespaceList.Items[0]

// Check for pods in the baseline namespace
err = assertBaselineNamespaceReady(client.GetClientSet(), flowId, baselineNamespace.Name)
if err != nil {
return fmt.Errorf("failed to assert that prod namespace is ready: %v", err)
return fmt.Errorf("failed to assert that baseline namespace is ready: %v", err)
}

// Check for the Envoy filter before proceeding
Expand Down Expand Up @@ -155,17 +171,18 @@ func StartGateway(hostFlowIdMap map[string]string) error {
}

// TODO move to the kubernetes package
func assertProdNamespaceReady(client *kubernetes.Clientset, flowId string) error {
func assertBaselineNamespaceReady(client *kubernetes.Clientset, flowId string, baselineNamespace string) error {

for retry := 0; retry < maxRetries; retry++ {
pods, err := client.CoreV1().Pods(prodNamespace).List(context.Background(), metav1.ListOptions{})
pods, err := client.CoreV1().Pods(baselineNamespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
logrus.Printf("Error listing pods in prod namespace (attempt %d/%d): %v", retry+1, maxRetries, err)
logrus.Printf("Error listing pods in baseline namespace (attempt %d/%d): %v", retry+1, maxRetries, err)
time.Sleep(retryInterval)
continue
}

if len(pods.Items) == 0 {
logrus.Printf("No pods found in namespace %s (attempt %d/%d)", prodNamespace, retry+1, maxRetries)
logrus.Printf("No pods found in namespace %s (attempt %d/%d)", baselineNamespace, retry+1, maxRetries)
time.Sleep(retryInterval)
continue
}
Expand All @@ -190,15 +207,15 @@ func assertProdNamespaceReady(client *kubernetes.Clientset, flowId string) error
}

if allReady && flowIdFound {
logrus.Printf("All pods in namespace %s are ready and flowId %s found", prodNamespace, flowId)
logrus.Printf("All pods in namespace %s are ready and flowId %s found", baselineNamespace, flowId)
return nil
}

logrus.Printf("Waiting for all pods to be ready and flowId to be found (attempt %d/%d)", retry+1, maxRetries)
time.Sleep(retryInterval)
}

return fmt.Errorf("failed to assert all pods are ready and flowId %s found in namespace %s after %d attempts", flowId, prodNamespace, maxRetries)
return fmt.Errorf("failed to assert all pods are ready and flowId %s found in namespace %s after %d attempts", flowId, baselineNamespace, maxRetries)
}

func isPodReady(pod *corev1.Pod) bool {
Expand Down
25 changes: 25 additions & 0 deletions kardinal-cli/kubernetes/kubernetes_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,31 @@ func (client *kubernetesClient) RemoveNamespaceResourcesByLabels(ctx context.Con
return nil
}

func (client *kubernetesClient) GetNamespacesByLabels(ctx context.Context, namespaceLabels map[string]string) (*corev1.NamespaceList, error) {
namespaceClient := client.clientSet.CoreV1().Namespaces()

listOptions := buildListOptionsFromLabels(namespaceLabels)
namespaces, err := namespaceClient.List(ctx, listOptions)
if err != nil {
return nil, stacktrace.Propagate(err, "Failed to list namespaces with labels '%+v'", namespaceLabels)
}

// Only return objects not tombstoned by Kubernetes
var namespacesNotMarkedForDeletionList []corev1.Namespace
for _, namespace := range namespaces.Items {
deletionTimestamp := namespace.GetObjectMeta().GetDeletionTimestamp()
if deletionTimestamp == nil {
namespacesNotMarkedForDeletionList = append(namespacesNotMarkedForDeletionList, namespace)
}
}
namespacesNotMarkedForDeletionnamespaceList := corev1.NamespaceList{
Items: namespacesNotMarkedForDeletionList,
TypeMeta: namespaces.TypeMeta,
ListMeta: namespaces.ListMeta,
}
return &namespacesNotMarkedForDeletionnamespaceList, nil
}

func buildListOptionsFromLabels(labelsMap map[string]string) metav1.ListOptions {
return metav1.ListOptions{
TypeMeta: metav1.TypeMeta{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const (
istioLabel = "istio-injection"
enabledIstioValue = "enabled"
telepresenceRestartedAtAnnotation = "telepresence.getambassador.io/restartedAt"

// TODO move these values to a shared library between Kardinal Manager, Kontrol and Kardinal CLI
kardinalLabelKey = "kardinal.dev"
enabledKardinal = "enabled"
)

var (
Expand Down Expand Up @@ -389,7 +393,8 @@ func (manager *ClusterManager) ensureNamespace(ctx context.Context, name string)
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: map[string]string{
istioLabel: enabledIstioValue,
istioLabel: enabledIstioValue,
kardinalLabelKey: enabledKardinal,
},
},
}
Expand Down

0 comments on commit 7615ce3

Please sign in to comment.