Skip to content

Instantly share code, notes, and snippets.

@ialidzhikov
Created September 30, 2022 14:49
Show Gist options
  • Select an option

  • Save ialidzhikov/c33b1c69e830bb0248e516f5260885c5 to your computer and use it in GitHub Desktop.

Select an option

Save ialidzhikov/c33b1c69e830bb0248e516f5260885c5 to your computer and use it in GitHub Desktop.
package main
import (
"context"
"flag"
"fmt"
"time"
gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1"
"github.com/gardener/gardener/pkg/client/kubernetes"
versionutils "github.com/gardener/gardener/pkg/utils/version"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"
)
var gardenKubeconfig = flag.String("garden-kubeconfig", "", "Garden cluster's kubeconfig path")
var createdInLastDays = flag.Duration("created-in-last-days", 10*24*time.Hour, "Filter for Shoots created in the last n days")
func main() {
flag.Parse()
if gardenKubeconfig == nil || len(*gardenKubeconfig) == 0 {
panic("--garden-kubeconfig is required")
}
ctx := context.Background()
gardenClientset, err := kubernetes.NewClientFromFile(
"",
*gardenKubeconfig,
kubernetes.WithClientOptions(client.Options{Scheme: kubernetes.GardenScheme}),
kubernetes.WithDisabledCachedClient(),
)
if err != nil {
panic(err)
}
gardenClient := gardenClientset.Client()
shootList := &gardencorev1beta1.ShootList{}
if err := gardenClient.List(ctx, shootList, client.MatchingFields{"spec.cloudProfileName": "aws"}); err != nil {
panic(err)
}
for _, shoot := range shootList.Items {
fmt.Printf("> %s/%s\n", shoot.Namespace, shoot.Name)
time.Sleep(time.Second / 2)
createdBefore := time.Now().UTC().Sub(shoot.CreationTimestamp.UTC())
if createdBefore >= *createdInLastDays {
fmt.Printf("Shoot is created before %+v days. Skipping...\n", createdBefore.Hours()/24)
continue
}
greaterEqual122, err := versionutils.CompareVersions(shoot.Spec.Kubernetes.Version, ">=", "1.22")
if err != nil {
panic(err)
}
// Only K8s >= 1.22 Shoots are affected
if !greaterEqual122 {
fmt.Println("Shoot's Kubernetes version is < 1.22. Skipping...")
continue
}
// Only multi-zone Shoots are affected
if !hasMultizoneWorkerPool(&shoot) {
fmt.Println("Shoot does not have a multi-zone worker pool. Skipping...")
continue
}
shootClientset, err := kubernetes.NewClientFromSecret(ctx, gardenClient, shoot.Namespace, shoot.Name+".kubeconfig")
if err != nil {
fmt.Printf("Potentially affected! Failed to construct Shoot client: %+v\n", err)
continue
}
shootClient := shootClientset.Client()
ipPool := &unstructured.Unstructured{}
ipPool.SetAPIVersion("crd.projectcalico.org/v1")
ipPool.SetKind("IPPool")
key := client.ObjectKey{Namespace: "default", Name: "default-ipv4-ippool"}
if err := shootClient.Get(ctx, key, ipPool); err != nil {
fmt.Printf("Potentially affected! Failed to fetch IPPool: %+v\n", err)
continue
}
value, found, err := unstructured.NestedString(ipPool.Object, "spec", "ipipMode")
if err != nil {
fmt.Printf("Potentially affected! Failed to check for the ipipMode field of IPPool: %+v\n", err)
continue
}
if !found {
fmt.Printf("Potentially affected! Failed to find the ipipMode field of IPPool: %+v\n", err)
continue
}
if value == "Never" {
fmt.Printf("Affected! %s/%s, creationTimestamp=%+v\n", shoot.Namespace, shoot.Name, shoot.CreationTimestamp.UTC().Format(time.RFC3339))
} else if value == "Always" {
fmt.Println("Not affected!")
}
}
}
func hasMultizoneWorkerPool(shoot *gardencorev1beta1.Shoot) bool {
for _, pool := range shoot.Spec.Provider.Workers {
if len(pool.Zones) > 1 {
return true
}
}
return false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment