Stitch any CI into Tangled
151
fork

Configure Feed

Select the types of activity you want to include in your feed.

add internal/k8s, remove client-go

authored by

Mitchell Hashimoto and committed by
Tangled
add9d2eb e7055aa9

+1287 -583
+1 -28
go.mod
··· 8 8 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 9 9 github.com/mattn/go-sqlite3 v1.14.44 10 10 go.yaml.in/yaml/v2 v2.4.3 11 - k8s.io/api v0.35.3 12 - k8s.io/apimachinery v0.35.3 13 - k8s.io/client-go v0.35.3 14 11 tangled.org/core v1.13.0-alpha.0.20260502074102-37303f21368b 15 12 ) 16 13 ··· 32 29 github.com/charmbracelet/x/term v0.2.1 // indirect 33 30 github.com/cloudflare/circl v1.6.2-0.20250618153321-aa837fd1539d // indirect 34 31 github.com/cyphar/filepath-securejoin v0.4.1 // indirect 35 - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 36 32 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 37 33 github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect 38 - github.com/emicklei/go-restful/v3 v3.12.2 // indirect 39 34 github.com/emirpasic/gods v1.18.1 // indirect 40 35 github.com/felixge/httpsnoop v1.0.4 // indirect 41 - github.com/fxamacker/cbor/v2 v2.9.0 // indirect 42 36 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 43 37 github.com/go-git/go-billy/v5 v5.6.2 // indirect 44 38 github.com/go-git/go-git/v5 v5.14.0 // indirect ··· 46 40 github.com/go-logfmt/logfmt v0.6.1 // indirect 47 41 github.com/go-logr/logr v1.4.3 // indirect 48 42 github.com/go-logr/stdr v1.2.2 // indirect 49 - github.com/go-openapi/jsonpointer v0.21.0 // indirect 50 - github.com/go-openapi/jsonreference v0.20.2 // indirect 51 - github.com/go-openapi/swag v0.23.0 // indirect 52 43 github.com/go-redis/cache/v9 v9.0.0 // indirect 53 44 github.com/goccy/go-json v0.10.5 // indirect 54 45 github.com/gogo/protobuf v1.3.2 // indirect 55 - github.com/google/gnostic-models v0.7.0 // indirect 56 46 github.com/google/uuid v1.6.0 // indirect 57 47 github.com/hashicorp/errwrap v1.1.0 // indirect 58 48 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect ··· 76 66 github.com/ipfs/go-log v1.0.5 // indirect 77 67 github.com/ipfs/go-log/v2 v2.9.1 // indirect 78 68 github.com/ipfs/go-metrics-interface v0.3.0 // indirect 79 - github.com/josharian/intern v1.0.0 // indirect 80 - github.com/json-iterator/go v1.1.12 // indirect 81 69 github.com/klauspost/compress v1.18.0 // indirect 82 70 github.com/klauspost/cpuid/v2 v2.3.0 // indirect 83 71 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect 84 - github.com/mailru/easyjson v0.7.7 // indirect 85 72 github.com/mattn/go-isatty v0.0.20 // indirect 86 73 github.com/mattn/go-runewidth v0.0.16 // indirect 87 74 github.com/minio/sha256-simd v1.0.1 // indirect 88 75 github.com/mitchellh/mapstructure v1.5.0 // indirect 89 - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 90 - github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect 91 76 github.com/mr-tron/base58 v1.2.0 // indirect 92 77 github.com/muesli/termenv v0.16.0 // indirect 93 78 github.com/multiformats/go-base32 v0.1.0 // indirect ··· 96 81 github.com/multiformats/go-multihash v0.2.3 // indirect 97 82 github.com/multiformats/go-varint v0.1.0 // indirect 98 83 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 84 + github.com/onsi/gomega v1.38.2 // indirect 99 85 github.com/openbao/openbao/api/v2 v2.3.0 // indirect 100 86 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect 101 87 github.com/pjbgf/sha1cd v0.3.2 // indirect ··· 113 99 github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect 114 100 github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect 115 101 github.com/whyrusleeping/cbor-gen v0.3.1 // indirect 116 - github.com/x448/float16 v0.8.4 // indirect 117 102 github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect 118 103 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect 119 104 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect ··· 125 110 go.uber.org/atomic v1.11.0 // indirect 126 111 go.uber.org/multierr v1.11.0 // indirect 127 112 go.uber.org/zap v1.27.1 // indirect 128 - go.yaml.in/yaml/v3 v3.0.4 // indirect 129 113 golang.org/x/crypto v0.48.0 // indirect 130 114 golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect 131 115 golang.org/x/net v0.50.0 // indirect 132 - golang.org/x/oauth2 v0.34.0 // indirect 133 116 golang.org/x/sync v0.19.0 // indirect 134 117 golang.org/x/sys v0.42.0 // indirect 135 - golang.org/x/term v0.40.0 // indirect 136 118 golang.org/x/text v0.34.0 // indirect 137 119 golang.org/x/time v0.12.0 // indirect 138 120 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect 139 121 google.golang.org/protobuf v1.36.11 // indirect 140 - gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect 141 - gopkg.in/inf.v0 v0.9.1 // indirect 142 122 gopkg.in/warnings.v0 v0.1.2 // indirect 143 123 gopkg.in/yaml.v3 v3.0.1 // indirect 144 - k8s.io/klog/v2 v2.130.1 // indirect 145 - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect 146 - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect 147 124 lukechampine.com/blake3 v1.4.1 // indirect 148 - sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect 149 - sigs.k8s.io/randfill v1.0.0 // indirect 150 - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect 151 - sigs.k8s.io/yaml v1.6.0 // indirect 152 125 ) 153 126 154 127 // tangled.org/core uses these forks for extra commit/patch metadata fields.
-381
go.sum
··· 1 - cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= 2 1 dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= 3 2 dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= 4 - github.com/Blank-Xu/sql-adapter v1.1.1/go.mod h1:o2g8EZhZ3TudnYEGDkoU+3jCTCgDgx1o/Ig5ajKkaLY= 5 3 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 6 - github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= 7 - github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ= 8 - github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 9 - github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= 10 - github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 11 - github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= 12 4 github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= 13 5 github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= 14 - github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= 15 6 github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= 16 7 github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= 17 - github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo= 18 - github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0= 19 - github.com/RussellLuo/slidingwindow v0.0.0-20200528002341-535bb99d338b/go.mod h1:4+EPqMRApwwE/6yo6CxiHoSnBzjRr3jsqer7frxP8y4= 20 - github.com/adrg/frontmatter v0.2.0/go.mod h1:93rQCj3z3ZlwyxxpQioRKC1wDLto4aXHrbqIsnH9wmE= 21 8 github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= 22 9 github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= 23 - github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= 24 - github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= 25 10 github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= 26 11 github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= 27 - github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= 28 - github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5/go.mod h1:Y2QMoi1vgtOIfc+6DhrMOGkLoGzqSV2rKp4Sm+opsyA= 29 - github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= 30 - github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= 31 - github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 32 - github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 33 12 github.com/avast/retry-go/v4 v4.6.1 h1:VkOLRubHdisGrHnTu89g08aQEWEgRU7LVEop3GbIcMk= 34 13 github.com/avast/retry-go/v4 v4.6.1/go.mod h1:V6oF8njAwxJ5gRo1Q7Cxab24xs5NCWZBeaHHBklR8mA= 35 - github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= 36 - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.7/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= 37 - github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= 38 - github.com/aws/aws-sdk-go-v2/credentials v1.19.12/go.mod h1:U3R1RtSHx6NB0DvEQFGyf/0sbrpJrluENHdPy1j/3TE= 39 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20/go.mod h1:z/MVwUARehy6GAg/yQ1GO2IMl0k++cu1ohP9zo887wE= 40 - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o= 41 - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc= 42 - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= 43 - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.21/go.mod h1:UUxgWxofmOdAMuqEsSppbDtGKLfR04HGsD0HXzvhI1k= 44 - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= 45 - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.12/go.mod h1:v2pNpJbRNl4vEUWEh5ytQok0zACAKfdmKS51Hotc3pQ= 46 - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.20/go.mod h1:V4X406Y666khGa8ghKmphma/7C0DAtEQYhkq9z4vpbk= 47 - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.20/go.mod h1:4TLZCmVJDM3FOu5P5TJP0zOlu9zWgDWU7aUxWbr+rcw= 48 - github.com/aws/aws-sdk-go-v2/service/s3 v1.97.1/go.mod h1:qXVal5H0ChqXP63t6jze5LmFalc7+ZE7wOdLtZ0LCP0= 49 - github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE= 50 - github.com/aws/aws-sdk-go-v2/service/sso v1.30.13/go.mod h1:2h/xGEowcW/g38g06g3KpRWDlT+OTfxxI0o1KqayAB8= 51 - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.17/go.mod h1:Al9fFsXjv4KfbzQHGe6V4NZSZQXecFcvaIF4e70FoRA= 52 - github.com/aws/aws-sdk-go-v2/service/sts v1.41.9/go.mod h1:LrlIndBDdjA/EeXeyNBle+gyCwTlizzW5ycgWnvIxkk= 53 - github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= 54 14 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= 55 15 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= 56 - github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= 57 - github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= 58 - github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 59 16 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 60 17 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 61 - github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 62 - github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= 63 - github.com/blevesearch/bleve/v2 v2.5.3/go.mod h1:Z/e8aWjiq8HeX+nW8qROSxiE0830yQA071dwR3yoMzw= 64 - github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0= 65 - github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8= 66 - github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk= 67 - github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= 68 - github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk= 69 - github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= 70 - github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8= 71 - github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= 72 - github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs= 73 - github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ= 74 - github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y= 75 - github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc= 76 - github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58= 77 - github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk= 78 - github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8= 79 - github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw= 80 - github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs= 81 18 github.com/bluesky-social/indigo v0.0.0-20260220055544-bf41e2ee75ab h1:Cs35T2tAN3Q6mMH5mBaY09nmCNOn/GkZS1F7jfMxlR8= 82 19 github.com/bluesky-social/indigo v0.0.0-20260220055544-bf41e2ee75ab/go.mod h1:VG/LeqLGNI3Ew7lsYixajnZGFfWPv144qbUddh+Oyag= 83 20 github.com/bluesky-social/jetstream v0.0.0-20260226214936-e0274250f654 h1:OK76FcHhZp8ohjRB0OMWgti0oYAWFlt3KDQcIkH1pfI= 84 21 github.com/bluesky-social/jetstream v0.0.0-20260226214936-e0274250f654/go.mod h1:vt8kVRKtvrBspt9G38wDD8+BotjIMO8u8IYoVnyE4zY= 85 22 github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE= 86 23 github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= 87 - github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c= 88 - github.com/brianvoe/gofakeit/v6 v6.25.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= 89 24 github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= 90 25 github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= 91 26 github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= 92 27 github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= 93 - github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= 94 28 github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc= 95 29 github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8= 96 - github.com/casbin/casbin/v2 v2.103.0/go.mod h1:Ee33aqGrmES+GNL17L0h9X28wXuo829wnNUnS0edAco= 97 - github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= 98 30 github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 99 31 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 100 - github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= 101 32 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 102 33 github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 103 34 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= ··· 112 43 github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= 113 44 github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= 114 45 github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= 115 - github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= 116 46 github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= 117 47 github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= 118 48 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= ··· 120 50 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 121 51 github.com/cloudflare/circl v1.6.2-0.20250618153321-aa837fd1539d h1:IiIprFGH6SqstblP0Y9NIo3eaUJGkI/YDOFVSL64Uq4= 122 52 github.com/cloudflare/circl v1.6.2-0.20250618153321-aa837fd1539d/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= 123 - github.com/cloudflare/cloudflare-go/v6 v6.7.0/go.mod h1:Lj3MUqjvKctXRpdRhLQxZYRrNZHuRs0XYuH8JtQGyoI= 124 - github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8= 125 - github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M= 126 - github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= 127 - github.com/cockroachdb/pebble v1.1.2/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU= 128 - github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= 129 - github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= 130 - github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= 131 - github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= 132 - github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= 133 53 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 134 - github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 135 - github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= 136 54 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 137 - github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis= 138 55 github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= 139 56 github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= 140 57 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 141 58 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 142 59 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 143 60 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 144 - github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= 145 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= 146 - github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU= 147 61 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 148 62 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 149 - github.com/did-method-plc/go-didplc v0.2.2/go.mod h1:bKdJ21irnwNHgVLWWL32zUWqZueXYbJRUcxplZghByo= 150 - github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= 151 - github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= 152 - github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 153 - github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= 154 - github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 155 - github.com/dunglas/httpsfv v1.1.0/go.mod h1:zID2mqw9mFsnt7YC3vYQ9/cjq30q41W+1AnDwH8TiMg= 156 - github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 157 63 github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg= 158 64 github.com/earthboundkid/versioninfo/v2 v2.24.1/go.mod h1:VcWEooDEuyUJnMfbdTh0uFN4cfEIg+kHMuWB2CDCLjw= 159 - github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= 160 - github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= 161 - github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 162 65 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 163 66 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 164 67 github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= 165 68 github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= 166 69 github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= 167 70 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 168 - github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs= 169 - github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= 170 71 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 171 72 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 172 73 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= 173 74 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= 174 - github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= 175 - github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= 176 - github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= 177 - github.com/gammazero/chanqueue v1.1.1/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc= 178 - github.com/gammazero/deque v1.2.0/go.mod h1:JVrR+Bj1NMQbPnYclvDlvSX0nVGReLrQZ0aUMuWLctg= 179 - github.com/getsentry/sentry-go v0.28.0/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg= 180 - github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= 181 - github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 182 - github.com/go-enry/go-enry/v2 v2.9.2/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= 183 - github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4= 184 75 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= 185 76 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 186 77 github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= 187 78 github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= 188 79 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= 189 80 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= 190 - github.com/go-git/go-git-fixtures/v5 v5.0.0-20241203230421-0753e18f8f03/go.mod h1:hMKrMnUE4W0SJ7bFyM00dyz/HoknZoptGWzrj6M+dEM= 191 81 github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY= 192 82 github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= 193 83 github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= ··· 198 88 github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 199 89 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 200 90 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 201 - github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= 202 - github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= 203 - github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= 204 - github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= 205 - github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= 206 - github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 207 - github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= 208 - github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= 209 91 github.com/go-redis/cache/v9 v9.0.0 h1:0thdtFo0xJi0/WXbRVu8B066z8OvVymXTJGaXrVWnN0= 210 92 github.com/go-redis/cache/v9 v9.0.0/go.mod h1:cMwi1N8ASBOufbIvk7cdXe2PbPjK/WMRL95FFHWsSgI= 211 - github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 212 - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= 213 93 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 214 - github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= 215 - github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= 216 94 github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= 217 95 github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 218 96 github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= 219 97 github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= 220 98 github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= 221 - github.com/gocql/gocql v1.7.0/go.mod h1:vnlvXyFZeLBF0Wy+RS8hrOdbn0UWsWtdg07XJnFxZ+4= 222 99 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 223 100 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 224 - github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 225 - github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= 226 101 github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= 227 102 github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= 228 - github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 229 103 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 230 104 github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 231 105 github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= ··· 235 109 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 236 110 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 237 111 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 238 - github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 239 - github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 240 - github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 241 - github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= 242 - github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= 243 112 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 244 113 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 245 114 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= ··· 248 117 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 249 118 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 250 119 github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 251 - github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= 252 - github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 253 - github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 254 120 github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 255 - github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= 256 - github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= 257 121 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 258 122 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 259 123 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 260 124 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 261 125 github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= 262 126 github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 263 - github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= 264 - github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y= 265 - github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= 266 - github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= 267 - github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= 268 127 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo= 269 128 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= 270 - github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 271 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs= 272 - github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= 273 129 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 274 130 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 275 131 github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= ··· 289 145 github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= 290 146 github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= 291 147 github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 292 - github.com/hashicorp/golang-lru/arc/v2 v2.0.6/go.mod h1:cfdDIX05DWvYV6/shsxDfa/OVcRieOt+q4FnM8x+Xno= 293 148 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= 294 149 github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= 295 150 github.com/hashicorp/hcl v1.0.1-vault-7 h1:ag5OxFVy3QYTFTJODRzTKVZ6xvdfLLCA1cy/Y6xGI0I= 296 151 github.com/hashicorp/hcl v1.0.1-vault-7/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= 297 152 github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= 298 153 github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= 299 - github.com/hiddeco/sshsig v0.2.0/go.mod h1:nJc98aGgiH6Yql2doqH4CTBVHexQA40Q+hMMLHP4EqE= 300 154 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 301 - github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 302 - github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= 303 155 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 304 - github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 305 156 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= 306 157 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= 307 158 github.com/ipfs/boxo v0.36.0 h1:DarrMBM46xCs6GU6Vz+AL8VUyXykqHAqZYx8mR0Oics= 308 159 github.com/ipfs/boxo v0.36.0/go.mod h1:92hnRXfP5ScKEIqlq9Ns7LR1dFXEVADKWVGH0fjk83k= 309 - github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU= 310 160 github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk= 311 161 github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA= 312 - github.com/ipfs/go-blockservice v0.5.2/go.mod h1:VpMblFEqG67A/H2sHKAemeH9vlURVavlysbdUI632yk= 313 162 github.com/ipfs/go-cid v0.6.0 h1:DlOReBV1xhHBhhfy/gBNNTSyfOM6rLiIx9J7A4DGf30= 314 163 github.com/ipfs/go-cid v0.6.0/go.mod h1:NC4kS1LZjzfhK40UGmpXv5/qD2kcMzACYJNntCUiDhQ= 315 - github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA= 316 164 github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w= 317 165 github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg= 318 166 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= 319 167 github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= 320 - github.com/ipfs/go-ds-flatfs v0.5.1/go.mod h1:RWTV7oZD/yZYBKdbVIFXTX2fdY2Tbvl94NsWqmoyAX4= 321 - github.com/ipfs/go-dsqueue v0.1.2/go.mod h1:OU94YuMVUIF/ctR7Ysov9PI4gOa2XjPGN9nd8imSv78= 322 168 github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ= 323 169 github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE= 324 - github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= 325 170 github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw= 326 171 github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo= 327 - github.com/ipfs/go-ipfs-exchange-interface v0.2.1/go.mod h1:MUsYn6rKbG6CTtsDp+lKJPmVt3ZrCViNyH3rfPGsZ2E= 328 - github.com/ipfs/go-ipfs-pq v0.0.4/go.mod h1:9UdLOIIb99IFrgT0Fc53pvbvlJBhpUb4GJuAQf3+O2A= 329 - github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw= 330 172 github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0= 331 173 github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs= 332 174 github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E= 333 175 github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A= 334 176 github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8= 335 177 github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk= 336 - github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7eYlWeAOPyDU= 337 - github.com/ipfs/go-libipfs v0.7.0/go.mod h1:KsIf/03CqhICzyRGyGo68tooiBE2iFbI/rXW7FhAYr0= 338 178 github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= 339 179 github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= 340 180 github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= 341 181 github.com/ipfs/go-log/v2 v2.9.1 h1:3JXwHWU31dsCpvQ+7asz6/QsFJHqFr4gLgQ0FWteujk= 342 182 github.com/ipfs/go-log/v2 v2.9.1/go.mod h1:evFx7sBiohUN3AG12mXlZBw5hacBQld3ZPHrowlJYoo= 343 - github.com/ipfs/go-merkledag v0.11.0/go.mod h1:Q4f/1ezvBiJV0YCIXvt51W/9/kqJGH4I1LsA7+djsM4= 344 183 github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU= 345 184 github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY= 346 - github.com/ipfs/go-peertaskqueue v0.8.3/go.mod h1:OqVync4kPOcXEGdj/LKvox9DCB5mkSBeXsPczCxLtYA= 347 - github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o= 348 - github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg= 349 - github.com/ipfs/go-verifcid v0.0.3/go.mod h1:gcCtGniVzelKrbk9ooUSX/pM3xlH73fZZJDzQJRvOUw= 350 - github.com/ipld/go-car v0.6.2/go.mod h1:oEGXdwp6bmxJCZ+rARSkDliTeYnVzv3++eXajZ+Bmr8= 351 - github.com/ipld/go-car/v2 v2.16.0/go.mod h1:RqFGWN9ifcXVmCrTAVnfnxiWZk1+jIx67SYhenlmL34= 352 - github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM= 353 - github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= 354 - github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= 355 - github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= 356 - github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw= 357 - github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= 358 - github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= 359 - github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= 360 - github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= 361 - github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 362 - github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 363 - github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 364 - github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 365 - github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 366 - github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 367 - github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 368 - github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 369 185 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 370 186 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 371 - github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 372 187 github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= 373 188 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 374 189 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= ··· 378 193 github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= 379 194 github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= 380 195 github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= 381 - github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI= 382 196 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 383 - github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 384 197 github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 385 198 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 386 199 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= ··· 388 201 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 389 202 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 390 203 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 391 - github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 392 - github.com/labstack/echo-contrib v0.15.0/go.mod h1:lei+qt5CLB4oa7VHTE0yEfQSEB9XTJI1LUqko9UWvo4= 393 - github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws= 394 - github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM= 395 - github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= 396 - github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= 397 - github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= 398 - github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= 399 - github.com/lestrrat-go/jwx/v2 v2.0.12/go.mod h1:Mq4KN1mM7bp+5z/W5HS8aCNs5RKZ911G/0y2qUjAQuQ= 400 - github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= 401 - github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= 402 - github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= 403 - github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU= 404 - github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo= 405 - github.com/libp2p/go-libp2p v0.47.0/go.mod h1:s8HPh7mMV933OtXzONaGFseCg/BE//m1V34p3x4EUOY= 406 - github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= 407 - github.com/libp2p/go-libp2p-kad-dht v0.37.1/go.mod h1:Uwokdh232k9Y1uMy2yJOK5zb7hpMHn4P8uWS4s9i05Q= 408 - github.com/libp2p/go-libp2p-kbucket v0.8.0/go.mod h1:JMlxqcEyKwO6ox716eyC0hmiduSWZZl6JY93mGaaqc4= 409 - github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E= 410 - github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98= 411 - github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= 412 - github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= 413 - github.com/libp2p/go-netroute v0.4.0/go.mod h1:Nkd5ShYgSMS5MUKy/MU2T57xFoOKvvLR92Lic48LEyA= 414 - github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= 415 - github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU= 416 204 github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= 417 205 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 418 - github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 419 - github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 420 - github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= 421 206 github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= 422 207 github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= 423 208 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= ··· 426 211 github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 427 212 github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8= 428 213 github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= 429 - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 430 - github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= 431 - github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= 432 - github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= 433 - github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= 434 - github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 435 214 github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= 436 215 github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 437 - github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= 438 - github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= 439 - github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= 440 216 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 441 217 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 442 - github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 443 - github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= 444 - github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= 445 - github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= 446 - github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= 447 - github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 448 - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 449 - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 450 - github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 451 - github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= 452 - github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 453 - github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= 454 218 github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= 455 219 github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 456 - github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= 457 220 github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= 458 221 github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= 459 222 github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= 460 223 github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 461 224 github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= 462 225 github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= 463 - github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= 464 - github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc= 465 - github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= 466 226 github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= 467 227 github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= 468 - github.com/multiformats/go-multicodec v0.10.0/go.mod h1:wg88pM+s2kZJEQfRCKBNU+g32F5aWBEjyFHXvZLTcLI= 469 228 github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= 470 229 github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= 471 - github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw= 472 230 github.com/multiformats/go-varint v0.1.0 h1:i2wqFp4sdl3IcIxfAonHQV9qU5OsZ4Ts9IOoETFs5dI= 473 231 github.com/multiformats/go-varint v0.1.0/go.mod h1:5KVAVXegtfmNQQm/lCY+ATvDzvJJhSkUlGQV9wgObdI= 474 232 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 475 233 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 476 - github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 477 - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 478 234 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 479 235 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 480 236 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= ··· 490 246 github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= 491 247 github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= 492 248 github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= 493 - github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= 494 - github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= 495 249 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 496 250 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 497 251 github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= ··· 506 260 github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= 507 261 github.com/openbao/openbao/api/v2 v2.3.0 h1:61FO3ILtpKoxbD9kTWeGaCq8pz1sdt4dv2cmTXsiaAc= 508 262 github.com/openbao/openbao/api/v2 v2.3.0/go.mod h1:T47WKHb7DqHa3Ms3xicQtl5EiPE+U8diKjb9888okWs= 509 - github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 510 - github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= 511 - github.com/opensearch-project/opensearch-go/v2 v2.3.0/go.mod h1:8LDr9FCgUTVoT+5ESjc2+iaZuldqE+23Iq0r1XeNue8= 512 263 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= 513 264 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= 514 265 github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= 515 - github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= 516 266 github.com/oppiliappan/go-git/v5 v5.17.0 h1:CuJnpcIDxr0oiNaSHMconovSWnowHznVDG+AhjGuSEo= 517 267 github.com/oppiliappan/go-git/v5 v5.17.0/go.mod h1:q/FE8C3SPMoRN7LoH9vRFiBzidAOBWJPS1CqVS8DN+w= 518 - github.com/orandin/slog-gorm v1.3.2/go.mod h1:MoZ51+b7xE9lwGNPYEhxcUtRNrYzjdcKvA8QXQQGEPA= 519 - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= 520 - github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= 521 - github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 522 - github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= 523 - github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= 524 - github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU= 525 - github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= 526 - github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= 527 - github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= 528 - github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= 529 - github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= 530 - github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= 531 - github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= 532 - github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= 533 - github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= 534 - github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY= 535 - github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= 536 - github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= 537 - github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E= 538 - github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= 539 - github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= 540 - github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U= 541 268 github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= 542 269 github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= 543 270 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= ··· 548 275 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 549 276 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0= 550 277 github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= 551 - github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 552 - github.com/posthog/posthog-go v1.5.5/go.mod h1:3RqUmSnPuwmeVj/GYrS75wNGqcAKdpODiwc83xZWgdE= 553 278 github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= 554 279 github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= 555 280 github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= ··· 558 283 github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= 559 284 github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= 560 285 github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= 561 - github.com/puzpuzpuz/xsync/v3 v3.0.2/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA= 562 - github.com/puzpuzpuz/xsync/v4 v4.2.0/go.mod h1:VJDmTCJMBt8igNxnkQd86r+8KUeN1quSfNKu5bLYFQo= 563 - github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= 564 - github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= 565 - github.com/quic-go/webtransport-go v0.10.0/go.mod h1:LeGIXr5BQKE3UsynwVBeQrU1TPrbh73MGoC6jd+V7ow= 566 286 github.com/redis/go-redis/v9 v9.0.0-rc.4/go.mod h1:Vo3EsyWnicKnSKCA7HhgnvnyA74wOA69Cd2Meli5mmA= 567 287 github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= 568 288 github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= 569 - github.com/resend/resend-go/v3 v3.5.0/go.mod h1:iI7VA0NoGjWvsNii5iNC5Dy0llsI3HncXPejhniYzwE= 570 289 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 571 290 github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= 572 291 github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= ··· 575 294 github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= 576 295 github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= 577 296 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 578 - github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 579 - github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 580 297 github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= 581 298 github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= 582 - github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= 583 - github.com/samber/slog-echo v1.8.0/go.mod h1:0ab2AwcciQXNAXEcjkHwD9okOh9vEHEYn8xP97ocuhM= 584 - github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= 585 299 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= 586 300 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= 587 - github.com/sethvargo/go-envconfig v1.1.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw= 588 - github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 589 301 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 590 - github.com/slok/go-http-metrics v0.13.0/go.mod h1:HIr7t/HbN2sJaunvnt9wKP9xoBBVZFo1/KiHU3b0w+4= 591 302 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= 592 303 github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= 593 304 github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= 594 305 github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= 595 306 github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 596 307 github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 597 - github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 598 - github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= 599 - github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 600 - github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= 601 - github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= 602 308 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 603 309 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 604 310 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 605 - github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= 606 - github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 607 311 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 608 312 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 609 313 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= ··· 614 318 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 615 319 github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 616 320 github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 617 - github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 618 - github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 619 - github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 620 - github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 621 - github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb/go.mod h1:ikPs9bRWicNw3S7XpJ8sK/smGwU9WcSVU3dy9qahYBM= 622 321 github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 623 - github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= 624 - github.com/urfave/cli/v3 v3.6.2/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= 625 - github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 626 - github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 627 322 github.com/vmihailenco/go-tinylfu v0.2.2 h1:H1eiG6HM36iniK6+21n9LLpzx1G9R3DJa2UjUjbynsI= 628 323 github.com/vmihailenco/go-tinylfu v0.2.2/go.mod h1:CutYi2Q9puTxfcolkliPq4npPuofg9N9t8JVrjzwa3Q= 629 324 github.com/vmihailenco/msgpack/v5 v5.3.4/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= ··· 633 328 github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= 634 329 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= 635 330 github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= 636 - github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM= 637 - github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ= 638 331 github.com/whyrusleeping/cbor-gen v0.3.1 h1:82ioxmhEYut7LBVGhGq8xoRkXPLElVuh5mV67AFfdv0= 639 332 github.com/whyrusleeping/cbor-gen v0.3.1/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= 640 - github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= 641 - github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6/go.mod h1:39U9RRVr4CKbXpXYopWn+FSH5s+vWu6+RmguSPWAq5s= 642 - github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= 643 - github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= 644 - github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= 645 - github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= 646 - github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= 647 - github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= 648 333 github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= 649 334 github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= 650 - github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= 651 335 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 652 336 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 653 337 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 654 338 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 655 - github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= 656 - github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= 657 - github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= 658 - gitlab.com/staticnoise/goldmark-callout v0.0.0-20240609120641-6366b799e4ab/go.mod h1:SPu13/NPe1kMrbGoJldQwqtpNhXsmIuHCfm/aaGjU0c= 659 339 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA= 660 340 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= 661 341 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= 662 342 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= 663 - go.abhg.dev/goldmark/mermaid v0.6.0/go.mod h1:uMc+PcnIH2NVL7zjH10Q1wr7hL3+4n4jUMifhyBYB9I= 664 - go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk= 665 - go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 666 343 go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= 667 344 go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= 668 - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.45.0/go.mod h1:Px9kH7SJ+NhsgWRtD/eMcs15Tyt4uL3rM7X54qv6pfA= 669 345 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0 h1:7iP2uCb7sGddAr30RRS6xjKy7AZ2JtTOPA3oolgVSw8= 670 346 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.65.0/go.mod h1:c7hN3ddxs/z6q9xwvfLPk+UHlWRQyaeR1LdgfL/66l0= 671 347 go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= 672 348 go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= 673 - go.opentelemetry.io/otel/exporters/jaeger v1.14.0/go.mod h1:4Ay9kk5vELRrbg5z4cpP9EtmQRFap2Wb0woPG4lujZA= 674 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU= 675 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk= 676 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4= 677 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE= 678 - go.opentelemetry.io/otel/exporters/zipkin v1.38.0/go.mod h1:Su/nq/K5zRjDKKC3Il0xbViE3juWgG3JDoqLumFx5G0= 679 349 go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= 680 350 go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= 681 351 go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= ··· 684 354 go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= 685 355 go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= 686 356 go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= 687 - go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= 688 357 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 689 358 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 690 359 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= 691 360 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 692 - go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= 693 - go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= 694 - go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo= 695 361 go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 696 362 go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 697 - go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= 698 363 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 699 364 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 700 365 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= ··· 718 383 golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= 719 384 golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= 720 385 golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= 721 - golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA= 722 386 golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 723 387 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 724 388 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= ··· 728 392 golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= 729 393 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 730 394 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 731 - golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= 732 - golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= 733 395 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 734 396 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 735 397 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= ··· 751 413 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 752 414 golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= 753 415 golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= 754 - golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= 755 - golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= 756 416 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 757 417 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 758 418 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= ··· 791 451 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 792 452 golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= 793 453 golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= 794 - golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= 795 454 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 796 455 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 797 456 golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= ··· 801 460 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 802 461 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 803 462 golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 804 - golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= 805 - golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= 806 463 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 807 464 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 808 465 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= ··· 832 489 golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= 833 490 golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= 834 491 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 835 - golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= 836 - golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= 837 - golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= 838 - golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= 839 492 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 840 493 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 841 494 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 842 495 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 843 496 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= 844 497 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 845 - gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= 846 - google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= 847 - google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= 848 - google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= 849 498 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 850 499 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 851 500 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= ··· 863 512 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 864 513 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 865 514 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 866 - gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= 867 - gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= 868 515 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 869 - gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 870 - gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 871 516 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 872 517 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 873 518 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= ··· 879 524 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 880 525 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 881 526 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 882 - gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= 883 - gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE= 884 - gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= 885 - gorm.io/plugin/opentelemetry v0.1.3/go.mod h1:tndJHOdvPT0pyGhOb8E2209eXJCUxhC5UpKw7bGVWeI= 886 - gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= 887 527 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 888 - k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ= 889 - k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4= 890 - k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8= 891 - k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= 892 - k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= 893 - k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= 894 - k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= 895 - k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= 896 - k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 897 - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= 898 - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= 899 - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= 900 - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 901 528 lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= 902 529 lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= 903 - sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= 904 - sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= 905 - sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= 906 - sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= 907 - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= 908 - sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= 909 - sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= 910 - sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= 911 530 tangled.org/core v1.13.0-alpha.0.20260502074102-37303f21368b h1:5g3kGPrs6IGoHuFAb3kqrL5EwgGTl4ulbJTYsX1WfTM= 912 531 tangled.org/core v1.13.0-alpha.0.20260502074102-37303f21368b/go.mod h1:abXVlFoPAeM9pZier/WF1Cnn1ZoO9YE5h59WLEUy+Hk= 913 532 tangled.sh/oppi.li/go-gitdiff v0.8.2 h1:pASJJNWaFn6EmEIUNNjHZQ3stRu6BqTO2YyjKvTcxIc=
+27
internal/k8s/doc.go
··· 1 + /* 2 + Copyright 2014 The Kubernetes Authors. 3 + 4 + Licensed under the Apache License, Version 2.0 (the "License"); 5 + you may not use this file except in compliance with the License. 6 + You may obtain a copy of the License at 7 + 8 + http://www.apache.org/licenses/LICENSE-2.0 9 + 10 + Unless required by applicable law or agreed to in writing, software 11 + distributed under the License is distributed on an "AS IS" BASIS, 12 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 + See the License for the specific language governing permissions and 14 + limitations under the License. 15 + */ 16 + 17 + // Package k8s provides the tiny slice of the Kubernetes API tack's Tekton 18 + // provider needs. 19 + // 20 + // The package is based on the shape and behavior of Kubernetes client-go's 21 + // in-cluster REST client and watch plumbing, but reimplemented here with a much 22 + // smaller API surface so tack doesn't need to import the full client-go module 23 + // graph just to create resources, watch them, and stream pod logs. 24 + // 25 + // The Apache 2.0 notice above records that upstream client-go provenance in one 26 + // place for the package. 27 + package k8s
+416
internal/k8s/fake.go
··· 1 + package k8s 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + "io" 7 + "strings" 8 + "sync" 9 + "time" 10 + ) 11 + 12 + // FakeClient is a tiny in-memory implementation used by Tekton tests. It keeps 13 + // the test surface aligned with the real client package without reintroducing 14 + // external Kubernetes fakes. 15 + type FakeClient struct { 16 + mu sync.Mutex 17 + nextUID int64 18 + nextWatchID int 19 + objects map[objectKey]Object 20 + watchers map[int]*watchRegistration 21 + pods map[string]map[string]Pod 22 + podLogs map[podLogKey]string 23 + } 24 + 25 + var _ Client = (*FakeClient)(nil) 26 + 27 + type objectKey struct { 28 + gvr GVR 29 + namespace string 30 + name string 31 + } 32 + 33 + type podLogKey struct { 34 + namespace string 35 + podName string 36 + container string 37 + } 38 + 39 + type watchRegistration struct { 40 + gvr GVR 41 + namespace string 42 + opts ListOptions 43 + watch *fakeWatch 44 + } 45 + 46 + // NewFakeClient returns an empty fake client. 47 + func NewFakeClient() *FakeClient { 48 + return &FakeClient{ 49 + objects: map[objectKey]Object{}, 50 + watchers: map[int]*watchRegistration{}, 51 + pods: map[string]map[string]Pod{}, 52 + podLogs: map[podLogKey]string{}, 53 + } 54 + } 55 + 56 + // SeedObject preloads an object without emitting watch events. 57 + func (c *FakeClient) SeedObject(gvr GVR, namespace string, obj Object) { 58 + c.mu.Lock() 59 + defer c.mu.Unlock() 60 + stored := c.prepareObjectLocked(namespace, obj.DeepCopy()) 61 + c.objects[objectKey{gvr: gvr, namespace: namespace, name: stored.GetName()}] = stored 62 + } 63 + 64 + // UpdateObject overwrites an existing object and emits a MODIFIED watch event. 65 + func (c *FakeClient) UpdateObject(gvr GVR, namespace string, obj Object) { 66 + stored, watchers := c.storeObject(gvr, namespace, obj.DeepCopy()) 67 + c.broadcast(watchers, WatchEvent{Type: "MODIFIED", Object: stored}) 68 + } 69 + 70 + // SeedPod preloads a pod for later ListPods or StreamPodLogs calls. 71 + func (c *FakeClient) SeedPod(namespace string, pod Pod) { 72 + c.mu.Lock() 73 + defer c.mu.Unlock() 74 + if namespace == "" { 75 + namespace = pod.Namespace 76 + } 77 + if namespace == "" { 78 + namespace = "default" 79 + } 80 + pod.Namespace = namespace 81 + if pod.CreationTimestamp.IsZero() { 82 + pod.CreationTimestamp = time.Now().UTC() 83 + } 84 + if pod.Labels != nil { 85 + pod.Labels = cloneLabels(pod.Labels) 86 + } 87 + if _, ok := c.pods[namespace]; !ok { 88 + c.pods[namespace] = map[string]Pod{} 89 + } 90 + c.pods[namespace][pod.Name] = clonePod(pod) 91 + } 92 + 93 + // SetPodLog stores the exact bytes StreamPodLogs should later return. 94 + func (c *FakeClient) SetPodLog(namespace, podName, container, content string) { 95 + c.mu.Lock() 96 + defer c.mu.Unlock() 97 + c.podLogs[podLogKey{ 98 + namespace: namespace, 99 + podName: podName, 100 + container: container, 101 + }] = content 102 + } 103 + 104 + func (c *FakeClient) CreateObject( 105 + ctx context.Context, 106 + gvr GVR, 107 + namespace string, 108 + obj Object, 109 + ) (Object, error) { 110 + select { 111 + case <-ctx.Done(): 112 + return nil, ctx.Err() 113 + default: 114 + } 115 + 116 + stored, watchers, err := c.createObject(gvr, namespace, obj.DeepCopy()) 117 + if err != nil { 118 + return nil, err 119 + } 120 + c.broadcast(watchers, WatchEvent{Type: "ADDED", Object: stored}) 121 + return stored.DeepCopy(), nil 122 + } 123 + 124 + func (c *FakeClient) GetObject( 125 + ctx context.Context, 126 + gvr GVR, 127 + namespace string, 128 + name string, 129 + ) (Object, error) { 130 + select { 131 + case <-ctx.Done(): 132 + return nil, ctx.Err() 133 + default: 134 + } 135 + 136 + c.mu.Lock() 137 + defer c.mu.Unlock() 138 + obj, ok := c.objects[objectKey{gvr: gvr, namespace: namespace, name: name}] 139 + if !ok { 140 + return nil, fmt.Errorf("%w: %s/%s", ErrNotFound, namespace, name) 141 + } 142 + return obj.DeepCopy(), nil 143 + } 144 + 145 + func (c *FakeClient) ListObjects( 146 + ctx context.Context, 147 + gvr GVR, 148 + namespace string, 149 + opts ListOptions, 150 + ) ([]Object, error) { 151 + select { 152 + case <-ctx.Done(): 153 + return nil, ctx.Err() 154 + default: 155 + } 156 + 157 + c.mu.Lock() 158 + defer c.mu.Unlock() 159 + out := make([]Object, 0) 160 + for key, obj := range c.objects { 161 + if key.gvr != gvr || key.namespace != namespace { 162 + continue 163 + } 164 + if !matchesListOptions(obj, opts) { 165 + continue 166 + } 167 + out = append(out, obj.DeepCopy()) 168 + } 169 + return out, nil 170 + } 171 + 172 + func (c *FakeClient) WatchObjects( 173 + ctx context.Context, 174 + gvr GVR, 175 + namespace string, 176 + opts ListOptions, 177 + ) (WatchInterface, error) { 178 + c.mu.Lock() 179 + id := c.nextWatchID 180 + c.nextWatchID++ 181 + w := &fakeWatch{ch: make(chan WatchEvent, 64)} 182 + w.stop = func() { 183 + c.mu.Lock() 184 + defer c.mu.Unlock() 185 + delete(c.watchers, id) 186 + } 187 + c.watchers[id] = &watchRegistration{ 188 + gvr: gvr, 189 + namespace: namespace, 190 + opts: opts, 191 + watch: w, 192 + } 193 + c.mu.Unlock() 194 + 195 + go func() { 196 + <-ctx.Done() 197 + w.Stop() 198 + }() 199 + return w, nil 200 + } 201 + 202 + func (c *FakeClient) ListPods( 203 + ctx context.Context, 204 + namespace string, 205 + labelSelector string, 206 + ) ([]Pod, error) { 207 + select { 208 + case <-ctx.Done(): 209 + return nil, ctx.Err() 210 + default: 211 + } 212 + 213 + c.mu.Lock() 214 + defer c.mu.Unlock() 215 + entries := c.pods[namespace] 216 + out := make([]Pod, 0, len(entries)) 217 + for _, pod := range entries { 218 + if !matchesSelector(pod.Labels, labelSelector) { 219 + continue 220 + } 221 + out = append(out, clonePod(pod)) 222 + } 223 + return out, nil 224 + } 225 + 226 + func (c *FakeClient) StreamPodLogs( 227 + ctx context.Context, 228 + namespace string, 229 + podName string, 230 + container string, 231 + ) (io.ReadCloser, error) { 232 + select { 233 + case <-ctx.Done(): 234 + return nil, ctx.Err() 235 + default: 236 + } 237 + 238 + c.mu.Lock() 239 + defer c.mu.Unlock() 240 + raw, ok := c.podLogs[podLogKey{ 241 + namespace: namespace, 242 + podName: podName, 243 + container: container, 244 + }] 245 + if !ok { 246 + return nil, fmt.Errorf( 247 + "%w: pod log %s/%s[%s]", 248 + ErrNotFound, namespace, podName, container, 249 + ) 250 + } 251 + return io.NopCloser(strings.NewReader(raw)), nil 252 + } 253 + 254 + func (c *FakeClient) createObject( 255 + gvr GVR, 256 + namespace string, 257 + obj Object, 258 + ) (Object, []*fakeWatch, error) { 259 + c.mu.Lock() 260 + defer c.mu.Unlock() 261 + stored := c.prepareObjectLocked(namespace, obj) 262 + key := objectKey{gvr: gvr, namespace: namespace, name: stored.GetName()} 263 + if _, ok := c.objects[key]; ok { 264 + return nil, nil, fmt.Errorf("%w: %s/%s", ErrAlreadyExists, namespace, key.name) 265 + } 266 + c.objects[key] = stored 267 + return stored.DeepCopy(), c.matchingWatchersLocked(gvr, namespace, stored), nil 268 + } 269 + 270 + func (c *FakeClient) storeObject( 271 + gvr GVR, 272 + namespace string, 273 + obj Object, 274 + ) (Object, []*fakeWatch) { 275 + c.mu.Lock() 276 + defer c.mu.Unlock() 277 + stored := c.prepareObjectLocked(namespace, obj) 278 + key := objectKey{gvr: gvr, namespace: namespace, name: stored.GetName()} 279 + c.objects[key] = stored 280 + return stored.DeepCopy(), c.matchingWatchersLocked(gvr, namespace, stored) 281 + } 282 + 283 + func (c *FakeClient) prepareObjectLocked(namespace string, obj Object) Object { 284 + if obj.GetName() == "" { 285 + panic("k8s.FakeClient: object missing metadata.name") 286 + } 287 + meta := ensureNestedMap(obj, "metadata") 288 + if namespace != "" && meta["namespace"] == nil { 289 + meta["namespace"] = namespace 290 + } 291 + if obj.GetUID() == "" { 292 + c.nextUID++ 293 + obj.SetUID(fmt.Sprintf("fake-%d", c.nextUID)) 294 + } 295 + if obj.GetCreationTimestamp().IsZero() { 296 + obj.SetCreationTimestamp(time.Now().UTC()) 297 + } 298 + return obj 299 + } 300 + 301 + func (c *FakeClient) matchingWatchersLocked( 302 + gvr GVR, 303 + namespace string, 304 + obj Object, 305 + ) []*fakeWatch { 306 + watchers := make([]*fakeWatch, 0) 307 + for _, registration := range c.watchers { 308 + if registration.gvr != gvr || registration.namespace != namespace { 309 + continue 310 + } 311 + if !matchesListOptions(obj, registration.opts) { 312 + continue 313 + } 314 + watchers = append(watchers, registration.watch) 315 + } 316 + return watchers 317 + } 318 + 319 + func (c *FakeClient) broadcast(watchers []*fakeWatch, event WatchEvent) { 320 + for _, watcher := range watchers { 321 + watcher.send(event) 322 + } 323 + } 324 + 325 + type fakeWatch struct { 326 + ch chan WatchEvent 327 + stop func() 328 + once sync.Once 329 + } 330 + 331 + var _ WatchInterface = (*fakeWatch)(nil) 332 + 333 + func (w *fakeWatch) ResultChan() <-chan WatchEvent { 334 + return w.ch 335 + } 336 + 337 + func (w *fakeWatch) Stop() { 338 + w.once.Do(func() { 339 + if w.stop != nil { 340 + w.stop() 341 + } 342 + close(w.ch) 343 + }) 344 + } 345 + 346 + func (w *fakeWatch) send(event WatchEvent) { 347 + defer func() { 348 + _ = recover() 349 + }() 350 + w.ch <- WatchEvent{Type: event.Type, Object: event.Object.DeepCopy()} 351 + } 352 + 353 + func matchesListOptions(obj Object, opts ListOptions) bool { 354 + if !matchesSelector(obj.GetLabels(), opts.LabelSelector) { 355 + return false 356 + } 357 + if !matchesFieldSelector(obj, opts.FieldSelector) { 358 + return false 359 + } 360 + return true 361 + } 362 + 363 + func matchesFieldSelector(obj Object, selector string) bool { 364 + selector = strings.TrimSpace(selector) 365 + if selector == "" { 366 + return true 367 + } 368 + parts := strings.Split(selector, ",") 369 + for _, part := range parts { 370 + part = strings.TrimSpace(part) 371 + if part == "" { 372 + continue 373 + } 374 + key, value, ok := strings.Cut(part, "=") 375 + if !ok { 376 + return false 377 + } 378 + if strings.TrimSpace(key) != "metadata.name" { 379 + return false 380 + } 381 + if obj.GetName() != strings.TrimSpace(value) { 382 + return false 383 + } 384 + } 385 + return true 386 + } 387 + 388 + func matchesSelector(labels map[string]string, selector string) bool { 389 + selector = strings.TrimSpace(selector) 390 + if selector == "" { 391 + return true 392 + } 393 + parts := strings.Split(selector, ",") 394 + for _, part := range parts { 395 + part = strings.TrimSpace(part) 396 + if part == "" { 397 + continue 398 + } 399 + key, value, ok := strings.Cut(part, "=") 400 + if !ok { 401 + return false 402 + } 403 + if labels[strings.TrimSpace(key)] != strings.TrimSpace(value) { 404 + return false 405 + } 406 + } 407 + return true 408 + } 409 + 410 + func clonePod(pod Pod) Pod { 411 + out := pod 412 + out.Labels = cloneLabels(pod.Labels) 413 + out.InitContainers = append([]Container(nil), pod.InitContainers...) 414 + out.Containers = append([]Container(nil), pod.Containers...) 415 + return out 416 + }
+402
internal/k8s/incluster.go
··· 1 + package k8s 2 + 3 + import ( 4 + "bytes" 5 + "context" 6 + "crypto/tls" 7 + "crypto/x509" 8 + "encoding/json" 9 + "fmt" 10 + "io" 11 + "net/http" 12 + "net/url" 13 + "os" 14 + "strings" 15 + "sync" 16 + "time" 17 + ) 18 + 19 + const ( 20 + serviceAccountDir = "/var/run/secrets/kubernetes.io/serviceaccount" 21 + serviceTokenPath = serviceAccountDir + "/token" 22 + serviceAccountCA = serviceAccountDir + "/ca.crt" 23 + podsResource = "pods" 24 + podLogsSubresource = "log" 25 + ) 26 + 27 + // InClusterClient talks to the Kubernetes API server from inside the cluster 28 + // using the pod's mounted service-account credentials. 29 + type InClusterClient struct { 30 + baseURL string 31 + token string 32 + http *http.Client 33 + } 34 + 35 + var _ Client = (*InClusterClient)(nil) 36 + 37 + // NewInClusterClient loads the conventional in-cluster service-account files and 38 + // builds an HTTPS client pinned to the cluster CA. 39 + func NewInClusterClient() (*InClusterClient, error) { 40 + host := os.Getenv("KUBERNETES_SERVICE_HOST") 41 + port := os.Getenv("KUBERNETES_SERVICE_PORT_HTTPS") 42 + if port == "" { 43 + port = os.Getenv("KUBERNETES_SERVICE_PORT") 44 + } 45 + if host == "" || port == "" { 46 + return nil, fmt.Errorf( 47 + "kubernetes service env is incomplete: host=%q port=%q", 48 + host, port, 49 + ) 50 + } 51 + 52 + token, err := os.ReadFile(serviceTokenPath) 53 + if err != nil { 54 + return nil, fmt.Errorf("read service-account token: %w", err) 55 + } 56 + caPEM, err := os.ReadFile(serviceAccountCA) 57 + if err != nil { 58 + return nil, fmt.Errorf("read service-account CA: %w", err) 59 + } 60 + 61 + roots := x509.NewCertPool() 62 + if !roots.AppendCertsFromPEM(caPEM) { 63 + return nil, fmt.Errorf("parse service-account CA: no certificates found") 64 + } 65 + 66 + transport := http.DefaultTransport.(*http.Transport).Clone() 67 + transport.TLSClientConfig = &tls.Config{RootCAs: roots} 68 + 69 + return newClient( 70 + fmt.Sprintf("https://%s:%s", host, port), 71 + strings.TrimSpace(string(token)), 72 + &http.Client{Transport: transport}, 73 + ), nil 74 + } 75 + 76 + func newClient(baseURL, token string, httpClient *http.Client) *InClusterClient { 77 + return &InClusterClient{ 78 + baseURL: strings.TrimRight(baseURL, "/"), 79 + token: token, 80 + http: httpClient, 81 + } 82 + } 83 + 84 + func (c *InClusterClient) CreateObject( 85 + ctx context.Context, 86 + gvr GVR, 87 + namespace string, 88 + obj Object, 89 + ) (Object, error) { 90 + body, err := json.Marshal(obj) 91 + if err != nil { 92 + return nil, fmt.Errorf("marshal object: %w", err) 93 + } 94 + resp, err := c.do(ctx, http.MethodPost, resourcePath(gvr, namespace, ""), 95 + nil, bytes.NewReader(body), "application/json") 96 + if err != nil { 97 + return nil, err 98 + } 99 + defer resp.Body.Close() 100 + 101 + var out map[string]any 102 + if err := json.NewDecoder(resp.Body).Decode(&out); err != nil { 103 + return nil, fmt.Errorf("decode created object: %w", err) 104 + } 105 + return Object(out), nil 106 + } 107 + 108 + func (c *InClusterClient) GetObject( 109 + ctx context.Context, 110 + gvr GVR, 111 + namespace string, 112 + name string, 113 + ) (Object, error) { 114 + resp, err := c.do(ctx, http.MethodGet, resourcePath(gvr, namespace, name), 115 + nil, nil, "") 116 + if err != nil { 117 + return nil, err 118 + } 119 + defer resp.Body.Close() 120 + 121 + var out map[string]any 122 + if err := json.NewDecoder(resp.Body).Decode(&out); err != nil { 123 + return nil, fmt.Errorf("decode object: %w", err) 124 + } 125 + return Object(out), nil 126 + } 127 + 128 + func (c *InClusterClient) ListObjects( 129 + ctx context.Context, 130 + gvr GVR, 131 + namespace string, 132 + opts ListOptions, 133 + ) ([]Object, error) { 134 + resp, err := c.do(ctx, http.MethodGet, resourcePath(gvr, namespace, ""), 135 + listQuery(opts), nil, "") 136 + if err != nil { 137 + return nil, err 138 + } 139 + defer resp.Body.Close() 140 + 141 + var out struct { 142 + Items []map[string]any `json:"items"` 143 + } 144 + if err := json.NewDecoder(resp.Body).Decode(&out); err != nil { 145 + return nil, fmt.Errorf("decode object list: %w", err) 146 + } 147 + items := make([]Object, 0, len(out.Items)) 148 + for _, item := range out.Items { 149 + items = append(items, Object(item)) 150 + } 151 + return items, nil 152 + } 153 + 154 + func (c *InClusterClient) WatchObjects( 155 + ctx context.Context, 156 + gvr GVR, 157 + namespace string, 158 + opts ListOptions, 159 + ) (WatchInterface, error) { 160 + watchCtx, cancel := context.WithCancel(ctx) 161 + query := listQuery(opts) 162 + query.Set("watch", "1") 163 + 164 + resp, err := c.do(watchCtx, http.MethodGet, 165 + resourcePath(gvr, namespace, ""), query, nil, "") 166 + if err != nil { 167 + cancel() 168 + return nil, err 169 + } 170 + 171 + w := &httpWatch{ 172 + ch: make(chan WatchEvent), 173 + cancel: cancel, 174 + } 175 + go w.run(watchCtx, resp) 176 + return w, nil 177 + } 178 + 179 + func (c *InClusterClient) ListPods( 180 + ctx context.Context, 181 + namespace string, 182 + labelSelector string, 183 + ) ([]Pod, error) { 184 + query := url.Values{} 185 + if labelSelector != "" { 186 + query.Set("labelSelector", labelSelector) 187 + } 188 + resp, err := c.do(ctx, http.MethodGet, coreResourcePath(namespace, podsResource, "", ""), 189 + query, nil, "") 190 + if err != nil { 191 + return nil, err 192 + } 193 + defer resp.Body.Close() 194 + 195 + var out struct { 196 + Items []struct { 197 + Metadata struct { 198 + Name string `json:"name"` 199 + Namespace string `json:"namespace"` 200 + UID string `json:"uid"` 201 + Labels map[string]string `json:"labels"` 202 + CreationTimestamp time.Time `json:"creationTimestamp"` 203 + } `json:"metadata"` 204 + Spec struct { 205 + InitContainers []struct { 206 + Name string `json:"name"` 207 + } `json:"initContainers"` 208 + Containers []struct { 209 + Name string `json:"name"` 210 + } `json:"containers"` 211 + } `json:"spec"` 212 + } `json:"items"` 213 + } 214 + if err := json.NewDecoder(resp.Body).Decode(&out); err != nil { 215 + return nil, fmt.Errorf("decode pod list: %w", err) 216 + } 217 + 218 + pods := make([]Pod, 0, len(out.Items)) 219 + for _, item := range out.Items { 220 + pod := Pod{ 221 + Name: item.Metadata.Name, 222 + Namespace: item.Metadata.Namespace, 223 + UID: item.Metadata.UID, 224 + Labels: cloneLabels(item.Metadata.Labels), 225 + CreationTimestamp: item.Metadata.CreationTimestamp, 226 + InitContainers: make([]Container, 0, len(item.Spec.InitContainers)), 227 + Containers: make([]Container, 0, len(item.Spec.Containers)), 228 + } 229 + for _, container := range item.Spec.InitContainers { 230 + pod.InitContainers = append(pod.InitContainers, Container{Name: container.Name}) 231 + } 232 + for _, container := range item.Spec.Containers { 233 + pod.Containers = append(pod.Containers, Container{Name: container.Name}) 234 + } 235 + pods = append(pods, pod) 236 + } 237 + return pods, nil 238 + } 239 + 240 + func (c *InClusterClient) StreamPodLogs( 241 + ctx context.Context, 242 + namespace string, 243 + podName string, 244 + container string, 245 + ) (io.ReadCloser, error) { 246 + query := url.Values{} 247 + if container != "" { 248 + query.Set("container", container) 249 + } 250 + resp, err := c.do(ctx, http.MethodGet, 251 + coreResourcePath(namespace, podsResource, podName, podLogsSubresource), 252 + query, nil, "") 253 + if err != nil { 254 + return nil, err 255 + } 256 + return resp.Body, nil 257 + } 258 + 259 + func (c *InClusterClient) do( 260 + ctx context.Context, 261 + method string, 262 + path string, 263 + query url.Values, 264 + body io.Reader, 265 + contentType string, 266 + ) (*http.Response, error) { 267 + uri := c.baseURL + path 268 + if encoded := query.Encode(); encoded != "" { 269 + uri += "?" + encoded 270 + } 271 + 272 + req, err := http.NewRequestWithContext(ctx, method, uri, body) 273 + if err != nil { 274 + return nil, fmt.Errorf("build request: %w", err) 275 + } 276 + req.Header.Set("Authorization", "Bearer "+c.token) 277 + if contentType != "" { 278 + req.Header.Set("Content-Type", contentType) 279 + } 280 + 281 + resp, err := c.http.Do(req) 282 + if err != nil { 283 + return nil, fmt.Errorf("request %s %s: %w", method, path, err) 284 + } 285 + if resp.StatusCode >= 200 && resp.StatusCode < 300 { 286 + return resp, nil 287 + } 288 + defer resp.Body.Close() 289 + raw, _ := io.ReadAll(io.LimitReader(resp.Body, 4096)) 290 + bodyText := strings.TrimSpace(string(raw)) 291 + switch resp.StatusCode { 292 + case http.StatusNotFound: 293 + return nil, fmt.Errorf("%w: %s %s: %s", ErrNotFound, method, path, bodyText) 294 + case http.StatusConflict: 295 + return nil, fmt.Errorf("%w: %s %s: %s", ErrAlreadyExists, method, path, bodyText) 296 + default: 297 + return nil, fmt.Errorf("k8s api %s %s: status %d: %s", 298 + method, path, resp.StatusCode, bodyText, 299 + ) 300 + } 301 + } 302 + 303 + func listQuery(opts ListOptions) url.Values { 304 + query := url.Values{} 305 + if opts.LabelSelector != "" { 306 + query.Set("labelSelector", opts.LabelSelector) 307 + } 308 + if opts.FieldSelector != "" { 309 + query.Set("fieldSelector", opts.FieldSelector) 310 + } 311 + return query 312 + } 313 + 314 + func resourcePath(gvr GVR, namespace, name string) string { 315 + prefix := "/apis/" + url.PathEscape(gvr.Group) + "/" + url.PathEscape(gvr.Version) 316 + if gvr.Group == "" { 317 + prefix = "/api/" + url.PathEscape(gvr.Version) 318 + } 319 + path := prefix 320 + if namespace != "" { 321 + path += "/namespaces/" + url.PathEscape(namespace) 322 + } 323 + path += "/" + url.PathEscape(gvr.Resource) 324 + if name != "" { 325 + path += "/" + url.PathEscape(name) 326 + } 327 + return path 328 + } 329 + 330 + func coreResourcePath(namespace, resource, name, subresource string) string { 331 + path := "/api/v1" 332 + if namespace != "" { 333 + path += "/namespaces/" + url.PathEscape(namespace) 334 + } 335 + path += "/" + url.PathEscape(resource) 336 + if name != "" { 337 + path += "/" + url.PathEscape(name) 338 + } 339 + if subresource != "" { 340 + path += "/" + url.PathEscape(subresource) 341 + } 342 + return path 343 + } 344 + 345 + func cloneLabels(in map[string]string) map[string]string { 346 + if len(in) == 0 { 347 + return nil 348 + } 349 + out := make(map[string]string, len(in)) 350 + for key, value := range in { 351 + out[key] = value 352 + } 353 + return out 354 + } 355 + 356 + type httpWatch struct { 357 + ch chan WatchEvent 358 + cancel context.CancelFunc 359 + once sync.Once 360 + } 361 + 362 + var _ WatchInterface = (*httpWatch)(nil) 363 + 364 + func (w *httpWatch) ResultChan() <-chan WatchEvent { 365 + return w.ch 366 + } 367 + 368 + func (w *httpWatch) Stop() { 369 + w.close() 370 + } 371 + 372 + func (w *httpWatch) run(ctx context.Context, resp *http.Response) { 373 + defer resp.Body.Close() 374 + defer w.close() 375 + 376 + dec := json.NewDecoder(resp.Body) 377 + for { 378 + var event struct { 379 + Type string `json:"type"` 380 + Object map[string]any `json:"object"` 381 + } 382 + if err := dec.Decode(&event); err != nil { 383 + if err == io.EOF || ctx.Err() != nil { 384 + return 385 + } 386 + return 387 + } 388 + 389 + select { 390 + case w.ch <- WatchEvent{Type: event.Type, Object: Object(event.Object)}: 391 + case <-ctx.Done(): 392 + return 393 + } 394 + } 395 + } 396 + 397 + func (w *httpWatch) close() { 398 + w.once.Do(func() { 399 + w.cancel() 400 + close(w.ch) 401 + }) 402 + }
+309
internal/k8s/k8s.go
··· 1 + package k8s 2 + 3 + // Package k8s exposes the tiny slice of the Kubernetes API tack's Tekton 4 + // provider actually needs. The goal is to keep Tekton support in-process 5 + // without dragging the full client-go stack into the module graph. 6 + 7 + import ( 8 + "context" 9 + "errors" 10 + "io" 11 + "time" 12 + ) 13 + 14 + // ErrNotFound mirrors the API server's 404 in a way callers can branch on with 15 + // errors.Is instead of inspecting status codes or response bodies. 16 + var ErrNotFound = errors.New("k8s: not found") 17 + 18 + // ErrAlreadyExists mirrors the API server's 409 for create calls whose name is 19 + // already present. 20 + var ErrAlreadyExists = errors.New("k8s: already exists") 21 + 22 + // Client is the minimal Kubernetes surface tack needs today: CRUD-ish access to 23 + // arbitrary JSON objects, plus pod listing and log streaming. 24 + type Client interface { 25 + CreateObject( 26 + ctx context.Context, 27 + gvr GVR, 28 + namespace string, 29 + obj Object, 30 + ) (Object, error) 31 + 32 + GetObject( 33 + ctx context.Context, 34 + gvr GVR, 35 + namespace string, 36 + name string, 37 + ) (Object, error) 38 + 39 + ListObjects( 40 + ctx context.Context, 41 + gvr GVR, 42 + namespace string, 43 + opts ListOptions, 44 + ) ([]Object, error) 45 + 46 + WatchObjects( 47 + ctx context.Context, 48 + gvr GVR, 49 + namespace string, 50 + opts ListOptions, 51 + ) (WatchInterface, error) 52 + 53 + ListPods( 54 + ctx context.Context, 55 + namespace string, 56 + labelSelector string, 57 + ) ([]Pod, error) 58 + 59 + StreamPodLogs( 60 + ctx context.Context, 61 + namespace string, 62 + podName string, 63 + container string, 64 + ) (io.ReadCloser, error) 65 + } 66 + 67 + // GVR identifies a Kubernetes resource by the path segments the API server 68 + // routes on. 69 + type GVR struct { 70 + Group string 71 + Version string 72 + Resource string 73 + } 74 + 75 + // ListOptions is the subset of query options tack currently uses. 76 + type ListOptions struct { 77 + LabelSelector string 78 + FieldSelector string 79 + } 80 + 81 + // WatchInterface matches the shape provider code already expects from a watch: 82 + // a receive-only event channel and an explicit stop hook. 83 + type WatchInterface interface { 84 + ResultChan() <-chan WatchEvent 85 + Stop() 86 + } 87 + 88 + // WatchEvent mirrors the API server's streaming watch envelope. 89 + type WatchEvent struct { 90 + Type string 91 + Object Object 92 + } 93 + 94 + // Object is an arbitrary Kubernetes resource decoded from JSON. 95 + type Object map[string]any 96 + 97 + // DeepCopy returns a recursive copy so callers can safely mutate the returned 98 + // object without aliasing shared test fixtures or cached state. 99 + func (o Object) DeepCopy() Object { 100 + if o == nil { 101 + return nil 102 + } 103 + return Object(deepCopyMap(map[string]any(o))) 104 + } 105 + 106 + // GetName returns metadata.name, or the empty string when absent. 107 + func (o Object) GetName() string { 108 + v, _ := NestedString(map[string]any(o), "metadata", "name") 109 + return v 110 + } 111 + 112 + // GetNamespace returns metadata.namespace, or the empty string when absent. 113 + func (o Object) GetNamespace() string { 114 + v, _ := NestedString(map[string]any(o), "metadata", "namespace") 115 + return v 116 + } 117 + 118 + // GetAPIVersion returns apiVersion, or the empty string when absent. 119 + func (o Object) GetAPIVersion() string { 120 + v, _ := NestedString(map[string]any(o), "apiVersion") 121 + return v 122 + } 123 + 124 + // GetKind returns kind, or the empty string when absent. 125 + func (o Object) GetKind() string { 126 + v, _ := NestedString(map[string]any(o), "kind") 127 + return v 128 + } 129 + 130 + // GetUID returns metadata.uid, or the empty string when absent. 131 + func (o Object) GetUID() string { 132 + v, _ := NestedString(map[string]any(o), "metadata", "uid") 133 + return v 134 + } 135 + 136 + // SetUID writes metadata.uid, creating metadata as needed. 137 + func (o Object) SetUID(uid string) { 138 + meta := ensureNestedMap(o, "metadata") 139 + meta["uid"] = uid 140 + } 141 + 142 + // SetCreationTimestamp writes metadata.creationTimestamp in UTC RFC3339 form. 143 + func (o Object) SetCreationTimestamp(ts time.Time) { 144 + meta := ensureNestedMap(o, "metadata") 145 + meta["creationTimestamp"] = ts.UTC().Format(time.RFC3339Nano) 146 + } 147 + 148 + // GetCreationTimestamp returns metadata.creationTimestamp, or the zero time when 149 + // the field is missing or malformed. 150 + func (o Object) GetCreationTimestamp() time.Time { 151 + raw, ok := NestedString(map[string]any(o), "metadata", "creationTimestamp") 152 + if !ok || raw == "" { 153 + return time.Time{} 154 + } 155 + for _, layout := range []string{time.RFC3339Nano, time.RFC3339} { 156 + if ts, err := time.Parse(layout, raw); err == nil { 157 + return ts 158 + } 159 + } 160 + return time.Time{} 161 + } 162 + 163 + // GetLabels returns metadata.labels as a string map. Non-string label values are 164 + // ignored because Kubernetes labels are strings on the wire. 165 + func (o Object) GetLabels() map[string]string { 166 + raw, ok := NestedMap(map[string]any(o), "metadata", "labels") 167 + if !ok { 168 + return nil 169 + } 170 + out := make(map[string]string, len(raw)) 171 + for key, value := range raw { 172 + if s, ok := value.(string); ok { 173 + out[key] = s 174 + } 175 + } 176 + return out 177 + } 178 + 179 + // GetAnnotations returns metadata.annotations as a string map. 180 + func (o Object) GetAnnotations() map[string]string { 181 + raw, ok := NestedMap(map[string]any(o), "metadata", "annotations") 182 + if !ok { 183 + return nil 184 + } 185 + out := make(map[string]string, len(raw)) 186 + for key, value := range raw { 187 + if s, ok := value.(string); ok { 188 + out[key] = s 189 + } 190 + } 191 + return out 192 + } 193 + 194 + // NestedString returns a nested string field from the object. 195 + func (o Object) NestedString(fields ...string) (string, bool) { 196 + return NestedString(map[string]any(o), fields...) 197 + } 198 + 199 + // NestedSlice returns a nested slice field from the object. 200 + func (o Object) NestedSlice(fields ...string) ([]any, bool) { 201 + return NestedSlice(map[string]any(o), fields...) 202 + } 203 + 204 + // NestedMap returns a nested map field from the object. 205 + func (o Object) NestedMap(fields ...string) (map[string]any, bool) { 206 + return NestedMap(map[string]any(o), fields...) 207 + } 208 + 209 + // NestedString returns a nested string field from obj. 210 + func NestedString(obj map[string]any, fields ...string) (string, bool) { 211 + value, ok := nestedValue(obj, fields...) 212 + if !ok { 213 + return "", false 214 + } 215 + s, ok := value.(string) 216 + return s, ok 217 + } 218 + 219 + // NestedSlice returns a nested slice field from obj. 220 + func NestedSlice(obj map[string]any, fields ...string) ([]any, bool) { 221 + value, ok := nestedValue(obj, fields...) 222 + if !ok { 223 + return nil, false 224 + } 225 + slice, ok := value.([]any) 226 + return slice, ok 227 + } 228 + 229 + // NestedMap returns a nested map field from obj. 230 + func NestedMap(obj map[string]any, fields ...string) (map[string]any, bool) { 231 + value, ok := nestedValue(obj, fields...) 232 + if !ok { 233 + return nil, false 234 + } 235 + m, ok := value.(map[string]any) 236 + return m, ok 237 + } 238 + 239 + // Container is the small slice of a pod container spec tack cares about for 240 + // log streaming. 241 + type Container struct { 242 + Name string 243 + } 244 + 245 + // Pod is the reduced pod shape tack uses to order containers and request logs. 246 + type Pod struct { 247 + Name string 248 + Namespace string 249 + UID string 250 + Labels map[string]string 251 + CreationTimestamp time.Time 252 + InitContainers []Container 253 + Containers []Container 254 + } 255 + 256 + func nestedValue(obj map[string]any, fields ...string) (any, bool) { 257 + current := any(obj) 258 + for _, field := range fields { 259 + m, ok := current.(map[string]any) 260 + if !ok { 261 + return nil, false 262 + } 263 + current, ok = m[field] 264 + if !ok { 265 + return nil, false 266 + } 267 + } 268 + return current, true 269 + } 270 + 271 + func ensureNestedMap(obj map[string]any, fields ...string) map[string]any { 272 + current := obj 273 + for _, field := range fields { 274 + next, ok := current[field].(map[string]any) 275 + if !ok { 276 + next = map[string]any{} 277 + current[field] = next 278 + } 279 + current = next 280 + } 281 + return current 282 + } 283 + 284 + func deepCopyMap(in map[string]any) map[string]any { 285 + out := make(map[string]any, len(in)) 286 + for key, value := range in { 287 + out[key] = deepCopyValue(value) 288 + } 289 + return out 290 + } 291 + 292 + func deepCopySlice(in []any) []any { 293 + out := make([]any, len(in)) 294 + for i, value := range in { 295 + out[i] = deepCopyValue(value) 296 + } 297 + return out 298 + } 299 + 300 + func deepCopyValue(value any) any { 301 + switch v := value.(type) { 302 + case map[string]any: 303 + return deepCopyMap(v) 304 + case []any: 305 + return deepCopySlice(v) 306 + default: 307 + return v 308 + } 309 + }
+95 -113
provider_tekton.go
··· 20 20 "time" 21 21 "unicode" 22 22 23 - corev1 "k8s.io/api/core/v1" 24 - apierrors "k8s.io/apimachinery/pkg/api/errors" 25 - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 27 - "k8s.io/apimachinery/pkg/fields" 28 - "k8s.io/apimachinery/pkg/labels" 29 - runtimeschema "k8s.io/apimachinery/pkg/runtime/schema" 30 - "k8s.io/client-go/dynamic" 31 - "k8s.io/client-go/kubernetes" 32 - "k8s.io/client-go/rest" 33 23 "tangled.org/core/api/tangled" 34 24 25 + "go.mitchellh.com/tack/internal/k8s" 35 26 "go.yaml.in/yaml/v2" 36 27 ) 37 28 ··· 52 43 ) 53 44 54 45 var ( 55 - pipelineRunsGVR = runtimeschema.GroupVersionResource{ 46 + pipelineRunsGVR = k8s.GVR{ 56 47 Group: "tekton.dev", Version: "v1", Resource: "pipelineruns", 57 48 } 58 - taskRunsGVR = runtimeschema.GroupVersionResource{ 49 + taskRunsGVR = k8s.GVR{ 59 50 Group: "tekton.dev", Version: "v1", Resource: "taskruns", 60 51 } 61 52 ) ··· 97 88 br *broker 98 89 st *store 99 90 log *slog.Logger 100 - dyn dynamic.Interface 101 - kube kubernetes.Interface 91 + client k8s.Client 102 92 namespace string 103 93 } 104 94 ··· 107 97 func newTektonProvider( 108 98 br *broker, 109 99 st *store, 110 - dyn dynamic.Interface, 111 - kube kubernetes.Interface, 100 + client k8s.Client, 112 101 namespace string, 113 102 log *slog.Logger, 114 103 ) *tektonProvider { ··· 116 105 br: br, 117 106 st: st, 118 107 log: log.With("component", "provider", "kind", "tekton"), 119 - dyn: dyn, 120 - kube: kube, 108 + client: client, 121 109 namespace: namespace, 122 110 } 123 111 } ··· 128 116 namespace string, 129 117 log *slog.Logger, 130 118 ) (*tektonProvider, error) { 131 - cfg, err := rest.InClusterConfig() 132 - if err != nil { 133 - return nil, fmt.Errorf("load in-cluster kubernetes config: %w", err) 134 - } 135 - dyn, err := dynamic.NewForConfig(cfg) 136 - if err != nil { 137 - return nil, fmt.Errorf("create dynamic kubernetes client: %w", err) 138 - } 139 - kube, err := kubernetes.NewForConfig(cfg) 119 + client, err := k8s.NewInClusterClient() 140 120 if err != nil { 141 - return nil, fmt.Errorf("create kubernetes client: %w", err) 121 + return nil, fmt.Errorf("configure in-cluster kubernetes client: %w", err) 142 122 } 143 - return newTektonProvider(br, st, dyn, kube, namespace, log), nil 123 + return newTektonProvider(br, st, client, namespace, log), nil 144 124 } 145 125 146 126 func (p *tektonProvider) Spawn( ··· 192 172 p.namespace, name, cfg, knot, pipelineRkey, actor, commit, branch, wf, 193 173 ) 194 174 195 - runs := p.dyn.Resource(pipelineRunsGVR).Namespace(p.namespace) 196 - created, err := runs.Create(ctx, pr, metav1.CreateOptions{}) 197 - if apierrors.IsAlreadyExists(err) { 198 - created, err = runs.Get(ctx, name, metav1.GetOptions{}) 175 + created, err := p.client.CreateObject(ctx, pipelineRunsGVR, p.namespace, pr) 176 + if errors.Is(err, k8s.ErrAlreadyExists) { 177 + created, err = p.client.GetObject(ctx, pipelineRunsGVR, p.namespace, name) 199 178 } 200 179 if err != nil { 201 180 logger.Error("create tekton PipelineRun", "err", err, ··· 211 190 Workflow: wf.Name, 212 191 Namespace: p.namespace, 213 192 PipelineRunName: name, 214 - PipelineRunUID: string(created.GetUID()), 193 + PipelineRunUID: created.GetUID(), 215 194 PipelineName: cfg.Pipeline, 216 195 PipelineURI: pipelineATURI(knot, pipelineRkey), 217 196 } ··· 241 220 cfg *tektonWorkflowConfig, 242 221 knot, pipelineRkey, actor, commit, branch string, 243 222 wf *tangled.Pipeline_Workflow, 244 - ) *unstructured.Unstructured { 245 - obj := &unstructured.Unstructured{ 246 - Object: map[string]interface{}{ 247 - "apiVersion": tektonAPIVersion, 248 - "kind": tektonRunKind, 249 - "metadata": map[string]interface{}{ 250 - "name": name, 251 - "namespace": namespace, 252 - "labels": map[string]interface{}{ 253 - tektonLabelManagedBy: "tack", 254 - tektonLabelPipelineRkey: labelValue(pipelineRkey), 255 - tektonLabelWorkflow: labelValue(wf.Name), 256 - }, 257 - "annotations": map[string]interface{}{ 258 - tektonAnnotationKnot: knot, 259 - tektonAnnotationPipelineRkey: pipelineRkey, 260 - tektonAnnotationWorkflow: wf.Name, 261 - tektonAnnotationActor: actor, 262 - tektonAnnotationCommit: commit, 263 - tektonAnnotationBranch: branch, 264 - }, 223 + ) k8s.Object { 224 + obj := k8s.Object{ 225 + "apiVersion": tektonAPIVersion, 226 + "kind": tektonRunKind, 227 + "metadata": map[string]any{ 228 + "name": name, 229 + "namespace": namespace, 230 + "labels": map[string]any{ 231 + tektonLabelManagedBy: "tack", 232 + tektonLabelPipelineRkey: labelValue(pipelineRkey), 233 + tektonLabelWorkflow: labelValue(wf.Name), 265 234 }, 266 - "spec": map[string]interface{}{ 267 - "pipelineRef": map[string]interface{}{ 268 - "name": cfg.Pipeline, 269 - }, 235 + "annotations": map[string]any{ 236 + tektonAnnotationKnot: knot, 237 + tektonAnnotationPipelineRkey: pipelineRkey, 238 + tektonAnnotationWorkflow: wf.Name, 239 + tektonAnnotationActor: actor, 240 + tektonAnnotationCommit: commit, 241 + tektonAnnotationBranch: branch, 242 + }, 243 + }, 244 + "spec": map[string]any{ 245 + "pipelineRef": map[string]any{ 246 + "name": cfg.Pipeline, 270 247 }, 271 248 }, 272 249 } 273 - spec := obj.Object["spec"].(map[string]interface{}) 250 + spec := obj["spec"].(map[string]any) 274 251 if cfg.ServiceAccount != "" { 275 252 spec["serviceAccountName"] = cfg.ServiceAccount 276 253 } ··· 280 257 keys = append(keys, key) 281 258 } 282 259 sort.Strings(keys) 283 - params := make([]interface{}, 0, len(keys)) 260 + params := make([]any, 0, len(keys)) 284 261 for _, key := range keys { 285 - params = append(params, map[string]interface{}{ 262 + params = append(params, map[string]any{ 286 263 "name": key, 287 264 "value": cfg.Params[key], 288 265 }) ··· 304 281 logger.Debug("watchPipelineRun: starting") 305 282 306 283 last := "" 307 - if obj, err := p.dyn.Resource(pipelineRunsGVR).Namespace(ref.Namespace). 308 - Get(ctx, ref.PipelineRunName, metav1.GetOptions{}); err == nil { 284 + if obj, err := p.client.GetObject(ctx, pipelineRunsGVR, ref.Namespace, 285 + ref.PipelineRunName); err == nil { 309 286 status, terminal, ok := mapTektonPipelineRunStatus(obj) 310 287 logger.Debug("watchPipelineRun: initial status read", 311 288 "status", status, "terminal", terminal, "ok", ok, ··· 321 298 return 322 299 } 323 300 } 324 - } else if apierrors.IsNotFound(err) { 301 + } else if errors.Is(err, k8s.ErrNotFound) { 325 302 logger.Warn("PipelineRun disappeared while watching") 326 303 return 327 304 } else { 328 305 logger.Debug("initial PipelineRun status read", "err", err) 329 306 } 330 307 331 - w, err := p.dyn.Resource(pipelineRunsGVR).Namespace(ref.Namespace). 332 - Watch(ctx, metav1.ListOptions{ 333 - FieldSelector: fields.OneTermEqualSelector( 334 - "metadata.name", ref.PipelineRunName, 335 - ).String(), 336 - }) 308 + w, err := p.client.WatchObjects(ctx, pipelineRunsGVR, ref.Namespace, 309 + k8s.ListOptions{FieldSelector: "metadata.name=" + ref.PipelineRunName}, 310 + ) 337 311 if err != nil { 338 312 logger.Debug("watchPipelineRun: watch failed; falling back to polling", "err", err) 339 313 p.pollPipelineRun(ctx, ref, logger, last) ··· 353 327 p.pollPipelineRun(ctx, ref, logger, last) 354 328 return 355 329 } 356 - obj, ok := ev.Object.(*unstructured.Unstructured) 357 - if !ok { 358 - logger.Debug("watchPipelineRun: non-Unstructured event object", "type", fmt.Sprintf("%T", ev.Object)) 359 - continue 360 - } 361 - status, terminal, ok := mapTektonPipelineRunStatus(obj) 330 + status, terminal, ok := mapTektonPipelineRunStatus(ev.Object) 362 331 logger.Debug("watchPipelineRun: watch event", 363 332 "event_type", ev.Type, 364 333 "status", status, "terminal", terminal, "ok", ok, "last", last, ··· 400 369 logger.Debug("pollPipelineRun: context cancelled") 401 370 return 402 371 case <-ticker.C: 403 - obj, err := p.dyn.Resource(pipelineRunsGVR).Namespace(ref.Namespace). 404 - Get(ctx, ref.PipelineRunName, metav1.GetOptions{}) 405 - if apierrors.IsNotFound(err) { 372 + obj, err := p.client.GetObject(ctx, pipelineRunsGVR, ref.Namespace, 373 + ref.PipelineRunName, 374 + ) 375 + if errors.Is(err, k8s.ErrNotFound) { 406 376 logger.Warn("PipelineRun disappeared while watching") 407 377 return 408 378 } ··· 438 408 439 409 // mapTektonPipelineRunStatus translates Tekton's Succeeded condition 440 410 // into the Tangled status strings consumed by the appview. 441 - func mapTektonPipelineRunStatus(obj *unstructured.Unstructured) (status string, terminal bool, ok bool) { 442 - conditions, ok, _ := unstructured.NestedSlice(obj.Object, "status", "conditions") 411 + func mapTektonPipelineRunStatus(obj k8s.Object) (status string, terminal bool, ok bool) { 412 + conditions, ok := obj.NestedSlice("status", "conditions") 443 413 if !ok || len(conditions) == 0 { 444 414 slog.Debug("mapTektonPipelineRunStatus: no conditions found", 445 415 "pipeline_run", obj.GetName(), ··· 557 527 558 528 // isPipelineRunTerminal returns true if the PipelineRun is in a terminal state right now. 559 529 func (p *tektonProvider) isPipelineRunTerminal(ctx context.Context, ref TektonRunRef) bool { 560 - obj, err := p.dyn.Resource(pipelineRunsGVR).Namespace(ref.Namespace). 561 - Get(ctx, ref.PipelineRunName, metav1.GetOptions{}) 530 + obj, err := p.client.GetObject(ctx, pipelineRunsGVR, ref.Namespace, 531 + ref.PipelineRunName, 532 + ) 562 533 if err != nil { 563 534 p.log.Debug("isPipelineRunTerminal: failed to get PipelineRun", "err", err, "pipeline_run", ref.PipelineRunName) 564 535 return false ··· 576 547 ctx context.Context, 577 548 out chan<- LogLine, 578 549 ref TektonRunRef, 579 - tr unstructured.Unstructured, 550 + tr k8s.Object, 580 551 stepID int, 581 552 ) { 582 553 trName := tr.GetName() ··· 593 564 594 565 // Emit a summary line from the TaskRun status (steps[*].terminated) so we 595 566 // get exit codes and reasons even if the pod logs are sparse. 596 - steps, _, _ := unstructured.NestedSlice(tr.Object, "status", "steps") 567 + steps, _ := tr.NestedSlice("status", "steps") 597 568 for _, rawStep := range steps { 598 - step, _ := rawStep.(map[string]interface{}) 569 + step, _ := rawStep.(map[string]any) 599 570 stepName, _ := step["name"].(string) 600 - term, _ := step["terminated"].(map[string]interface{}) 571 + term, _ := step["terminated"].(map[string]any) 601 572 if term == nil { 602 573 continue 603 574 } 604 - exitCode, _ := term["exitCode"].(int64) 575 + exitCode := numberToInt64(term["exitCode"]) 605 576 reason, _ := term["reason"].(string) 606 577 msg, _ := term["message"].(string) 607 578 line := fmt.Sprintf("[step %s] exit=%d reason=%s", stepName, exitCode, reason) ··· 624 595 } 625 596 626 597 for _, pod := range pods { 627 - containers := append(pod.Spec.InitContainers, pod.Spec.Containers...) 598 + containers := append([]k8s.Container(nil), pod.InitContainers...) 599 + containers = append(containers, pod.Containers...) 628 600 p.log.Debug("fetchCompletedTaskRunLogs: reading pod containers", 629 601 "pod", pod.Name, "container_count", len(containers), 630 602 ) ··· 632 604 p.log.Debug("fetchCompletedTaskRunLogs: reading container logs", 633 605 "pod", pod.Name, "container", c.Name, 634 606 ) 635 - req := p.kube.CoreV1().Pods(ref.Namespace).GetLogs(pod.Name, &corev1.PodLogOptions{ 636 - Container: c.Name, 637 - }) 638 - rc, err := req.Stream(ctx) 607 + rc, err := p.client.StreamPodLogs(ctx, ref.Namespace, pod.Name, c.Name) 639 608 if err != nil { 640 609 p.log.Debug("fetchCompletedTaskRunLogs: stream failed", "err", err, 641 610 "pod", pod.Name, "container", c.Name, ··· 651 620 } 652 621 } 653 622 654 - func (p *tektonProvider) taskRunsForPipelineRun(ctx context.Context, ref TektonRunRef) ([]unstructured.Unstructured, error) { 655 - sel := labels.Set{"tekton.dev/pipelineRun": ref.PipelineRunName}.String() 656 - list, err := p.dyn.Resource(taskRunsGVR).Namespace(ref.Namespace). 657 - List(ctx, metav1.ListOptions{LabelSelector: sel}) 623 + func (p *tektonProvider) taskRunsForPipelineRun(ctx context.Context, ref TektonRunRef) ([]k8s.Object, error) { 624 + list, err := p.client.ListObjects(ctx, taskRunsGVR, ref.Namespace, k8s.ListOptions{ 625 + LabelSelector: "tekton.dev/pipelineRun=" + ref.PipelineRunName, 626 + }) 658 627 if err != nil { 659 628 return nil, fmt.Errorf("list Tekton TaskRuns: %w", err) 660 629 } 661 - items := append([]unstructured.Unstructured(nil), list.Items...) 630 + items := append([]k8s.Object(nil), list...) 662 631 sort.Slice(items, func(i, j int) bool { 663 632 ti := items[i].GetCreationTimestamp() 664 633 tj := items[j].GetCreationTimestamp() 665 - return ti.Before(&tj) 634 + return ti.Before(tj) 666 635 }) 667 636 return items, nil 668 637 } ··· 671 640 ctx context.Context, 672 641 out chan<- LogLine, 673 642 ref TektonRunRef, 674 - tr unstructured.Unstructured, 643 + tr k8s.Object, 675 644 stepID int, 676 645 ) { 677 646 pods, err := p.podsForTaskRun(ctx, ref.Namespace, tr.GetName()) ··· 685 654 "task_run", tr.GetName(), "pod_count", len(pods), 686 655 ) 687 656 for _, pod := range pods { 688 - containers := append(pod.Spec.InitContainers, pod.Spec.Containers...) 657 + containers := append([]k8s.Container(nil), pod.InitContainers...) 658 + containers = append(containers, pod.Containers...) 689 659 p.log.Debug("streamTaskRunLogs: streaming pod containers", 690 660 "pod", pod.Name, "container_count", len(containers), 691 661 ) ··· 693 663 p.log.Debug("streamTaskRunLogs: streaming container", 694 664 "pod", pod.Name, "container", c.Name, "step_id", stepID, 695 665 ) 696 - req := p.kube.CoreV1().Pods(ref.Namespace).GetLogs(pod.Name, &corev1.PodLogOptions{ 697 - Container: c.Name, 698 - }) 699 - rc, err := req.Stream(ctx) 666 + rc, err := p.client.StreamPodLogs(ctx, ref.Namespace, pod.Name, c.Name) 700 667 if err != nil { 701 668 p.log.Debug("streamTaskRunLogs: stream pod logs failed", "err", err, 702 669 "pod", pod.Name, "container", c.Name, ··· 712 679 } 713 680 } 714 681 715 - func (p *tektonProvider) podsForTaskRun(ctx context.Context, namespace, taskRun string) ([]corev1.Pod, error) { 716 - sel := labels.Set{"tekton.dev/taskRun": taskRun}.String() 717 - list, err := p.kube.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{ 718 - LabelSelector: sel, 719 - }) 682 + func (p *tektonProvider) podsForTaskRun(ctx context.Context, namespace, taskRun string) ([]k8s.Pod, error) { 683 + list, err := p.client.ListPods(ctx, namespace, 684 + "tekton.dev/taskRun="+taskRun, 685 + ) 720 686 if err != nil { 721 687 return nil, fmt.Errorf("list pods: %w", err) 722 688 } 723 - pods := append([]corev1.Pod(nil), list.Items...) 689 + pods := append([]k8s.Pod(nil), list...) 724 690 sort.Slice(pods, func(i, j int) bool { 725 - return pods[i].CreationTimestamp.Before(&pods[j].CreationTimestamp) 691 + return pods[i].CreationTimestamp.Before(pods[j].CreationTimestamp) 726 692 }) 727 693 return pods, nil 728 694 } ··· 747 713 } 748 714 if err := scanner.Err(); err != nil { 749 715 p.log.Debug("scan pod log", "err", err) 716 + } 717 + } 718 + 719 + func numberToInt64(value any) int64 { 720 + switch v := value.(type) { 721 + case int64: 722 + return v 723 + case int: 724 + return int64(v) 725 + case float64: 726 + return int64(v) 727 + case json.Number: 728 + i, _ := v.Int64() 729 + return i 730 + default: 731 + return 0 750 732 } 751 733 } 752 734
+37 -61
provider_tekton_test.go
··· 8 8 "testing" 9 9 "time" 10 10 11 - corev1 "k8s.io/api/core/v1" 12 - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 14 - "k8s.io/apimachinery/pkg/runtime" 15 - runtimeschema "k8s.io/apimachinery/pkg/runtime/schema" 16 - dynamicfake "k8s.io/client-go/dynamic/fake" 17 - kubefake "k8s.io/client-go/kubernetes/fake" 18 11 "tangled.org/core/api/tangled" 12 + 13 + "go.mitchellh.com/tack/internal/k8s" 19 14 ) 20 15 21 - func newTektonTestProvider(t *testing.T, objs ...runtime.Object) (*tektonProvider, *store, *broker) { 16 + func newTektonTestProvider(t *testing.T) (*tektonProvider, *store, *broker, *k8s.FakeClient) { 22 17 t.Helper() 23 18 st := newTestStore(t) 24 19 br := newBroker(st) 25 - dyn := dynamicfake.NewSimpleDynamicClientWithCustomListKinds( 26 - runtime.NewScheme(), 27 - map[runtimeschema.GroupVersionResource]string{ 28 - pipelineRunsGVR: "PipelineRunList", 29 - taskRunsGVR: "TaskRunList", 30 - }, 31 - objs..., 32 - ) 33 - kube := kubefake.NewSimpleClientset() 34 - p := newTektonProvider(br, st, dyn, kube, "ci", slog.Default()) 35 - return p, st, br 20 + client := k8s.NewFakeClient() 21 + p := newTektonProvider(br, st, client, "ci", slog.Default()) 22 + return p, st, br, client 36 23 } 37 24 38 25 func TestTektonWorkflowConfig(t *testing.T) { ··· 73 60 if obj.GetAPIVersion() != tektonAPIVersion || obj.GetKind() != tektonRunKind { 74 61 t.Fatalf("type meta mismatch: %s %s", obj.GetAPIVersion(), obj.GetKind()) 75 62 } 76 - pipeline, _, _ := unstructured.NestedString(obj.Object, "spec", "pipelineRef", "name") 77 - if pipeline != "repo-ci" { 63 + pipeline, ok := obj.NestedString("spec", "pipelineRef", "name") 64 + if !ok || pipeline != "repo-ci" { 78 65 t.Fatalf("pipelineRef.name = %q", pipeline) 79 66 } 80 - sa, _, _ := unstructured.NestedString(obj.Object, "spec", "serviceAccountName") 81 - if sa != "runner" { 67 + sa, ok := obj.NestedString("spec", "serviceAccountName") 68 + if !ok || sa != "runner" { 82 69 t.Fatalf("serviceAccountName = %q", sa) 83 70 } 84 - params, _, _ := unstructured.NestedSlice(obj.Object, "spec", "params") 85 - if len(params) != 1 { 71 + params, ok := obj.NestedSlice("spec", "params") 72 + if !ok || len(params) != 1 { 86 73 t.Fatalf("params = %+v", params) 87 74 } 88 75 if obj.GetAnnotations()[tektonAnnotationActor] != "did:plc:actor" || ··· 119 106 } 120 107 121 108 func TestTektonSpawnCreatesPipelineRun(t *testing.T) { 122 - p, st, _ := newTektonTestProvider(t) 109 + p, st, _, client := newTektonTestProvider(t) 123 110 ctx, cancel := context.WithCancel(context.Background()) 124 111 defer cancel() 125 112 ··· 139 126 t.Fatalf("ref mismatch: %+v", ref) 140 127 } 141 128 142 - obj, err := p.dyn.Resource(pipelineRunsGVR).Namespace("ci"). 143 - Get(context.Background(), ref.PipelineRunName, metav1.GetOptions{}) 129 + obj, err := client.GetObject(context.Background(), pipelineRunsGVR, "ci", ref.PipelineRunName) 144 130 if err != nil { 145 131 t.Fatalf("get PipelineRun: %v", err) 146 132 } 147 - pipeline, _, _ := unstructured.NestedString(obj.Object, "spec", "pipelineRef", "name") 148 - if pipeline != "repo-ci" { 133 + pipeline, ok := obj.NestedString("spec", "pipelineRef", "name") 134 + if !ok || pipeline != "repo-ci" { 149 135 t.Fatalf("pipelineRef.name = %q", pipeline) 150 136 } 151 137 ··· 166 152 } 167 153 168 154 func TestTektonSpawnAlreadyExists(t *testing.T) { 155 + p, st, _, client := newTektonTestProvider(t) 169 156 name := tektonPipelineRunName("knot.example.com", "rkey-1", "ci.yml", "abcdef0123", "main") 170 157 existing := buildTektonPipelineRun("ci", name, 171 158 &tektonWorkflowConfig{Pipeline: "repo-ci"}, ··· 173 160 &tangled.Pipeline_Workflow{Name: "ci.yml"}, 174 161 ) 175 162 existing.SetUID("uid-1") 176 - p, st, _ := newTektonTestProvider(t, existing) 163 + client.SeedObject(pipelineRunsGVR, "ci", existing) 164 + 177 165 ctx, cancel := context.WithCancel(context.Background()) 178 166 defer cancel() 179 - 180 167 p.Spawn(ctx, "knot.example.com", "rkey-1", "did:plc:actor", 181 168 &tangled.Pipeline_TriggerMetadata{Push: &tangled.Pipeline_PushTriggerData{ 182 169 NewSha: "abcdef0123", ··· 193 180 } 194 181 195 182 func TestTektonLogsLookup(t *testing.T) { 196 - p, st, _ := newTektonTestProvider(t) 183 + p, st, _, client := newTektonTestProvider(t) 197 184 ctx := context.Background() 198 185 if _, err := p.Logs(ctx, "knot.example.com", "rkey-1", "ci.yml"); !errors.Is(err, ErrLogsNotFound) { 199 186 t.Fatalf("logs before mapping err = %v; want ErrLogsNotFound", err) ··· 215 202 t.Fatalf("logs before TaskRuns err = %v; want ErrLogsNotFound", err) 216 203 } 217 204 218 - taskRun := &unstructured.Unstructured{Object: map[string]interface{}{ 205 + client.SeedObject(taskRunsGVR, "ci", k8s.Object{ 219 206 "apiVersion": "tekton.dev/v1", 220 207 "kind": "TaskRun", 221 - "metadata": map[string]interface{}{ 208 + "metadata": map[string]any{ 222 209 "name": "task-1", 223 210 "namespace": "ci", 224 - "labels": map[string]interface{}{ 211 + "labels": map[string]any{ 225 212 "tekton.dev/pipelineRun": "run-1", 226 213 }, 227 214 }, 228 - }} 229 - _, err := p.dyn.Resource(taskRunsGVR).Namespace("ci"). 230 - Create(ctx, taskRun, metav1.CreateOptions{}) 231 - if err != nil { 232 - t.Fatalf("create TaskRun: %v", err) 233 - } 234 - _, err = p.kube.CoreV1().Pods("ci").Create(ctx, &corev1.Pod{ 235 - ObjectMeta: metav1.ObjectMeta{ 236 - Name: "pod-1", 237 - Namespace: "ci", 238 - Labels: map[string]string{ 239 - "tekton.dev/taskRun": "task-1", 240 - }, 215 + }) 216 + client.SeedPod("ci", k8s.Pod{ 217 + Name: "pod-1", 218 + Namespace: "ci", 219 + Labels: map[string]string{ 220 + "tekton.dev/taskRun": "task-1", 241 221 }, 242 - Spec: corev1.PodSpec{ 243 - Containers: []corev1.Container{{Name: "step-test", Image: "busybox"}}, 244 - }, 245 - }, metav1.CreateOptions{}) 246 - if err != nil { 247 - t.Fatalf("create pod: %v", err) 248 - } 222 + Containers: []k8s.Container{{Name: "step-test"}}, 223 + }) 224 + client.SetPodLog("ci", "pod-1", "step-test", "hello\n") 249 225 250 226 ch, err := p.Logs(ctx, "knot.example.com", "rkey-1", "ci.yml") 251 227 if err != nil { ··· 261 237 } 262 238 } 263 239 264 - func tektonStatusObject(condStatus, reason string) *unstructured.Unstructured { 265 - return &unstructured.Unstructured{Object: map[string]interface{}{ 266 - "status": map[string]interface{}{ 267 - "conditions": []interface{}{map[string]interface{}{ 240 + func tektonStatusObject(condStatus, reason string) k8s.Object { 241 + return k8s.Object{ 242 + "status": map[string]any{ 243 + "conditions": []any{map[string]any{ 268 244 "type": "Succeeded", 269 245 "status": condStatus, 270 246 "reason": reason, 271 247 }}, 272 248 }, 273 - }} 249 + } 274 250 } 275 251 276 252 func waitTektonRef(t *testing.T, st *store, knot, rkey, workflow string) *TektonRunRef {