-
Notifications
You must be signed in to change notification settings - Fork 4
fix(gc): improve error handling in object reading functions #708
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
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
Diff@@ spec.templates.run.volumes.gc-script.configMap.name @@
# argoproj.io/v1alpha1/WorkflowTemplate/harbor/gc
! ± value change
- gc-script-4dbgtgttmk
+ gc-script-5578gbhb94
@@ (root level) @@
# v1/ConfigMap/harbor/gc-script-4dbgtgttmk
! - one document removed:
- ---
- apiVersion: v1
- data:
- entrypoint.sh: |
- #!/usr/bin/env bash
-
- set -euxo pipefail
-
- apt update
- apt install -y zip
- curl https://rclone.org/install.sh | bash
-
- go run . -read-object-prefix trap-wasabi-registry:/trap-ns-registry/ -doit
-
- go.mod: |
- module playground
-
- go 1.23.0
-
- toolchain go1.24.2
-
- require (
- github.com/samber/lo v1.49.1
- github.com/schollz/progressbar/v3 v3.18.0
- github.com/sirupsen/logrus v1.9.3
- github.com/sourcegraph/conc v0.3.0
- golang.org/x/text v0.23.0
- )
-
- require (
- github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
- github.com/rivo/uniseg v0.4.7 // indirect
- go.uber.org/atomic v1.7.0 // indirect
- go.uber.org/multierr v1.9.0 // indirect
- golang.org/x/sys v0.29.0 // indirect
- golang.org/x/term v0.28.0 // indirect
- )
-
- go.sum: |
- github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
- github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
- github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
- github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
- github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
- github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
- github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
- github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
- github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
- github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
- github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
- github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
- github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
- github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
- github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
- github.com/samber/lo v1.48.0 h1:ELOfcaM7vdYPe0egBS2Nxa8LxkY4lR+9LBzj0l6cHJ0=
- github.com/samber/lo v1.48.0/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
- github.com/samber/lo v1.49.0 h1:AGnTnQrg1jpFuwECPUSoxZCfVH5W22b605kWSry3YxM=
- github.com/samber/lo v1.49.0/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
- github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
- github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
- github.com/schollz/progressbar/v3 v3.17.1 h1:bI1MTaoQO+v5kzklBjYNRQLoVpe0zbyRZNK6DFkVC5U=
- github.com/schollz/progressbar/v3 v3.17.1/go.mod h1:RzqpnsPQNjUyIgdglUjRLgD7sVnxN1wpmBMV+UiEbL4=
- github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
- github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
- github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
- github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
- github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
- github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
- github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
- github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
- github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
- github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
- github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
- go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
- go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
- go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
- go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
- golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
- golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
- golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
- golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
- golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
- golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
- golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
- golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
- golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
- golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
- golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
- golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
- golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
- golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
- golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
- gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
- gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
- gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
- gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-
- main.go: |
- package main
-
- import (
- "bytes"
- "encoding/json"
- "flag"
- "fmt"
- "os"
- "os/exec"
- "regexp"
- "slices"
- "strconv"
- "strings"
- "time"
-
- "github.com/samber/lo"
- "github.com/schollz/progressbar/v3"
- log "github.com/sirupsen/logrus"
- "github.com/sourcegraph/conc"
- "github.com/sourcegraph/conc/pool"
- "golang.org/x/text/language"
- "golang.org/x/text/message"
- )
-
- var (
- readObjectPrefix = flag.String("read-object-prefix", "trap-wasabi-registry:/trap-ns-registry/", "rclone object prefix")
- doit = flag.Bool("doit", false, "Disable dryrun and actually delete files")
- deleteRepoPrefix = "ns-apps-tmp/"
- gcRepoPrefix = "ns-apps/"
- )
-
- func init() {
- flag.Parse()
- }
-
- var (
- digestPattern = regexp.MustCompile("^[0-9a-f]{64}$")
- uploadsPattern = regexp.MustCompile("^(docker/registry/v2/repositories/[^/]+/[^/]+/_uploads/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/).+$")
- blobPattern = regexp.MustCompile("^docker/registry/v2/blobs/sha256/[0-9a-f]{2}/([0-9a-f]{64})/data$")
- layersPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_layers/sha256/([0-9a-f]{64})/link$")
- revisionsPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_manifests/revisions/sha256/([0-9a-f]{64})/link$")
- currentTagPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_manifests/tags/([^/]+)/current/link$")
- tagPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_manifests/tags/([^/]+)/index/sha256/([0-9a-f]{64})/link$")
- )
-
- func constructBlobPath(digest string) string {
- return fmt.Sprintf("docker/registry/v2/blobs/sha256/%s/%s/data", digest[:2], digest)
- }
-
- var objects map[string]*Object
-
- type Object struct {
- Size int
- Modified time.Time
- Path string
- }
-
- type Uploads struct {
- StartedAt time.Time
- Objects []*Object
- }
-
- type Repository struct {
- Layers map[string]*Object // SHA256 digest to object
- ManifestRevisions map[string]*Object // SHA256 digest to object
- Tags map[string]*RepositoryTag // Tag name to tag data
- }
-
- type RepositoryTag struct {
- CurrentBlob string // SHA256 digest pointed by CurrentObject
- CurrentObject *Object
- Objects map[string]*Object // SHA256 digest to object
- }
-
- func cmdExec(name string, args ...string) ([]byte, error) {
- var buf bytes.Buffer
- cmd := exec.Command(name, args...)
- cmd.Stdout = &buf
- cmd.Stderr = os.Stderr
-
- err := cmd.Run()
- if err != nil {
- return nil, err
- }
-
- return buf.Bytes(), nil
- }
-
- var remoteReqSem = make(chan struct{}, 30)
-
- func readObject(path string) ([]byte, error) {
- remoteReqSem <- struct{}{}
- defer func() {
- <-remoteReqSem
- }()
- log.Debugf("Reading object %v", path)
- return cmdExec("rclone", "--error-on-no-transfer", "cat", *readObjectPrefix+path)
- }
-
- func deleteObject(path string) error {
- remoteReqSem <- struct{}{}
- defer func() {
- <-remoteReqSem
- }()
- log.Debugf("Deleting object %v", path)
- _, err := cmdExec("rclone", "deletefile", *readObjectPrefix+path)
- return err
- }
-
- func getReachableBlobs(digest string) []string {
- objectPath := constructBlobPath(digest)
- digests := []string{digest}
-
- if _, ok := objects[objectPath]; !ok {
- log.Warnf("Object %v does not exist, skipping", objectPath)
- return nil
- }
-
- b := lo.Must(readObject(objectPath))
-
- var m map[string]any
- lo.Must0(json.Unmarshal(b, &m))
-
- // https://github.com/openshift/docker-distribution/blob/master/docs/spec/manifest-v2-2.md
- // https://github.com/opencontainers/image-spec/blob/main/image-index.md
- switch mediaType := m["mediaType"]; mediaType {
- case "application/vnd.oci.image.index.v1+json":
- manifests := m["manifests"].([]any)
- manifestDigests := lo.Map(manifests, func(manifest any, _ int) string {
- manifestObj := manifest.(map[string]any)
- manifestDigest := manifestObj["digest"].(string)
- return strings.TrimPrefix(manifestDigest, "sha256:")
- })
- p := pool.NewWithResults[[]string]()
- for _, manifestDigest := range manifestDigests {
- p.Go(func() []string {
- return getReachableBlobs(manifestDigest)
- })
- }
- for _, childDigests := range p.Wait() {
- digests = append(digests, childDigests...)
- }
- return digests
- case "application/vnd.docker.distribution.manifest.v2+json", "application/vnd.oci.image.manifest.v1+json":
- configDigest := m["config"].(map[string]any)["digest"].(string)
- configDigest = strings.TrimPrefix(configDigest, "sha256:")
- digests = append(digests, configDigest)
-
- layers := m["layers"].([]any)
- layerDigests := lo.Map(layers, func(manifest any, _ int) string {
- manifestObj := manifest.(map[string]any)
- manifestDigest := manifestObj["digest"].(string)
- return strings.TrimPrefix(manifestDigest, "sha256:")
- })
- digests = append(digests, layerDigests...)
- return digests
- default:
- panic(fmt.Sprintf("unknown mediaType: %v", mediaType))
- }
- }
-
- func main() {
- //log.SetLevel(log.DebugLevel)
- if *doit {
- log.Warnf("Dryrun disabled! This run WILL DELETE files.")
- }
-
- // Read the output of "rclone lsl"
- log.Infof("Listing objects ...")
- b := lo.Must(cmdExec("rclone", "lsl", *readObjectPrefix))
- //b := lo.Must(io.ReadAll(os.Stdin)) // or from stdin
- s := strings.Trim(string(b), "\n")
- lines := strings.Split(s, "\n")
-
- log.Infof("Reading objects ...")
- objects = lo.SliceToMap(lines, func(line string) (string, *Object) {
- fields := strings.Fields(line)
- if len(fields) != 4 {
- panic(fmt.Sprintf("expected line to have 4 fields, but has %v fields: %v", len(fields), line))
- }
-
- size, modified, path := fields[0], fields[1]+" "+fields[2], fields[3]
- return path, &Object{
- Size: lo.Must(strconv.Atoi(size)),
- Modified: lo.Must(time.ParseInLocation("2006-01-02 15:04:05.999999999", modified, time.Local)),
- Path: path,
- }
- })
- blobs := make(map[string]*Object)
- uploads := make(map[string]*Uploads) // uploads prefix to uploads metadata
- repos := make(map[string]*Repository)
- ensureRepoMap := func(repoName string) {
- if _, ok := repos[repoName]; !ok {
- repos[repoName] = &Repository{
- Layers: make(map[string]*Object),
- ManifestRevisions: make(map[string]*Object),
- Tags: make(map[string]*RepositoryTag),
- }
- }
- }
- ensureTagMap := func(repoName, tagName string) {
- if _, ok := repos[repoName].Tags[tagName]; !ok {
- repos[repoName].Tags[tagName] = &RepositoryTag{
- CurrentBlob: "",
- CurrentObject: nil,
- Objects: make(map[string]*Object),
- }
- }
- }
- for _, object := range objects {
- switch {
- case uploadsPattern.MatchString(object.Path):
- m := uploadsPattern.FindStringSubmatch(object.Path)
- prefix := m[1]
- if _, ok := uploads[prefix]; !ok {
- uploads[prefix] = &Uploads{}
- }
- uploads[prefix].Objects = append(uploads[prefix].Objects, object)
- case blobPattern.MatchString(object.Path):
- m := blobPattern.FindStringSubmatch(object.Path)
- blobs[m[1]] = object
- case layersPattern.MatchString(object.Path):
- m := layersPattern.FindStringSubmatch(object.Path)
- repoName, digest := m[1], m[2]
- ensureRepoMap(repoName)
- repos[repoName].Layers[digest] = object
- case revisionsPattern.MatchString(object.Path):
- m := revisionsPattern.FindStringSubmatch(object.Path)
- repoName, digest := m[1], m[2]
- ensureRepoMap(repoName)
- repos[repoName].ManifestRevisions[digest] = object
- case currentTagPattern.MatchString(object.Path):
- m := currentTagPattern.FindStringSubmatch(object.Path)
- repoName, tagName := m[1], m[2]
- ensureRepoMap(repoName)
- ensureTagMap(repoName, tagName)
- if repos[repoName].Tags[tagName].CurrentObject != nil {
- panic(fmt.Sprintf("multiple current object read: %v", object.Path))
- }
- repos[repoName].Tags[tagName].CurrentObject = object
- case tagPattern.MatchString(object.Path):
- m := tagPattern.FindStringSubmatch(object.Path)
- repoName, tagName, digest := m[1], m[2], m[3]
- ensureRepoMap(repoName)
- ensureTagMap(repoName, tagName)
- repos[repoName].Tags[tagName].Objects[digest] = object
- default:
- panic(fmt.Sprintf("unknown object path pattern: %v", object.Path))
- }
- }
-
- // Read uploads "startedat"
- log.Infof("Reading _uploads date ...")
- wg := conc.NewWaitGroup()
- for prefix, upload := range uploads {
- wg.Go(func() {
- objectPath := prefix + "startedat"
- if _, ok := objects[objectPath]; !ok {
- log.Warnf("Object %v does not exist, making startedat fallback to file modified date...", objectPath)
- upload.StartedAt = lo.MaxBy(upload.Objects, func(a *Object, b *Object) bool { return a.Modified.Before(b.Modified) }).Modified
- return
- }
- str := string(lo.Must(readObject(objectPath)))
- t, err := time.Parse(time.RFC3339, str)
- upload.StartedAt = lo.Must(t, err, fmt.Sprintf("%v has invalid format: %v", objectPath, str))
- })
- }
- wg.Wait()
-
- // Read current tag links
- log.Infof("Reading current tag links ...")
- for repoName, repo := range repos {
- for tagName, tag := range repo.Tags {
- if tag.CurrentObject == nil {
- log.Warnf("%v:%v current tag link is nil", repoName, tagName)
- delete(repos[repoName].Tags, tagName)
- continue
- }
- wg.Go(func() {
- digest := strings.TrimPrefix(string(lo.Must(readObject(tag.CurrentObject.Path))), "sha256:")
- if !digestPattern.MatchString(digest) {
- panic(fmt.Sprintf("expected to match digest pattern: %v", digest))
- }
- tag.CurrentBlob = digest
- })
- }
- }
- wg.Wait()
-
- log.Infof("Objects %d", len(objects))
- log.Infof(" -> Blobs %d", len(blobs))
- log.Infof(" -> Repositories %d", len(repos))
-
- // Calculate reachable blobs
- log.Infof("Calculating reachable blobs ...")
-
- reachableDigests := make(map[string]struct{})
- p := pool.NewWithResults[[]string]()
- for repoName, repo := range repos {
- if strings.HasPrefix(repoName, deleteRepoPrefix) {
- log.Infof("Not counting repo %v ...", repoName)
- continue
- }
- for tagName, tag := range repo.Tags {
- if strings.HasPrefix(repoName, gcRepoPrefix) && len(tag.Objects) >= 2 {
- log.Infof("Not counting tag %v:%v as it has 2 or more tag objects ...", repoName, tagName)
- continue
- }
- for digest := range tag.Objects {
- p.Go(func() []string {
- return getReachableBlobs(digest)
- })
- }
- }
- }
- for _, digests := range p.Wait() {
- for _, digest := range digests {
- reachableDigests[digest] = struct{}{}
- }
- }
- log.Infof("%d reachable blobs found", len(reachableDigests))
-
- // Check unreachable objects
- {
- // Check old _uploads directory
- var deletableUploads []*Object
- deleteUploadOlderThan := time.Now().Add(-time.Hour)
- for _, upload := range uploads {
- if !upload.StartedAt.IsZero() && upload.StartedAt.Before(deleteUploadOlderThan) {
- deletableUploads = append(deletableUploads, upload.Objects...)
- }
- }
-
- // Check unreachable blobs
- var unreachableBlobs []*Object
- for digest, blob := range blobs {
- if _, ok := reachableDigests[digest]; !ok {
- unreachableBlobs = append(unreachableBlobs, blob)
- }
- }
-
- // Check unreachable repository objects
- var (
- unreachableLayers []*Object
- unreachableRevisions []*Object
- unreachableTags []*Object
- unreachableTagObjects []*Object
- )
- for _, repo := range repos {
- for digest, object := range repo.Layers {
- if _, ok := reachableDigests[digest]; !ok {
- unreachableLayers = append(unreachableLayers, object)
- }
- }
- for digest, object := range repo.ManifestRevisions {
- if _, ok := reachableDigests[digest]; !ok {
- unreachableRevisions = append(unreachableRevisions, object)
- }
- }
- for _, tag := range repo.Tags {
- _, tagCurrentReachable := reachableDigests[tag.CurrentBlob]
- if !tagCurrentReachable {
- unreachableTags = append(unreachableTags, tag.CurrentObject)
- }
- for digest, object := range tag.Objects {
- if _, ok := reachableDigests[digest]; !ok || !tagCurrentReachable { // delete all tag objects if current link is not reachable
- unreachableTagObjects = append(unreachableTagObjects, object)
- }
- }
- }
- }
-
- log.Infof("%d old _uploads objects found eligible for deletion", len(deletableUploads))
- log.Infof("%d unreachable blobs found", len(unreachableBlobs))
- log.Infof("%d unreachable layers found", len(unreachableLayers))
- log.Infof("%d unreachable revisions found", len(unreachableRevisions))
- log.Infof("%d unreachable tags found", len(unreachableTags))
- log.Infof("%d unreachable tag objects found", len(unreachableTagObjects))
-
- deletionCandidates := slices.Concat(deletableUploads, unreachableBlobs, unreachableLayers, unreachableRevisions, unreachableTags, unreachableTagObjects)
- deleteObjectOlderThan := time.Now().Add(-time.Hour) // Do not delete objects that have uploads in progress
- objectsToDelete := lo.Filter(deletionCandidates, func(object *Object, _ int) bool { return object.Modified.Before(deleteObjectOlderThan) })
- log.Infof("%d objects are candidates for deletion; of which, %d objects are old enough and safe to delete", len(deletionCandidates), len(objectsToDelete))
- estimatedFreedBytes := lo.SumBy(objectsToDelete, func(upload *Object) int { return upload.Size })
- prettyFreedBytes := message.NewPrinter(language.English).Sprintf("%d", estimatedFreedBytes)
- log.Infof("Estimated freed bytes %v bytes", prettyFreedBytes)
-
- // Execute deletion
- if *doit {
- log.Infof("Deleting files ...")
- bar := progressbar.Default(int64(len(objectsToDelete)))
- for _, object := range objectsToDelete {
- wg.Go(func() {
- lo.Must0(deleteObject(object.Path))
- lo.Must0(bar.Add(1))
- })
- }
- wg.Wait()
- log.Infof("Deletion complete.")
- } else {
- log.Infof("Dryrun enabled, not actually deleting files. Instead, here is the list of files planned to be deleted:")
- now := time.Now()
- for _, object := range objectsToDelete {
- fmt.Printf("%v B, %v (%v ago): %v\n", object.Size, object.Modified, now.Sub(object.Modified), object.Path)
- }
- }
- }
- }
-
- kind: ConfigMap
- metadata:
- name: gc-script-4dbgtgttmk
- namespace: harbor
@@ (root level) @@
# v1/ConfigMap/harbor/gc-script-5578gbhb94
! + one document added:
+ ---
+ apiVersion: v1
+ data:
+ entrypoint.sh: |
+ #!/usr/bin/env bash
+
+ set -euxo pipefail
+
+ apt update
+ apt install -y zip
+ curl https://rclone.org/install.sh | bash
+
+ go run . -read-object-prefix trap-wasabi-registry:/trap-ns-registry/ -doit
+
+ go.mod: |
+ module playground
+
+ go 1.23.0
+
+ toolchain go1.24.2
+
+ require (
+ github.com/samber/lo v1.49.1
+ github.com/schollz/progressbar/v3 v3.18.0
+ github.com/sirupsen/logrus v1.9.3
+ github.com/sourcegraph/conc v0.3.0
+ golang.org/x/text v0.23.0
+ )
+
+ require (
+ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ go.uber.org/atomic v1.7.0 // indirect
+ go.uber.org/multierr v1.9.0 // indirect
+ golang.org/x/sys v0.29.0 // indirect
+ golang.org/x/term v0.28.0 // indirect
+ )
+
+ go.sum: |
+ github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
+ github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
+ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+ github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
+ github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
+ github.com/samber/lo v1.48.0 h1:ELOfcaM7vdYPe0egBS2Nxa8LxkY4lR+9LBzj0l6cHJ0=
+ github.com/samber/lo v1.48.0/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
+ github.com/samber/lo v1.49.0 h1:AGnTnQrg1jpFuwECPUSoxZCfVH5W22b605kWSry3YxM=
+ github.com/samber/lo v1.49.0/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
+ github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
+ github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
+ github.com/schollz/progressbar/v3 v3.17.1 h1:bI1MTaoQO+v5kzklBjYNRQLoVpe0zbyRZNK6DFkVC5U=
+ github.com/schollz/progressbar/v3 v3.17.1/go.mod h1:RzqpnsPQNjUyIgdglUjRLgD7sVnxN1wpmBMV+UiEbL4=
+ github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
+ github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
+ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
+ github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
+ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
+ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+ golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
+ golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+ golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+ golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+ golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
+ golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
+ golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+ golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
+ golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+ golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+ golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
+ golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
+ golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+
+ main.go: |
+ package main
+
+ import (
+ "bytes"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "regexp"
+ "slices"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/samber/lo"
+ "github.com/schollz/progressbar/v3"
+ log "github.com/sirupsen/logrus"
+ "github.com/sourcegraph/conc"
+ "github.com/sourcegraph/conc/pool"
+ "golang.org/x/text/language"
+ "golang.org/x/text/message"
+ )
+
+ var (
+ readObjectPrefix = flag.String("read-object-prefix", "trap-wasabi-registry:/trap-ns-registry/", "rclone object prefix")
+ doit = flag.Bool("doit", false, "Disable dryrun and actually delete files")
+ deleteRepoPrefix = "ns-apps-tmp/"
+ gcRepoPrefix = "ns-apps/"
+ )
+
+ func init() {
+ flag.Parse()
+ }
+
+ var (
+ digestPattern = regexp.MustCompile("^[0-9a-f]{64}$")
+ uploadsPattern = regexp.MustCompile("^(docker/registry/v2/repositories/[^/]+/[^/]+/_uploads/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/).+$")
+ blobPattern = regexp.MustCompile("^docker/registry/v2/blobs/sha256/[0-9a-f]{2}/([0-9a-f]{64})/data$")
+ layersPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_layers/sha256/([0-9a-f]{64})/link$")
+ revisionsPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_manifests/revisions/sha256/([0-9a-f]{64})/link$")
+ currentTagPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_manifests/tags/([^/]+)/current/link$")
+ tagPattern = regexp.MustCompile("^docker/registry/v2/repositories/([^/]+/[^/]+)/_manifests/tags/([^/]+)/index/sha256/([0-9a-f]{64})/link$")
+ )
+
+ func constructBlobPath(digest string) string {
+ return fmt.Sprintf("docker/registry/v2/blobs/sha256/%s/%s/data", digest[:2], digest)
+ }
+
+ var objects map[string]*Object
+
+ type Object struct {
+ Size int
+ Modified time.Time
+ Path string
+ }
+
+ type Uploads struct {
+ StartedAt time.Time
+ Objects []*Object
+ }
+
+ type Repository struct {
+ Layers map[string]*Object // SHA256 digest to object
+ ManifestRevisions map[string]*Object // SHA256 digest to object
+ Tags map[string]*RepositoryTag // Tag name to tag data
+ }
+
+ type RepositoryTag struct {
+ CurrentBlob string // SHA256 digest pointed by CurrentObject
+ CurrentObject *Object
+ Objects map[string]*Object // SHA256 digest to object
+ }
+
+ func cmdExec(name string, args ...string) ([]byte, error) {
+ var buf bytes.Buffer
+ cmd := exec.Command(name, args...)
+ cmd.Stdout = &buf
+ cmd.Stderr = os.Stderr
+
+ err := cmd.Run()
+ return buf.Bytes(), err
+ }
+
+ var remoteReqSem = make(chan struct{}, 30)
+
+ func readObject(path string) ([]byte, error) {
+ remoteReqSem <- struct{}{}
+ defer func() {
+ <-remoteReqSem
+ }()
+ log.Debugf("Reading object %v", path)
+ return cmdExec("rclone", "--error-on-no-transfer", "cat", *readObjectPrefix+path)
+ }
+
+ func deleteObject(path string) error {
+ remoteReqSem <- struct{}{}
+ defer func() {
+ <-remoteReqSem
+ }()
+ log.Debugf("Deleting object %v", path)
+ _, err := cmdExec("rclone", "deletefile", *readObjectPrefix+path)
+ return err
+ }
+
+ func getReachableBlobs(digest string) []string {
+ objectPath := constructBlobPath(digest)
+ digests := []string{digest}
+
+ if _, ok := objects[objectPath]; !ok {
+ log.Warnf("Object %v does not exist, skipping", objectPath)
+ return nil
+ }
+
+ b, err := readObject(objectPath)
+ if err != nil {
+ log.Error(string(b))
+ panic(fmt.Sprintf("failed to read object %v: %v", objectPath, err))
+ }
+
+ var m map[string]any
+ lo.Must0(json.Unmarshal(b, &m))
+
+ // https://github.com/openshift/docker-distribution/blob/master/docs/spec/manifest-v2-2.md
+ // https://github.com/opencontainers/image-spec/blob/main/image-index.md
+ switch mediaType := m["mediaType"]; mediaType {
+ case "application/vnd.oci.image.index.v1+json":
+ manifests := m["manifests"].([]any)
+ manifestDigests := lo.Map(manifests, func(manifest any, _ int) string {
+ manifestObj := manifest.(map[string]any)
+ manifestDigest := manifestObj["digest"].(string)
+ return strings.TrimPrefix(manifestDigest, "sha256:")
+ })
+ p := pool.NewWithResults[[]string]()
+ for _, manifestDigest := range manifestDigests {
+ p.Go(func() []string {
+ return getReachableBlobs(manifestDigest)
+ })
+ }
+ for _, childDigests := range p.Wait() {
+ digests = append(digests, childDigests...)
+ }
+ return digests
+ case "application/vnd.docker.distribution.manifest.v2+json", "application/vnd.oci.image.manifest.v1+json":
+ configDigest := m["config"].(map[string]any)["digest"].(string)
+ configDigest = strings.TrimPrefix(configDigest, "sha256:")
+ digests = append(digests, configDigest)
+
+ layers := m["layers"].([]any)
+ layerDigests := lo.Map(layers, func(manifest any, _ int) string {
+ manifestObj := manifest.(map[string]any)
+ manifestDigest := manifestObj["digest"].(string)
+ return strings.TrimPrefix(manifestDigest, "sha256:")
+ })
+ digests = append(digests, layerDigests...)
+ return digests
+ default:
+ panic(fmt.Sprintf("unknown mediaType: %v", mediaType))
+ }
+ }
+
+ func main() {
+ //log.SetLevel(log.DebugLevel)
+ if *doit {
+ log.Warnf("Dryrun disabled! This run WILL DELETE files.")
+ }
+
+ // Read the output of "rclone lsl"
+ log.Infof("Listing objects ...")
+ b := lo.Must(cmdExec("rclone", "lsl", *readObjectPrefix))
+ //b := lo.Must(io.ReadAll(os.Stdin)) // or from stdin
+ s := strings.Trim(string(b), "\n")
+ lines := strings.Split(s, "\n")
+
+ log.Infof("Reading objects ...")
+ objects = lo.SliceToMap(lines, func(line string) (string, *Object) {
+ fields := strings.Fields(line)
+ if len(fields) != 4 {
+ panic(fmt.Sprintf("expected line to have 4 fields, but has %v fields: %v", len(fields), line))
+ }
+
+ size, modified, path := fields[0], fields[1]+" "+fields[2], fields[3]
+ return path, &Object{
+ Size: lo.Must(strconv.Atoi(size)),
+ Modified: lo.Must(time.ParseInLocation("2006-01-02 15:04:05.999999999", modified, time.Local)),
+ Path: path,
+ }
+ })
+ blobs := make(map[string]*Object)
+ uploads := make(map[string]*Uploads) // uploads prefix to uploads metadata
+ repos := make(map[string]*Repository)
+ ensureRepoMap := func(repoName string) {
+ if _, ok := repos[repoName]; !ok {
+ repos[repoName] = &Repository{
+ Layers: make(map[string]*Object),
+ ManifestRevisions: make(map[string]*Object),
+ Tags: make(map[string]*RepositoryTag),
+ }
+ }
+ }
+ ensureTagMap := func(repoName, tagName string) {
+ if _, ok := repos[repoName].Tags[tagName]; !ok {
+ repos[repoName].Tags[tagName] = &RepositoryTag{
+ CurrentBlob: "",
+ CurrentObject: nil,
+ Objects: make(map[string]*Object),
+ }
+ }
+ }
+ for _, object := range objects {
+ switch {
+ case uploadsPattern.MatchString(object.Path):
+ m := uploadsPattern.FindStringSubmatch(object.Path)
+ prefix := m[1]
+ if _, ok := uploads[prefix]; !ok {
+ uploads[prefix] = &Uploads{}
+ }
+ uploads[prefix].Objects = append(uploads[prefix].Objects, object)
+ case blobPattern.MatchString(object.Path):
+ m := blobPattern.FindStringSubmatch(object.Path)
+ blobs[m[1]] = object
+ case layersPattern.MatchString(object.Path):
+ m := layersPattern.FindStringSubmatch(object.Path)
+ repoName, digest := m[1], m[2]
+ ensureRepoMap(repoName)
+ repos[repoName].Layers[digest] = object
+ case revisionsPattern.MatchString(object.Path):
+ m := revisionsPattern.FindStringSubmatch(object.Path)
+ repoName, digest := m[1], m[2]
+ ensureRepoMap(repoName)
+ repos[repoName].ManifestRevisions[digest] = object
+ case currentTagPattern.MatchString(object.Path):
+ m := currentTagPattern.FindStringSubmatch(object.Path)
+ repoName, tagName := m[1], m[2]
+ ensureRepoMap(repoName)
+ ensureTagMap(repoName, tagName)
+ if repos[repoName].Tags[tagName].CurrentObject != nil {
+ panic(fmt.Sprintf("multiple current object read: %v", object.Path))
+ }
+ repos[repoName].Tags[tagName].CurrentObject = object
+ case tagPattern.MatchString(object.Path):
+ m := tagPattern.FindStringSubmatch(object.Path)
+ repoName, tagName, digest := m[1], m[2], m[3]
+ ensureRepoMap(repoName)
+ ensureTagMap(repoName, tagName)
+ repos[repoName].Tags[tagName].Objects[digest] = object
+ default:
+ panic(fmt.Sprintf("unknown object path pattern: %v", object.Path))
+ }
+ }
+
+ // Read uploads "startedat"
+ log.Infof("Reading _uploads date ...")
+ wg := conc.NewWaitGroup()
+ for prefix, upload := range uploads {
+ wg.Go(func() {
+ objectPath := prefix + "startedat"
+ if _, ok := objects[objectPath]; !ok {
+ log.Warnf("Object %v does not exist, making startedat fallback to file modified date...", objectPath)
+ upload.StartedAt = lo.MaxBy(upload.Objects, func(a *Object, b *Object) bool { return a.Modified.Before(b.Modified) }).Modified
+ return
+ }
+ b, err := readObject(objectPath)
+ if err != nil {
+ log.Error(string(b))
+ panic(fmt.Sprintf("failed to read object %v: %v", objectPath, err))
+ }
+ t, err := time.Parse(time.RFC3339, string(b))
+ upload.StartedAt = lo.Must(t, err, fmt.Sprintf("%s has invalid format: %s", objectPath, b))
+ })
+ }
+ wg.Wait()
+
+ // Read current tag links
+ log.Infof("Reading current tag links ...")
+ for repoName, repo := range repos {
+ for tagName, tag := range repo.Tags {
+ if tag.CurrentObject == nil {
+ log.Warnf("%v:%v current tag link is nil", repoName, tagName)
+ delete(repos[repoName].Tags, tagName)
+ continue
+ }
+ wg.Go(func() {
+ b, err := readObject(tag.CurrentObject.Path)
+ if err != nil {
+ log.Error(string(b))
+ panic(fmt.Sprintf("failed to read object %v: %v", tag.CurrentObject.Path, err))
+ }
+ digest := strings.TrimPrefix(string(b), "sha256:")
+ if !digestPattern.MatchString(digest) {
+ panic(fmt.Sprintf("expected to match digest pattern: %v", digest))
+ }
+ tag.CurrentBlob = digest
+ })
+ }
+ }
+ wg.Wait()
+
+ log.Infof("Objects %d", len(objects))
+ log.Infof(" -> Blobs %d", len(blobs))
+ log.Infof(" -> Repositories %d", len(repos))
+
+ // Calculate reachable blobs
+ log.Infof("Calculating reachable blobs ...")
+
+ reachableDigests := make(map[string]struct{})
+ p := pool.NewWithResults[[]string]()
+ for repoName, repo := range repos {
+ if strings.HasPrefix(repoName, deleteRepoPrefix) {
+ log.Infof("Not counting repo %v ...", repoName)
+ continue
+ }
+ for tagName, tag := range repo.Tags {
+ if strings.HasPrefix(repoName, gcRepoPrefix) && len(tag.Objects) >= 2 {
+ log.Infof("Not counting tag %v:%v as it has 2 or more tag objects ...", repoName, tagName)
+ continue
+ }
+ for digest := range tag.Objects {
+ p.Go(func() []string {
+ return getReachableBlobs(digest)
+ })
+ }
+ }
+ }
+ for _, digests := range p.Wait() {
+ for _, digest := range digests {
+ reachableDigests[digest] = struct{}{}
+ }
+ }
+ log.Infof("%d reachable blobs found", len(reachableDigests))
+
+ // Check unreachable objects
+ {
+ // Check old _uploads directory
+ var deletableUploads []*Object
+ deleteUploadOlderThan := time.Now().Add(-time.Hour)
+ for _, upload := range uploads {
+ if !upload.StartedAt.IsZero() && upload.StartedAt.Before(deleteUploadOlderThan) {
+ deletableUploads = append(deletableUploads, upload.Objects...)
+ }
+ }
+
+ // Check unreachable blobs
+ var unreachableBlobs []*Object
+ for digest, blob := range blobs {
+ if _, ok := reachableDigests[digest]; !ok {
+ unreachableBlobs = append(unreachableBlobs, blob)
+ }
+ }
+
+ // Check unreachable repository objects
+ var (
+ unreachableLayers []*Object
+ unreachableRevisions []*Object
+ unreachableTags []*Object
+ unreachableTagObjects []*Object
+ )
+ for _, repo := range repos {
+ for digest, object := range repo.Layers {
+ if _, ok := reachableDigests[digest]; !ok {
+ unreachableLayers = append(unreachableLayers, object)
+ }
+ }
+ for digest, object := range repo.ManifestRevisions {
+ if _, ok := reachableDigests[digest]; !ok {
+ unreachableRevisions = append(unreachableRevisions, object)
+ }
+ }
+ for _, tag := range repo.Tags {
+ _, tagCurrentReachable := reachableDigests[tag.CurrentBlob]
+ if !tagCurrentReachable {
+ unreachableTags = append(unreachableTags, tag.CurrentObject)
+ }
+ for digest, object := range tag.Objects {
+ if _, ok := reachableDigests[digest]; !ok || !tagCurrentReachable { // delete all tag objects if current link is not reachable
+ unreachableTagObjects = append(unreachableTagObjects, object)
+ }
+ }
+ }
+ }
+
+ log.Infof("%d old _uploads objects found eligible for deletion", len(deletableUploads))
+ log.Infof("%d unreachable blobs found", len(unreachableBlobs))
+ log.Infof("%d unreachable layers found", len(unreachableLayers))
+ log.Infof("%d unreachable revisions found", len(unreachableRevisions))
+ log.Infof("%d unreachable tags found", len(unreachableTags))
+ log.Infof("%d unreachable tag objects found", len(unreachableTagObjects))
+
+ deletionCandidates := slices.Concat(deletableUploads, unreachableBlobs, unreachableLayers, unreachableRevisions, unreachableTags, unreachableTagObjects)
+ deleteObjectOlderThan := time.Now().Add(-time.Hour) // Do not delete objects that have uploads in progress
+ objectsToDelete := lo.Filter(deletionCandidates, func(object *Object, _ int) bool { return object.Modified.Before(deleteObjectOlderThan) })
+ log.Infof("%d objects are candidates for deletion; of which, %d objects are old enough and safe to delete", len(deletionCandidates), len(objectsToDelete))
+ estimatedFreedBytes := lo.SumBy(objectsToDelete, func(upload *Object) int { return upload.Size })
+ prettyFreedBytes := message.NewPrinter(language.English).Sprintf("%d", estimatedFreedBytes)
+ log.Infof("Estimated freed bytes %v bytes", prettyFreedBytes)
+
+ // Execute deletion
+ if *doit {
+ log.Infof("Deleting files ...")
+ bar := progressbar.Default(int64(len(objectsToDelete)))
+ for _, object := range objectsToDelete {
+ wg.Go(func() {
+ lo.Must0(deleteObject(object.Path))
+ lo.Must0(bar.Add(1))
+ })
+ }
+ wg.Wait()
+ log.Infof("Deletion complete.")
+ } else {
+ log.Infof("Dryrun enabled, not actually deleting files. Instead, here is the list of files planned to be deleted:")
+ now := time.Now()
+ for _, object := range objectsToDelete {
+ fmt.Printf("%v B, %v (%v ago): %v\n", object.Size, object.Modified, now.Sub(object.Modified), object.Path)
+ }
+ }
+ }
+ }
+
+ kind: ConfigMap
+ metadata:
+ name: gc-script-5578gbhb94
+ namespace: harbor
@@ (file level) @@
! ⇆ order changed
v1/ServiceAccount/alloy/alloy v1/ServiceAccount/alloy/alloy
v1/ServiceAccount/alloy/alloy-ds v1/ServiceAccount/alloy/alloy-ds
rbac.authorization.k8s.io/v1/ClusterRole/alloy/alloy rbac.authorization.k8s.io/v1/ClusterRole/alloy/alloy
rbac.authorization.k8s.io/v1/ClusterRole/alloy/alloy-ds rbac.authorization.k8s.io/v1/ClusterRole/alloy/alloy-ds
rbac.authorization.k8s.io/v1/ClusterRoleBinding/alloy/alloy rbac.authorization.k8s.io/v1/ClusterRoleBinding/alloy/alloy
rbac.authorization.k8s.io/v1/ClusterRoleBinding/alloy/alloy-ds rbac.authorization.k8s.io/v1/ClusterRoleBinding/alloy/alloy-ds
v1/ConfigMap/alloy/alloy v1/ConfigMap/alloy/alloy
v1/ConfigMap/alloy/alloy-ds v1/ConfigMap/alloy/alloy-ds
v1/Service/alloy/alloy v1/Service/alloy/alloy
v1/Service/alloy/alloy-ds v1/Service/alloy/alloy-ds
apps/v1/Deployment/alloy/alloy apps/v1/Deployment/alloy/alloy
apps/v1/DaemonSet/alloy/alloy-ds apps/v1/DaemonSet/alloy/alloy-ds
argoproj.io/v1alpha1/AppProject/argocd/default argoproj.io/v1alpha1/AppProject/argocd/default
argoproj.io/v1alpha1/AppProject/argocd/preview argoproj.io/v1alpha1/AppProject/argocd/preview
argoproj.io/v1alpha1/ApplicationSet/argocd/application-set argoproj.io/v1alpha1/ApplicationSet/argocd/application-set
v1/Node/applications/taki-ws1.tokyotech.org v1/Node/applications/taki-ws1.tokyotech.org
v1/Node/applications/taki-ws2.tokyotech.org v1/Node/applications/taki-ws2.tokyotech.org
v1/Node/applications/taki-ws3.tokyotech.org v1/Node/applications/taki-ws3.tokyotech.org
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/clusterworkflowtemplates.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/clusterworkflowtemplates.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/cronworkflows.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/cronworkflows.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowartifactgctasks.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowartifactgctasks.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workfloweventbindings.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workfloweventbindings.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflows.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflows.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowtaskresults.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowtaskresults.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowtasksets.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowtasksets.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowtemplates.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argo/workflowtemplates.argoproj.io
v1/ServiceAccount/argo/argo-argo-workflows-server v1/ServiceAccount/argo/argo-argo-workflows-server
v1/ServiceAccount/argo/argo-argo-workflows-workflow-controller v1/ServiceAccount/argo/argo-argo-workflows-workflow-controller
v1/ServiceAccount/argo/argo-workflow v1/ServiceAccount/argo/argo-workflow
v1/ServiceAccount/backup/argo-workflow v1/ServiceAccount/backup/argo-workflow
v1/ServiceAccount/harbor/argo-workflow v1/ServiceAccount/harbor/argo-workflow
v1/ServiceAccount/monitor/argo-workflow v1/ServiceAccount/monitor/argo-workflow
v1/ServiceAccount/ns-system/argo-workflow v1/ServiceAccount/ns-system/argo-workflow
rbac.authorization.k8s.io/v1/Role/argo/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/Role/argo/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/Role/backup/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/Role/backup/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/Role/harbor/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/Role/harbor/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/Role/monitor/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/Role/monitor/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/Role/ns-system/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/Role/ns-system/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-admin rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-admin
rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-edit rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-edit
rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-server rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-server
rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-server-cluster-template rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-server-cluster-template
rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-view rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-view
rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-workflow-controller rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-workflow-controller
rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-workflow-controller-cluster-template rbac.authorization.k8s.io/v1/ClusterRole/argo/argo-argo-workflows-workflow-controller-cluster-template
rbac.authorization.k8s.io/v1/RoleBinding/argo/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/RoleBinding/argo/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/RoleBinding/backup/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/RoleBinding/backup/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/RoleBinding/harbor/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/RoleBinding/harbor/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/RoleBinding/monitor/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/RoleBinding/monitor/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/RoleBinding/ns-system/argo-argo-workflows-workflow rbac.authorization.k8s.io/v1/RoleBinding/ns-system/argo-argo-workflows-workflow
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-server rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-server
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-server-cluster-template rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-server-cluster-template
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-workflow-controller rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-workflow-controller
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-workflow-controller-cluster-template rbac.authorization.k8s.io/v1/ClusterRoleBinding/argo/argo-argo-workflows-workflow-controller-cluster-template
v1/ConfigMap/argo/argo-argo-workflows-workflow-controller-configmap v1/ConfigMap/argo/argo-argo-workflows-workflow-controller-configmap
v1/Service/argo/argo-argo-workflows-server v1/Service/argo/argo-argo-workflows-server
apps/v1/Deployment/argo/argo-argo-workflows-server apps/v1/Deployment/argo/argo-argo-workflows-server
apps/v1/Deployment/argo/argo-argo-workflows-workflow-controller apps/v1/Deployment/argo/argo-argo-workflows-workflow-controller
argoproj.io/v1alpha1/ClusterWorkflowTemplate/argo/traq-webhook argoproj.io/v1alpha1/ClusterWorkflowTemplate/argo/traq-webhook
argoproj.io/v1alpha1/WorkflowTemplate/argo/test-fail argoproj.io/v1alpha1/WorkflowTemplate/argo/test-fail
argoproj.io/v1alpha1/WorkflowTemplate/argo/test-success argoproj.io/v1alpha1/WorkflowTemplate/argo/test-success
cert-manager.io/v1/Certificate/argo/argo-workflow cert-manager.io/v1/Certificate/argo/argo-workflow
traefik.io/v1alpha1/IngressRoute/argo/argo-workflow traefik.io/v1alpha1/IngressRoute/argo/argo-workflow
apiextensions.k8s.io/v1/CustomResourceDefinition/argocd/applications.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argocd/applications.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argocd/applicationsets.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argocd/applicationsets.argoproj.io
apiextensions.k8s.io/v1/CustomResourceDefinition/argocd/appprojects.argoproj.io apiextensions.k8s.io/v1/CustomResourceDefinition/argocd/appprojects.argoproj.io
v1/ServiceAccount/argocd/argocd-application-controller v1/ServiceAccount/argocd/argocd-application-controller
v1/ServiceAccount/argocd/argocd-applicationset-controller v1/ServiceAccount/argocd/argocd-applicationset-controller
v1/ServiceAccount/argocd/argocd-dex-server v1/ServiceAccount/argocd/argocd-dex-server
v1/ServiceAccount/argocd/argocd-notifications-controller v1/ServiceAccount/argocd/argocd-notifications-controller
v1/ServiceAccount/argocd/argocd-redis v1/ServiceAccount/argocd/argocd-redis
v1/ServiceAccount/argocd/argocd-repo-server v1/ServiceAccount/argocd/argocd-repo-server
v1/ServiceAccount/argocd/argocd-server v1/ServiceAccount/argocd/argocd-server
rbac.authorization.k8s.io/v1/Role/argocd/argocd-application-controller rbac.authorization.k8s.io/v1/Role/argocd/argocd-application-controller
rbac.authorization.k8s.io/v1/Role/argocd/argocd-applicationset-controller rbac.authorization.k8s.io/v1/Role/argocd/argocd-applicationset-controller
rbac.authorization.k8s.io/v1/Role/argocd/argocd-dex-server rbac.authorization.k8s.io/v1/Role/argocd/argocd-dex-server
rbac.authorization.k8s.io/v1/Role/argocd/argocd-notifications-controller rbac.authorization.k8s.io/v1/Role/argocd/argocd-notifications-controller
rbac.authorization.k8s.io/v1/Role/argocd/argocd-redis rbac.authorization.k8s.io/v1/Role/argocd/argocd-redis
rbac.authorization.k8s.io/v1/Role/argocd/argocd-server rbac.authorization.k8s.io/v1/Role/argocd/argocd-server
rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-application-controller rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-application-controller
rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-applicationset-controller rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-applicationset-controller
rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-repo-server rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-repo-server
rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-server rbac.authorization.k8s.io/v1/ClusterRole/argocd/argocd-server
rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-application-controller rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-application-controller
rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-applicationset-controller rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-applicationset-controller
rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-dex-server rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-dex-server
rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-notifications-controller rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-notifications-controller
rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-redis rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-redis
rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-server rbac.authorization.k8s.io/v1/RoleBinding/argocd/argocd-server
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-application-controller rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-application-controller
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-applicationset-controller rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-applicationset-controller
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-repo-server rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-repo-server
rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-server rbac.authorization.k8s.io/v1/ClusterRoleBinding/argocd/argocd-server
v1/ConfigMap/argocd/argocd-cm v1/ConfigMap/argocd/argocd-cm
v1/ConfigMap/argocd/argocd-cmd-params-cm v1/ConfigMap/argocd/argocd-cmd-params-cm
v1/ConfigMap/argocd/argocd-gpg-keys-cm v1/ConfigMap/argocd/argocd-gpg-keys-cm
v1/ConfigMap/argocd/argocd-notifications-cm v1/ConfigMap/argocd/argocd-notifications-cm
v1/ConfigMap/argocd/argocd-rbac-cm v1/ConfigMap/argocd/argocd-rbac-cm
v1/ConfigMap/argocd/argocd-ssh-known-hosts-cm v1/ConfigMap/argocd/argocd-ssh-known-hosts-cm
v1/ConfigMap/argocd/argocd-tls-certs-cm v1/ConfigMap/argocd/argocd-tls-certs-cm
v1/ConfigMap/argocd/helm-replace-6ht4bgdhdm v1/ConfigMap/argocd/helm-replace-6ht4bgdhdm
v1/Secret/argocd/argocd-notifications-secret v1/Secret/argocd/argocd-notifications-secret
v1/Secret/argocd/argocd-secret v1/Secret/argocd/argocd-secret
v1/Secret/argocd/preview-pr-generator v1/Secret/argocd/preview-pr-generator
v1/Service/argocd/argocd-applicationset-controller v1/Service/argocd/argocd-applicationset-controller
v1/Service/argocd/argocd-dex-server v1/Service/argocd/argocd-dex-server
v1/Service/argocd/argocd-metrics v1/Service/argocd/argocd-metrics
v1/Service/argocd/argocd-notifications-controller-metrics v1/Service/argocd/argocd-notifications-controller-metrics
v1/Service/argocd/argocd-redis v1/Service/argocd/argocd-redis
v1/Service/argocd/argocd-repo-server v1/Service/argocd/argocd-repo-server
v1/Service/argocd/argocd-server v1/Service/argocd/argocd-server
v1/Service/argocd/argocd-server-metrics v1/Service/argocd/argocd-server-metrics
apps/v1/Deployment/argocd/argocd-applicationset-controller apps/v1/Deployment/argocd/argocd-applicationset-controller
apps/v1/Deployment/argocd/argocd-dex-server apps/v1/Deployment/argocd/argocd-dex-server
apps/v1/Deployment/argocd/argocd-notifications-controller apps/v1/Deployment/argocd/argocd-notifications-controller
apps/v1/Deployment/argocd/argocd-redis apps/v1/Deployment/argocd/argocd-redis
apps/v1/Deployment/argocd/argocd-repo-server apps/v1/Deployment/argocd/argocd-repo-server
apps/v1/Deployment/argocd/argocd-server apps/v1/Deployment/argocd/argocd-server
apps/v1/StatefulSet/argocd/argocd-application-controller apps/v1/StatefulSet/argocd/argocd-application-controller
cert-manager.io/v1/Certificate/argocd/appset cert-manager.io/v1/Certificate/argocd/appset
cert-manager.io/v1/Certificate/argocd/argocd-server cert-manager.io/v1/Certificate/argocd/argocd-server
traefik.io/v1alpha1/IngressRoute/argocd/appset traefik.io/v1alpha1/IngressRoute/argocd/appset
traefik.io/v1alpha1/IngressRoute/argocd/argocd-server traefik.io/v1alpha1/IngressRoute/argocd/argocd-server
v1/ConfigMap/auth/auth-trap-games v1/ConfigMap/auth/auth-trap-games
v1/ConfigMap/auth/auth-trap-jp v1/ConfigMap/auth/auth-trap-jp
v1/ConfigMap/auth/auth-trap-show v1/ConfigMap/auth/auth-trap-show
v1/ConfigMap/auth/auth-trapti-tech v1/ConfigMap/auth/auth-trapti-tech
v1/Secret/auth/auth-trap-games v1/Secret/auth/auth-trap-games
v1/Secret/auth/auth-trap-jp v1/Secret/auth/auth-trap-jp
v1/Secret/auth/auth-trap-show v1/Secret/auth/auth-trap-show
v1/Secret/auth/auth-trapti-tech v1/Secret/auth/auth-trapti-tech
v1/Secret/auth/common-secret v1/Secret/auth/common-secret
v1/Service/auth/auth-trap-games v1/Service/auth/auth-trap-games
v1/Service/auth/auth-trap-jp v1/Service/auth/auth-trap-jp
v1/Service/auth/auth-trap-show v1/Service/auth/auth-trap-show
v1/Service/auth/auth-trapti-tech v1/Service/auth/auth-trapti-tech
apps/v1/Deployment/auth/auth-trap-games apps/v1/Deployment/auth/auth-trap-games
apps/v1/Deployment/auth/auth-trap-jp apps/v1/Deployment/auth/auth-trap-jp
apps/v1/Deployment/auth/auth-trap-show apps/v1/Deployment/auth/auth-trap-show
apps/v1/Deployment/auth/auth-trapti-tech apps/v1/Deployment/auth/auth-trapti-tech
cert-manager.io/v1/Certificate/auth/auth-trap-games cert-manager.io/v1/Certificate/auth/auth-trap-games
cert-manager.io/v1/Certificate/auth/auth-trap-jp cert-manager.io/v1/Certificate/auth/auth-trap-jp
cert-manager.io/v1/Certificate/auth/auth-trap-show cert-manager.io/v1/Certificate/auth/auth-trap-show
cert-manager.io/v1/Certificate/auth/auth-trapti-tech cert-manager.io/v1/Certificate/auth/auth-trapti-tech
traefik.io/v1alpha1/IngressRoute/auth/auth-trap-games traefik.io/v1alpha1/IngressRoute/auth/auth-trap-games
traefik.io/v1alpha1/IngressRoute/auth/auth-trap-jp traefik.io/v1alpha1/IngressRoute/auth/auth-trap-jp
traefik.io/v1alpha1/IngressRoute/auth/auth-trap-show traefik.io/v1alpha1/IngressRoute/auth/auth-trap-show
traefik.io/v1alpha1/IngressRoute/auth/auth-trapti-tech traefik.io/v1alpha1/IngressRoute/auth/auth-trapti-tech
traefik.io/v1alpha1/Middleware/auth/auth-trap-games-admin traefik.io/v1alpha1/Middleware/auth/auth-trap-games-admin
traefik.io/v1alpha1/Middleware/auth/auth-trap-games-core traefik.io/v1alpha1/Middleware/auth/auth-trap-games-core
traefik.io/v1alpha1/Middleware/auth/auth-trap-games-hard traefik.io/v1alpha1/Middleware/auth/auth-trap-games-hard
traefik.io/v1alpha1/Middleware/auth/auth-trap-games-mode-admin traefik.io/v1alpha1/Middleware/auth/auth-trap-games-mode-admin
traefik.io/v1alpha1/Middleware/auth/auth-trap-games-mode-hard traefik.io/v1alpha1/Middleware/auth/auth-trap-games-mode-hard
traefik.io/v1alpha1/Middleware/auth/auth-trap-games-mode-soft traefik.io/v1alpha1/Middleware/auth/auth-trap-games-mode-soft
traefik.io/v1alpha1/Middleware/auth/auth-trap-games-soft traefik.io/v1alpha1/Middleware/auth/auth-trap-games-soft
traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-admin traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-admin
traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-core traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-core
traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-hard traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-hard
traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-mode-admin traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-mode-admin
traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-mode-hard traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-mode-hard
traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-mode-soft traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-mode-soft
traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-soft traefik.io/v1alpha1/Middleware/auth/auth-trap-jp-soft
traefik.io/v1alpha1/Middleware/auth/auth-trap-show-admin traefik.io/v1alpha1/Middleware/auth/auth-trap-show-admin
traefik.io/v1alpha1/Middleware/auth/auth-trap-show-core traefik.io/v1alpha1/Middleware/auth/auth-trap-show-core
traefik.io/v1alpha1/Middleware/auth/auth-trap-show-hard traefik.io/v1alpha1/Middleware/auth/auth-trap-show-hard
traefik.io/v1alpha1/Middleware/auth/auth-trap-show-mode-admin traefik.io/v1alpha1/Middleware/auth/auth-trap-show-mode-admin
traefik.io/v1alpha1/Middleware/auth/auth-trap-show-mode-hard traefik.io/v1alpha1/Middleware/auth/auth-trap-show-mode-hard
traefik.io/v1alpha1/Middleware/auth/auth-trap-show-mode-soft traefik.io/v1alpha1/Middleware/auth/auth-trap-show-mode-soft
traefik.io/v1alpha1/Middleware/auth/auth-trap-show-soft traefik.io/v1alpha1/Middleware/auth/auth-trap-show-soft
traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-admin traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-admin
traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-core traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-core
traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-hard traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-hard
traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-mode-admin traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-mode-admin
traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-mode-hard traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-mode-hard
traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-mode-soft traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-mode-soft
traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-soft traefik.io/v1alpha1/Middleware/auth/auth-trapti-tech-soft
v1/ConfigMap/backup/backup-scripts-k4c9k4h8g4 v1/ConfigMap/backup/backup-scripts-k4c9k4h8g4
v1/Secret/backup/backup-keys-bk2fd9b95t v1/Secret/backup/backup-keys-bk2fd9b95t
argoproj.io/v1alpha1/CronWorkflow/backup/k3s-backup-cron argoproj.io/v1alpha1/CronWorkflow/backup/k3s-backup-cron
argoproj.io/v1alpha1/WorkflowTemplate/backup/k3s-backup argoproj.io/v1alpha1/WorkflowTemplate/backup/k3s-backup
v1/Namespace/cert-manager/cert-manager v1/Namespace/cert-manager/cert-manager
apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/certificaterequests.cert-manager.io apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/certificaterequests.cert-manager.io
apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/certificates.cert-manager.io apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/certificates.cert-manager.io
apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/challenges.acme.cert-manager.io apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/challenges.acme.cert-manager.io
apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/clusterissuers.cert-manager.io apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/clusterissuers.cert-manager.io
apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/issuers.cert-manager.io apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/issuers.cert-manager.io
apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/orders.acme.cert-manager.io apiextensions.k8s.io/v1/CustomResourceDefinition/cert-manager/orders.acme.cert-manager.io
v1/ServiceAccount/cert-manager/cert-manager v1/ServiceAccount/cert-manager/cert-manager
v1/ServiceAccount/cert-manager/cert-manager-cainjector v1/ServiceAccount/cert-manager/cert-manager-cainjector
v1/ServiceAccount/cert-manager/cert-manager-webhook v1/ServiceAccount/cert-manager/cert-manager-webhook
rbac.authorization.k8s.io/v1/Role/cert-manager/cert-manager-tokenrequest rbac.authorization.k8s.io/v1/Role/cert-manager/cert-manager-tokenrequest
rbac.authorization.k8s.io/v1/Role/cert-manager/cert-manager-webhook:dynamic-serving rbac.authorization.k8s.io/v1/Role/cert-manager/cert-manager-webhook:dynamic-serving
rbac.authorization.k8s.io/v1/Role/kube-system/cert-manager-cainjector:leaderelection rbac.authorization.k8s.io/v1/Role/kube-system/cert-manager-cainjector:leaderelection
rbac.authorization.k8s.io/v1/Role/kube-system/cert-manager:leaderelection rbac.authorization.k8s.io/v1/Role/kube-system/cert-manager:leaderelection
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-cainjector rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-cainjector
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-cluster-view rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-cluster-view
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-approve:cert-manager-io rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-approve:cert-manager-io
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-certificates rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-certificates
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-certificatesigningrequests rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-certificatesigningrequests
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-challenges rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-challenges
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-clusterissuers rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-clusterissuers
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-ingress-shim rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-ingress-shim
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-issuers rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-issuers
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-orders rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-controller-orders
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-edit rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-edit
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-view rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-view
rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-webhook:subjectaccessreviews rbac.authorization.k8s.io/v1/ClusterRole/cert-manager/cert-manager-webhook:subjectaccessreviews
rbac.authorization.k8s.io/v1/RoleBinding/cert-manager/cert-manager-cert-manager-tokenrequest rbac.authorization.k8s.io/v1/RoleBinding/cert-manager/cert-manager-cert-manager-tokenrequest
rbac.authorization.k8s.io/v1/RoleBinding/cert-manager/cert-manager-webhook:dynamic-serving rbac.authorization.k8s.io/v1/RoleBinding/cert-manager/cert-manager-webhook:dynamic-serving
rbac.authorization.k8s.io/v1/RoleBinding/kube-system/cert-manager-cainjector:leaderelection rbac.authorization.k8s.io/v1/RoleBinding/kube-system/cert-manager-cainjector:leaderelection
rbac.authorization.k8s.io/v1/RoleBinding/kube-system/cert-manager:leaderelection rbac.authorization.k8s.io/v1/RoleBinding/kube-system/cert-manager:leaderelection
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-cainjector rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-cainjector
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-approve:cert-manager-io rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-approve:cert-manager-io
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-certificates rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-certificates
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-certificatesigningrequests rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-certificatesigningrequests
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-challenges rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-challenges
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-clusterissuers rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-clusterissuers
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-ingress-shim rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-ingress-shim
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-issuers rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-issuers
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-orders rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-controller-orders
rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-webhook:subjectaccessreviews rbac.authorization.k8s.io/v1/ClusterRoleBinding/cert-manager/cert-manager-webhook:subjectaccessreviews
v1/Secret/cert-manager/dns-solver-tbb8t2mtk8 v1/Secret/cert-manager/dns-solver-tbb8t2mtk8
v1/Service/cert-manager/cert-manager v1/Service/cert-manager/cert-manager
v1/Service/cert-manager/cert-manager-cainjector v1/Service/cert-manager/cert-manager-cainjector
v1/Service/cert-manager/cert-manager-webhook v1/Service/cert-manager/cert-manager-webhook
apps/v1/Deployment/cert-manager/cert-manager apps/v1/Deployment/cert-manager/cert-manager
apps/v1/Deployment/cert-manager/cert-manager-cainjector apps/v1/Deployment/cert-manager/cert-manager-cainjector
apps/v1/Deployment/cert-manager/cert-manager-webhook apps/v1/Deployment/cert-manager/cert-manager-webhook
cert-manager.io/v1/ClusterIssuer/cert-manager/cluster-issuer cert-manager.io/v1/ClusterIssuer/cert-manager/cluster-issuer
admissionregistration.k8s.io/v1/MutatingWebhookConfiguration/cert-manager/cert-manager-webhook admissionregistration.k8s.io/v1/MutatingWebhookConfiguration/cert-manager/cert-manager-webhook
admissionregistration.k8s.io/v1/ValidatingWebhookConfiguration/cert-manager/cert-manager-webhook admissionregistration.k8s.io/v1/ValidatingWebhookConfiguration/cert-manager/cert-manager-webhook
v1/ConfigMap/crowi/es-config-dgkgb2t976 v1/ConfigMap/crowi/es-config-dgkgb2t976
v1/Service/crowi/es v1/Service/crowi/es
apps/v1/StatefulSet/crowi/es apps/v1/StatefulSet/crowi/es
v1/ServiceAccount/dev-ops-bot/dev-ops-bot v1/ServiceAccount/dev-ops-bot/dev-ops-bot
rbac.authorization.k8s.io/v1/ClusterRole/dev-ops-bot/dev-ops-bot-extra rbac.authorization.k8s.io/v1/ClusterRole/dev-ops-bot/dev-ops-bot-extra
rbac.authorization.k8s.io/v1/ClusterRoleBinding/dev-ops-bot/dev-ops-bot-extra rbac.authorization.k8s.io/v1/ClusterRoleBinding/dev-ops-bot/dev-ops-bot-extra
rbac.authorization.k8s.io/v1/ClusterRoleBinding/dev-ops-bot/dev-ops-bot-view rbac.authorization.k8s.io/v1/ClusterRoleBinding/dev-ops-bot/dev-ops-bot-view
v1/ConfigMap/dev-ops-bot/config-mf4mb8c6kg v1/ConfigMap/dev-ops-bot/config-mf4mb8c6kg
v1/ConfigMap/dev-ops-bot/entrypoint-522t5d9d25 v1/ConfigMap/dev-ops-bot/entrypoint-522t5d9d25
v1/ConfigMap/dev-ops-bot/known-hosts-km4d855gbd v1/ConfigMap/dev-ops-bot/known-hosts-km4d855gbd
v1/Secret/dev-ops-bot/dev-ops-bot-6gtd59757g v1/Secret/dev-ops-bot/dev-ops-bot-6gtd59757g
apps/v1/Deployment/dev-ops-bot/dev-ops-bot apps/v1/Deployment/dev-ops-bot/dev-ops-bot
v1/ServiceAccount/gitea/gitea-act-runner v1/ServiceAccount/gitea/gitea-act-runner
rbac.authorization.k8s.io/v1/Role/gitea/gitea-act-runner rbac.authorization.k8s.io/v1/Role/gitea/gitea-act-runner
rbac.authorization.k8s.io/v1/RoleBinding/gitea/gitea-act-runner rbac.authorization.k8s.io/v1/RoleBinding/gitea/gitea-act-runner
v1/ConfigMap/gitea/act-runner-b47btfcdbc v1/ConfigMap/gitea/act-runner-b47btfcdbc
v1/Secret/gitea/act-runner-6bfckm57dc v1/Secret/gitea/act-runner-6bfckm57dc
v1/Service/gitea/gitea-act-runner v1/Service/gitea/gitea-act-runner
apps/v1/Deployment/gitea/act-runner apps/v1/Deployment/gitea/act-runner
apps/v1/StatefulSet/gitea/gitea-act-runner apps/v1/StatefulSet/gitea/gitea-act-runner
v1/ConfigMap/harbor/harbor-core v1/ConfigMap/harbor/harbor-core
v1/ConfigMap/harbor/harbor-jobservice v1/ConfigMap/harbor/harbor-jobservice
v1/ConfigMap/harbor/harbor-jobservice-env v1/ConfigMap/harbor/harbor-jobservice-env
v1/ConfigMap/harbor/harbor-nginx v1/ConfigMap/harbor/harbor-nginx
v1/ConfigMap/harbor/harbor-portal v1/ConfigMap/harbor/harbor-portal
v1/ConfigMap/harbor/harbor-registry v1/ConfigMap/harbor/harbor-registry
v1/ConfigMap/harbor/harbor-registryctl v1/ConfigMap/harbor/harbor-registryctl
v1/ConfigMap/harbor/gc-script-4dbgtgttmk v1/ConfigMap/harbor/gc-script-5578gbhb94
v1/Secret/harbor/harbor-core v1/Secret/harbor/harbor-core
v1/Secret/harbor/harbor-database v1/Secret/harbor/harbor-database
v1/Secret/harbor/harbor-jobservice v1/Secret/harbor/harbor-jobservice
v1/Secret/harbor/harbor-registry v1/Secret/harbor/harbor-registry
v1/Secret/harbor/harbor-registry-htpasswd v1/Secret/harbor/harbor-registry-htpasswd
v1/Secret/harbor/harbor-registryctl v1/Secret/harbor/harbor-registryctl
v1/Secret/harbor/harbor-trivy v1/Secret/harbor/harbor-trivy
v1/Secret/harbor/admin-password v1/Secret/harbor/admin-password
v1/Secret/harbor/core-cert v1/Secret/harbor/core-cert
v1/Secret/harbor/gc-rclone-config v1/Secret/harbor/gc-rclone-config
v1/Secret/harbor/secret-key v1/Secret/harbor/secret-key
v1/Secret/harbor/storage v1/Secret/harbor/storage
v1/Service/harbor/harbor v1/Service/harbor/harbor
v1/Service/harbor/harbor-core v1/Service/harbor/harbor-core
v1/Service/harbor/harbor-database v1/Service/harbor/harbor-database
v1/Service/harbor/harbor-jobservice v1/Service/harbor/harbor-jobservice
v1/Service/harbor/harbor-portal v1/Service/harbor/harbor-portal
v1/Service/harbor/harbor-redis v1/Service/harbor/harbor-redis
v1/Service/harbor/harbor-registry v1/Service/harbor/harbor-registry
v1/Service/harbor/harbor-trivy v1/Service/harbor/harbor-trivy
apps/v1/Deployment/harbor/harbor-core apps/v1/Deployment/harbor/harbor-core
apps/v1/Deployment/harbor/harbor-jobservice apps/v1/Deployment/harbor/harbor-jobservice
apps/v1/Deployment/harbor/harbor-nginx apps/v1/Deployment/harbor/harbor-nginx
apps/v1/Deployment/harbor/harbor-portal apps/v1/Deployment/harbor/harbor-portal
apps/v1/Deployment/harbor/harbor-registry apps/v1/Deployment/harbor/harbor-registry
apps/v1/StatefulSet/harbor/harbor-database apps/v1/StatefulSet/harbor/harbor-database
apps/v1/StatefulSet/harbor/harbor-redis apps/v1/StatefulSet/harbor/harbor-redis
apps/v1/StatefulSet/harbor/harbor-trivy apps/v1/StatefulSet/harbor/harbor-trivy
argoproj.io/v1alpha1/CronWorkflow/harbor/gc-cron argoproj.io/v1alpha1/CronWorkflow/harbor/gc-cron
argoproj.io/v1alpha1/WorkflowTemplate/harbor/gc argoproj.io/v1alpha1/WorkflowTemplate/harbor/gc
cert-manager.io/v1/Certificate/harbor/registry cert-manager.io/v1/Certificate/harbor/registry
traefik.io/v1alpha1/IngressRoute/harbor/registry traefik.io/v1alpha1/IngressRoute/harbor/registry
v1/ServiceAccount/monitor/kube-state-metrics v1/ServiceAccount/monitor/kube-state-metrics
v1/ServiceAccount/monitor/victoria-metrics v1/ServiceAccount/monitor/victoria-metrics
rbac.authorization.k8s.io/v1/ClusterRole/monitor/kube-state-metrics rbac.authorization.k8s.io/v1/ClusterRole/monitor/kube-state-metrics
rbac.authorization.k8s.io/v1/ClusterRole/monitor/victoria-metrics rbac.authorization.k8s.io/v1/ClusterRole/monitor/victoria-metrics
rbac.authorization.k8s.io/v1/ClusterRoleBinding/monitor/kube-state-metrics rbac.authorization.k8s.io/v1/ClusterRoleBinding/monitor/kube-state-metrics
rbac.authorization.k8s.io/v1/ClusterRoleBinding/monitor/victoria-metrics rbac.authorization.k8s.io/v1/ClusterRoleBinding/monitor/victoria-metrics
v1/ConfigMap/monitor/backup-scripts-k8k44c2g76 v1/ConfigMap/monitor/backup-scripts-k8k44c2g76
v1/ConfigMap/monitor/grafana-c4f5fkdgmg v1/ConfigMap/monitor/grafana-c4f5fkdgmg
v1/ConfigMap/monitor/loki-config-6262526hh9 v1/ConfigMap/monitor/loki-config-6262526hh9
v1/ConfigMap/monitor/loki-runtime-config-b997gkk284 v1/ConfigMap/monitor/loki-runtime-config-b997gkk284
v1/ConfigMap/monitor/prometheus-config-6dhfmc5k9f v1/ConfigMap/monitor/prometheus-config-6dhfmc5k9f
v1/Secret/monitor/backup-keys-bk2fd9b95t v1/Secret/monitor/backup-keys-bk2fd9b95t
v1/Secret/monitor/blackbox-exporter-cfhf6f89hd v1/Secret/monitor/blackbox-exporter-cfhf6f89hd
v1/Secret/monitor/conoha-exporter-b82b5c878g v1/Secret/monitor/conoha-exporter-b82b5c878g
v1/Secret/monitor/s3-credentials-md2hg57588 v1/Secret/monitor/s3-credentials-md2hg57588
v1/Secret/monitor/s3-exporter-ht76mbfd5f v1/Secret/monitor/s3-exporter-ht76mbfd5f
v1/Secret/monitor/tailscale-credential-kh24fd482t v1/Secret/monitor/tailscale-credential-kh24fd482t
v1/Service/monitor/blackbox-exporter v1/Service/monitor/blackbox-exporter
v1/Service/monitor/conoha-exporter v1/Service/monitor/conoha-exporter
v1/Service/monitor/domain-exporter v1/Service/monitor/domain-exporter
v1/Service/monitor/grafana v1/Service/monitor/grafana
v1/Service/monitor/kube-state-metrics v1/Service/monitor/kube-state-metrics
v1/Service/monitor/loki v1/Service/monitor/loki
v1/Service/monitor/loki-memberlist v1/Service/monitor/loki-memberlist
v1/Service/monitor/s3-exporter v1/Service/monitor/s3-exporter
v1/Service/monitor/ssl-exporter v1/Service/monitor/ssl-exporter
v1/Service/monitor/victoria-metrics v1/Service/monitor/victoria-metrics
apps/v1/Deployment/monitor/blackbox-exporter apps/v1/Deployment/monitor/blackbox-exporter
apps/v1/Deployment/monitor/conoha-exporter apps/v1/Deployment/monitor/conoha-exporter
apps/v1/Deployment/monitor/domain-exporter apps/v1/Deployment/monitor/domain-exporter
apps/v1/Deployment/monitor/grafana apps/v1/Deployment/monitor/grafana
apps/v1/Deployment/monitor/kube-state-metrics apps/v1/Deployment/monitor/kube-state-metrics
apps/v1/Deployment/monitor/s3-exporter apps/v1/Deployment/monitor/s3-exporter
apps/v1/Deployment/monitor/ssl-exporter apps/v1/Deployment/monitor/ssl-exporter
apps/v1/StatefulSet/monitor/loki apps/v1/StatefulSet/monitor/loki
apps/v1/StatefulSet/monitor/victoria-metrics apps/v1/StatefulSet/monitor/victoria-metrics
apps/v1/DaemonSet/monitor/node-exporter apps/v1/DaemonSet/monitor/node-exporter
argoproj.io/v1alpha1/CronWorkflow/monitor/grafana-backup-cron argoproj.io/v1alpha1/CronWorkflow/monitor/grafana-backup-cron
argoproj.io/v1alpha1/WorkflowTemplate/monitor/grafana-backup argoproj.io/v1alpha1/WorkflowTemplate/monitor/grafana-backup
cert-manager.io/v1/Certificate/monitor/grafana cert-manager.io/v1/Certificate/monitor/grafana
traefik.io/v1alpha1/IngressRoute/monitor/grafana traefik.io/v1alpha1/IngressRoute/monitor/grafana
v1/Namespace/ns-system/ns-apps v1/Namespace/ns-system/ns-apps
v1/ServiceAccount/ns-system/ns-controller v1/ServiceAccount/ns-system/ns-controller
v1/ServiceAccount/ns-system/ns-sablier v1/ServiceAccount/ns-system/ns-sablier
rbac.authorization.k8s.io/v1/ClusterRole/ns-system/ns-controller rbac.authorization.k8s.io/v1/ClusterRole/ns-system/ns-controller
rbac.authorization.k8s.io/v1/ClusterRole/ns-system/ns-sablier rbac.authorization.k8s.io/v1/ClusterRole/ns-system/ns-sablier
rbac.authorization.k8s.io/v1/ClusterRoleBinding/ns-system/ns-controller rbac.authorization.k8s.io/v1/ClusterRoleBinding/ns-system/ns-controller
rbac.authorization.k8s.io/v1/ClusterRoleBinding/ns-system/ns-sablier rbac.authorization.k8s.io/v1/ClusterRoleBinding/ns-system/ns-sablier
v1/ConfigMap/ns-system/backup-scripts-6d8k4mt659 v1/ConfigMap/ns-system/backup-scripts-6d8k4mt659
v1/ConfigMap/ns-system/known-hosts-fg62g76cfg v1/ConfigMap/ns-system/known-hosts-fg62g76cfg
v1/ConfigMap/ns-system/mariadb-config-f87556c8m6 v1/ConfigMap/ns-system/mariadb-config-f87556c8m6
v1/ConfigMap/ns-system/ns-config-5dfc665ck6 v1/ConfigMap/ns-system/ns-config-5dfc665ck6
v1/ConfigMap/ns-system/ns-sablier-4ff9cfhfd8 v1/ConfigMap/ns-system/ns-sablier-4ff9cfhfd8
v1/Secret/ns-system/backup-keys-bk2fd9b95t v1/Secret/ns-system/backup-keys-bk2fd9b95t
v1/Secret/ns-system/ns-keys-6kb98958ct v1/Secret/ns-system/ns-keys-6kb98958ct
v1/Secret/ns-system/ns-khmkk9c4cg v1/Secret/ns-system/ns-khmkk9c4cg
v1/Service/ns-system/adminer v1/Service/ns-system/adminer
v1/Service/ns-system/mariadb v1/Service/ns-system/mariadb
v1/Service/ns-system/mongo v1/Service/ns-system/mongo
v1/Service/ns-system/ns-controller v1/Service/ns-system/ns-controller
v1/Service/ns-system/ns-dashboard v1/Service/ns-system/ns-dashboard
v1/Service/ns-system/ns-gateway v1/Service/ns-system/ns-gateway
v1/Service/ns-system/ns-gitea-integration v1/Service/ns-system/ns-gitea-integration
v1/Service/ns-system/ns-sablier v1/Service/ns-system/ns-sablier
v1/Service/ns-system/ns-ssgen v1/Service/ns-system/ns-ssgen
v1/Service/ns-system/ns-ssh v1/Service/ns-system/ns-ssh
apps/v1/Deployment/ns-system/adminer apps/v1/Deployment/ns-system/adminer
apps/v1/Deployment/ns-system/ns-builder apps/v1/Deployment/ns-system/ns-builder
apps/v1/Deployment/ns-system/ns-dashboard apps/v1/Deployment/ns-system/ns-dashboard
apps/v1/Deployment/ns-system/ns-gateway apps/v1/Deployment/ns-system/ns-gateway
apps/v1/Deployment/ns-system/ns-sablier apps/v1/Deployment/ns-system/ns-sablier
apps/v1/StatefulSet/ns-system/mariadb apps/v1/StatefulSet/ns-system/mariadb
apps/v1/StatefulSet/ns-system/mongo apps/v1/StatefulSet/ns-system/mongo
apps/v1/StatefulSet/ns-system/ns-controller apps/v1/StatefulSet/ns-system/ns-controller
apps/v1/StatefulSet/ns-system/ns-gitea-integration apps/v1/StatefulSet/ns-system/ns-gitea-integration
apps/v1/StatefulSet/ns-system/ns-ssgen apps/v1/StatefulSet/ns-system/ns-ssgen
argoproj.io/v1alpha1/CronWorkflow/ns-system/mariadb-backup-cron argoproj.io/v1alpha1/CronWorkflow/ns-system/mariadb-backup-cron
argoproj.io/v1alpha1/CronWorkflow/ns-system/mongodb-backup-cron argoproj.io/v1alpha1/CronWorkflow/ns-system/mongodb-backup-cron
argoproj.io/v1alpha1/WorkflowTemplate/ns-system/mariadb-backup argoproj.io/v1alpha1/WorkflowTemplate/ns-system/mariadb-backup
argoproj.io/v1alpha1/WorkflowTemplate/ns-system/mongodb-backup argoproj.io/v1alpha1/WorkflowTemplate/ns-system/mongodb-backup
batch/v1/Job/ns-system/ns-migrate batch/v1/Job/ns-system/ns-migrate
cert-manager.io/v1/Certificate/ns-system/adminer cert-manager.io/v1/Certificate/ns-system/adminer
cert-manager.io/v1/Certificate/ns-system/ns cert-manager.io/v1/Certificate/ns-system/ns
traefik.io/v1alpha1/IngressRoute/ns-system/adminer traefik.io/v1alpha1/IngressRoute/ns-system/adminer
traefik.io/v1alpha1/IngressRoute/ns-system/ns traefik.io/v1alpha1/IngressRoute/ns-system/ns
v1/Service/preview-ns/ns-dashboard-staging v1/Service/preview-ns/ns-dashboard-staging
apps/v1/Deployment/preview-ns/ns-dashboard-staging apps/v1/Deployment/preview-ns/ns-dashboard-staging
argoproj.io/v1alpha1/ApplicationSet/argocd/preview-ns argoproj.io/v1alpha1/ApplicationSet/argocd/preview-ns
cert-manager.io/v1/Certificate/preview-ns/preview-ns cert-manager.io/v1/Certificate/preview-ns/preview-ns
traefik.io/v1alpha1/IngressRoute/preview-ns/ns-preview-staging traefik.io/v1alpha1/IngressRoute/preview-ns/ns-preview-staging
traefik.io/v1alpha1/Middleware/preview-ns/sablier-staging traefik.io/v1alpha1/Middleware/preview-ns/sablier-staging
v1/Service/preview-portfolio-ui/portfolio-ui-staging v1/Service/preview-portfolio-ui/portfolio-ui-staging
apps/v1/Deployment/preview-portfolio-ui/portfolio-ui-staging apps/v1/Deployment/preview-portfolio-ui/portfolio-ui-staging
argoproj.io/v1alpha1/ApplicationSet/argocd/preview-portfolio-ui argoproj.io/v1alpha1/ApplicationSet/argocd/preview-portfolio-ui
cert-manager.io/v1/Certificate/preview-portfolio-ui/preview-portfolio-ui cert-manager.io/v1/Certificate/preview-portfolio-ui/preview-portfolio-ui
traefik.io/v1alpha1/IngressRoute/preview-portfolio-ui/portfolio-ui-preview-staging traefik.io/v1alpha1/IngressRoute/preview-portfolio-ui/portfolio-ui-preview-staging
traefik.io/v1alpha1/Middleware/preview-portfolio-ui/sablier-staging traefik.io/v1alpha1/Middleware/preview-portfolio-ui/sablier-staging
v1/Service/preview-traq/traq-ui-staging v1/Service/preview-traq/traq-ui-staging
apps/v1/Deployment/preview-traq/traq-ui-staging apps/v1/Deployment/preview-traq/traq-ui-staging
argoproj.io/v1alpha1/ApplicationSet/argocd/preview-traq argoproj.io/v1alpha1/ApplicationSet/argocd/preview-traq
cert-manager.io/v1/Certificate/preview-traq/preview-traq cert-manager.io/v1/Certificate/preview-traq/preview-traq
traefik.io/v1alpha1/IngressRoute/preview-traq/traq-preview-staging traefik.io/v1alpha1/IngressRoute/preview-traq/traq-preview-staging
traefik.io/v1alpha1/Middleware/preview-traq/sablier-staging traefik.io/v1alpha1/Middleware/preview-traq/sablier-staging
v1/ServiceAccount/sablier/sablier v1/ServiceAccount/sablier/sablier
rbac.authorization.k8s.io/v1/ClusterRole/sablier/sablier rbac.authorization.k8s.io/v1/ClusterRole/sablier/sablier
rbac.authorization.k8s.io/v1/ClusterRoleBinding/sablier/sablier rbac.authorization.k8s.io/v1/ClusterRoleBinding/sablier/sablier
v1/ConfigMap/sablier/sablier-h5d66tdb6b v1/ConfigMap/sablier/sablier-h5d66tdb6b
v1/Service/sablier/sablier v1/Service/sablier/sablier
apps/v1/Deployment/sablier/sablier apps/v1/Deployment/sablier/sablier
v1/Namespace/system-upgrade/system-upgrade v1/Namespace/system-upgrade/system-upgrade
apiextensions.k8s.io/v1/CustomResourceDefinition/system-upgrade/plans.upgrade.cattle.io apiextensions.k8s.io/v1/CustomResourceDefinition/system-upgrade/plans.upgrade.cattle.io
v1/ServiceAccount/system-upgrade/system-upgrade v1/ServiceAccount/system-upgrade/system-upgrade
rbac.authorization.k8s.io/v1/Role/system-upgrade/system-upgrade-controller rbac.authorization.k8s.io/v1/Role/system-upgrade/system-upgrade-controller
rbac.authorization.k8s.io/v1/ClusterRole/system-upgrade/system-upgrade-controller rbac.authorization.k8s.io/v1/ClusterRole/system-upgrade/system-upgrade-controller
rbac.authorization.k8s.io/v1/ClusterRole/system-upgrade/system-upgrade-controller-drainer rbac.authorization.k8s.io/v1/ClusterRole/system-upgrade/system-upgrade-controller-drainer
rbac.authorization.k8s.io/v1/RoleBinding/system-upgrade/system-upgrade rbac.authorization.k8s.io/v1/RoleBinding/system-upgrade/system-upgrade
rbac.authorization.k8s.io/v1/ClusterRoleBinding/system-upgrade/system-upgrade rbac.authorization.k8s.io/v1/ClusterRoleBinding/system-upgrade/system-upgrade
rbac.authorization.k8s.io/v1/ClusterRoleBinding/system-upgrade/system-upgrade-drainer rbac.authorization.k8s.io/v1/ClusterRoleBinding/system-upgrade/system-upgrade-drainer
v1/ConfigMap/system-upgrade/default-controller-env v1/ConfigMap/system-upgrade/default-controller-env
apps/v1/Deployment/system-upgrade/system-upgrade-controller apps/v1/Deployment/system-upgrade/system-upgrade-controller
upgrade.cattle.io/v1/Plan/system-upgrade/agent-plan upgrade.cattle.io/v1/Plan/system-upgrade/agent-plan
upgrade.cattle.io/v1/Plan/system-upgrade/server-plan upgrade.cattle.io/v1/Plan/system-upgrade/server-plan
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/ingressroutes.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/ingressroutes.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/ingressroutetcps.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/ingressroutetcps.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/ingressrouteudps.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/ingressrouteudps.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/middlewares.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/middlewares.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/middlewaretcps.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/middlewaretcps.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/serverstransports.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/serverstransports.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/serverstransporttcps.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/serverstransporttcps.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/tlsoptions.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/tlsoptions.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/tlsstores.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/tlsstores.traefik.io
apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/traefikservices.traefik.io apiextensions.k8s.io/v1/CustomResourceDefinition/traefik/traefikservices.traefik.io
v1/ServiceAccount/traefik/traefik v1/ServiceAccount/traefik/traefik
rbac.authorization.k8s.io/v1/ClusterRole/traefik/traefik rbac.authorization.k8s.io/v1/ClusterRole/traefik/traefik
rbac.authorization.k8s.io/v1/ClusterRoleBinding/traefik/traefik rbac.authorization.k8s.io/v1/ClusterRoleBinding/traefik/traefik
v1/ConfigMap/traefik/config-ghg6bf59dc v1/ConfigMap/traefik/config-ghg6bf59dc
v1/ConfigMap/traefik/custom-errors-assets-4t2tbcgdc4 v1/ConfigMap/traefik/custom-errors-assets-4t2tbcgdc4
v1/ConfigMap/traefik/custom-errors-config-849k6bgtc5 v1/ConfigMap/traefik/custom-errors-config-849k6bgtc5
v1/Service/traefik/custom-errors v1/Service/traefik/custom-errors
v1/Service/traefik/metrics v1/Service/traefik/metrics
v1/Service/traefik/traefik v1/Service/traefik/traefik
apps/v1/Deployment/traefik/custom-errors apps/v1/Deployment/traefik/custom-errors
apps/v1/DaemonSet/traefik/traefik apps/v1/DaemonSet/traefik/traefik
cert-manager.io/v1/Certificate/traefik/catch-all-https-trap-games cert-manager.io/v1/Certificate/traefik/catch-all-https-trap-games
cert-manager.io/v1/Certificate/traefik/catch-all-https-trap-jp cert-manager.io/v1/Certificate/traefik/catch-all-https-trap-jp
cert-manager.io/v1/Certificate/traefik/catch-all-https-trap-show cert-manager.io/v1/Certificate/traefik/catch-all-https-trap-show
cert-manager.io/v1/Certificate/traefik/catch-all-https-trapti-tech cert-manager.io/v1/Certificate/traefik/catch-all-https-trapti-tech
cert-manager.io/v1/Certificate/traefik/dashboard cert-manager.io/v1/Certificate/traefik/dashboard
traefik.io/v1alpha1/IngressRoute/traefik/catch-all-http traefik.io/v1alpha1/IngressRoute/traefik/catch-all-http
traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trap-games traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trap-games
traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trap-jp traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trap-jp
traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trap-show traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trap-show
traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trapti-tech traefik.io/v1alpha1/IngressRoute/traefik/catch-all-trapti-tech
traefik.io/v1alpha1/IngressRoute/traefik/dashboard traefik.io/v1alpha1/IngressRoute/traefik/dashboard
traefik.io/v1alpha1/Middleware/traefik/https-redirect traefik.io/v1alpha1/Middleware/traefik/https-redirect
v1/ConfigMap/traq/es-config-dgkgb2t976 v1/ConfigMap/traq/es-config-dgkgb2t976
v1/Secret/traq/es-password-9k8h548fg9 v1/Secret/traq/es-password-9k8h548fg9
v1/Secret/traq/system-bot-cbc6ttb9gb v1/Secret/traq/system-bot-cbc6ttb9gb
v1/Service/traq/es v1/Service/traq/es
apps/v1/Deployment/traq/system-bot apps/v1/Deployment/traq/system-bot
apps/v1/StatefulSet/traq/es apps/v1/StatefulSet/traq/es
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.