Skip to content

Commit

Permalink
Improve reporting + small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
VOID404 committed Jan 8, 2025
1 parent b409500 commit 2040cec
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 101 deletions.
26 changes: 24 additions & 2 deletions hack/runtime-migrator/cmd/crb-cleanup/cleaner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package main

import (
"context"
"encoding/json"
"io"
"log/slog"

v1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -19,7 +22,6 @@ type Compared struct {
}

type Cleaner interface {
Compare(ctx context.Context, old []v1.ClusterRoleBinding, new []v1.ClusterRoleBinding) Compared
Clean(context.Context, []v1.ClusterRoleBinding) []Failure
}

Expand All @@ -32,12 +34,15 @@ type Failure struct {
Err error `json:"error"`
}

// Clean deletes CRBs, returning list of deleting errors
func (c CRBCleaner) Clean(ctx context.Context, crbs []v1.ClusterRoleBinding) []Failure {
failures := make([]Failure, 0)

for _, crb := range crbs {
slog.Debug("Removing CRB", "crb", crb.Name)
err := c.client.Delete(ctx, crb.Name, metav1.DeleteOptions{})
if err != nil {
slog.Error("Error removing CRB", "crb", crb.Name)
failures = append(failures, Failure{
CRB: crb,
Err: err,
Expand All @@ -48,7 +53,8 @@ func (c CRBCleaner) Clean(ctx context.Context, crbs []v1.ClusterRoleBinding) []F
return failures
}

func (c CRBCleaner) Compare(ctx context.Context, old []v1.ClusterRoleBinding, new []v1.ClusterRoleBinding) Compared {
// Compare returns missing, additional and original CRBs
func Compare(ctx context.Context, old []v1.ClusterRoleBinding, new []v1.ClusterRoleBinding) Compared {
missing, additional := difference(old, new, CRBEquals)

return Compared{
Expand All @@ -64,3 +70,19 @@ func NewCRBCleaner(client KubeDeleter) Cleaner {
client: client,
}
}

type PretendCleaner struct {
removed io.Writer
}

func (p PretendCleaner) Clean(_ context.Context, crbs []v1.ClusterRoleBinding) []Failure {
err := json.NewEncoder(p.removed).Encode(crbs)
slog.Error("Error saving removed CRBs", "error", err, "crbs", crbs)
return nil
}

func NewPretendCleaner(removed io.Writer) Cleaner {
return PretendCleaner{
removed: removed,
}
}
53 changes: 43 additions & 10 deletions hack/runtime-migrator/cmd/crb-cleanup/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"context"
"log/slog"
"os"

"encoding/json"
)

// const LabelSelectorOld = "kyma-project.io/deprecation=to-be-removed-soon,reconciler.kyma-project.io/managed-by=provisioner"
const LabelSelectorOld = "reconciler.kyma-project.io/managed-by=infrastructure-manager"
const LabelSelectorOld = "kyma-project.io/deprecation=to-be-removed-soon,reconciler.kyma-project.io/managed-by=provisioner"
const LabelSelectorNew = "reconciler.kyma-project.io/managed-by=infrastructure-manager"

func main() {
Expand All @@ -21,26 +22,58 @@ func main() {

client := setupKubectl(cfg.Kubeconfig).RbacV1().ClusterRoleBindings()
fetcher := NewCRBFetcher(client, cfg.OldLabel, cfg.NewLabel)
cleaner := NewCRBCleaner(client)

ProcessCRBs(fetcher, cleaner, cfg)
var cleaner Cleaner
if cfg.Pretend {
slog.Info("Running in pretend mode")
file, err := os.OpenFile("./removed.json", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
slog.Error("Error opening file, to save list of removed", "error", err)
os.Exit(1)
}
defer file.Close()
cleaner = NewPretendCleaner(file)
} else {
cleaner = NewCRBCleaner(client)
}

file, err := os.OpenFile("./failures.json", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
slog.Error("Error opening file, to save list of failures", "error", err)
os.Exit(1)
}
defer file.Close()
failures, err := ProcessCRBs(fetcher, cleaner, cfg)
if err != nil {
slog.Error("Error processing CRBs", "error", err)
os.Exit(1)
}
err = json.NewEncoder(file).Encode(failures)
if err != nil {
slog.Error("Error marshaling list of failures", "error", err, "failures", failures)
os.Exit(1)
}
}

func ProcessCRBs(fetcher Fetcher, cleaner Cleaner, cfg Config) []Failure {
// ProcessCRBs fetches old and new CRBs, compares them and cleans old CRBs
// It returns error on fetch errors
// It does nothing, if old CRBs are not found in new CRBs, unless force flag is set
// It returns list of failures on removal errors
func ProcessCRBs(fetcher Fetcher, cleaner Cleaner, cfg Config) ([]Failure, error) {
ctx := context.Background()
oldCRBs, err := fetcher.FetchOld(ctx)
if err != nil {
slog.Error("Error fetching old CRBs", "error", err)
os.Exit(1)
return nil, err
}

newCRBs, err := fetcher.FetchNew(ctx)
if err != nil {
slog.Error("Error fetching new CRBs", "error", err)
os.Exit(1)
return nil, err
}

compared := cleaner.Compare(ctx, oldCRBs, newCRBs)
compared := Compare(ctx, oldCRBs, newCRBs)

if len(compared.additional) != 0 {
slog.Info("New CRBs not found in old CRBs", "crbs", compared.additional)
Expand All @@ -49,9 +82,9 @@ func ProcessCRBs(fetcher Fetcher, cleaner Cleaner, cfg Config) []Failure {
slog.Warn("Old CRBs not found in new CRBs", "crbs", compared.missing)
if !cfg.Force {
slog.Info("Use -force to remove old CRBs without match")
os.Exit(1)
return nil, nil
}
}

return cleaner.Clean(ctx, oldCRBs)
return cleaner.Clean(ctx, oldCRBs), nil
}
68 changes: 66 additions & 2 deletions hack/runtime-migrator/cmd/crb-cleanup/main_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main_test
package main

import (
"context"
Expand All @@ -24,6 +24,16 @@ var _ = Describe("Envtest", func() {
fetcher := NewCRBFetcher(crbClient, "old=true", "new=true")
cleaner := NewCRBCleaner(crbClient)

BeforeEach(func() {
new, err := fetcher.FetchNew(ctx)
Expect(err).ToNot(HaveOccurred())

old, err := fetcher.FetchOld(ctx)
Expect(err).ToNot(HaveOccurred())

cleaner.Clean(ctx, append(new, old...))
})

It("removes old CRBs", func() {
By("Generate test data")
old, new := generateCRBs(5)
Expand All @@ -34,7 +44,34 @@ var _ = Describe("Envtest", func() {
}

By("Processing CRBs")
failures := ProcessCRBs(fetcher, cleaner, Config{
failures, err := ProcessCRBs(fetcher, cleaner, Config{
Kubeconfig: "",
Pretend: false,
Verbose: false,
Force: false,
OldLabel: "",
NewLabel: "",
})

Expect(err).ToNot(HaveOccurred())
Expect(failures).To(BeEmpty())

Eventually(func() ([]rbacv1.ClusterRoleBinding, error) {
return fetcher.FetchOld(ctx)
}).Should(BeEmpty())
})

It("skips removal when mismatch is found", func() {
By("Generate test data")
old, new := generateCRBs(5)

for _, crb := range append(old, new[3:]...) {
_, err := crbClient.Create(ctx, crb, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred(), "Failed to create CRB %q", crb.Name)
}

By("Processing CRBs")
failures, err := ProcessCRBs(fetcher, cleaner, Config{
Kubeconfig: "",
Pretend: false,
Verbose: false,
Expand All @@ -43,6 +80,33 @@ var _ = Describe("Envtest", func() {
NewLabel: "",
})

Expect(err).ToNot(HaveOccurred())
Expect(failures).To(BeEmpty())
Consistently(func() ([]rbacv1.ClusterRoleBinding, error) {
return fetcher.FetchOld(ctx)
}).Should(HaveLen(5))
})

It("removes despite mismatch, with -force", func() {
By("Generate test data")
old, new := generateCRBs(5)

for _, crb := range append(old, new[3:]...) {
_, err := crbClient.Create(ctx, crb, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred(), "Failed to create CRB %q", crb.Name)
}

By("Processing CRBs")
failures, err := ProcessCRBs(fetcher, cleaner, Config{
Kubeconfig: "",
Pretend: false,
Verbose: false,
Force: true,
OldLabel: "",
NewLabel: "",
})

Expect(err).ToNot(HaveOccurred())
Expect(failures).To(BeEmpty())
Eventually(func() ([]rbacv1.ClusterRoleBinding, error) {
return fetcher.FetchOld(ctx)
Expand Down
86 changes: 0 additions & 86 deletions hack/runtime-migrator/cmd/crb-cleanup/main_test.go.bak

This file was deleted.

2 changes: 1 addition & 1 deletion hack/runtime-migrator/cmd/crb-cleanup/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ func CRBEquals(crbA, crbB *v1.ClusterRoleBinding) bool {
return true
}


func setupKubectl(kubeconfig string) *kubernetes.Clientset {
slog.Info("Loading kubeconfig", "path", kubeconfig)
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
slog.Error("Error building kubeconfig", "error", err)
Expand Down

0 comments on commit 2040cec

Please sign in to comment.