Last active
May 20, 2025 06:38
-
-
Save ialidzhikov/d9896a9d23d26a4b8c70eb29c0c055cf to your computer and use it in GitHub Desktop.
Find Shoots with missing APIServerProxyUsesHTTPProxy constraint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Check if the correct number of arguments is provided | |
| if [ "$#" -ne 2 ]; then | |
| echo "Usage: $0 <namespace> <shoot_name>" | |
| exit 1 | |
| fi | |
| NAMESPACE=$1 | |
| SHOOT_NAME=$2 | |
| # Retrieve the current constraints | |
| CURRENT_CONSTRAINTS=$(kubectl -n "$NAMESPACE" get shoots "$SHOOT_NAME" -o jsonpath='{.status.constraints}' | jq '.') | |
| # Define the new constraint to be added | |
| NEW_CONSTRAINT='{ | |
| "type": "APIServerProxyUsesHTTPProxy", | |
| "status": "True", | |
| "lastTransitionTime": "2025-02-18T01:23:25Z", | |
| "lastUpdateTime": "2025-02-18T01:23:25Z", | |
| "reason": "APIServerProxyUsesHTTPProxy", | |
| "message": "Manually patched. Nessesary for enablement of RemoveAPIServerProxyLegacyPort feature gate as cluster was failing to reconcile successfully since longtime and prevented feature gate enablement" | |
| }' | |
| echo "Current Constraints:" | |
| echo "$CURRENT_CONSTRAINTS" | jq '.' | |
| # Append the new constraint to the current constraints | |
| UPDATED_CONSTRAINTS=$(echo "$CURRENT_CONSTRAINTS" | jq --argjson newConstraint "$NEW_CONSTRAINT" '. += [$newConstraint]') | |
| echo "Updated Constraint:" | |
| echo "$UPDATED_CONSTRAINTS" | jq '.' | |
| # Ask for permission to patch | |
| read -p "Do you want to proceed with patching the resource? (yes/no): " CONFIRMATION | |
| if [[ "$CONFIRMATION" == "yes" ]]; then | |
| # Patch the resource with the updated constraints | |
| kubectl -n "$NAMESPACE" patch shoots "$SHOOT_NAME" --type=merge --patch "$(jq -n --argjson constraints "$UPDATED_CONSTRAINTS" '{"status": {"constraints": $constraints}}')" --subresource=status | |
| echo "Resource patched successfully." | |
| else | |
| echo "Patching aborted." | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "context" | |
| "fmt" | |
| "os" | |
| gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" | |
| v1beta1helper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper" | |
| "k8s.io/apimachinery/pkg/runtime" | |
| "k8s.io/apimachinery/pkg/util/sets" | |
| "k8s.io/client-go/tools/clientcmd" | |
| "sigs.k8s.io/controller-runtime/pkg/client" | |
| ) | |
| var endUserErrorCodes = sets.New( | |
| gardencorev1beta1.ErrorInfraUnauthenticated, | |
| gardencorev1beta1.ErrorInfraUnauthorized, | |
| gardencorev1beta1.ErrorInfraDependencies, | |
| gardencorev1beta1.ErrorInfraQuotaExceeded, | |
| gardencorev1beta1.ErrorConfigurationProblem, | |
| ) | |
| func main() { | |
| ctx := context.Background() | |
| kubeconfig := os.Getenv("KUBECONFIG") | |
| if kubeconfig == "" { | |
| panic(fmt.Errorf("KUBECONFIG env var is not set")) | |
| } | |
| config, err := clientcmd.BuildConfigFromFlags("", kubeconfig) | |
| if err != nil { | |
| panic(fmt.Errorf("failed to create client config: %w", err)) | |
| } | |
| scheme := runtime.NewScheme() | |
| gardencorev1beta1.AddToScheme(scheme) | |
| client, err := client.New(config, client.Options{ | |
| Scheme: scheme, | |
| }) | |
| if err != nil { | |
| panic(fmt.Errorf("failed to create a client: %w", err)) | |
| } | |
| shoots := &gardencorev1beta1.ShootList{} | |
| if err := client.List(ctx, shoots); err != nil { | |
| panic(fmt.Errorf("failed to list shoots: %w", err)) | |
| } | |
| for _, shoot := range shoots.Items { | |
| if v1beta1helper.IsWorkerless(&shoot) { | |
| continue | |
| } | |
| if shoot.Status.LastOperation == nil || ((shoot.Status.LastOperation.Type == gardencorev1beta1.LastOperationTypeCreate || shoot.Status.LastOperation.Type == gardencorev1beta1.LastOperationTypeDelete) && shoot.Status.LastOperation.State != gardencorev1beta1.LastOperationStateSucceeded) { | |
| continue | |
| } | |
| if cond := v1beta1helper.GetCondition(shoot.Status.Constraints, gardencorev1beta1.ShootAPIServerProxyUsesHTTPProxy); cond != nil && cond.Status == gardencorev1beta1.ConditionTrue { | |
| continue | |
| } | |
| fmt.Printf("%s/%s: ", shoot.Namespace, shoot.Name) | |
| lastOperation := shoot.Status.LastOperation | |
| fmt.Printf("%s %s; ", lastOperation.Type, lastOperation.State) | |
| if lastErrors := shoot.Status.LastErrors; lastErrors != nil { | |
| for _, lastError := range lastErrors { | |
| for _, code := range lastError.Codes { | |
| if endUserErrorCodes.Has(code) { | |
| fmt.Printf("%s;", code) | |
| } | |
| } | |
| } | |
| } | |
| fmt.Println() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment