From e927d39a278cca8b11b6f332e48986ca62f1fc0a Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 21 Jun 2022 12:33:50 +0300 Subject: [PATCH 01/32] Add OCI internal package Implement OCI artifacts operations using crane Signed-off-by: Stefan Prodan --- go.mod | 12 +- go.sum | 426 +++++++++++++++++++++++++++++++++++++++++- internal/oci/build.go | 139 ++++++++++++++ internal/oci/meta.go | 60 ++++++ internal/oci/pull.go | 75 ++++++++ internal/oci/push.go | 81 ++++++++ internal/oci/tag.go | 40 ++++ 7 files changed, 829 insertions(+), 4 deletions(-) create mode 100644 internal/oci/build.go create mode 100644 internal/oci/meta.go create mode 100644 internal/oci/pull.go create mode 100644 internal/oci/push.go create mode 100644 internal/oci/tag.go diff --git a/go.mod b/go.mod index 190a5ba006..cbd12b6125 100644 --- a/go.mod +++ b/go.mod @@ -72,8 +72,13 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect + github.com/containerd/stargz-snapshotter/estargz v0.11.4 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/docker/cli v20.10.16+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/docker/docker v20.10.16+incompatible // indirect + github.com/docker/docker-credential-helpers v0.6.4 // indirect github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 // indirect github.com/emicklei/go-restful v2.9.5+incompatible // indirect github.com/emirpasic/gods v1.12.0 // indirect @@ -115,6 +120,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/klauspost/compress v1.15.4 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 // indirect @@ -132,6 +138,8 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.12.1 // indirect @@ -139,10 +147,12 @@ require ( github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/russross/blackfriday v1.5.2 // indirect + github.com/russross/blackfriday v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect github.com/texttheater/golang-levenshtein v1.0.1 // indirect + github.com/vbatts/tar-split v0.11.2 // indirect github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect github.com/xanzy/go-gitlab v0.58.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect diff --git a/go.sum b/go.sum index 9998ddceff..e57cb655a7 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= +bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -11,6 +13,7 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= @@ -36,16 +39,22 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= +cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Antonboom/errname v0.1.5/go.mod h1:DugbBstvPFQbv/5uLcRRzfrNqKE9tVdVCqWCLp6Cifo= +github.com/Antonboom/nilnil v0.1.0/go.mod h1:PhHLvRPSghY5Y7mX4TW+BHZQYo1A8flE5H20D3IPZBo= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -63,14 +72,21 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= @@ -78,6 +94,7 @@ github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b h1:lcbBNuQhppsc7A5gjdHmdlqUqJfgGMylBdGyDs0j7G8= github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= @@ -85,6 +102,7 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -92,16 +110,28 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= +github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -112,7 +142,12 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec= +github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= +github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -122,6 +157,8 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= +github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= @@ -133,35 +170,59 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/containerd/stargz-snapshotter/estargz v0.11.4 h1:LjrYUZpyOhiSaU7hHrdR82/RBoxfGWSaC0VeSSMXqnk= +github.com/containerd/stargz-snapshotter/estargz v0.11.4/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/daixiang0/gci v0.2.9/go.mod h1:+4dZ7TISfSmqfAGv59ePaHfNzgGtIkHAhhdKggP1JAc= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61icFuZl6iKYs= +github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ= +github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -177,7 +238,10 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= +github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= @@ -186,8 +250,11 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwC github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluxcd/go-git-providers v0.6.0 h1:XJc3MTYFpuahBSoKTVxmH9OBPCeIyvYoQkTjTqa3fH4= github.com/fluxcd/go-git-providers v0.6.0/go.mod h1:UMFHnMCIO9CBpEln7ZsArEWyXSNxTpm76fyQxUmClrc= @@ -229,12 +296,15 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= @@ -262,6 +332,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -271,15 +343,35 @@ github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -295,6 +387,7 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -314,6 +407,16 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.43.0/go.mod h1:VIFlUqidx5ggxDfQagdvd9E67UjMXtTHBkBQ7sHoC5Q= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/gonvenience/bunt v1.3.4 h1:Row599Ohja2BPooaqd1tHYdTAKu6SWq7W/UeakTXddM= github.com/gonvenience/bunt v1.3.4/go.mod h1:j8eqHLBo8eWCCYuc34oFdlgyxL1rZ4ywYz4BZa4b09w= @@ -333,6 +436,8 @@ github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -369,6 +474,7 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -380,6 +486,9 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= +github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -389,53 +498,89 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= +github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= +github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= +github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= +github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= +github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= +github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/homeport/dyff v1.5.4 h1:v+C6EcBQYMWXfeDRPcQhImxQy0CdbRENWPEcHX39HJ0= github.com/homeport/dyff v1.5.4/go.mod h1:bWhjPpTUbco6MxEqTB5qrYtvX+Y59ZIPh9K1N4cUwh0= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= @@ -444,12 +589,23 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= +github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -457,15 +613,25 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.4 h1:1kn4/7MepF/CHmYub99/nNX8az0IJjfSOU/jbnTVfqQ= +github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -477,11 +643,25 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= +github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/ldez/tagliatelle v0.2.0/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= +github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -491,29 +671,54 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= -github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= +github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 h1:BXxTozrOU8zgC5dkpn3J6NTRdoP+hjok/e+ACr4Hibk= github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3/go.mod h1:x1uk6vxTiVuNt6S5R2UYgdhpj3oKojXvOXauHZ7dEnI= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.1.2/go.mod h1:bnXsMr+ZTH09V5rssEI+jHAZ4z+ZdyhgO/zsy3EhK+0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -529,6 +734,9 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= @@ -540,47 +748,79 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= +github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= +github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= +github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nishanths/exhaustive v0.2.3/go.mod h1:bhIX678Nx8inLM9PbpvK1yv6oGtoP8BfaIeMzgBNKvc= +github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= +github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB9sbB1usJ+xjQE= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 h1:+czc/J8SlhPKLOtVLMQc+xDCFBT73ZStMsRhSsUhsSg= +github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198/go.mod h1:j4h1pJW6ZcJTgMZWP3+7RlG3zTaP02aDZ/Qw0sppK7Q= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -609,38 +849,67 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= +github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= +github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= +github.com/quasilyte/go-ruleguard v0.3.13/go.mod h1:Ul8wwdqR6kBVOCt2dipDBkE+T6vAV/iixkrKuRTN1oQ= +github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.10/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryancurrah/gomodguard v1.2.3/go.mod h1:rYbA/4Tg5c54mV1sv4sQTP5WOPBcoLtnBZ7/TEhXAbg= +github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= +github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= +github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= @@ -648,16 +917,22 @@ github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= +github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -666,29 +941,69 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ= +github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= +github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U= github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8= github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRzJr4= github.com/theckman/yacspin v0.13.12/go.mod h1:Rd2+oG2LmQi5f3zC3yeZAOl245z8QOvrH4OPOJNZxLg= +github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tomarrell/wrapcheck/v2 v2.4.0/go.mod h1:68bQ/eJg55BROaRTbMjC7vuhL2OgfoG8bLp9ZyoBfyY= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= +github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= +github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= github.com/xanzy/go-gitlab v0.58.0 h1:Entnl8GrVDlc1jd1BlOWhNR0QVQgiO3WDom5DJbT+1s= github.com/xanzy/go-gitlab v0.58.0/go.mod h1:F0QEXwmqiBUxCgJm8fE9S+1veX4XC9Z4cfaAbqwk4YM= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= @@ -699,6 +1014,7 @@ go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46O go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -720,30 +1036,42 @@ go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16g go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= @@ -758,6 +1086,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -783,6 +1112,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -802,7 +1132,10 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -810,6 +1143,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -828,8 +1162,11 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -859,6 +1196,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -876,7 +1214,9 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -885,11 +1225,15 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -898,12 +1242,14 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -918,6 +1264,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -937,10 +1284,15 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -948,6 +1300,7 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY= golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= @@ -962,21 +1315,29 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -986,8 +1347,14 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -995,9 +1362,11 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1007,28 +1376,57 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201118003311-bd56c0adb394/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1040,6 +1438,7 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1071,11 +1470,14 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1083,6 +1485,7 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= @@ -1103,6 +1506,8 @@ google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1137,15 +1542,19 @@ google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -1185,12 +1594,16 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1204,6 +1617,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1220,6 +1634,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY= k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ= k8s.io/apiextensions-apiserver v0.24.1 h1:5yBh9+ueTq/kfnHQZa0MAo6uNcPrtxPMpNQgorBaKS0= @@ -1252,6 +1667,10 @@ k8s.io/metrics v0.24.1/go.mod h1:vMs5xpcOyY9D+/XVwlaw8oUHYCo6JTGBCZfyXOOkAhE= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7/go.mod h1:hBpJkZE8H/sb+VRFvw2+rBpHNsTBcvSpk61hr8mzXZE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= @@ -1273,6 +1692,7 @@ sigs.k8s.io/kustomize/kyaml v0.13.7/go.mod h1:6K+IUOuir3Y7nucPRAjw9yth04KSWBnP5p sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/internal/oci/build.go b/internal/oci/build.go new file mode 100644 index 0000000000..ba508c0fdf --- /dev/null +++ b/internal/oci/build.go @@ -0,0 +1,139 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "os" + "path/filepath" + "time" +) + +// Build archives the given directory as a tarball to the given local path. +// While archiving, any environment specific data (for example, the user and group name) is stripped from file headers. +func Build(artifactPath, sourceDir string) error { + if f, err := os.Stat(sourceDir); os.IsNotExist(err) || !f.IsDir() { + return fmt.Errorf("invalid source dir path: %s", sourceDir) + } + + tf, err := os.CreateTemp(filepath.Split(sourceDir)) + if err != nil { + return err + } + tmpName := tf.Name() + defer func() { + if err != nil { + os.Remove(tmpName) + } + }() + + sz := &writeCounter{} + mw := io.MultiWriter(tf, sz) + + gw := gzip.NewWriter(mw) + tw := tar.NewWriter(gw) + if err := filepath.Walk(sourceDir, func(p string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + + // Ignore anything that is not a file or directories e.g. symlinks + if m := fi.Mode(); !(m.IsRegular() || m.IsDir()) { + return nil + } + + header, err := tar.FileInfoHeader(fi, p) + if err != nil { + return err + } + // The name needs to be modified to maintain directory structure + // as tar.FileInfoHeader only has access to the base name of the file. + // Ref: https://golang.org/src/archive/tar/common.go?#L626 + relFilePath := p + if filepath.IsAbs(sourceDir) { + relFilePath, err = filepath.Rel(sourceDir, p) + if err != nil { + return err + } + } + header.Name = relFilePath + + // Remove any environment specific data. + header.Gid = 0 + header.Uid = 0 + header.Uname = "" + header.Gname = "" + header.ModTime = time.Time{} + header.AccessTime = time.Time{} + header.ChangeTime = time.Time{} + + if err := tw.WriteHeader(header); err != nil { + return err + } + + if !fi.Mode().IsRegular() { + return nil + } + f, err := os.Open(p) + if err != nil { + f.Close() + return err + } + if _, err := io.Copy(tw, f); err != nil { + f.Close() + return err + } + return f.Close() + }); err != nil { + tw.Close() + gw.Close() + tf.Close() + return err + } + + if err := tw.Close(); err != nil { + gw.Close() + tf.Close() + return err + } + if err := gw.Close(); err != nil { + tf.Close() + return err + } + if err := tf.Close(); err != nil { + return err + } + + if err := os.Chmod(tmpName, 0o640); err != nil { + return err + } + + return os.Rename(tmpName, artifactPath) +} + +type writeCounter struct { + written int64 +} + +func (wc *writeCounter) Write(p []byte) (int, error) { + n := len(p) + wc.written += int64(n) + return n, nil +} diff --git a/internal/oci/meta.go b/internal/oci/meta.go new file mode 100644 index 0000000000..3196cb26dd --- /dev/null +++ b/internal/oci/meta.go @@ -0,0 +1,60 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "fmt" +) + +const ( + SourceAnnotation = "source.toolkit.fluxcd.io/url" + RevisionAnnotation = "source.toolkit.fluxcd.io/revision" +) + +type Metadata struct { + Source string `json:"source_url"` + Revision string `json:"source_revision"` + Digest string `json:"digest"` +} + +func (m *Metadata) ToAnnotations() map[string]string { + annotations := map[string]string{ + SourceAnnotation: m.Source, + RevisionAnnotation: m.Revision, + } + + return annotations +} + +func GetMetadata(annotations map[string]string) (*Metadata, error) { + source, ok := annotations[SourceAnnotation] + if !ok { + return nil, fmt.Errorf("'%s' annotation not found", SourceAnnotation) + } + + revision, ok := annotations[RevisionAnnotation] + if !ok { + return nil, fmt.Errorf("'%s' annotation not found", RevisionAnnotation) + } + + m := Metadata{ + Source: source, + Revision: revision, + } + + return &m, nil +} diff --git a/internal/oci/pull.go b/internal/oci/pull.go new file mode 100644 index 0000000000..b37642a83e --- /dev/null +++ b/internal/oci/pull.go @@ -0,0 +1,75 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "context" + "fmt" + + "github.com/fluxcd/pkg/untar" + "github.com/google/go-containerregistry/pkg/crane" + "github.com/google/go-containerregistry/pkg/name" +) + +// Pull downloads an artifact from an OCI repository and extracts the content to the given directory. +func Pull(ctx context.Context, url, outDir string) (*Metadata, error) { + ref, err := name.ParseReference(url) + if err != nil { + return nil, fmt.Errorf("invalid URL: %w", err) + } + + img, err := crane.Pull(url, craneOptions(ctx)...) + if err != nil { + return nil, err + } + + digest, err := img.Digest() + if err != nil { + return nil, fmt.Errorf("parsing digest failed: %w", err) + } + + manifest, err := img.Manifest() + if err != nil { + return nil, fmt.Errorf("parsing manifest failed: %w", err) + } + + meta, err := GetMetadata(manifest.Annotations) + if err != nil { + return nil, err + } + meta.Digest = ref.Context().Digest(digest.String()).String() + + layers, err := img.Layers() + if err != nil { + return nil, fmt.Errorf("failed to list layers: %w", err) + } + + if len(layers) < 1 { + return nil, fmt.Errorf("no layers found in artifact") + } + + blob, err := layers[0].Compressed() + if err != nil { + return nil, fmt.Errorf("extracting first layer failed: %w", err) + } + + if _, err = untar.Untar(blob, outDir); err != nil { + return nil, fmt.Errorf("failed to untar first layer: %w", err) + } + + return meta, nil +} diff --git a/internal/oci/push.go b/internal/oci/push.go new file mode 100644 index 0000000000..30d572c99c --- /dev/null +++ b/internal/oci/push.go @@ -0,0 +1,81 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "context" + "fmt" + "os" + "path/filepath" + + "github.com/google/go-containerregistry/pkg/crane" + "github.com/google/go-containerregistry/pkg/name" + gcrv1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/empty" + "github.com/google/go-containerregistry/pkg/v1/mutate" +) + +// Push creates an artifact from the given directory, uploads the artifact +// to the given OCI repository and returns the digest. +func Push(ctx context.Context, url, sourceDir string, meta Metadata) (string, error) { + ref, err := name.ParseReference(url) + if err != nil { + return "", fmt.Errorf("invalid URL: %w", err) + } + + tmpDir, err := os.MkdirTemp("", "oci") + if err != nil { + return "", err + } + defer os.RemoveAll(tmpDir) + + tmpFile := filepath.Join(tmpDir, "artifact.tgz") + + if err := Build(tmpFile, sourceDir); err != nil { + return "", err + } + + img, err := crane.Append(empty.Image, tmpFile) + if err != nil { + return "", fmt.Errorf("appeding content to artifact failed: %w", err) + } + + img = mutate.Annotations(img, meta.ToAnnotations()).(gcrv1.Image) + + if err := crane.Push(img, url, craneOptions(ctx)...); err != nil { + return "", fmt.Errorf("pushing artifact failed: %w", err) + } + + digest, err := img.Digest() + if err != nil { + return "", fmt.Errorf("parsing artifact digest failed: %w", err) + } + + return ref.Context().Digest(digest.String()).String(), err +} + +func craneOptions(ctx context.Context) []crane.Option { + return []crane.Option{ + crane.WithContext(ctx), + crane.WithUserAgent("flux/v2"), + crane.WithPlatform(&gcrv1.Platform{ + Architecture: "flux", + OS: "flux", + OSVersion: "v2", + }), + } +} diff --git a/internal/oci/tag.go b/internal/oci/tag.go new file mode 100644 index 0000000000..8e0140f66b --- /dev/null +++ b/internal/oci/tag.go @@ -0,0 +1,40 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "context" + "fmt" + "github.com/google/go-containerregistry/pkg/crane" + "github.com/google/go-containerregistry/pkg/name" +) + +// Tag creates a new tag for the given artifact using the same OCI repository as the origin. +func Tag(ctx context.Context, url, tag string) (string, error) { + ref, err := name.ParseReference(url) + if err != nil { + return "", fmt.Errorf("invalid URL: %w", err) + } + + if err := crane.Tag(url, tag, craneOptions(ctx)...); err != nil { + return "", err + } + + dst := ref.Context().Tag(tag) + + return dst.Name(), nil +} From 9503ecafb1c50a4bdb2ddaf984820fe6ea9c4391 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 21 Jun 2022 12:38:10 +0300 Subject: [PATCH 02/32] Add artifact commands Implement build, push, pull and tag artifact commands. For authentication purposes, all `flux artifact` commands are using the '~/.docker/config.json' config file and the Docker credential helpers. Signed-off-by: Stefan Prodan --- cmd/flux/build_artifact.go | 69 ++++++++++++++++++++++++++ cmd/flux/pull.go | 31 ++++++++++++ cmd/flux/pull_artifact.go | 81 +++++++++++++++++++++++++++++++ cmd/flux/push.go | 31 ++++++++++++ cmd/flux/push_artifact.go | 99 ++++++++++++++++++++++++++++++++++++++ cmd/flux/tag.go | 31 ++++++++++++ cmd/flux/tag_artifact.go | 74 ++++++++++++++++++++++++++++ 7 files changed, 416 insertions(+) create mode 100644 cmd/flux/build_artifact.go create mode 100644 cmd/flux/pull.go create mode 100644 cmd/flux/pull_artifact.go create mode 100644 cmd/flux/push.go create mode 100644 cmd/flux/push_artifact.go create mode 100644 cmd/flux/tag.go create mode 100644 cmd/flux/tag_artifact.go diff --git a/cmd/flux/build_artifact.go b/cmd/flux/build_artifact.go new file mode 100644 index 0000000000..83aa30eadb --- /dev/null +++ b/cmd/flux/build_artifact.go @@ -0,0 +1,69 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/fluxcd/flux2/internal/oci" +) + +var buildArtifactCmd = &cobra.Command{ + Use: "artifact", + Short: "Build artifact", + Long: `The build artifact command creates an tgz file with the manifests from the given directory.`, + Example: `# Build the given manifests directory into an artifact +flux build artifact --path ./path/to/local/manifests --output ./path/to/artifact.tgz +`, + RunE: buildArtifactCmdRun, +} + +type buildArtifactFlags struct { + output string + path string +} + +var buildArtifactArgs buildArtifactFlags + +func init() { + buildArtifactCmd.Flags().StringVar(&buildArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.") + buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.output, "output", "0", "artifact.tgz", "Path to where the artifact tgz file should be written.") + buildCmd.AddCommand(buildArtifactCmd) +} + +func buildArtifactCmdRun(cmd *cobra.Command, args []string) error { + if buildArtifactArgs.path == "" { + return fmt.Errorf("invalid path %q", buildArtifactArgs.path) + } + + if fs, err := os.Stat(buildArtifactArgs.path); err != nil || !fs.IsDir() { + return fmt.Errorf("invalid path %q", buildArtifactArgs.path) + } + + logger.Actionf("building artifact from %s", buildArtifactArgs.path) + + if err := oci.Build(buildArtifactArgs.output, buildArtifactArgs.path); err != nil { + return fmt.Errorf("bulding artifact failed, error: %w", err) + } + + logger.Successf("artifact created at %s", buildArtifactArgs.output) + + return nil +} diff --git a/cmd/flux/pull.go b/cmd/flux/pull.go new file mode 100644 index 0000000000..7ea48a1f0c --- /dev/null +++ b/cmd/flux/pull.go @@ -0,0 +1,31 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" +) + +var pullCmd = &cobra.Command{ + Use: "pull", + Short: "Pull artifacts", + Long: "The pull command is used to download OCI artifacts.", +} + +func init() { + rootCmd.AddCommand(pullCmd) +} diff --git a/cmd/flux/pull_artifact.go b/cmd/flux/pull_artifact.go new file mode 100644 index 0000000000..37560f68a4 --- /dev/null +++ b/cmd/flux/pull_artifact.go @@ -0,0 +1,81 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/fluxcd/flux2/internal/oci" +) + +var pullArtifactCmd = &cobra.Command{ + Use: "artifact", + Short: "Push artifact", + Long: `The pull artifact command downloads and extracts the OCI artifact content to the given path. +The pull command uses the credentials from '~/.docker/config.json'.`, + Example: `# Pull an OCI artifact created by flux from GHCR +flux pull artifact ghcr.io/org/manifests/app:v0.0.1 --output ./path/to/local/manifests +`, + RunE: pullArtifactCmdRun, +} + +type pullArtifactFlags struct { + output string +} + +var pullArtifactArgs pullArtifactFlags + +func init() { + pullArtifactCmd.Flags().StringVarP(&pullArtifactArgs.output, "output", "o", "", "Path where the artifact content should be extracted.") + pullCmd.AddCommand(pullArtifactCmd) +} + +func pullArtifactCmdRun(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("artifact name is required") + } + url := args[0] + + if pullArtifactArgs.output == "" { + return fmt.Errorf("invalid output path %s", pullArtifactArgs.output) + } + + if fs, err := os.Stat(pullArtifactArgs.output); err != nil || !fs.IsDir() { + return fmt.Errorf("invalid output path %s", pullArtifactArgs.output) + } + + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) + defer cancel() + + logger.Actionf("pulling artifact from %s", url) + + meta, err := oci.Pull(ctx, url, pullArtifactArgs.output) + if err != nil { + return err + } + + logger.Successf("source %s", meta.Source) + logger.Successf("revision %s", meta.Revision) + logger.Successf("digest %s", meta.Digest) + logger.Successf("artifact content extracted to %s", pullArtifactArgs.output) + + return nil +} diff --git a/cmd/flux/push.go b/cmd/flux/push.go new file mode 100644 index 0000000000..481c6ae9ae --- /dev/null +++ b/cmd/flux/push.go @@ -0,0 +1,31 @@ +/* +Copyright 2021 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" +) + +var pushCmd = &cobra.Command{ + Use: "push", + Short: "Push artifacts", + Long: "The push command is used to publish OCI artifacts.", +} + +func init() { + rootCmd.AddCommand(pushCmd) +} diff --git a/cmd/flux/push_artifact.go b/cmd/flux/push_artifact.go new file mode 100644 index 0000000000..813dbb46e1 --- /dev/null +++ b/cmd/flux/push_artifact.go @@ -0,0 +1,99 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/fluxcd/flux2/internal/oci" +) + +var pushArtifactCmd = &cobra.Command{ + Use: "artifact", + Short: "Push artifact", + Long: `The push artifact command creates a tarball from the given directory and uploads the artifact to a OCI repository. +The push command uses the credentials from '~/.docker/config.json'.`, + Example: `# Push the local manifests to GHCR +flux push artifact ghcr.io/org/manifests/app:v0.0.1 \ + --path="./path/to/local/manifests" \ + --source="$(git config --get remote.origin.url)" \ + --revision="$(git branch --show-current)/$(git rev-parse HEAD)" +`, + RunE: pushArtifactCmdRun, +} + +type pushArtifactFlags struct { + path string + source string + revision string +} + +var pushArtifactArgs pushArtifactFlags + +func init() { + pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.") + pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.source, "source", "", "The source address, e.g. Git URL.") + pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.revision, "revision", "", "The source revision in the format '/'") + pushCmd.AddCommand(pushArtifactCmd) +} + +func pushArtifactCmdRun(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("artifact name is required") + } + url := args[0] + + if pushArtifactArgs.source == "" { + return fmt.Errorf("--source is required") + } + + if pushArtifactArgs.revision == "" { + return fmt.Errorf("--revision is required") + } + + if pushArtifactArgs.path == "" { + return fmt.Errorf("invalid path %q", pushArtifactArgs.path) + } + + if fs, err := os.Stat(pushArtifactArgs.path); err != nil || !fs.IsDir() { + return fmt.Errorf("invalid path %q", pushArtifactArgs.path) + } + + meta := oci.Metadata{ + Source: pushArtifactArgs.source, + Revision: pushArtifactArgs.revision, + } + + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) + defer cancel() + + logger.Actionf("pushing artifact to %s", url) + + digest, err := oci.Push(ctx, url, pushArtifactArgs.path, meta) + if err != nil { + return fmt.Errorf("pushing artifact failed: %w", err) + } + + logger.Successf("artifact successfully pushed to %s", digest) + + return nil + +} diff --git a/cmd/flux/tag.go b/cmd/flux/tag.go new file mode 100644 index 0000000000..56c9485fb0 --- /dev/null +++ b/cmd/flux/tag.go @@ -0,0 +1,31 @@ +/* +Copyright 2021 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" +) + +var tagCmd = &cobra.Command{ + Use: "tag", + Short: "Tag artifacts", + Long: "The tag command is used to tag OCI artifacts.", +} + +func init() { + rootCmd.AddCommand(tagCmd) +} diff --git a/cmd/flux/tag_artifact.go b/cmd/flux/tag_artifact.go new file mode 100644 index 0000000000..be0a6387d7 --- /dev/null +++ b/cmd/flux/tag_artifact.go @@ -0,0 +1,74 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "fmt" + "github.com/fluxcd/flux2/internal/oci" + "github.com/spf13/cobra" +) + +var tagArtifactCmd = &cobra.Command{ + Use: "artifact", + Short: "Tag artifact", + Long: `The tag artifact command creates tags for the given OCI artifact. +The tag command uses the credentials from '~/.docker/config.json'.`, + Example: `# Tag an artifact version as latest +flux tag artifact ghcr.io/org/manifests/app:v0.0.1 --tag latest +`, + RunE: tagArtifactCmdRun, +} + +type tagArtifactFlags struct { + tags []string +} + +var tagArtifactArgs tagArtifactFlags + +func init() { + tagArtifactCmd.Flags().StringSliceVar(&tagArtifactArgs.tags, "tag", nil, "Tag name.") + tagCmd.AddCommand(tagArtifactCmd) +} + +func tagArtifactCmdRun(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("artifact name is required") + } + url := args[0] + + if len(tagArtifactArgs.tags) < 1 { + return fmt.Errorf("--tag is required") + } + + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) + defer cancel() + + logger.Actionf("tagging artifact") + + for _, tag := range tagArtifactArgs.tags { + img, err := oci.Tag(ctx, url, tag) + if err != nil { + return fmt.Errorf("tagging artifact failed: %w", err) + } + + logger.Successf("artifact tagged as %s", img) + } + + return nil + +} From 12a491f5389690d5c4fb13c0935a2a22394e3dd4 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 22 Jun 2022 08:58:40 +0300 Subject: [PATCH 03/32] Update controllers to OCI preview images Signed-off-by: Stefan Prodan --- manifests/bases/kustomize-controller/kustomization.yaml | 9 +++++++-- manifests/bases/source-controller/kustomization.yaml | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/manifests/bases/kustomize-controller/kustomization.yaml b/manifests/bases/kustomize-controller/kustomization.yaml index db3ecfc6e4..2ae59c8a81 100644 --- a/manifests/bases/kustomize-controller/kustomization.yaml +++ b/manifests/bases/kustomize-controller/kustomization.yaml @@ -1,8 +1,9 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization +# TODO: remove the hardcoded branch when OCIRepository is released resources: -- https://github.com/fluxcd/kustomize-controller/releases/download/v0.26.3/kustomize-controller.crds.yaml -- https://github.com/fluxcd/kustomize-controller/releases/download/v0.26.3/kustomize-controller.deployment.yaml +- https://github.com/fluxcd/kustomize-controller/config/crd?ref=oci +- https://github.com/fluxcd/kustomize-controller/releases/download/v0.26.1/kustomize-controller.deployment.yaml - account.yaml patchesJson6902: - target: @@ -11,3 +12,7 @@ patchesJson6902: kind: Deployment name: kustomize-controller path: patch.yaml +# TODO: remove the hardcoded image when OCIRepository is released +images: + - name: fluxcd/kustomize-controller + newTag: oci-7681bda9 diff --git a/manifests/bases/source-controller/kustomization.yaml b/manifests/bases/source-controller/kustomization.yaml index 20c65d325c..29147274da 100644 --- a/manifests/bases/source-controller/kustomization.yaml +++ b/manifests/bases/source-controller/kustomization.yaml @@ -1,8 +1,9 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization +# TODO: remove the hardcoded branch when OCIRepository is released resources: -- https://github.com/fluxcd/source-controller/releases/download/v0.25.11/source-controller.crds.yaml -- https://github.com/fluxcd/source-controller/releases/download/v0.25.11/source-controller.deployment.yaml +- https://github.com/fluxcd/source-controller/config/crd?ref=oci +- https://github.com/fluxcd/source-controller/releases/download/v0.25.5/source-controller.deployment.yaml - account.yaml patchesJson6902: - target: @@ -11,3 +12,7 @@ patchesJson6902: kind: Deployment name: source-controller path: patch.yaml +# TODO: remove the hardcoded image when OCIRepository is released +images: + - name: fluxcd/source-controller + newTag: oci-778f6d5d From 2d8db4f20de34f0525e85124ee218506bc39423a Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 22 Jun 2022 10:16:57 +0300 Subject: [PATCH 04/32] Implement OCIRepository commands Signed-off-by: Stefan Prodan --- .github/workflows/e2e.yaml | 21 +++ cmd/flux/create_kustomization.go | 7 + cmd/flux/create_source_oci.go | 222 +++++++++++++++++++++++++ cmd/flux/delete_source_oci.go | 40 +++++ cmd/flux/export_source_oci.go | 92 ++++++++++ cmd/flux/get_source_all.go | 4 + cmd/flux/get_source_oci.go | 98 +++++++++++ cmd/flux/reconcile_kustomization.go | 5 + cmd/flux/reconcile_source_oci.go | 50 ++++++ cmd/flux/resume_source_oci.go | 53 ++++++ cmd/flux/source.go | 34 ++++ cmd/flux/suspend_source_oci.go | 53 ++++++ internal/flags/kustomization_source.go | 2 +- internal/oci/build.go | 2 +- 14 files changed, 681 insertions(+), 2 deletions(-) create mode 100644 cmd/flux/create_source_oci.go create mode 100644 cmd/flux/delete_source_oci.go create mode 100644 cmd/flux/export_source_oci.go create mode 100644 cmd/flux/get_source_oci.go create mode 100644 cmd/flux/reconcile_source_oci.go create mode 100644 cmd/flux/resume_source_oci.go create mode 100644 cmd/flux/suspend_source_oci.go diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 14c38578a7..9f4fcb669d 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -168,6 +168,27 @@ jobs: - name: flux delete source git run: | /tmp/flux delete source git podinfo --silent + - name: flux oci + run: | + /tmp/flux create source oci podinfo-oci \ + --url ghcr.io/stefanprodan/manifests/podinfo \ + --tag 6.1.6 \ + --interval 10m + /tmp/flux create kustomization podinfo-oci \ + --source=OCIRepository/podinfo-oci \ + --path="./kustomize" \ + --prune=true \ + --interval=5m \ + --target-namespace=default \ + --wait=true \ + --health-check-timeout=3m + /tmp/flux reconcile source oci podinfo-oci + /tmp/flux suspend source oci podinfo-oci + /tmp/flux get sources oci + /tmp/flux resume source oci podinfo-oci + /tmp/flux export source oci podinfo-oci + /tmp/flux delete ks podinfo-oci --silent + /tmp/flux delete source oci podinfo-oci --silent - name: flux create tenant run: | /tmp/flux create tenant dev-team --with-namespace=apps diff --git a/cmd/flux/create_kustomization.go b/cmd/flux/create_kustomization.go index f808a99fea..26d1e3ea2c 100644 --- a/cmd/flux/create_kustomization.go +++ b/cmd/flux/create_kustomization.go @@ -68,6 +68,13 @@ var createKsCmd = &cobra.Command{ --prune=true \ --interval=5m + # Create a Kustomization resource that references an OCIRepository + flux create kustomization podinfo \ + --source=OCIRepository/podinfo \ + --target-namespace=default \ + --prune=true \ + --interval=5m + # Create a Kustomization resource that references a Bucket flux create kustomization secrets \ --source=Bucket/secrets \ diff --git a/cmd/flux/create_source_oci.go b/cmd/flux/create_source_oci.go new file mode 100644 index 0000000000..e1d26c4351 --- /dev/null +++ b/cmd/flux/create_source_oci.go @@ -0,0 +1,222 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "fmt" + "os" + "strings" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/fluxcd/pkg/apis/meta" + "github.com/fluxcd/pkg/runtime/conditions" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + + "github.com/fluxcd/flux2/internal/utils" +) + +var createSourceOCIRepositoryCmd = &cobra.Command{ + Use: "oci [name]", + Short: "Create or update an OCIRepository", + Long: `The create source oci command generates an OCIRepository resource and waits for it to be ready.`, + Example: ` # Create an OCIRepository for a public container image + flux create source oci podinfo \ + --url=ghcr.io/stefanprodan/manifests/podinfo \ + --tag=6.1.6 \ + --interval=10m +`, + RunE: createSourceOCIRepositoryCmdRun, +} + +type sourceOCIRepositoryFlags struct { + url string + tag string + digest string + secretRef string + ignorePaths []string +} + +var sourceOCIRepositoryArgs = sourceOCIRepositoryFlags{} + +func init() { + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.url, "url", "", "the OCI repository URL") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.tag, "tag", "", "the OCI artifact tag") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.digest, "digest", "", "the OCI artifact digest") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "secret-ref", "", "the name of an existing secret containing credentials") + createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)") + + createSourceCmd.AddCommand(createSourceOCIRepositoryCmd) +} + +func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error { + name := args[0] + + if sourceOCIRepositoryArgs.url == "" { + return fmt.Errorf("url is required") + } + + if sourceOCIRepositoryArgs.tag == "" && sourceOCIRepositoryArgs.digest == "" { + return fmt.Errorf("--tag or --digest is required") + } + + sourceLabels, err := parseLabels() + if err != nil { + return err + } + + tmpDir, err := os.MkdirTemp("", name) + if err != nil { + return err + } + defer os.RemoveAll(tmpDir) + + var ignorePaths *string + if len(sourceOCIRepositoryArgs.ignorePaths) > 0 { + ignorePathsStr := strings.Join(sourceOCIRepositoryArgs.ignorePaths, "\n") + ignorePaths = &ignorePathsStr + } + + repository := &sourcev1.OCIRepository{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: *kubeconfigArgs.Namespace, + Labels: sourceLabels, + }, + Spec: sourcev1.OCIRepositorySpec{ + URL: sourceOCIRepositoryArgs.url, + Interval: metav1.Duration{ + Duration: createArgs.interval, + }, + Reference: &sourcev1.OCIRepositoryRef{}, + Ignore: ignorePaths, + }, + } + + if sourceOCIRepositoryArgs.tag != "" { + repository.Spec.Reference.Tag = sourceOCIRepositoryArgs.tag + } + if sourceOCIRepositoryArgs.digest != "" { + repository.Spec.Reference.Digest = sourceOCIRepositoryArgs.digest + } + + if createSourceArgs.fetchTimeout > 0 { + repository.Spec.Timeout = &metav1.Duration{Duration: createSourceArgs.fetchTimeout} + } + + if sourceOCIRepositoryArgs.secretRef != "" { + repository.Spec.SecretRef = &meta.LocalObjectReference{ + Name: sourceOCIRepositoryArgs.secretRef, + } + } + + if createArgs.export { + return printExport(exportOCIRepository(repository)) + } + + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) + defer cancel() + + kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions) + if err != nil { + return err + } + + logger.Actionf("applying OCIRepository") + namespacedName, err := upsertOCIRepository(ctx, kubeClient, repository) + if err != nil { + return err + } + + logger.Waitingf("waiting for OCIRepository reconciliation") + if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout, + isOCIRepositoryReady(ctx, kubeClient, namespacedName, repository)); err != nil { + return err + } + logger.Successf("OCIRepository reconciliation completed") + + if repository.Status.Artifact == nil { + return fmt.Errorf("no artifact was found") + } + logger.Successf("fetched revision: %s", repository.Status.Artifact.Revision) + return nil +} + +func upsertOCIRepository(ctx context.Context, kubeClient client.Client, + ociRepository *sourcev1.OCIRepository) (types.NamespacedName, error) { + namespacedName := types.NamespacedName{ + Namespace: ociRepository.GetNamespace(), + Name: ociRepository.GetName(), + } + + var existing sourcev1.OCIRepository + err := kubeClient.Get(ctx, namespacedName, &existing) + if err != nil { + if errors.IsNotFound(err) { + if err := kubeClient.Create(ctx, ociRepository); err != nil { + return namespacedName, err + } else { + logger.Successf("OCIRepository created") + return namespacedName, nil + } + } + return namespacedName, err + } + + existing.Labels = ociRepository.Labels + existing.Spec = ociRepository.Spec + if err := kubeClient.Update(ctx, &existing); err != nil { + return namespacedName, err + } + ociRepository = &existing + logger.Successf("OCIRepository updated") + return namespacedName, nil +} + +func isOCIRepositoryReady(ctx context.Context, kubeClient client.Client, + namespacedName types.NamespacedName, ociRepository *sourcev1.OCIRepository) wait.ConditionFunc { + return func() (bool, error) { + err := kubeClient.Get(ctx, namespacedName, ociRepository) + if err != nil { + return false, err + } + + if c := conditions.Get(ociRepository, meta.ReadyCondition); c != nil { + // Confirm the Ready condition we are observing is for the + // current generation + if c.ObservedGeneration != ociRepository.GetGeneration() { + return false, nil + } + + // Further check the Status + switch c.Status { + case metav1.ConditionTrue: + return true, nil + case metav1.ConditionFalse: + return false, fmt.Errorf(c.Message) + } + } + return false, nil + } +} diff --git a/cmd/flux/delete_source_oci.go b/cmd/flux/delete_source_oci.go new file mode 100644 index 0000000000..1d641bbf51 --- /dev/null +++ b/cmd/flux/delete_source_oci.go @@ -0,0 +1,40 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" +) + +var deleteSourceOCIRepositoryCmd = &cobra.Command{ + Use: "oci [name]", + Short: "Delete a OCIRepository source", + Long: "The delete source oci command deletes the given OCIRepository from the cluster.", + Example: ` # Delete an OCIRepository + flux delete source oci podinfo`, + ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)), + RunE: deleteCommand{ + apiType: ociRepositoryType, + object: universalAdapter{&sourcev1.OCIRepository{}}, + }.run, +} + +func init() { + deleteSourceCmd.AddCommand(deleteSourceOCIRepositoryCmd) +} diff --git a/cmd/flux/export_source_oci.go b/cmd/flux/export_source_oci.go new file mode 100644 index 0000000000..c6ea9c7703 --- /dev/null +++ b/cmd/flux/export_source_oci.go @@ -0,0 +1,92 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" +) + +var exportSourceOCIRepositoryCmd = &cobra.Command{ + Use: "oci [name]", + Short: "Export OCIRepository sources in YAML format", + Long: "The export source oci command exports one or all OCIRepository sources in YAML format.", + Example: ` # Export all OCIRepository sources + flux export source oci --all > sources.yaml + + # Export a OCIRepository including the static credentials + flux export source oci my-app --with-credentials > source.yaml`, + ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)), + RunE: exportWithSecretCommand{ + list: ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{}}, + object: ociRepositoryAdapter{&sourcev1.OCIRepository{}}, + }.run, +} + +func init() { + exportSourceCmd.AddCommand(exportSourceOCIRepositoryCmd) +} + +func exportOCIRepository(source *sourcev1.OCIRepository) interface{} { + gvk := sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind) + export := sourcev1.OCIRepository{ + TypeMeta: metav1.TypeMeta{ + Kind: gvk.Kind, + APIVersion: gvk.GroupVersion().String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: source.Name, + Namespace: source.Namespace, + Labels: source.Labels, + Annotations: source.Annotations, + }, + Spec: source.Spec, + } + return export +} + +func getOCIRepositorySecret(source *sourcev1.OCIRepository) *types.NamespacedName { + if source.Spec.SecretRef != nil { + namespacedName := types.NamespacedName{ + Namespace: source.Namespace, + Name: source.Spec.SecretRef.Name, + } + + return &namespacedName + } + + return nil +} + +func (ex ociRepositoryAdapter) secret() *types.NamespacedName { + return getOCIRepositorySecret(ex.OCIRepository) +} + +func (ex ociRepositoryListAdapter) secretItem(i int) *types.NamespacedName { + return getOCIRepositorySecret(&ex.OCIRepositoryList.Items[i]) +} + +func (ex ociRepositoryAdapter) export() interface{} { + return exportOCIRepository(ex.OCIRepository) +} + +func (ex ociRepositoryListAdapter) exportItem(i int) interface{} { + return exportOCIRepository(&ex.OCIRepositoryList.Items[i]) +} diff --git a/cmd/flux/get_source_all.go b/cmd/flux/get_source_all.go index b9b6255532..ac6560fe83 100644 --- a/cmd/flux/get_source_all.go +++ b/cmd/flux/get_source_all.go @@ -40,6 +40,10 @@ var getSourceAllCmd = &cobra.Command{ } var allSourceCmd = []getCommand{ + { + apiType: ociRepositoryType, + list: &ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{}}, + }, { apiType: bucketType, list: &bucketListAdapter{&sourcev1.BucketList{}}, diff --git a/cmd/flux/get_source_oci.go b/cmd/flux/get_source_oci.go new file mode 100644 index 0000000000..8f948d8122 --- /dev/null +++ b/cmd/flux/get_source_oci.go @@ -0,0 +1,98 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + "strconv" + "strings" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" +) + +var getSourceOCIRepositoryCmd = &cobra.Command{ + Use: "oci", + Short: "Get OCIRepository status", + Long: "The get sources oci command prints the status of the OCIRepository sources.", + Example: ` # List all OCIRepositories and their status + flux get sources oci + + # List OCIRepositories from all namespaces + flux get sources oci --all-namespaces`, + ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)), + RunE: func(cmd *cobra.Command, args []string) error { + get := getCommand{ + apiType: ociRepositoryType, + list: &ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{}}, + funcMap: make(typeMap), + } + + err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) { + o, ok := obj.(*sourcev1.OCIRepository) + if !ok { + return nil, fmt.Errorf("impossible to cast type %#v to OCIRepository", obj) + } + + sink := &ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{ + Items: []sourcev1.OCIRepository{ + *o, + }}} + return sink, nil + }) + + if err != nil { + return err + } + + if err := get.run(cmd, args); err != nil { + return err + } + + return nil + }, +} + +func init() { + getSourceCmd.AddCommand(getSourceOCIRepositoryCmd) +} + +func (a *ociRepositoryListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string { + item := a.Items[i] + var revision string + if item.GetArtifact() != nil { + revision = item.GetArtifact().Revision + } + status, msg := statusAndMessage(item.Status.Conditions) + return append(nameColumns(&item, includeNamespace, includeKind), + revision, strings.Title(strconv.FormatBool(item.Spec.Suspend)), status, msg) +} + +func (a ociRepositoryListAdapter) headers(includeNamespace bool) []string { + headers := []string{"Name", "Revision", "Suspended", "Ready", "Message"} + if includeNamespace { + headers = append([]string{"Namespace"}, headers...) + } + return headers +} + +func (a ociRepositoryListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool { + item := a.Items[i] + return statusMatches(conditionType, conditionStatus, item.Status.Conditions) +} diff --git a/cmd/flux/reconcile_kustomization.go b/cmd/flux/reconcile_kustomization.go index 05035a5035..cdc6e7ac85 100644 --- a/cmd/flux/reconcile_kustomization.go +++ b/cmd/flux/reconcile_kustomization.go @@ -65,6 +65,11 @@ func (obj kustomizationAdapter) reconcileSource() bool { func (obj kustomizationAdapter) getSource() (reconcileCommand, types.NamespacedName) { var cmd reconcileCommand switch obj.Spec.SourceRef.Kind { + case sourcev1.OCIRepositoryKind: + cmd = reconcileCommand{ + apiType: ociRepositoryType, + object: ociRepositoryAdapter{&sourcev1.OCIRepository{}}, + } case sourcev1.GitRepositoryKind: cmd = reconcileCommand{ apiType: gitRepositoryType, diff --git a/cmd/flux/reconcile_source_oci.go b/cmd/flux/reconcile_source_oci.go new file mode 100644 index 0000000000..17df7174f8 --- /dev/null +++ b/cmd/flux/reconcile_source_oci.go @@ -0,0 +1,50 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + + "github.com/spf13/cobra" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" +) + +var reconcileSourceOCIRepositoryCmd = &cobra.Command{ + Use: "oci [name]", + Short: "Reconcile an OCIRepository", + Long: `The reconcile source command triggers a reconciliation of an OCIRepository resource and waits for it to finish.`, + Example: ` # Trigger a reconciliation for an existing source + flux reconcile source oci podinfo`, + ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)), + RunE: reconcileCommand{ + apiType: ociRepositoryType, + object: ociRepositoryAdapter{&sourcev1.OCIRepository{}}, + }.run, +} + +func init() { + reconcileSourceCmd.AddCommand(reconcileSourceOCIRepositoryCmd) +} + +func (obj ociRepositoryAdapter) lastHandledReconcileRequest() string { + return obj.Status.GetLastHandledReconcileRequest() +} + +func (obj ociRepositoryAdapter) successMessage() string { + return fmt.Sprintf("fetched revision %s", obj.Status.Artifact.Revision) +} diff --git a/cmd/flux/resume_source_oci.go b/cmd/flux/resume_source_oci.go new file mode 100644 index 0000000000..42ad48ab1d --- /dev/null +++ b/cmd/flux/resume_source_oci.go @@ -0,0 +1,53 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" +) + +var resumeSourceOCIRepositoryCmd = &cobra.Command{ + Use: "oci [name]", + Short: "Resume a suspended OCIRepository", + Long: `The resume command marks a previously suspended OCIRepository resource for reconciliation and waits for it to finish.`, + Example: ` # Resume reconciliation for an existing OCIRepository + flux resume source oci podinfo`, + ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)), + RunE: resumeCommand{ + apiType: ociRepositoryType, + object: ociRepositoryAdapter{&sourcev1.OCIRepository{}}, + list: ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{}}, + }.run, +} + +func init() { + resumeSourceCmd.AddCommand(resumeSourceOCIRepositoryCmd) +} + +func (obj ociRepositoryAdapter) getObservedGeneration() int64 { + return obj.OCIRepository.Status.ObservedGeneration +} + +func (obj ociRepositoryAdapter) setUnsuspended() { + obj.OCIRepository.Spec.Suspend = false +} + +func (a ociRepositoryListAdapter) resumeItem(i int) resumable { + return &ociRepositoryAdapter{&a.OCIRepositoryList.Items[i]} +} diff --git a/cmd/flux/source.go b/cmd/flux/source.go index b6c9077cbe..4177c159a5 100644 --- a/cmd/flux/source.go +++ b/cmd/flux/source.go @@ -26,6 +26,40 @@ import ( // the various commands. The *List adapters implement len(), since // it's used in at least a couple of commands. +// sourcev1.ociRepository + +var ociRepositoryType = apiType{ + kind: sourcev1.OCIRepositoryKind, + humanKind: "source oci", + groupVersion: sourcev1.GroupVersion, +} + +type ociRepositoryAdapter struct { + *sourcev1.OCIRepository +} + +func (a ociRepositoryAdapter) asClientObject() client.Object { + return a.OCIRepository +} + +func (a ociRepositoryAdapter) deepCopyClientObject() client.Object { + return a.OCIRepository.DeepCopy() +} + +// sourcev1.OCIRepositoryList + +type ociRepositoryListAdapter struct { + *sourcev1.OCIRepositoryList +} + +func (a ociRepositoryListAdapter) asClientList() client.ObjectList { + return a.OCIRepositoryList +} + +func (a ociRepositoryListAdapter) len() int { + return len(a.OCIRepositoryList.Items) +} + // sourcev1.Bucket var bucketType = apiType{ diff --git a/cmd/flux/suspend_source_oci.go b/cmd/flux/suspend_source_oci.go new file mode 100644 index 0000000000..06ab4c6c35 --- /dev/null +++ b/cmd/flux/suspend_source_oci.go @@ -0,0 +1,53 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" +) + +var suspendSourceOCIRepositoryCmd = &cobra.Command{ + Use: "oci [name]", + Short: "Suspend reconciliation of a OCIRepository", + Long: "The suspend command disables the reconciliation of an OCIRepository resource.", + Example: ` # Suspend reconciliation for an existing OCIRepository + flux suspend source oci podinfo`, + ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)), + RunE: suspendCommand{ + apiType: ociRepositoryType, + object: ociRepositoryAdapter{&sourcev1.OCIRepository{}}, + list: ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{}}, + }.run, +} + +func init() { + suspendSourceCmd.AddCommand(suspendSourceOCIRepositoryCmd) +} + +func (obj ociRepositoryAdapter) isSuspended() bool { + return obj.OCIRepository.Spec.Suspend +} + +func (obj ociRepositoryAdapter) setSuspended() { + obj.OCIRepository.Spec.Suspend = true +} + +func (a ociRepositoryListAdapter) item(i int) suspendable { + return &ociRepositoryAdapter{&a.OCIRepositoryList.Items[i]} +} diff --git a/internal/flags/kustomization_source.go b/internal/flags/kustomization_source.go index b506230d0a..f3455b25fb 100644 --- a/internal/flags/kustomization_source.go +++ b/internal/flags/kustomization_source.go @@ -25,7 +25,7 @@ import ( "github.com/fluxcd/flux2/internal/utils" ) -var supportedKustomizationSourceKinds = []string{sourcev1.GitRepositoryKind, sourcev1.BucketKind} +var supportedKustomizationSourceKinds = []string{sourcev1.OCIRepositoryKind, sourcev1.GitRepositoryKind, sourcev1.BucketKind} type KustomizationSource struct { Kind string diff --git a/internal/oci/build.go b/internal/oci/build.go index ba508c0fdf..3deb3fc69d 100644 --- a/internal/oci/build.go +++ b/internal/oci/build.go @@ -28,7 +28,7 @@ import ( // Build archives the given directory as a tarball to the given local path. // While archiving, any environment specific data (for example, the user and group name) is stripped from file headers. -func Build(artifactPath, sourceDir string) error { +func Build(artifactPath, sourceDir string) (err error) { if f, err := os.Stat(sourceDir); os.IsNotExist(err) || !f.IsDir() { return fmt.Errorf("invalid source dir path: %s", sourceDir) } From 2f35367a7f7259d7a1ae32825f858f759f2d1169 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Thu, 23 Jun 2022 08:51:24 +0300 Subject: [PATCH 05/32] Add list artifacts command Signed-off-by: Stefan Prodan --- cmd/flux/create_source_oci.go | 48 +++++++++++++----------- cmd/flux/list.go | 31 ++++++++++++++++ cmd/flux/list_artifact.go | 68 ++++++++++++++++++++++++++++++++++ internal/oci/list.go | 70 +++++++++++++++++++++++++++++++++++ internal/oci/meta.go | 3 +- internal/oci/pull.go | 2 +- 6 files changed, 198 insertions(+), 24 deletions(-) create mode 100644 cmd/flux/list.go create mode 100644 cmd/flux/list_artifact.go create mode 100644 internal/oci/list.go diff --git a/cmd/flux/create_source_oci.go b/cmd/flux/create_source_oci.go index e1d26c4351..a97c64fb12 100644 --- a/cmd/flux/create_source_oci.go +++ b/cmd/flux/create_source_oci.go @@ -19,7 +19,6 @@ package main import ( "context" "fmt" - "os" "strings" "github.com/spf13/cobra" @@ -43,7 +42,7 @@ var createSourceOCIRepositoryCmd = &cobra.Command{ Long: `The create source oci command generates an OCIRepository resource and waits for it to be ready.`, Example: ` # Create an OCIRepository for a public container image flux create source oci podinfo \ - --url=ghcr.io/stefanprodan/manifests/podinfo \ + --url=ghcr.io/stefanprodan/manifests/podinfo \ --tag=6.1.6 \ --interval=10m `, @@ -51,11 +50,13 @@ var createSourceOCIRepositoryCmd = &cobra.Command{ } type sourceOCIRepositoryFlags struct { - url string - tag string - digest string - secretRef string - ignorePaths []string + url string + tag string + semver string + digest string + secretRef string + serviceAccount string + ignorePaths []string } var sourceOCIRepositoryArgs = sourceOCIRepositoryFlags{} @@ -63,8 +64,10 @@ var sourceOCIRepositoryArgs = sourceOCIRepositoryFlags{} func init() { createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.url, "url", "", "the OCI repository URL") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.tag, "tag", "", "the OCI artifact tag") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.semver, "tag-semver", "", "the OCI artifact tag semver range") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.digest, "digest", "", "the OCI artifact digest") - createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "secret-ref", "", "the name of an existing secret containing credentials") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "secret-ref", "", "the name of the Kubernetes image pull secret (type 'kubernetes.io/dockerconfigjson')") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "service-account", "", "the name of the Kubernetes service account that refers to an image pull secret") createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)") createSourceCmd.AddCommand(createSourceOCIRepositoryCmd) @@ -77,8 +80,8 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("url is required") } - if sourceOCIRepositoryArgs.tag == "" && sourceOCIRepositoryArgs.digest == "" { - return fmt.Errorf("--tag or --digest is required") + if sourceOCIRepositoryArgs.semver == "" && sourceOCIRepositoryArgs.tag == "" && sourceOCIRepositoryArgs.digest == "" { + return fmt.Errorf("--tag, --tag-semver or --digest is required") } sourceLabels, err := parseLabels() @@ -86,12 +89,6 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error { return err } - tmpDir, err := os.MkdirTemp("", name) - if err != nil { - return err - } - defer os.RemoveAll(tmpDir) - var ignorePaths *string if len(sourceOCIRepositoryArgs.ignorePaths) > 0 { ignorePathsStr := strings.Join(sourceOCIRepositoryArgs.ignorePaths, "\n") @@ -114,20 +111,27 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error { }, } - if sourceOCIRepositoryArgs.tag != "" { - repository.Spec.Reference.Tag = sourceOCIRepositoryArgs.tag + if digest := sourceOCIRepositoryArgs.digest; digest != "" { + repository.Spec.Reference.Digest = digest } - if sourceOCIRepositoryArgs.digest != "" { - repository.Spec.Reference.Digest = sourceOCIRepositoryArgs.digest + if semver := sourceOCIRepositoryArgs.semver; semver != "" { + repository.Spec.Reference.SemVer = semver + } + if tag := sourceOCIRepositoryArgs.tag; tag != "" { + repository.Spec.Reference.Tag = tag } if createSourceArgs.fetchTimeout > 0 { repository.Spec.Timeout = &metav1.Duration{Duration: createSourceArgs.fetchTimeout} } - if sourceOCIRepositoryArgs.secretRef != "" { + if saName := sourceOCIRepositoryArgs.serviceAccount; saName != "" { + repository.Spec.ServiceAccountName = saName + } + + if secretName := sourceOCIRepositoryArgs.secretRef; secretName != "" { repository.Spec.SecretRef = &meta.LocalObjectReference{ - Name: sourceOCIRepositoryArgs.secretRef, + Name: secretName, } } diff --git a/cmd/flux/list.go b/cmd/flux/list.go new file mode 100644 index 0000000000..e89dc14963 --- /dev/null +++ b/cmd/flux/list.go @@ -0,0 +1,31 @@ +/* +Copyright 2021 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "github.com/spf13/cobra" +) + +var listCmd = &cobra.Command{ + Use: "list", + Short: "List artifacts", + Long: "The list command is used for printing the OCI artifacts metadata.", +} + +func init() { + rootCmd.AddCommand(listCmd) +} diff --git a/cmd/flux/list_artifact.go b/cmd/flux/list_artifact.go new file mode 100644 index 0000000000..a53e4f9975 --- /dev/null +++ b/cmd/flux/list_artifact.go @@ -0,0 +1,68 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "fmt" + "github.com/fluxcd/flux2/internal/oci" + "github.com/fluxcd/flux2/pkg/printers" + "github.com/spf13/cobra" +) + +var listArtifactsCmd = &cobra.Command{ + Use: "artifacts", + Short: "list artifacts", + Long: `The list command fetches the tags and their metadata from a remote OCI repository. +The list command uses the credentials from '~/.docker/config.json'.`, + Example: `# list the artifacts stored in an OCI repository +flux list artifact ghcr.io/org/manifests/app +`, + RunE: listArtifactsCmdRun, +} + +func init() { + listCmd.AddCommand(listArtifactsCmd) +} + +func listArtifactsCmdRun(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("artifact repository is required") + } + url := args[0] + + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) + defer cancel() + + metas, err := oci.List(ctx, url) + if err != nil { + return err + } + + var rows [][]string + for _, meta := range metas { + rows = append(rows, []string{meta.URL, meta.Digest, meta.Source, meta.Revision}) + } + + err = printers.TablePrinter([]string{"artifact", "digest", "source", "revision"}).Print(cmd.OutOrStdout(), rows) + if err != nil { + return err + } + + return nil + +} diff --git a/internal/oci/list.go b/internal/oci/list.go new file mode 100644 index 0000000000..e827c472c2 --- /dev/null +++ b/internal/oci/list.go @@ -0,0 +1,70 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "bytes" + "context" + "fmt" + "sort" + "strings" + + "github.com/google/go-containerregistry/pkg/crane" + gcrv1 "github.com/google/go-containerregistry/pkg/v1" +) + +// List fetches the tags and their manifests for a given OCI repository. +func List(ctx context.Context, url string) ([]Metadata, error) { + metas := make([]Metadata, 0) + tags, err := crane.ListTags(url, craneOptions(ctx)...) + if err != nil { + return nil, fmt.Errorf("listing tags failed: %w", err) + } + + sort.Slice(tags, func(i, j int) bool { return tags[i] > tags[j] }) + + for _, tag := range tags { + // exclude cosign signatures + if strings.HasSuffix(tag, ".sig") { + continue + } + + meta := Metadata{ + URL: fmt.Sprintf("%s:%s", url, tag), + } + + manifestJSON, err := crane.Manifest(meta.URL, craneOptions(ctx)...) + if err != nil { + return nil, fmt.Errorf("fetching manifest failed: %w", err) + } + + manifest, err := gcrv1.ParseManifest(bytes.NewReader(manifestJSON)) + if err != nil { + return nil, fmt.Errorf("parsing manifest failed: %w", err) + } + + meta.Digest = manifest.Config.Digest.String() + if m, err := MetadataFromAnnotations(manifest.Annotations); err == nil { + meta.Revision = m.Revision + meta.Source = m.Source + } + + metas = append(metas, meta) + } + + return metas, nil +} diff --git a/internal/oci/meta.go b/internal/oci/meta.go index 3196cb26dd..9e0c3c0ced 100644 --- a/internal/oci/meta.go +++ b/internal/oci/meta.go @@ -29,6 +29,7 @@ type Metadata struct { Source string `json:"source_url"` Revision string `json:"source_revision"` Digest string `json:"digest"` + URL string `json:"url"` } func (m *Metadata) ToAnnotations() map[string]string { @@ -40,7 +41,7 @@ func (m *Metadata) ToAnnotations() map[string]string { return annotations } -func GetMetadata(annotations map[string]string) (*Metadata, error) { +func MetadataFromAnnotations(annotations map[string]string) (*Metadata, error) { source, ok := annotations[SourceAnnotation] if !ok { return nil, fmt.Errorf("'%s' annotation not found", SourceAnnotation) diff --git a/internal/oci/pull.go b/internal/oci/pull.go index b37642a83e..f08c0e345d 100644 --- a/internal/oci/pull.go +++ b/internal/oci/pull.go @@ -47,7 +47,7 @@ func Pull(ctx context.Context, url, outDir string) (*Metadata, error) { return nil, fmt.Errorf("parsing manifest failed: %w", err) } - meta, err := GetMetadata(manifest.Annotations) + meta, err := MetadataFromAnnotations(manifest.Annotations) if err != nil { return nil, err } From e4fb8e75f965f33b06103686ab7dbbc4b4e507c4 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Thu, 23 Jun 2022 08:51:53 +0300 Subject: [PATCH 06/32] Add e2e tests for artifact commands Signed-off-by: Stefan Prodan --- .github/workflows/e2e.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 9f4fcb669d..2352f2e44b 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -9,6 +9,11 @@ on: jobs: kind: runs-on: ubuntu-latest + services: + registry: + image: registry:2 + ports: + - 5000:5000 steps: - name: Checkout uses: actions/checkout@v3 @@ -168,7 +173,16 @@ jobs: - name: flux delete source git run: | /tmp/flux delete source git podinfo --silent - - name: flux oci + - name: flux oci artifacts + run: | + /tmp/flux push artifact localhost:5000/fluxcd/flux:${{ github.sha }} \ + --path="./manifests" \ + --source="${{ github.repositoryUrl }}" \ + --revision="${{ github.ref }}/${{ github.sha }}" + /tmp/flux tag artifact localhost:5000/fluxcd/flux:${{ github.sha }} \ + --tag latest + /tmp/flux list artifact localhost:5000/fluxcd/flux + - name: flux oci repositories run: | /tmp/flux create source oci podinfo-oci \ --url ghcr.io/stefanprodan/manifests/podinfo \ From b6a78f42ea39d004d6e4ca8216321ef3ad190178 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Thu, 23 Jun 2022 09:08:06 +0300 Subject: [PATCH 07/32] Update SC with OCI semver support Signed-off-by: Stefan Prodan --- .github/workflows/e2e.yaml | 4 ++-- manifests/bases/source-controller/kustomization.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 2352f2e44b..1e0fdf57f3 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -181,12 +181,12 @@ jobs: --revision="${{ github.ref }}/${{ github.sha }}" /tmp/flux tag artifact localhost:5000/fluxcd/flux:${{ github.sha }} \ --tag latest - /tmp/flux list artifact localhost:5000/fluxcd/flux + /tmp/flux list artifacts localhost:5000/fluxcd/flux - name: flux oci repositories run: | /tmp/flux create source oci podinfo-oci \ --url ghcr.io/stefanprodan/manifests/podinfo \ - --tag 6.1.6 \ + --tag-semver 6.1.x \ --interval 10m /tmp/flux create kustomization podinfo-oci \ --source=OCIRepository/podinfo-oci \ diff --git a/manifests/bases/source-controller/kustomization.yaml b/manifests/bases/source-controller/kustomization.yaml index 29147274da..9d2e44e026 100644 --- a/manifests/bases/source-controller/kustomization.yaml +++ b/manifests/bases/source-controller/kustomization.yaml @@ -15,4 +15,4 @@ patchesJson6902: # TODO: remove the hardcoded image when OCIRepository is released images: - name: fluxcd/source-controller - newTag: oci-778f6d5d + newTag: oci-8509ac03 From 30e5389d02e60362f5ce2af89a7168830424e8e8 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Fri, 1 Jul 2022 15:18:21 +0300 Subject: [PATCH 08/32] Run e2e tests for PRs against oci branch Signed-off-by: Stefan Prodan --- .github/workflows/e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 1e0fdf57f3..709912de1c 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -4,7 +4,7 @@ on: push: branches: [ main ] pull_request: - branches: [ main ] + branches: [ main, oci ] jobs: kind: From adc7981f2290b4080aacf0cb81baed1ae96fb5ae Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Thu, 30 Jun 2022 12:07:29 +0100 Subject: [PATCH 09/32] Add tests for source oci command Signed-off-by: Somtochi Onyekwere --- cmd/flux/create_source_oci_test.go | 61 ++++++++++++++++ cmd/flux/image_test.go | 16 +++++ cmd/flux/main_test.go | 1 + cmd/flux/source_oci_test.go | 71 +++++++++++++++++++ .../testdata/oci/create_source_oci.golden | 5 ++ cmd/flux/testdata/oci/delete_oci.golden | 2 + cmd/flux/testdata/oci/export.golden | 12 ++++ .../testdata/oci/export_with_secret.golden | 14 ++++ cmd/flux/testdata/oci/get_oci.golden | 2 + cmd/flux/testdata/oci/reconcile_oci.golden | 4 ++ cmd/flux/testdata/oci/resume_oci.golden | 5 ++ cmd/flux/testdata/oci/suspend_oci.golden | 2 + 12 files changed, 195 insertions(+) create mode 100644 cmd/flux/create_source_oci_test.go create mode 100644 cmd/flux/source_oci_test.go create mode 100644 cmd/flux/testdata/oci/create_source_oci.golden create mode 100644 cmd/flux/testdata/oci/delete_oci.golden create mode 100644 cmd/flux/testdata/oci/export.golden create mode 100644 cmd/flux/testdata/oci/export_with_secret.golden create mode 100644 cmd/flux/testdata/oci/get_oci.golden create mode 100644 cmd/flux/testdata/oci/reconcile_oci.golden create mode 100644 cmd/flux/testdata/oci/resume_oci.golden create mode 100644 cmd/flux/testdata/oci/suspend_oci.golden diff --git a/cmd/flux/create_source_oci_test.go b/cmd/flux/create_source_oci_test.go new file mode 100644 index 0000000000..027c17899f --- /dev/null +++ b/cmd/flux/create_source_oci_test.go @@ -0,0 +1,61 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "testing" +) + +func TestCreateSourceOCI(t *testing.T) { + tests := []struct { + name string + args string + assertFunc assertFunc + }{ + { + name: "NoArgs", + args: "create source oci", + assertFunc: assertError("name is required"), + }, + { + name: "NoURL", + args: "create source oci podinfo", + assertFunc: assertError("url is required"), + }, + { + name: "export manifest", + args: "create source oci podinfo --url=ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m --export", + assertFunc: assertGoldenFile("./testdata/oci/export.golden"), + }, + { + name: "export manifest with secret", + args: "create source oci podinfo --url=ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m --secret-ref=creds --export", + assertFunc: assertGoldenFile("./testdata/oci/export_with_secret.golden"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := cmdTestCase{ + args: tt.args, + assert: tt.assertFunc, + } + + cmd.runTestCmd(t) + }) + } +} diff --git a/cmd/flux/image_test.go b/cmd/flux/image_test.go index a0e0b2574e..155326fadd 100644 --- a/cmd/flux/image_test.go +++ b/cmd/flux/image_test.go @@ -1,6 +1,22 @@ //go:build e2e // +build e2e +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package main import "testing" diff --git a/cmd/flux/main_test.go b/cmd/flux/main_test.go index 50127de7d8..59568dee79 100644 --- a/cmd/flux/main_test.go +++ b/cmd/flux/main_test.go @@ -388,6 +388,7 @@ func resetCmdArgs() { getArgs = GetFlags{} sourceHelmArgs = sourceHelmFlags{} secretGitArgs = NewSecretGitFlags() + *kubeconfigArgs.Namespace = rootArgs.defaults.Namespace } func isChangeError(err error) bool { diff --git a/cmd/flux/source_oci_test.go b/cmd/flux/source_oci_test.go new file mode 100644 index 0000000000..568ac73ee6 --- /dev/null +++ b/cmd/flux/source_oci_test.go @@ -0,0 +1,71 @@ +//go:build e2e +// +build e2e + +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "testing" +) + +func TestSourceOCI(t *testing.T) { + cases := []struct { + args string + goldenFile string + }{ + { + "create source oci thrfg --url=ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m", + "testdata/oci/create_source_oci.golden", + }, + { + "get source oci thrfg", + "testdata/oci/get_oci.golden", + }, + { + "reconcile source oci thrfg", + "testdata/oci/reconcile_oci.golden", + }, + { + "suspend source oci thrfg", + "testdata/oci/suspend_oci.golden", + }, + { + "resume source oci thrfg", + "testdata/oci/resume_oci.golden", + }, + { + "delete source oci thrfg --silent", + "testdata/oci/delete_oci.golden", + }, + } + + namespace := allocateNamespace("oci-test") + del, err := setupTestNamespace(namespace) + if err != nil { + t.Fatal(err) + } + defer del() + + for _, tc := range cases { + cmd := cmdTestCase{ + args: tc.args + " -n=" + namespace, + assert: assertGoldenTemplateFile(tc.goldenFile, map[string]string{"ns": namespace}), + } + cmd.runTestCmd(t) + } +} diff --git a/cmd/flux/testdata/oci/create_source_oci.golden b/cmd/flux/testdata/oci/create_source_oci.golden new file mode 100644 index 0000000000..9cca413855 --- /dev/null +++ b/cmd/flux/testdata/oci/create_source_oci.golden @@ -0,0 +1,5 @@ +► applying OCIRepository +✔ OCIRepository created +◎ waiting for OCIRepository reconciliation +✔ OCIRepository reconciliation completed +✔ fetched revision: 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de diff --git a/cmd/flux/testdata/oci/delete_oci.golden b/cmd/flux/testdata/oci/delete_oci.golden new file mode 100644 index 0000000000..8e8599fa12 --- /dev/null +++ b/cmd/flux/testdata/oci/delete_oci.golden @@ -0,0 +1,2 @@ +► deleting source oci thrfg in {{ .ns }} namespace +✔ source oci deleted diff --git a/cmd/flux/testdata/oci/export.golden b/cmd/flux/testdata/oci/export.golden new file mode 100644 index 0000000000..82d5fa19b5 --- /dev/null +++ b/cmd/flux/testdata/oci/export.golden @@ -0,0 +1,12 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: OCIRepository +metadata: + name: podinfo + namespace: flux-system +spec: + interval: 10m0s + ref: + tag: 6.1.6 + url: ghcr.io/stefanprodan/manifests/podinfo + diff --git a/cmd/flux/testdata/oci/export_with_secret.golden b/cmd/flux/testdata/oci/export_with_secret.golden new file mode 100644 index 0000000000..79fd98a5c9 --- /dev/null +++ b/cmd/flux/testdata/oci/export_with_secret.golden @@ -0,0 +1,14 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: OCIRepository +metadata: + name: podinfo + namespace: flux-system +spec: + interval: 10m0s + ref: + tag: 6.1.6 + secretRef: + name: creds + url: ghcr.io/stefanprodan/manifests/podinfo + diff --git a/cmd/flux/testdata/oci/get_oci.golden b/cmd/flux/testdata/oci/get_oci.golden new file mode 100644 index 0000000000..f4fa8333ba --- /dev/null +++ b/cmd/flux/testdata/oci/get_oci.golden @@ -0,0 +1,2 @@ +NAME REVISION SUSPENDED READY MESSAGE +thrfg 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de False True stored artifact for revision '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' diff --git a/cmd/flux/testdata/oci/reconcile_oci.golden b/cmd/flux/testdata/oci/reconcile_oci.golden new file mode 100644 index 0000000000..0c25881946 --- /dev/null +++ b/cmd/flux/testdata/oci/reconcile_oci.golden @@ -0,0 +1,4 @@ +► annotating OCIRepository thrfg in {{ .ns }} namespace +✔ OCIRepository annotated +◎ waiting for OCIRepository reconciliation +✔ fetched revision 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de diff --git a/cmd/flux/testdata/oci/resume_oci.golden b/cmd/flux/testdata/oci/resume_oci.golden new file mode 100644 index 0000000000..467514e7d8 --- /dev/null +++ b/cmd/flux/testdata/oci/resume_oci.golden @@ -0,0 +1,5 @@ +► resuming source oci thrfg in {{ .ns }} namespace +✔ source oci resumed +◎ waiting for OCIRepository reconciliation +✔ OCIRepository reconciliation completed +✔ fetched revision 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de diff --git a/cmd/flux/testdata/oci/suspend_oci.golden b/cmd/flux/testdata/oci/suspend_oci.golden new file mode 100644 index 0000000000..40a0420e37 --- /dev/null +++ b/cmd/flux/testdata/oci/suspend_oci.golden @@ -0,0 +1,2 @@ +► suspending source oci thrfg in {{ .ns }} namespace +✔ source oci suspended From 8049634e4d65e577288aaf105d2f83ab064b19e7 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 6 Jul 2022 19:02:39 +0300 Subject: [PATCH 10/32] Add `oci://` prefix Signed-off-by: Stefan Prodan --- .github/workflows/e2e.yaml | 8 +-- cmd/flux/create_source_oci.go | 4 +- cmd/flux/create_source_oci_test.go | 4 +- cmd/flux/list_artifact.go | 11 ++-- cmd/flux/main_test.go | 3 ++ cmd/flux/pull_artifact.go | 11 ++-- cmd/flux/push_artifact.go | 11 ++-- cmd/flux/source_oci_test.go | 2 +- cmd/flux/tag_artifact.go | 9 +++- cmd/flux/testdata/oci/export.golden | 2 +- .../testdata/oci/export_with_secret.golden | 2 +- internal/oci/url.go | 54 +++++++++++++++++++ .../source-controller/kustomization.yaml | 2 +- 13 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 internal/oci/url.go diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 709912de1c..6b8566e9a9 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -175,17 +175,17 @@ jobs: /tmp/flux delete source git podinfo --silent - name: flux oci artifacts run: | - /tmp/flux push artifact localhost:5000/fluxcd/flux:${{ github.sha }} \ + /tmp/flux push artifact oci://localhost:5000/fluxcd/flux:${{ github.sha }} \ --path="./manifests" \ --source="${{ github.repositoryUrl }}" \ --revision="${{ github.ref }}/${{ github.sha }}" - /tmp/flux tag artifact localhost:5000/fluxcd/flux:${{ github.sha }} \ + /tmp/flux tag artifact oci://localhost:5000/fluxcd/flux:${{ github.sha }} \ --tag latest - /tmp/flux list artifacts localhost:5000/fluxcd/flux + /tmp/flux list artifacts oci://localhost:5000/fluxcd/flux - name: flux oci repositories run: | /tmp/flux create source oci podinfo-oci \ - --url ghcr.io/stefanprodan/manifests/podinfo \ + --url oci://ghcr.io/stefanprodan/manifests/podinfo \ --tag-semver 6.1.x \ --interval 10m /tmp/flux create kustomization podinfo-oci \ diff --git a/cmd/flux/create_source_oci.go b/cmd/flux/create_source_oci.go index a97c64fb12..dd2b4fbfec 100644 --- a/cmd/flux/create_source_oci.go +++ b/cmd/flux/create_source_oci.go @@ -42,7 +42,7 @@ var createSourceOCIRepositoryCmd = &cobra.Command{ Long: `The create source oci command generates an OCIRepository resource and waits for it to be ready.`, Example: ` # Create an OCIRepository for a public container image flux create source oci podinfo \ - --url=ghcr.io/stefanprodan/manifests/podinfo \ + --url=oci://ghcr.io/stefanprodan/manifests/podinfo \ --tag=6.1.6 \ --interval=10m `, @@ -67,7 +67,7 @@ func init() { createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.semver, "tag-semver", "", "the OCI artifact tag semver range") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.digest, "digest", "", "the OCI artifact digest") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "secret-ref", "", "the name of the Kubernetes image pull secret (type 'kubernetes.io/dockerconfigjson')") - createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "service-account", "", "the name of the Kubernetes service account that refers to an image pull secret") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.serviceAccount, "service-account", "", "the name of the Kubernetes service account that refers to an image pull secret") createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)") createSourceCmd.AddCommand(createSourceOCIRepositoryCmd) diff --git a/cmd/flux/create_source_oci_test.go b/cmd/flux/create_source_oci_test.go index 027c17899f..04be9cb136 100644 --- a/cmd/flux/create_source_oci_test.go +++ b/cmd/flux/create_source_oci_test.go @@ -38,12 +38,12 @@ func TestCreateSourceOCI(t *testing.T) { }, { name: "export manifest", - args: "create source oci podinfo --url=ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m --export", + args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m --export", assertFunc: assertGoldenFile("./testdata/oci/export.golden"), }, { name: "export manifest with secret", - args: "create source oci podinfo --url=ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m --secret-ref=creds --export", + args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m --secret-ref=creds --export", assertFunc: assertGoldenFile("./testdata/oci/export_with_secret.golden"), }, } diff --git a/cmd/flux/list_artifact.go b/cmd/flux/list_artifact.go index a53e4f9975..e499fc7341 100644 --- a/cmd/flux/list_artifact.go +++ b/cmd/flux/list_artifact.go @@ -30,7 +30,7 @@ var listArtifactsCmd = &cobra.Command{ Long: `The list command fetches the tags and their metadata from a remote OCI repository. The list command uses the credentials from '~/.docker/config.json'.`, Example: `# list the artifacts stored in an OCI repository -flux list artifact ghcr.io/org/manifests/app +flux list artifact oci://ghcr.io/org/manifests/app `, RunE: listArtifactsCmdRun, } @@ -41,13 +41,18 @@ func init() { func listArtifactsCmdRun(cmd *cobra.Command, args []string) error { if len(args) < 1 { - return fmt.Errorf("artifact repository is required") + return fmt.Errorf("artifact repository URL is required") } - url := args[0] + ociURL := args[0] ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) defer cancel() + url, err := oci.ParseArtifactURL(ociURL) + if err != nil { + return err + } + metas, err := oci.List(ctx, url) if err != nil { return err diff --git a/cmd/flux/main_test.go b/cmd/flux/main_test.go index 59568dee79..2adf47159d 100644 --- a/cmd/flux/main_test.go +++ b/cmd/flux/main_test.go @@ -387,6 +387,9 @@ func resetCmdArgs() { createArgs = createFlags{} getArgs = GetFlags{} sourceHelmArgs = sourceHelmFlags{} + sourceOCIRepositoryArgs = sourceOCIRepositoryFlags{} + sourceGitArgs = sourceGitFlags{} + sourceBucketArgs = sourceBucketFlags{} secretGitArgs = NewSecretGitFlags() *kubeconfigArgs.Namespace = rootArgs.defaults.Namespace } diff --git a/cmd/flux/pull_artifact.go b/cmd/flux/pull_artifact.go index 37560f68a4..382cdc6954 100644 --- a/cmd/flux/pull_artifact.go +++ b/cmd/flux/pull_artifact.go @@ -32,7 +32,7 @@ var pullArtifactCmd = &cobra.Command{ Long: `The pull artifact command downloads and extracts the OCI artifact content to the given path. The pull command uses the credentials from '~/.docker/config.json'.`, Example: `# Pull an OCI artifact created by flux from GHCR -flux pull artifact ghcr.io/org/manifests/app:v0.0.1 --output ./path/to/local/manifests +flux pull artifact oci://ghcr.io/org/manifests/app:v0.0.1 --output ./path/to/local/manifests `, RunE: pullArtifactCmdRun, } @@ -50,9 +50,9 @@ func init() { func pullArtifactCmdRun(cmd *cobra.Command, args []string) error { if len(args) < 1 { - return fmt.Errorf("artifact name is required") + return fmt.Errorf("artifact URL is required") } - url := args[0] + ociURL := args[0] if pullArtifactArgs.output == "" { return fmt.Errorf("invalid output path %s", pullArtifactArgs.output) @@ -62,6 +62,11 @@ func pullArtifactCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("invalid output path %s", pullArtifactArgs.output) } + url, err := oci.ParseArtifactURL(ociURL) + if err != nil { + return err + } + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) defer cancel() diff --git a/cmd/flux/push_artifact.go b/cmd/flux/push_artifact.go index 813dbb46e1..49f6120287 100644 --- a/cmd/flux/push_artifact.go +++ b/cmd/flux/push_artifact.go @@ -32,7 +32,7 @@ var pushArtifactCmd = &cobra.Command{ Long: `The push artifact command creates a tarball from the given directory and uploads the artifact to a OCI repository. The push command uses the credentials from '~/.docker/config.json'.`, Example: `# Push the local manifests to GHCR -flux push artifact ghcr.io/org/manifests/app:v0.0.1 \ +flux push artifact oci://ghcr.io/org/manifests/app:v0.0.1 \ --path="./path/to/local/manifests" \ --source="$(git config --get remote.origin.url)" \ --revision="$(git branch --show-current)/$(git rev-parse HEAD)" @@ -57,9 +57,9 @@ func init() { func pushArtifactCmdRun(cmd *cobra.Command, args []string) error { if len(args) < 1 { - return fmt.Errorf("artifact name is required") + return fmt.Errorf("artifact URL is required") } - url := args[0] + ociURL := args[0] if pushArtifactArgs.source == "" { return fmt.Errorf("--source is required") @@ -73,6 +73,11 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("invalid path %q", pushArtifactArgs.path) } + url, err := oci.ParseArtifactURL(ociURL) + if err != nil { + return err + } + if fs, err := os.Stat(pushArtifactArgs.path); err != nil || !fs.IsDir() { return fmt.Errorf("invalid path %q", pushArtifactArgs.path) } diff --git a/cmd/flux/source_oci_test.go b/cmd/flux/source_oci_test.go index 568ac73ee6..c0f8125cbd 100644 --- a/cmd/flux/source_oci_test.go +++ b/cmd/flux/source_oci_test.go @@ -29,7 +29,7 @@ func TestSourceOCI(t *testing.T) { goldenFile string }{ { - "create source oci thrfg --url=ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m", + "create source oci thrfg --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.1.6 --interval 10m", "testdata/oci/create_source_oci.golden", }, { diff --git a/cmd/flux/tag_artifact.go b/cmd/flux/tag_artifact.go index be0a6387d7..2004cebc1a 100644 --- a/cmd/flux/tag_artifact.go +++ b/cmd/flux/tag_artifact.go @@ -29,7 +29,7 @@ var tagArtifactCmd = &cobra.Command{ Long: `The tag artifact command creates tags for the given OCI artifact. The tag command uses the credentials from '~/.docker/config.json'.`, Example: `# Tag an artifact version as latest -flux tag artifact ghcr.io/org/manifests/app:v0.0.1 --tag latest +flux tag artifact oci://ghcr.io/org/manifests/app:v0.0.1 --tag latest `, RunE: tagArtifactCmdRun, } @@ -49,12 +49,17 @@ func tagArtifactCmdRun(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("artifact name is required") } - url := args[0] + ociURL := args[0] if len(tagArtifactArgs.tags) < 1 { return fmt.Errorf("--tag is required") } + url, err := oci.ParseArtifactURL(ociURL) + if err != nil { + return err + } + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) defer cancel() diff --git a/cmd/flux/testdata/oci/export.golden b/cmd/flux/testdata/oci/export.golden index 82d5fa19b5..b9339d73e0 100644 --- a/cmd/flux/testdata/oci/export.golden +++ b/cmd/flux/testdata/oci/export.golden @@ -8,5 +8,5 @@ spec: interval: 10m0s ref: tag: 6.1.6 - url: ghcr.io/stefanprodan/manifests/podinfo + url: oci://ghcr.io/stefanprodan/manifests/podinfo diff --git a/cmd/flux/testdata/oci/export_with_secret.golden b/cmd/flux/testdata/oci/export_with_secret.golden index 79fd98a5c9..385f770711 100644 --- a/cmd/flux/testdata/oci/export_with_secret.golden +++ b/cmd/flux/testdata/oci/export_with_secret.golden @@ -10,5 +10,5 @@ spec: tag: 6.1.6 secretRef: name: creds - url: ghcr.io/stefanprodan/manifests/podinfo + url: oci://ghcr.io/stefanprodan/manifests/podinfo diff --git a/internal/oci/url.go b/internal/oci/url.go new file mode 100644 index 0000000000..38dafb1f50 --- /dev/null +++ b/internal/oci/url.go @@ -0,0 +1,54 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "fmt" + "strings" + + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + "github.com/google/go-containerregistry/pkg/name" +) + +// ParseArtifactURL validates the OCI URL and returns the address of the artifact. +func ParseArtifactURL(ociURL string) (string, error) { + if !strings.HasPrefix(ociURL, sourcev1.OCIRepositoryPrefix) { + return "", fmt.Errorf("URL must be in format 'oci:////'") + } + + url := strings.TrimPrefix(ociURL, sourcev1.OCIRepositoryPrefix) + if _, err := name.ParseReference(url); err != nil { + return "", fmt.Errorf("'%s' invalid URL: %w", ociURL, err) + } + + return url, nil +} + +// ParseRepositoryURL validates the OCI URL and returns the address of the artifact repository. +func ParseRepositoryURL(ociURL string) (string, error) { + if !strings.HasPrefix(ociURL, sourcev1.OCIRepositoryPrefix) { + return "", fmt.Errorf("URL must be in format 'oci:////'") + } + + url := strings.TrimPrefix(ociURL, sourcev1.OCIRepositoryPrefix) + ref, err := name.ParseReference(url) + if err != nil { + return "", fmt.Errorf("'%s' invalid URL: %w", ociURL, err) + } + + return ref.Context().Name(), nil +} diff --git a/manifests/bases/source-controller/kustomization.yaml b/manifests/bases/source-controller/kustomization.yaml index 9d2e44e026..f268590cfa 100644 --- a/manifests/bases/source-controller/kustomization.yaml +++ b/manifests/bases/source-controller/kustomization.yaml @@ -15,4 +15,4 @@ patchesJson6902: # TODO: remove the hardcoded image when OCIRepository is released images: - name: fluxcd/source-controller - newTag: oci-8509ac03 + newTag: oci-ba5f5353 From 6b985904614c468adc56a38847b69d6fcbefde59 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Fri, 8 Jul 2022 16:27:39 +0300 Subject: [PATCH 11/32] Add `--cert-ref` to `flux create source oci` Signed-off-by: Stefan Prodan --- cmd/flux/create_source_oci.go | 8 ++++++++ cmd/flux/testdata/oci/get_oci.golden | 2 +- manifests/bases/source-controller/kustomization.yaml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/flux/create_source_oci.go b/cmd/flux/create_source_oci.go index dd2b4fbfec..57d1a4728f 100644 --- a/cmd/flux/create_source_oci.go +++ b/cmd/flux/create_source_oci.go @@ -56,6 +56,7 @@ type sourceOCIRepositoryFlags struct { digest string secretRef string serviceAccount string + certSecretRef string ignorePaths []string } @@ -68,6 +69,7 @@ func init() { createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.digest, "digest", "", "the OCI artifact digest") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.secretRef, "secret-ref", "", "the name of the Kubernetes image pull secret (type 'kubernetes.io/dockerconfigjson')") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.serviceAccount, "service-account", "", "the name of the Kubernetes service account that refers to an image pull secret") + createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.certSecretRef, "cert-ref", "", "the name of a secret to use for TLS certificates") createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)") createSourceCmd.AddCommand(createSourceOCIRepositoryCmd) @@ -135,6 +137,12 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error { } } + if secretName := sourceOCIRepositoryArgs.certSecretRef; secretName != "" { + repository.Spec.CertSecretRef = &meta.LocalObjectReference{ + Name: secretName, + } + } + if createArgs.export { return printExport(exportOCIRepository(repository)) } diff --git a/cmd/flux/testdata/oci/get_oci.golden b/cmd/flux/testdata/oci/get_oci.golden index f4fa8333ba..3c9558bf70 100644 --- a/cmd/flux/testdata/oci/get_oci.golden +++ b/cmd/flux/testdata/oci/get_oci.golden @@ -1,2 +1,2 @@ NAME REVISION SUSPENDED READY MESSAGE -thrfg 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de False True stored artifact for revision '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' +thrfg 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de False True stored artifact for digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' diff --git a/manifests/bases/source-controller/kustomization.yaml b/manifests/bases/source-controller/kustomization.yaml index f268590cfa..3b42223df1 100644 --- a/manifests/bases/source-controller/kustomization.yaml +++ b/manifests/bases/source-controller/kustomization.yaml @@ -15,4 +15,4 @@ patchesJson6902: # TODO: remove the hardcoded image when OCIRepository is released images: - name: fluxcd/source-controller - newTag: oci-ba5f5353 + newTag: oci-09a9ef44 From 7dd736954b1497176951c0154d06bc97137a6ae2 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Mon, 11 Jul 2022 17:00:24 +0300 Subject: [PATCH 12/32] Use OCI standard annotations Signed-off-by: Stefan Prodan --- internal/oci/meta.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/oci/meta.go b/internal/oci/meta.go index 9e0c3c0ced..c1a43fa457 100644 --- a/internal/oci/meta.go +++ b/internal/oci/meta.go @@ -21,8 +21,8 @@ import ( ) const ( - SourceAnnotation = "source.toolkit.fluxcd.io/url" - RevisionAnnotation = "source.toolkit.fluxcd.io/revision" + SourceAnnotation = "org.opencontainers.image.source" + RevisionAnnotation = "org.opencontainers.image.revision" ) type Metadata struct { From 1b327e9d4eb0754b36a3a891cb1a69accd055afd Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Mon, 11 Jul 2022 18:15:35 +0300 Subject: [PATCH 13/32] Show artifact digest in list output Signed-off-by: Stefan Prodan --- internal/oci/list.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/oci/list.go b/internal/oci/list.go index e827c472c2..9901d1d826 100644 --- a/internal/oci/list.go +++ b/internal/oci/list.go @@ -57,12 +57,17 @@ func List(ctx context.Context, url string) ([]Metadata, error) { return nil, fmt.Errorf("parsing manifest failed: %w", err) } - meta.Digest = manifest.Config.Digest.String() if m, err := MetadataFromAnnotations(manifest.Annotations); err == nil { meta.Revision = m.Revision meta.Source = m.Source } + digest, err := crane.Digest(meta.URL, craneOptions(ctx)...) + if err != nil { + return nil, fmt.Errorf("fetching digest failed: %w", err) + } + meta.Digest = digest + metas = append(metas, meta) } From 3e15e83926da168c04bc2d610489a537e22a804f Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Fri, 8 Jul 2022 15:54:57 +0100 Subject: [PATCH 14/32] Add test for tag/list/build/pull/push artifacts Signed-off-by: Somtochi Onyekwere --- go.sum | 48 +++++++- internal/oci/build_test.go | 48 ++++++++ internal/oci/list_test.go | 53 ++++++++ internal/oci/push_pull_test.go | 64 ++++++++++ internal/oci/suite_test.go | 115 ++++++++++++++++++ internal/oci/tag_test.go | 46 +++++++ internal/oci/testdata/build/deployment.yaml | 0 internal/oci/testdata/build/somedir/repo.yaml | 0 8 files changed, 371 insertions(+), 3 deletions(-) create mode 100644 internal/oci/build_test.go create mode 100644 internal/oci/list_test.go create mode 100644 internal/oci/push_pull_test.go create mode 100644 internal/oci/suite_test.go create mode 100644 internal/oci/tag_test.go create mode 100644 internal/oci/testdata/build/deployment.yaml create mode 100644 internal/oci/testdata/build/somedir/repo.yaml diff --git a/go.sum b/go.sum index e57cb655a7..83432bf9e9 100644 --- a/go.sum +++ b/go.sum @@ -59,10 +59,12 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= +github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE= +github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= @@ -102,6 +104,8 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= @@ -140,6 +144,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= @@ -147,6 +152,14 @@ github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2y github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -211,6 +224,8 @@ github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1 github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/distribution/distribution/v3 v3.0.0-20220702071910-8857a1948739 h1:fOBqIwS8s+ircSm/N6VQcIZPaFoomoAWgxwG2Ssp15I= +github.com/distribution/distribution/v3 v3.0.0-20220702071910-8857a1948739/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61icFuZl6iKYs= github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= @@ -219,6 +234,12 @@ github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405c github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= @@ -255,6 +276,7 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluxcd/go-git-providers v0.6.0 h1:XJc3MTYFpuahBSoKTVxmH9OBPCeIyvYoQkTjTqa3fH4= github.com/fluxcd/go-git-providers v0.6.0/go.mod h1:UMFHnMCIO9CBpEln7ZsArEWyXSNxTpm76fyQxUmClrc= @@ -290,7 +312,6 @@ github.com/fluxcd/source-controller/api v0.25.11 h1:1YbH5vlQ1k96tbRKTdQHCBsBVMgp github.com/fluxcd/source-controller/api v0.25.11/go.mod h1:5kihSWjg+gIXLPTTXbe6AnY+g+iDmP+CY4g6nFqublc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -369,6 +390,9 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -418,6 +442,8 @@ github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPP github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gonvenience/bunt v1.3.4 h1:Row599Ohja2BPooaqd1tHYdTAKu6SWq7W/UeakTXddM= github.com/gonvenience/bunt v1.3.4/go.mod h1:j8eqHLBo8eWCCYuc34oFdlgyxL1rZ4ywYz4BZa4b09w= github.com/gonvenience/neat v1.3.10 h1:gHrVkQAvbUsZgnpEglPwsAJLPqSFQxOgfbB3FWLhmUo= @@ -503,6 +529,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -735,6 +763,7 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f h1:2+myh5ml7lgEU/51gbeLHfKGNfgEQQIWrlbdaOsidbQ= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= @@ -810,6 +839,8 @@ github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -825,6 +856,7 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= @@ -837,6 +869,7 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= @@ -844,6 +877,7 @@ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= @@ -999,6 +1033,12 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -1073,6 +1113,7 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -1225,6 +1266,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/internal/oci/build_test.go b/internal/oci/build_test.go new file mode 100644 index 0000000000..085dfe9c89 --- /dev/null +++ b/internal/oci/build_test.go @@ -0,0 +1,48 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "os" + "path/filepath" + "testing" + + . "github.com/onsi/gomega" +) + +func TestBuild(t *testing.T) { + g := NewWithT(t) + testDir := "./testdata/build" + + tmpDir := t.TempDir() + artifactPath := filepath.Join(tmpDir, "files.tar.gz") + + // test with non-existent path + err := Build(artifactPath, "testdata/non-existent") + g.Expect(err).To(HaveOccurred()) + + err = Build(artifactPath, testDir) + g.Expect(err).ToNot(HaveOccurred()) + + if _, err := os.Stat(artifactPath); err != nil { + g.Expect(err).ToNot(HaveOccurred()) + } + + if err != nil { + t.Errorf("error working directory, %s", err) + } +} diff --git a/internal/oci/list_test.go b/internal/oci/list_test.go new file mode 100644 index 0000000000..0a21237d83 --- /dev/null +++ b/internal/oci/list_test.go @@ -0,0 +1,53 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "context" + "fmt" + "testing" + + "github.com/google/go-containerregistry/pkg/crane" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/random" + . "github.com/onsi/gomega" +) + +func Test_List(t *testing.T) { + g := NewWithT(t) + ctx := context.Background() + repo := "test-list" + randStringRunes(5) + tags := []string{"v0.0.1", "v0.0.2", "v0.0.3"} + + for _, tag := range tags { + dst := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag) + img, err := random.Image(1024, 1) + g.Expect(err).ToNot(HaveOccurred()) + err = crane.Push(img, dst, craneOptions(ctx)...) + g.Expect(err).ToNot(HaveOccurred()) + } + + metadata, err := List(ctx, fmt.Sprintf("%s/%s", dockerReg, repo)) + g.Expect(err).ToNot(HaveOccurred()) + + g.Expect(len(metadata)).To(Equal(len(tags))) + for _, meta := range metadata { + tag, err := name.NewTag(meta.URL) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(tag.TagStr()).Should(BeElementOf(tags)) + } +} diff --git a/internal/oci/push_pull_test.go b/internal/oci/push_pull_test.go new file mode 100644 index 0000000000..f2ebc9bead --- /dev/null +++ b/internal/oci/push_pull_test.go @@ -0,0 +1,64 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "context" + "fmt" + "io/fs" + "os" + "path/filepath" + "testing" + + "github.com/google/go-containerregistry/pkg/crane" + . "github.com/onsi/gomega" +) + +func Test_Push_Pull(t *testing.T) { + g := NewWithT(t) + ctx := context.Background() + tag := "v0.0.1" + repo := "test-push" + randStringRunes(5) + + url := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag) + metadata := Metadata{ + Source: "github.com/fluxcd/fluxv2", + Revision: "rev", + } + + testDir := "testdata/build" + _, err := Push(ctx, url, testDir, metadata) + g.Expect(err).ToNot(HaveOccurred()) + + tags, err := crane.ListTags(fmt.Sprintf("%s/%s", dockerReg, repo)) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(len(tags)).To(BeEquivalentTo(1)) + + tmpDir := t.TempDir() + _, err = Pull(ctx, url, tmpDir) + g.Expect(err).ToNot(HaveOccurred()) + + // Walk directory the test directory and check that each path exists in the extracted archive + err = filepath.Walk(testDir, func(path string, info fs.FileInfo, err error) error { + tmpPath := filepath.Join(tmpDir, path) + if _, err := os.Stat(tmpPath); err != nil && os.IsNotExist(err) { + return fmt.Errorf("path '%s' doesn't exist in archive", path) + } + + return nil + }) +} diff --git a/internal/oci/suite_test.go b/internal/oci/suite_test.go new file mode 100644 index 0000000000..2ac5d2692b --- /dev/null +++ b/internal/oci/suite_test.go @@ -0,0 +1,115 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "context" + "fmt" + "io/ioutil" + "math/rand" + "os" + "path/filepath" + "testing" + "time" + + ctrl "sigs.k8s.io/controller-runtime" + + "github.com/distribution/distribution/v3/configuration" + "github.com/distribution/distribution/v3/registry" + _ "github.com/distribution/distribution/v3/registry/auth/htpasswd" + _ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory" + "github.com/phayes/freeport" + "golang.org/x/crypto/bcrypt" +) + +const ( + testRegistryHtpasswdFileBasename = "authtest.htpasswd" + testRegistryUsername = "myuser" + testRegistryPassword = "mypass" +) + +var ( + dockerReg string +) + +func init() { + rand.Seed(time.Now().UnixNano()) +} + +func setupRegistryServer(ctx context.Context) error { + // Create a temporary workspace directory for the registry + workspaceDir, err := os.MkdirTemp("", "registry-test-") + if err != nil { + return fmt.Errorf("failed to create workspace directory: %w", err) + } + + // create htpasswd file (w BCrypt, which is required) + pwBytes, err := bcrypt.GenerateFromPassword([]byte(testRegistryPassword), bcrypt.DefaultCost) + if err != nil { + return fmt.Errorf("failed to generate password: %s", err) + } + + htpasswdPath := filepath.Join(workspaceDir, testRegistryHtpasswdFileBasename) + err = ioutil.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testRegistryUsername, string(pwBytes))), 0644) + if err != nil { + return fmt.Errorf("failed to create htpasswd file: %s", err) + } + + // Registry config + config := &configuration.Configuration{} + port, err := freeport.GetFreePort() + if err != nil { + return fmt.Errorf("failed to get free port: %s", err) + } + + dockerReg = fmt.Sprintf("localhost:%d", port) + config.HTTP.Addr = fmt.Sprintf("127.0.0.1:%d", port) + config.HTTP.DrainTimeout = time.Duration(10) * time.Second + config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} + dockerRegistry, err := registry.NewRegistry(ctx, config) + if err != nil { + return fmt.Errorf("failed to create docker registry: %w", err) + } + + // Start Docker registry + go dockerRegistry.ListenAndServe() + + return nil +} + +func TestMain(m *testing.M) { + ctx := ctrl.SetupSignalHandler() + + err := setupRegistryServer(ctx) + if err != nil { + panic(fmt.Sprintf("failed to start docker registry: %s", err)) + } + + code := m.Run() + + os.Exit(code) +} + +var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890") + +func randStringRunes(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return string(b) +} diff --git a/internal/oci/tag_test.go b/internal/oci/tag_test.go new file mode 100644 index 0000000000..81cbebb11e --- /dev/null +++ b/internal/oci/tag_test.go @@ -0,0 +1,46 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package oci + +import ( + "context" + "fmt" + "testing" + + "github.com/google/go-containerregistry/pkg/crane" + "github.com/google/go-containerregistry/pkg/v1/random" + . "github.com/onsi/gomega" +) + +func Test_Tag(t *testing.T) { + g := NewWithT(t) + ctx := context.Background() + testRepo := "test-tag" + url := fmt.Sprintf("%s/%s:v0.0.1", dockerReg, testRepo) + img, err := random.Image(1024, 1) + g.Expect(err).ToNot(HaveOccurred()) + err = crane.Push(img, url, craneOptions(ctx)...) + g.Expect(err).ToNot(HaveOccurred()) + + _, err = Tag(ctx, url, "v0.0.2") + g.Expect(err).ToNot(HaveOccurred()) + + tags, err := crane.ListTags(fmt.Sprintf("%s/%s", dockerReg, testRepo)) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(len(tags)).To(BeEquivalentTo(2)) + g.Expect(tags).To(BeEquivalentTo([]string{"v0.0.1", "v0.0.2"})) +} diff --git a/internal/oci/testdata/build/deployment.yaml b/internal/oci/testdata/build/deployment.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/oci/testdata/build/somedir/repo.yaml b/internal/oci/testdata/build/somedir/repo.yaml new file mode 100644 index 0000000000..e69de29bb2 From b78bbd5b9d54f0cdc2724b4c0612706f98ffbc74 Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Fri, 8 Jul 2022 16:20:01 +0100 Subject: [PATCH 15/32] fill test files Signed-off-by: Somtochi Onyekwere --- internal/oci/build_test.go | 4 --- internal/oci/push_pull_test.go | 2 +- internal/oci/suite_test.go | 29 ------------------- internal/oci/testdata/build/deployment.yaml | 21 ++++++++++++++ internal/oci/testdata/build/somedir/repo.yaml | 8 +++++ 5 files changed, 30 insertions(+), 34 deletions(-) diff --git a/internal/oci/build_test.go b/internal/oci/build_test.go index 085dfe9c89..2f6c561678 100644 --- a/internal/oci/build_test.go +++ b/internal/oci/build_test.go @@ -41,8 +41,4 @@ func TestBuild(t *testing.T) { if _, err := os.Stat(artifactPath); err != nil { g.Expect(err).ToNot(HaveOccurred()) } - - if err != nil { - t.Errorf("error working directory, %s", err) - } } diff --git a/internal/oci/push_pull_test.go b/internal/oci/push_pull_test.go index f2ebc9bead..c37c92d29e 100644 --- a/internal/oci/push_pull_test.go +++ b/internal/oci/push_pull_test.go @@ -52,7 +52,7 @@ func Test_Push_Pull(t *testing.T) { _, err = Pull(ctx, url, tmpDir) g.Expect(err).ToNot(HaveOccurred()) - // Walk directory the test directory and check that each path exists in the extracted archive + // Walk directory the test directory and check that all paths exists in the extracted archive err = filepath.Walk(testDir, func(path string, info fs.FileInfo, err error) error { tmpPath := filepath.Join(tmpDir, path) if _, err := os.Stat(tmpPath); err != nil && os.IsNotExist(err) { diff --git a/internal/oci/suite_test.go b/internal/oci/suite_test.go index 2ac5d2692b..c611e1ab5c 100644 --- a/internal/oci/suite_test.go +++ b/internal/oci/suite_test.go @@ -19,10 +19,8 @@ package oci import ( "context" "fmt" - "io/ioutil" "math/rand" "os" - "path/filepath" "testing" "time" @@ -33,13 +31,6 @@ import ( _ "github.com/distribution/distribution/v3/registry/auth/htpasswd" _ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory" "github.com/phayes/freeport" - "golang.org/x/crypto/bcrypt" -) - -const ( - testRegistryHtpasswdFileBasename = "authtest.htpasswd" - testRegistryUsername = "myuser" - testRegistryPassword = "mypass" ) var ( @@ -51,24 +42,6 @@ func init() { } func setupRegistryServer(ctx context.Context) error { - // Create a temporary workspace directory for the registry - workspaceDir, err := os.MkdirTemp("", "registry-test-") - if err != nil { - return fmt.Errorf("failed to create workspace directory: %w", err) - } - - // create htpasswd file (w BCrypt, which is required) - pwBytes, err := bcrypt.GenerateFromPassword([]byte(testRegistryPassword), bcrypt.DefaultCost) - if err != nil { - return fmt.Errorf("failed to generate password: %s", err) - } - - htpasswdPath := filepath.Join(workspaceDir, testRegistryHtpasswdFileBasename) - err = ioutil.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testRegistryUsername, string(pwBytes))), 0644) - if err != nil { - return fmt.Errorf("failed to create htpasswd file: %s", err) - } - // Registry config config := &configuration.Configuration{} port, err := freeport.GetFreePort() @@ -93,14 +66,12 @@ func setupRegistryServer(ctx context.Context) error { func TestMain(m *testing.M) { ctx := ctrl.SetupSignalHandler() - err := setupRegistryServer(ctx) if err != nil { panic(fmt.Sprintf("failed to start docker registry: %s", err)) } code := m.Run() - os.Exit(code) } diff --git a/internal/oci/testdata/build/deployment.yaml b/internal/oci/testdata/build/deployment.yaml index e69de29bb2..007ecd317d 100644 --- a/internal/oci/testdata/build/deployment.yaml +++ b/internal/oci/testdata/build/deployment.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + labels: + app: nginx +spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/internal/oci/testdata/build/somedir/repo.yaml b/internal/oci/testdata/build/somedir/repo.yaml index e69de29bb2..253b76323e 100644 --- a/internal/oci/testdata/build/somedir/repo.yaml +++ b/internal/oci/testdata/build/somedir/repo.yaml @@ -0,0 +1,8 @@ +apiVersion: source.toolkit.fluxcd.io/v1beta1 +kind: HelmRepository +metadata: + name: podinfo + namespace: flux-system +spec: + interval: 2m + url: https://stefanprodan.github.io/podinfo From 9e76787e9fa050f3e5ee23553abc4a97f7aa4868 Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Mon, 11 Jul 2022 16:28:44 +0100 Subject: [PATCH 16/32] working golden files Signed-off-by: Somtochi Onyekwere --- cmd/flux/testdata/oci/get_oci.golden | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/flux/testdata/oci/get_oci.golden b/cmd/flux/testdata/oci/get_oci.golden index 3c9558bf70..d88eb6c0bf 100644 --- a/cmd/flux/testdata/oci/get_oci.golden +++ b/cmd/flux/testdata/oci/get_oci.golden @@ -1,2 +1,2 @@ -NAME REVISION SUSPENDED READY MESSAGE -thrfg 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de False True stored artifact for digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' +NAME REVISION SUSPENDED READY MESSAGE +thrfg 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de False True stored artifact for digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' From 009413affd1a54f29f24ec87be9b80d1b3f402f9 Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Mon, 11 Jul 2022 17:15:22 +0100 Subject: [PATCH 17/32] Add test for annotations Signed-off-by: Somtochi Onyekwere --- internal/oci/list_test.go | 15 +++++++++++++++ internal/oci/push_pull_test.go | 10 +++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/internal/oci/list_test.go b/internal/oci/list_test.go index 0a21237d83..c67a3a6cf3 100644 --- a/internal/oci/list_test.go +++ b/internal/oci/list_test.go @@ -23,6 +23,8 @@ import ( "github.com/google/go-containerregistry/pkg/crane" "github.com/google/go-containerregistry/pkg/name" + gcrv1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/mutate" "github.com/google/go-containerregistry/pkg/v1/random" . "github.com/onsi/gomega" ) @@ -32,11 +34,18 @@ func Test_List(t *testing.T) { ctx := context.Background() repo := "test-list" + randStringRunes(5) tags := []string{"v0.0.1", "v0.0.2", "v0.0.3"} + source := "github.com/fluxcd/fluxv2" + rev := "rev" + m := Metadata{ + Source: source, + Revision: rev, + } for _, tag := range tags { dst := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag) img, err := random.Image(1024, 1) g.Expect(err).ToNot(HaveOccurred()) + img = mutate.Annotations(img, m.ToAnnotations()).(gcrv1.Image) err = crane.Push(img, dst, craneOptions(ctx)...) g.Expect(err).ToNot(HaveOccurred()) } @@ -49,5 +58,11 @@ func Test_List(t *testing.T) { tag, err := name.NewTag(meta.URL) g.Expect(err).ToNot(HaveOccurred()) g.Expect(tag.TagStr()).Should(BeElementOf(tags)) + + g.Expect(meta.ToAnnotations()).To(Equal(m.ToAnnotations())) + + digest, err := crane.Digest(meta.URL, craneOptions(ctx)...) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(meta.Digest).To(Equal(digest)) } } diff --git a/internal/oci/push_pull_test.go b/internal/oci/push_pull_test.go index c37c92d29e..1083dcddda 100644 --- a/internal/oci/push_pull_test.go +++ b/internal/oci/push_pull_test.go @@ -36,9 +36,10 @@ func Test_Push_Pull(t *testing.T) { url := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag) metadata := Metadata{ - Source: "github.com/fluxcd/fluxv2", + Source: "github.com/fluxcd/flux2", Revision: "rev", } + annotations := metadata.ToAnnotations() testDir := "testdata/build" _, err := Push(ctx, url, testDir, metadata) @@ -48,6 +49,13 @@ func Test_Push_Pull(t *testing.T) { g.Expect(err).ToNot(HaveOccurred()) g.Expect(len(tags)).To(BeEquivalentTo(1)) + image, err := crane.Pull(fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag)) + g.Expect(err).ToNot(HaveOccurred()) + + manifest, err := image.Manifest() + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(manifest.Annotations).To(BeEquivalentTo(annotations)) + tmpDir := t.TempDir() _, err = Pull(ctx, url, tmpDir) g.Expect(err).ToNot(HaveOccurred()) From 030b6bc77c372c1aeb3c52337b6f64e5788c4fae Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 13 Jul 2022 13:17:00 +0300 Subject: [PATCH 18/32] Update source-controller with OCI metadata Signed-off-by: Stefan Prodan --- manifests/bases/source-controller/kustomization.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/bases/source-controller/kustomization.yaml b/manifests/bases/source-controller/kustomization.yaml index 3b42223df1..921ebff12c 100644 --- a/manifests/bases/source-controller/kustomization.yaml +++ b/manifests/bases/source-controller/kustomization.yaml @@ -15,4 +15,4 @@ patchesJson6902: # TODO: remove the hardcoded image when OCIRepository is released images: - name: fluxcd/source-controller - newTag: oci-09a9ef44 + newTag: oci-102e9a94 From 803104578fe7942e3459238d93a0ee2719ef9d56 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 13 Jul 2022 13:17:23 +0300 Subject: [PATCH 19/32] Add `make build-dev` command Signed-off-by: Stefan Prodan --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 7942926d7a..8daf0426ae 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ VERSION?=$(shell grep 'VERSION' cmd/flux/main.go | awk '{ print $$4 }' | head -n 1 | tr -d '"') +DEV_VERSION?=0.0.0-$(shell git rev-parse --abbrev-ref HEAD)-$(shell git rev-parse --short HEAD)-$(shell date +%s) EMBEDDED_MANIFESTS_TARGET=cmd/flux/.manifests.done TEST_KUBECONFIG?=/tmp/flux-e2e-test-kubeconfig # Architecture to use envtest with @@ -55,6 +56,9 @@ $(EMBEDDED_MANIFESTS_TARGET): $(call rwildcard,manifests/,*.yaml *.json) build: $(EMBEDDED_MANIFESTS_TARGET) CGO_ENABLED=0 go build -ldflags="-s -w -X main.VERSION=$(VERSION)" -o ./bin/flux ./cmd/flux +build-dev: $(EMBEDDED_MANIFESTS_TARGET) + CGO_ENABLED=0 go build -ldflags="-s -w -X main.VERSION=$(DEV_VERSION)" -o ./bin/flux ./cmd/flux + .PHONY: install install: CGO_ENABLED=0 go install ./cmd/flux From 70d30fd52e68d6287e7c84ab4f338cc2d403e121 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 13 Jul 2022 13:39:32 +0300 Subject: [PATCH 20/32] Update golden files to latest digest Signed-off-by: Stefan Prodan --- cmd/flux/testdata/oci/create_source_oci.golden | 2 +- cmd/flux/testdata/oci/get_oci.golden | 2 +- cmd/flux/testdata/oci/reconcile_oci.golden | 2 +- cmd/flux/testdata/oci/resume_oci.golden | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/flux/testdata/oci/create_source_oci.golden b/cmd/flux/testdata/oci/create_source_oci.golden index 9cca413855..6b2563c914 100644 --- a/cmd/flux/testdata/oci/create_source_oci.golden +++ b/cmd/flux/testdata/oci/create_source_oci.golden @@ -2,4 +2,4 @@ ✔ OCIRepository created ◎ waiting for OCIRepository reconciliation ✔ OCIRepository reconciliation completed -✔ fetched revision: 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de +✔ fetched revision: ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 diff --git a/cmd/flux/testdata/oci/get_oci.golden b/cmd/flux/testdata/oci/get_oci.golden index d88eb6c0bf..3d5a8a1cb7 100644 --- a/cmd/flux/testdata/oci/get_oci.golden +++ b/cmd/flux/testdata/oci/get_oci.golden @@ -1,2 +1,2 @@ NAME REVISION SUSPENDED READY MESSAGE -thrfg 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de False True stored artifact for digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' +thrfg ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 False True stored artifact for digest 'ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59' diff --git a/cmd/flux/testdata/oci/reconcile_oci.golden b/cmd/flux/testdata/oci/reconcile_oci.golden index 0c25881946..c0223e8d20 100644 --- a/cmd/flux/testdata/oci/reconcile_oci.golden +++ b/cmd/flux/testdata/oci/reconcile_oci.golden @@ -1,4 +1,4 @@ ► annotating OCIRepository thrfg in {{ .ns }} namespace ✔ OCIRepository annotated ◎ waiting for OCIRepository reconciliation -✔ fetched revision 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de +✔ fetched revision ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 diff --git a/cmd/flux/testdata/oci/resume_oci.golden b/cmd/flux/testdata/oci/resume_oci.golden index 467514e7d8..0851c4877e 100644 --- a/cmd/flux/testdata/oci/resume_oci.golden +++ b/cmd/flux/testdata/oci/resume_oci.golden @@ -2,4 +2,4 @@ ✔ source oci resumed ◎ waiting for OCIRepository reconciliation ✔ OCIRepository reconciliation completed -✔ fetched revision 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de +✔ fetched revision ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 From 4c576bf59920a34663128a9f7aa3f2dc0e9bd8eb Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Mon, 18 Jul 2022 15:54:41 +0100 Subject: [PATCH 21/32] Add create oci secret command Signed-off-by: Somtochi Onyekwere --- cmd/flux/create_secret_helm_test.go | 16 +++ cmd/flux/create_secret_oci.go | 117 ++++++++++++++++++ cmd/flux/create_secret_oci_test.go | 51 ++++++++ .../create_secret/oci/create-secret.yaml | 10 ++ pkg/manifestgen/sourcesecret/options.go | 1 + pkg/manifestgen/sourcesecret/sourcesecret.go | 48 ++++++- 6 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 cmd/flux/create_secret_oci.go create mode 100644 cmd/flux/create_secret_oci_test.go create mode 100644 cmd/flux/testdata/create_secret/oci/create-secret.yaml diff --git a/cmd/flux/create_secret_helm_test.go b/cmd/flux/create_secret_helm_test.go index fe0bc0c941..821f8311be 100644 --- a/cmd/flux/create_secret_helm_test.go +++ b/cmd/flux/create_secret_helm_test.go @@ -1,3 +1,19 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package main import ( diff --git a/cmd/flux/create_secret_oci.go b/cmd/flux/create_secret_oci.go new file mode 100644 index 0000000000..decd680c3a --- /dev/null +++ b/cmd/flux/create_secret_oci.go @@ -0,0 +1,117 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "fmt" + + "github.com/fluxcd/flux2/internal/utils" + "github.com/fluxcd/flux2/pkg/manifestgen/sourcesecret" + "github.com/google/go-containerregistry/pkg/name" + "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" +) + +var createSecretOCICmd = &cobra.Command{ + Use: "oci [name]", + Short: "Create or update a Kubernetes secret for docker authentication", + Long: `The create secret oci command generates a Kubernetes secret with `, + Example: ` # Create a secret for a OCI repository using basic authentication + flux create secret oci podinfo-auth \ + --url=ghcr.io/stefanprodan/charts \ + --username=username \ + --password=password + `, + RunE: createSecretOCICmdRun, +} + +type secretOCIFlags struct { + url string + password string + username string +} + +var secretOCIArgs = secretOCIFlags{} + +func init() { + createSecretOCICmd.Flags().StringVar(&secretOCIArgs.url, "url", "", "oci repository address e.g ghcr.io/stefanprodan/charts") + createSecretOCICmd.Flags().StringVarP(&secretOCIArgs.username, "username", "u", "", "basic authentication username") + createSecretOCICmd.Flags().StringVarP(&secretOCIArgs.password, "password", "p", "", "basic authentication") + + createSecretCmd.AddCommand(createSecretOCICmd) +} + +func createSecretOCICmdRun(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("name is required") + } + + secretName := args[0] + + if secretOCIArgs.url == "" { + return fmt.Errorf("--url is required") + } + + if secretOCIArgs.username == "" { + return fmt.Errorf("--username is required") + } + + if secretOCIArgs.password == "" { + return fmt.Errorf("--password is required") + } + + if _, err := name.ParseReference(secretOCIArgs.url); err != nil { + return fmt.Errorf("error parsing url: '%s'", err) + } + + opts := sourcesecret.Options{ + Name: secretName, + Namespace: *kubeconfigArgs.Namespace, + Registry: secretOCIArgs.url, + Password: secretOCIArgs.password, + Username: secretOCIArgs.username, + } + + secret, err := sourcesecret.Generate(opts) + if err != nil { + return err + } + + if createArgs.export { + rootCmd.Println(secret.Content) + return nil + } + + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) + defer cancel() + kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions) + if err != nil { + return err + } + var s corev1.Secret + if err := yaml.Unmarshal([]byte(secret.Content), &s); err != nil { + return err + } + if err := upsertSecret(ctx, kubeClient, s); err != nil { + return err + } + + logger.Actionf("oci secret '%s' created in '%s' namespace", secretName, *kubeconfigArgs.Namespace) + return nil +} diff --git a/cmd/flux/create_secret_oci_test.go b/cmd/flux/create_secret_oci_test.go new file mode 100644 index 0000000000..a78977961e --- /dev/null +++ b/cmd/flux/create_secret_oci_test.go @@ -0,0 +1,51 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "testing" +) + +func TestCreateSecretOCI(t *testing.T) { + tests := []struct { + name string + args string + assert assertFunc + }{ + { + args: "create secret oci", + assert: assertError("name is required"), + }, + { + args: "create secret oci ghcr", + assert: assertError("--url is required"), + }, + { + args: "create secret oci ghcr --namespace=my-namespace --url ghcr.io --username stefanprodan --password=password --export", + assert: assertGoldenFile("testdata/create_secret/oci/create-secret.yaml"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := cmdTestCase{ + args: tt.args, + assert: tt.assert, + } + cmd.runTestCmd(t) + }) + } +} diff --git a/cmd/flux/testdata/create_secret/oci/create-secret.yaml b/cmd/flux/testdata/create_secret/oci/create-secret.yaml new file mode 100644 index 0000000000..b023bbe287 --- /dev/null +++ b/cmd/flux/testdata/create_secret/oci/create-secret.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: ghcr + namespace: my-namespace +stringData: + .dockerconfigjson: '{"auths":{"ghcr.io":{"username":"stefanprodan","password":"password","auth":"c3RlZmFucHJvZGFuOnBhc3N3b3Jk"}}}' +type: kubernetes.io/dockerconfigjson + diff --git a/pkg/manifestgen/sourcesecret/options.go b/pkg/manifestgen/sourcesecret/options.go index c5239bfbd8..371e6f9b15 100644 --- a/pkg/manifestgen/sourcesecret/options.go +++ b/pkg/manifestgen/sourcesecret/options.go @@ -43,6 +43,7 @@ type Options struct { Name string Namespace string Labels map[string]string + Registry string SSHHostname string PrivateKeyAlgorithm PrivateKeyAlgorithm RSAKeyBits int diff --git a/pkg/manifestgen/sourcesecret/sourcesecret.go b/pkg/manifestgen/sourcesecret/sourcesecret.go index 53806328be..2ea33227ba 100644 --- a/pkg/manifestgen/sourcesecret/sourcesecret.go +++ b/pkg/manifestgen/sourcesecret/sourcesecret.go @@ -18,6 +18,8 @@ package sourcesecret import ( "bytes" + "encoding/base64" + "encoding/json" "fmt" "net" "os" @@ -36,6 +38,18 @@ import ( const defaultSSHPort = 22 +type DockerConfigJson struct { + Auths DockerConfig `json:"auths"` +} + +type DockerConfig map[string]DockerConfigEntry + +type DockerConfigEntry struct { + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Auth string `json:"auth,omitempty"` +} + func Generate(options Options) (*manifestgen.Manifest, error) { var err error @@ -77,7 +91,15 @@ func Generate(options Options) (*manifestgen.Manifest, error) { } } - secret := buildSecret(keypair, hostKey, caFile, certFile, keyFile, options) + var dockerCfgJson []byte + if options.Registry != "" { + dockerCfgJson, err = generateDockerConfigJson(options.Registry, options.Username, options.Password) + if err != nil { + return nil, fmt.Errorf("failed to generate json for docker config: %w", err) + } + } + + secret := buildSecret(keypair, hostKey, caFile, certFile, keyFile, dockerCfgJson, options) b, err := yaml.Marshal(secret) if err != nil { return nil, err @@ -89,7 +111,7 @@ func Generate(options Options) (*manifestgen.Manifest, error) { }, nil } -func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile []byte, options Options) (secret corev1.Secret) { +func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile, dockerCfg []byte, options Options) (secret corev1.Secret) { secret.TypeMeta = metav1.TypeMeta{ APIVersion: "v1", Kind: "Secret", @@ -101,6 +123,12 @@ func buildSecret(keypair *ssh.KeyPair, hostKey, caFile, certFile, keyFile []byte secret.Labels = options.Labels secret.StringData = map[string]string{} + if dockerCfg != nil { + secret.Type = corev1.SecretTypeDockerConfigJson + secret.StringData[corev1.DockerConfigJsonKey] = string(dockerCfg) + return + } + if options.Username != "" && options.Password != "" { secret.StringData[UsernameSecretKey] = options.Username secret.StringData[PasswordSecretKey] = options.Password @@ -189,3 +217,19 @@ func resourceToString(data []byte) string { data = bytes.Replace(data, []byte("status: {}\n"), []byte(""), 1) return string(data) } + +func generateDockerConfigJson(url, username, password string) ([]byte, error) { + cred := fmt.Sprintf("%s:%s", username, password) + auth := base64.StdEncoding.EncodeToString([]byte(cred)) + cfg := DockerConfigJson{ + Auths: map[string]DockerConfigEntry{ + url: { + Username: username, + Password: password, + Auth: auth, + }, + }, + } + + return json.Marshal(cfg) +} From fe4b65972a18d54091d55c958f616d933966716a Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Tue, 19 Jul 2022 08:20:34 +0100 Subject: [PATCH 22/32] Update cli description Signed-off-by: Somtochi Onyekwere --- cmd/flux/create_secret_oci.go | 12 ++++++++---- pkg/manifestgen/sourcesecret/sourcesecret.go | 10 ++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/cmd/flux/create_secret_oci.go b/cmd/flux/create_secret_oci.go index decd680c3a..8adc184c50 100644 --- a/cmd/flux/create_secret_oci.go +++ b/cmd/flux/create_secret_oci.go @@ -30,13 +30,17 @@ import ( var createSecretOCICmd = &cobra.Command{ Use: "oci [name]", - Short: "Create or update a Kubernetes secret for docker authentication", + Short: "Create or update a Kubernetes secret for OCI Registry authentication", Long: `The create secret oci command generates a Kubernetes secret with `, - Example: ` # Create a secret for a OCI repository using basic authentication + Example: ` # Create an OCI authentication secret on disk and encrypt it with Mozilla SOPS flux create secret oci podinfo-auth \ - --url=ghcr.io/stefanprodan/charts \ + --url=ghcr.io \ --username=username \ - --password=password + --password=password \ + --export > repo-auth.yaml + + sops --encrypt --encrypted-regex '^(data|stringData)$' \ + --in-place repo-auth.yaml `, RunE: createSecretOCICmdRun, } diff --git a/pkg/manifestgen/sourcesecret/sourcesecret.go b/pkg/manifestgen/sourcesecret/sourcesecret.go index 2ea33227ba..cbca1c7301 100644 --- a/pkg/manifestgen/sourcesecret/sourcesecret.go +++ b/pkg/manifestgen/sourcesecret/sourcesecret.go @@ -38,12 +38,18 @@ import ( const defaultSSHPort = 22 -type DockerConfigJson struct { +// DockerConfigJSON represents a local docker auth config file +// for pulling images. +type DockerConfigJSON struct { Auths DockerConfig `json:"auths"` } +// DockerConfig represents the config file used by the docker CLI. +// This config that represents the credentials that should be used +// when pulling images from specific image repositories. type DockerConfig map[string]DockerConfigEntry +// DockerConfigEntry holds the user information that grant the access to docker registry type DockerConfigEntry struct { Username string `json:"username,omitempty"` Password string `json:"password,omitempty"` @@ -221,7 +227,7 @@ func resourceToString(data []byte) string { func generateDockerConfigJson(url, username, password string) ([]byte, error) { cred := fmt.Sprintf("%s:%s", username, password) auth := base64.StdEncoding.EncodeToString([]byte(cred)) - cfg := DockerConfigJson{ + cfg := DockerConfigJSON{ Auths: map[string]DockerConfigEntry{ url: { Username: username, From fcd38c9395eae61c3af416738a146cd3393575f4 Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Tue, 19 Jul 2022 08:28:11 +0100 Subject: [PATCH 23/32] Fix cli description Signed-off-by: Somtochi Onyekwere --- cmd/flux/create_secret_oci.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/flux/create_secret_oci.go b/cmd/flux/create_secret_oci.go index 8adc184c50..2e86f4618f 100644 --- a/cmd/flux/create_secret_oci.go +++ b/cmd/flux/create_secret_oci.go @@ -37,9 +37,9 @@ var createSecretOCICmd = &cobra.Command{ --url=ghcr.io \ --username=username \ --password=password \ - --export > repo-auth.yaml + --export > repo-auth.yaml - sops --encrypt --encrypted-regex '^(data|stringData)$' \ + sops --encrypt --encrypted-regex '^(data|stringData)$' \ --in-place repo-auth.yaml `, RunE: createSecretOCICmdRun, @@ -56,7 +56,7 @@ var secretOCIArgs = secretOCIFlags{} func init() { createSecretOCICmd.Flags().StringVar(&secretOCIArgs.url, "url", "", "oci repository address e.g ghcr.io/stefanprodan/charts") createSecretOCICmd.Flags().StringVarP(&secretOCIArgs.username, "username", "u", "", "basic authentication username") - createSecretOCICmd.Flags().StringVarP(&secretOCIArgs.password, "password", "p", "", "basic authentication") + createSecretOCICmd.Flags().StringVarP(&secretOCIArgs.password, "password", "p", "", "basic authentication password") createSecretCmd.AddCommand(createSecretOCICmd) } From 41aac68193ef302c907c4df9595389ce41aa6759 Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Tue, 19 Jul 2022 19:25:47 +0100 Subject: [PATCH 24/32] Add link to kubectl repo Signed-off-by: Somtochi Onyekwere --- pkg/manifestgen/sourcesecret/sourcesecret.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/manifestgen/sourcesecret/sourcesecret.go b/pkg/manifestgen/sourcesecret/sourcesecret.go index cbca1c7301..87567168d0 100644 --- a/pkg/manifestgen/sourcesecret/sourcesecret.go +++ b/pkg/manifestgen/sourcesecret/sourcesecret.go @@ -38,6 +38,8 @@ import ( const defaultSSHPort = 22 +// types gotten from https://github.com/kubernetes/kubectl/blob/master/pkg/cmd/create/create_secret_docker.go#L64-L84 + // DockerConfigJSON represents a local docker auth config file // for pulling images. type DockerConfigJSON struct { @@ -53,6 +55,7 @@ type DockerConfig map[string]DockerConfigEntry type DockerConfigEntry struct { Username string `json:"username,omitempty"` Password string `json:"password,omitempty"` + Email string `json:"email,omitempty"` Auth string `json:"auth,omitempty"` } From 69e26ca1d945c90a52256e010e56284bc55284db Mon Sep 17 00:00:00 2001 From: Kingdon Barrett Date: Tue, 2 Aug 2022 16:36:49 -0400 Subject: [PATCH 25/32] Pull artifact not push artifact Fixup docs string to match pull command Signed-off-by: Kingdon Barrett --- cmd/flux/pull_artifact.go | 2 +- go.mod | 25 +++++++++++++++++++++---- go.sum | 8 ++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/cmd/flux/pull_artifact.go b/cmd/flux/pull_artifact.go index 382cdc6954..3178f7fa3a 100644 --- a/cmd/flux/pull_artifact.go +++ b/cmd/flux/pull_artifact.go @@ -28,7 +28,7 @@ import ( var pullArtifactCmd = &cobra.Command{ Use: "artifact", - Short: "Push artifact", + Short: "Pull artifact", Long: `The pull artifact command downloads and extracts the OCI artifact content to the given path. The pull command uses the credentials from '~/.docker/config.json'.`, Example: `# Pull an OCI artifact created by flux from GHCR diff --git a/go.mod b/go.mod index cbd12b6125..b86f16f5fe 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b github.com/cyphar/filepath-securejoin v0.2.3 + github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f github.com/fluxcd/go-git-providers v0.6.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/image-automation-controller/api v0.23.5 @@ -19,7 +20,7 @@ require ( github.com/fluxcd/pkg/ssh v0.5.0 github.com/fluxcd/pkg/untar v0.1.0 github.com/fluxcd/pkg/version v0.1.0 - github.com/fluxcd/source-controller/api v0.25.11 + github.com/fluxcd/source-controller/api v0.25.10-0.20220803075204-d95db9403032 github.com/go-git/go-git/v5 v5.4.2 github.com/gonvenience/bunt v1.3.4 github.com/gonvenience/ytbx v1.4.4 @@ -32,6 +33,7 @@ require ( github.com/mattn/go-shellwords v1.0.12 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/gomega v1.19.0 + github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/theckman/yacspin v0.13.12 @@ -57,8 +59,8 @@ require ( cloud.google.com/go v0.99.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.18 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect + github.com/Azure/go-autorest/autorest v0.11.24 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect @@ -67,8 +69,13 @@ require ( github.com/Microsoft/go-winio v0.5.2 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect github.com/acomagu/bufpipe v1.0.3 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect + github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd // indirect + github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b // indirect + github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect @@ -79,15 +86,18 @@ require ( github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v20.10.16+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect + github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect + github.com/docker/go-metrics v0.0.1 // indirect + github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 // indirect github.com/emicklei/go-restful v2.9.5+incompatible // indirect github.com/emirpasic/gods v1.12.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/color v1.13.0 // indirect + github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect github.com/fluxcd/pkg/apis/kustomize v0.4.2 // indirect - github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/go-errors/errors v1.0.1 // indirect github.com/go-git/gcfg v1.5.0 // indirect @@ -97,8 +107,10 @@ require ( github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/gomodule/redigo v1.8.2 // indirect github.com/gonvenience/neat v1.3.10 // indirect github.com/gonvenience/term v1.0.2 // indirect github.com/gonvenience/text v1.0.7 // indirect @@ -110,6 +122,8 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -157,6 +171,9 @@ require ( github.com/xanzy/go-gitlab v0.58.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect + github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect + github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 // indirect + github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 // indirect diff --git a/go.sum b/go.sum index 83432bf9e9..7d33a4b0fb 100644 --- a/go.sum +++ b/go.sum @@ -224,8 +224,8 @@ github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1 github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/distribution/distribution/v3 v3.0.0-20220702071910-8857a1948739 h1:fOBqIwS8s+ircSm/N6VQcIZPaFoomoAWgxwG2Ssp15I= -github.com/distribution/distribution/v3 v3.0.0-20220702071910-8857a1948739/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= +github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f h1:3NCYdjXycNd/Xn/iICZzmxkiDX1e1cjTHjbMAz+wRVk= +github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61icFuZl6iKYs= github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= @@ -308,8 +308,8 @@ github.com/fluxcd/pkg/untar v0.1.0 h1:k97V/xV5hFrAkIkVPuv5AVhyxh1ZzzAKba/lbDfGo6 github.com/fluxcd/pkg/untar v0.1.0/go.mod h1:aGswNyzB1mlz/T/kpOS58mITBMxMKc9tlJBH037A2HY= github.com/fluxcd/pkg/version v0.1.0 h1:v+SmCanmCB5Tj2Cx9TXlj+kNRfPGbAvirkeqsp7ZEAQ= github.com/fluxcd/pkg/version v0.1.0/go.mod h1:V7Z/w8dxLQzv0FHqa5ox5TeyOd2zOd49EeuWFgnwyj4= -github.com/fluxcd/source-controller/api v0.25.11 h1:1YbH5vlQ1k96tbRKTdQHCBsBVMgpp/QaRpKG/r29koQ= -github.com/fluxcd/source-controller/api v0.25.11/go.mod h1:5kihSWjg+gIXLPTTXbe6AnY+g+iDmP+CY4g6nFqublc= +github.com/fluxcd/source-controller/api v0.25.10-0.20220803075204-d95db9403032 h1:qJgj+/LGV4bjxutw5ENVLHgAe1MpdfMASC00Qb75NIY= +github.com/fluxcd/source-controller/api v0.25.10-0.20220803075204-d95db9403032/go.mod h1:1W0Xx/GpZ14Z/sOltxjsQKXeCv8zxAqSivbX9e4s+H8= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= From 08401f62b2ad7b4573cb85847a56c35288aa530f Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 3 Aug 2022 11:53:28 +0300 Subject: [PATCH 26/32] Add OCI provider arg Signed-off-by: Stefan Prodan --- cmd/flux/create_source_oci.go | 14 ++++- internal/flags/source_bucket_provider.go | 7 ++- internal/flags/source_oci_provider.go | 62 +++++++++++++++++++ .../source-controller/kustomization.yaml | 2 +- 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 internal/flags/source_oci_provider.go diff --git a/cmd/flux/create_source_oci.go b/cmd/flux/create_source_oci.go index 57d1a4728f..2481fe7d03 100644 --- a/cmd/flux/create_source_oci.go +++ b/cmd/flux/create_source_oci.go @@ -33,6 +33,7 @@ import ( sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + "github.com/fluxcd/flux2/internal/flags" "github.com/fluxcd/flux2/internal/utils" ) @@ -58,11 +59,19 @@ type sourceOCIRepositoryFlags struct { serviceAccount string certSecretRef string ignorePaths []string + provider flags.SourceOCIProvider } -var sourceOCIRepositoryArgs = sourceOCIRepositoryFlags{} +var sourceOCIRepositoryArgs = newSourceOCIFlags() + +func newSourceOCIFlags() sourceOCIRepositoryFlags { + return sourceOCIRepositoryFlags{ + provider: flags.SourceOCIProvider(sourcev1.GenericOCIProvider), + } +} func init() { + createSourceOCIRepositoryCmd.Flags().Var(&sourceOCIRepositoryArgs.provider, "provider", sourceBucketArgs.provider.Description()) createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.url, "url", "", "the OCI repository URL") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.tag, "tag", "", "the OCI artifact tag") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.semver, "tag-semver", "", "the OCI artifact tag semver range") @@ -104,7 +113,8 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error { Labels: sourceLabels, }, Spec: sourcev1.OCIRepositorySpec{ - URL: sourceOCIRepositoryArgs.url, + Provider: sourceOCIRepositoryArgs.provider.String(), + URL: sourceOCIRepositoryArgs.url, Interval: metav1.Duration{ Duration: createArgs.interval, }, diff --git a/internal/flags/source_bucket_provider.go b/internal/flags/source_bucket_provider.go index f5c62c719c..6e2bfaa5cf 100644 --- a/internal/flags/source_bucket_provider.go +++ b/internal/flags/source_bucket_provider.go @@ -24,7 +24,12 @@ import ( sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" ) -var supportedSourceBucketProviders = []string{sourcev1.GenericBucketProvider, sourcev1.AmazonBucketProvider} +var supportedSourceBucketProviders = []string{ + sourcev1.GenericBucketProvider, + sourcev1.AmazonBucketProvider, + sourcev1.AzureBucketProvider, + sourcev1.GoogleBucketProvider, +} type SourceBucketProvider string diff --git a/internal/flags/source_oci_provider.go b/internal/flags/source_oci_provider.go new file mode 100644 index 0000000000..5f5067abc7 --- /dev/null +++ b/internal/flags/source_oci_provider.go @@ -0,0 +1,62 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "fmt" + "strings" + + "github.com/fluxcd/flux2/internal/utils" + sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" +) + +var supportedSourceOCIProviders = []string{ + sourcev1.GenericOCIProvider, + sourcev1.AmazonOCIProvider, + sourcev1.AzureOCIProvider, + sourcev1.GoogleOCIProvider, +} + +type SourceOCIProvider string + +func (p *SourceOCIProvider) String() string { + return string(*p) +} + +func (p *SourceOCIProvider) Set(str string) error { + if strings.TrimSpace(str) == "" { + return fmt.Errorf("no source OCI provider given, please specify %s", + p.Description()) + } + if !utils.ContainsItemString(supportedSourceOCIProviders, str) { + return fmt.Errorf("source OCI provider '%s' is not supported, must be one of: %v", + str, strings.Join(supportedSourceOCIProviders, ", ")) + } + *p = SourceOCIProvider(str) + return nil +} + +func (p *SourceOCIProvider) Type() string { + return "sourceOCIProvider" +} + +func (p *SourceOCIProvider) Description() string { + return fmt.Sprintf( + "the OCI provider name, available options are: (%s)", + strings.Join(supportedSourceOCIProviders, ", "), + ) +} diff --git a/manifests/bases/source-controller/kustomization.yaml b/manifests/bases/source-controller/kustomization.yaml index 921ebff12c..2e882adaa6 100644 --- a/manifests/bases/source-controller/kustomization.yaml +++ b/manifests/bases/source-controller/kustomization.yaml @@ -15,4 +15,4 @@ patchesJson6902: # TODO: remove the hardcoded image when OCIRepository is released images: - name: fluxcd/source-controller - newTag: oci-102e9a94 + newTag: oci-d95db940 From 7c7e76f9f0b8f9226eba3e3125f58de40a2a0bd6 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 3 Aug 2022 12:55:50 +0300 Subject: [PATCH 27/32] Use fluxcd/pkg/oci/client Signed-off-by: Stefan Prodan --- cmd/flux/build_artifact.go | 5 +- cmd/flux/list_artifact.go | 11 +- cmd/flux/pull_artifact.go | 5 +- cmd/flux/push_artifact.go | 5 +- cmd/flux/tag_artifact.go | 7 +- go.mod | 60 +++----- go.sum | 97 ++++++------ internal/oci/build.go | 139 ------------------ internal/oci/build_test.go | 44 ------ internal/oci/list.go | 75 ---------- internal/oci/list_test.go | 68 --------- internal/oci/meta.go | 61 -------- internal/oci/pull.go | 75 ---------- internal/oci/push.go | 81 ---------- internal/oci/push_pull_test.go | 72 --------- internal/oci/suite_test.go | 86 ----------- internal/oci/tag.go | 40 ----- internal/oci/tag_test.go | 46 ------ internal/oci/testdata/build/deployment.yaml | 21 --- internal/oci/testdata/build/somedir/repo.yaml | 8 - internal/oci/url.go | 54 ------- 21 files changed, 88 insertions(+), 972 deletions(-) delete mode 100644 internal/oci/build.go delete mode 100644 internal/oci/build_test.go delete mode 100644 internal/oci/list.go delete mode 100644 internal/oci/list_test.go delete mode 100644 internal/oci/meta.go delete mode 100644 internal/oci/pull.go delete mode 100644 internal/oci/push.go delete mode 100644 internal/oci/push_pull_test.go delete mode 100644 internal/oci/suite_test.go delete mode 100644 internal/oci/tag.go delete mode 100644 internal/oci/tag_test.go delete mode 100644 internal/oci/testdata/build/deployment.yaml delete mode 100644 internal/oci/testdata/build/somedir/repo.yaml delete mode 100644 internal/oci/url.go diff --git a/cmd/flux/build_artifact.go b/cmd/flux/build_artifact.go index 83aa30eadb..a2b6eaa4ff 100644 --- a/cmd/flux/build_artifact.go +++ b/cmd/flux/build_artifact.go @@ -22,7 +22,7 @@ import ( "github.com/spf13/cobra" - "github.com/fluxcd/flux2/internal/oci" + oci "github.com/fluxcd/pkg/oci/client" ) var buildArtifactCmd = &cobra.Command{ @@ -59,7 +59,8 @@ func buildArtifactCmdRun(cmd *cobra.Command, args []string) error { logger.Actionf("building artifact from %s", buildArtifactArgs.path) - if err := oci.Build(buildArtifactArgs.output, buildArtifactArgs.path); err != nil { + ociClient := oci.NewLocalClient() + if err := ociClient.Build(buildArtifactArgs.output, buildArtifactArgs.path); err != nil { return fmt.Errorf("bulding artifact failed, error: %w", err) } diff --git a/cmd/flux/list_artifact.go b/cmd/flux/list_artifact.go index e499fc7341..6632c1a377 100644 --- a/cmd/flux/list_artifact.go +++ b/cmd/flux/list_artifact.go @@ -19,9 +19,12 @@ package main import ( "context" "fmt" - "github.com/fluxcd/flux2/internal/oci" - "github.com/fluxcd/flux2/pkg/printers" + "github.com/spf13/cobra" + + oci "github.com/fluxcd/pkg/oci/client" + + "github.com/fluxcd/flux2/pkg/printers" ) var listArtifactsCmd = &cobra.Command{ @@ -48,12 +51,13 @@ func listArtifactsCmdRun(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) defer cancel() + ociClient := oci.NewLocalClient() url, err := oci.ParseArtifactURL(ociURL) if err != nil { return err } - metas, err := oci.List(ctx, url) + metas, err := ociClient.List(ctx, url) if err != nil { return err } @@ -69,5 +73,4 @@ func listArtifactsCmdRun(cmd *cobra.Command, args []string) error { } return nil - } diff --git a/cmd/flux/pull_artifact.go b/cmd/flux/pull_artifact.go index 3178f7fa3a..7f508e5366 100644 --- a/cmd/flux/pull_artifact.go +++ b/cmd/flux/pull_artifact.go @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" - "github.com/fluxcd/flux2/internal/oci" + oci "github.com/fluxcd/pkg/oci/client" ) var pullArtifactCmd = &cobra.Command{ @@ -62,6 +62,7 @@ func pullArtifactCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("invalid output path %s", pullArtifactArgs.output) } + ociClient := oci.NewLocalClient() url, err := oci.ParseArtifactURL(ociURL) if err != nil { return err @@ -72,7 +73,7 @@ func pullArtifactCmdRun(cmd *cobra.Command, args []string) error { logger.Actionf("pulling artifact from %s", url) - meta, err := oci.Pull(ctx, url, pullArtifactArgs.output) + meta, err := ociClient.Pull(ctx, url, pullArtifactArgs.output) if err != nil { return err } diff --git a/cmd/flux/push_artifact.go b/cmd/flux/push_artifact.go index 49f6120287..f16ee98d15 100644 --- a/cmd/flux/push_artifact.go +++ b/cmd/flux/push_artifact.go @@ -23,7 +23,7 @@ import ( "github.com/spf13/cobra" - "github.com/fluxcd/flux2/internal/oci" + oci "github.com/fluxcd/pkg/oci/client" ) var pushArtifactCmd = &cobra.Command{ @@ -73,6 +73,7 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("invalid path %q", pushArtifactArgs.path) } + ociClient := oci.NewLocalClient() url, err := oci.ParseArtifactURL(ociURL) if err != nil { return err @@ -92,7 +93,7 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error { logger.Actionf("pushing artifact to %s", url) - digest, err := oci.Push(ctx, url, pushArtifactArgs.path, meta) + digest, err := ociClient.Push(ctx, url, pushArtifactArgs.path, meta) if err != nil { return fmt.Errorf("pushing artifact failed: %w", err) } diff --git a/cmd/flux/tag_artifact.go b/cmd/flux/tag_artifact.go index 2004cebc1a..4f82bf7f23 100644 --- a/cmd/flux/tag_artifact.go +++ b/cmd/flux/tag_artifact.go @@ -19,8 +19,10 @@ package main import ( "context" "fmt" - "github.com/fluxcd/flux2/internal/oci" + "github.com/spf13/cobra" + + oci "github.com/fluxcd/pkg/oci/client" ) var tagArtifactCmd = &cobra.Command{ @@ -55,6 +57,7 @@ func tagArtifactCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("--tag is required") } + ociClient := oci.NewLocalClient() url, err := oci.ParseArtifactURL(ociURL) if err != nil { return err @@ -66,7 +69,7 @@ func tagArtifactCmdRun(cmd *cobra.Command, args []string) error { logger.Actionf("tagging artifact") for _, tag := range tagArtifactArgs.tags { - img, err := oci.Tag(ctx, url, tag) + img, err := ociClient.Tag(ctx, url, tag) if err != nil { return fmt.Errorf("tagging artifact failed: %w", err) } diff --git a/go.mod b/go.mod index b86f16f5fe..9a8e80f8d8 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b github.com/cyphar/filepath-securejoin v0.2.3 - github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f github.com/fluxcd/go-git-providers v0.6.0 github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/image-automation-controller/api v0.23.5 @@ -15,6 +14,7 @@ require ( github.com/fluxcd/notification-controller/api v0.24.1 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/pkg/kustomize v0.5.2 + github.com/fluxcd/pkg/oci v0.2.0 github.com/fluxcd/pkg/runtime v0.16.2 github.com/fluxcd/pkg/ssa v0.17.0 github.com/fluxcd/pkg/ssh v0.5.0 @@ -25,7 +25,7 @@ require ( github.com/gonvenience/bunt v1.3.4 github.com/gonvenience/ytbx v1.4.4 github.com/google/go-cmp v0.5.8 - github.com/google/go-containerregistry v0.9.0 + github.com/google/go-containerregistry v0.10.0 github.com/hashicorp/go-multierror v1.1.1 github.com/homeport/dyff v1.5.4 github.com/lucasb-eyer/go-colorful v1.2.0 @@ -33,17 +33,16 @@ require ( github.com/mattn/go-shellwords v1.0.12 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/gomega v1.19.0 - github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 github.com/theckman/yacspin v0.13.12 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 - k8s.io/api v0.24.1 - k8s.io/apiextensions-apiserver v0.24.1 - k8s.io/apimachinery v0.24.1 + k8s.io/api v0.24.2 + k8s.io/apiextensions-apiserver v0.24.2 + k8s.io/apimachinery v0.24.2 k8s.io/cli-runtime v0.24.1 - k8s.io/client-go v0.24.1 + k8s.io/client-go v0.24.2 k8s.io/kubectl v0.24.1 sigs.k8s.io/cli-utils v0.31.2 sigs.k8s.io/controller-runtime v0.11.2 @@ -67,35 +66,24 @@ require ( github.com/BurntSushi/toml v1.0.0 // indirect github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect github.com/Microsoft/go-winio v0.5.2 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect github.com/acomagu/bufpipe v1.0.3 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect - github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd // indirect - github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b // indirect - github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/containerd/stargz-snapshotter/estargz v0.11.4 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/docker/cli v20.10.16+incompatible // indirect + github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.16+incompatible // indirect + github.com/docker/docker v20.10.17+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect - github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect - github.com/docker/go-metrics v0.0.1 // indirect - github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 // indirect github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 // indirect - github.com/emicklei/go-restful v2.9.5+incompatible // indirect + github.com/emicklei/go-restful v2.15.0+incompatible // indirect github.com/emirpasic/gods v1.12.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/color v1.13.0 // indirect - github.com/felixge/httpsnoop v1.0.1 // indirect github.com/fluxcd/pkg/apis/acl v0.0.3 // indirect github.com/fluxcd/pkg/apis/kustomize v0.4.2 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect @@ -104,26 +92,23 @@ require ( github.com/go-git/go-billy/v5 v5.3.1 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.21.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect + github.com/golang-jwt/jwt/v4 v4.4.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/gomodule/redigo v1.8.2 // indirect github.com/gonvenience/neat v1.3.10 // indirect github.com/gonvenience/term v1.0.2 // indirect github.com/gonvenience/text v1.0.7 // indirect github.com/gonvenience/wrap v1.1.1 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gnostic v0.6.9 // indirect github.com/google/go-github/v42 v42.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/gorilla/handlers v1.5.1 // indirect - github.com/gorilla/mux v1.8.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -136,7 +121,7 @@ require ( github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/klauspost/compress v1.15.4 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect @@ -164,21 +149,18 @@ require ( github.com/russross/blackfriday v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/texttheater/golang-levenshtein v1.0.1 // indirect github.com/vbatts/tar-split v0.11.2 // indirect github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect github.com/xanzy/go-gitlab v0.58.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect - github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 // indirect - github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 // indirect - github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect - golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 // indirect + golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect + golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92 // indirect golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect - golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect @@ -188,10 +170,10 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/component-base v0.24.1 // indirect + k8s.io/component-base v0.24.2 // indirect k8s.io/klog/v2 v2.60.1 // indirect - k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661 // indirect + k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6 // indirect k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect - sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect + sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect ) diff --git a/go.sum b/go.sum index 7d33a4b0fb..b38fa82b90 100644 --- a/go.sum +++ b/go.sum @@ -100,12 +100,9 @@ github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmU github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b h1:lcbBNuQhppsc7A5gjdHmdlqUqJfgGMylBdGyDs0j7G8= github.com/ProtonMail/go-crypto v0.0.0-20220517143526-88bb52951d5b/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= @@ -144,7 +141,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= @@ -153,13 +149,10 @@ github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -225,21 +218,17 @@ github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCF github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f h1:3NCYdjXycNd/Xn/iICZzmxkiDX1e1cjTHjbMAz+wRVk= -github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= -github.com/docker/cli v20.10.16+incompatible h1:aLQ8XowgKpR3/IysPj8qZQJBVQ+Qws61icFuZl6iKYs= -github.com/docker/cli v20.10.16+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ= -github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46 h1:7QPwrLT79GlD5sizHf27aoY2RTvw62mO6x7mxkScNk0= github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= @@ -248,8 +237,9 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.15.0+incompatible h1:8KpYO/Xl/ZudZs5RNOEhWMBY4hmzlZhhRd9cu+jrZP4= +github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -278,6 +268,7 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fluxcd/go-git-providers v0.6.0 h1:XJc3MTYFpuahBSoKTVxmH9OBPCeIyvYoQkTjTqa3fH4= github.com/fluxcd/go-git-providers v0.6.0/go.mod h1:UMFHnMCIO9CBpEln7ZsArEWyXSNxTpm76fyQxUmClrc= github.com/fluxcd/helm-controller/api v0.22.2 h1:nh0GZBsUE0gNzm4PmPa4aOoqYlbZbpGt2pcIL9S2184= @@ -298,6 +289,8 @@ github.com/fluxcd/pkg/apis/meta v0.14.2 h1:/Hf7I/Vz01vv3m7Qx7DtQvrzAL1oVt0MJcLb/ github.com/fluxcd/pkg/apis/meta v0.14.2/go.mod h1:ijZ61VG/8T3U17gj0aFL3fdtZL+mulD6V8VrLLUCAgM= github.com/fluxcd/pkg/kustomize v0.5.2 h1:Nhaw/Tqwt588Cp4PYa83nj45t3mGgojMl23zhq/t/fM= github.com/fluxcd/pkg/kustomize v0.5.2/go.mod h1:X3Uls1l13giFPwig1NDoXvrF53yyXUemSyR3nYGw28s= +github.com/fluxcd/pkg/oci v0.2.0 h1:pvLF6iKmSj9u48Da7qlBDVIiH2NLOrbFUFE4Yr431Lc= +github.com/fluxcd/pkg/oci v0.2.0/go.mod h1:c1pj9E/G5927gSa6ooACAyZe+HwjgmPk9johL7oXDHw= github.com/fluxcd/pkg/runtime v0.16.2 h1:CexfMmJK+r12sHTvKWyAax0pcPomjd6VnaHXcxjUrRY= github.com/fluxcd/pkg/runtime v0.16.2/go.mod h1:OHSKsrO+T+Ym8WZRS2oidrnauWRARuE2nfm8ewevm7M= github.com/fluxcd/pkg/ssa v0.17.0 h1:iO4EQ+/xIbd79VKrh+8fvsAvq3RlmgAdWtnzOAUxD5s= @@ -359,11 +352,13 @@ github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34 github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -391,8 +386,9 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ= +github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -443,7 +439,6 @@ github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4M github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= -github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gonvenience/bunt v1.3.4 h1:Row599Ohja2BPooaqd1tHYdTAKu6SWq7W/UeakTXddM= github.com/gonvenience/bunt v1.3.4/go.mod h1:j8eqHLBo8eWCCYuc34oFdlgyxL1rZ4ywYz4BZa4b09w= github.com/gonvenience/neat v1.3.10 h1:gHrVkQAvbUsZgnpEglPwsAJLPqSFQxOgfbB3FWLhmUo= @@ -464,8 +459,9 @@ github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMS github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -480,8 +476,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.9.0 h1:5Ths7RjxyFV0huKChQTgY6fLzvHhZMpLTFNja8U0/0w= -github.com/google/go-containerregistry v0.9.0/go.mod h1:9eq4BnSufyT1kHNffX+vSXVonaJ7yaIOulrKZejMxnQ= +github.com/google/go-containerregistry v0.10.0 h1:qd/fv2nQajGZJenaNcdaghlwSPjQ0NphN9hzArr2WWg= +github.com/google/go-containerregistry v0.10.0/go.mod h1:C7uwbB1QUAtvnknyd3ethxJRd4gtEjU/9WLXzckfI1Y= github.com/google/go-github/v42 v42.0.0 h1:YNT0FwjPrEysRkLIiKuEfSvBPCGKphW5aS5PxwaoLec= github.com/google/go-github/v42 v42.0.0/go.mod h1:jgg/jvyI0YlDOM1/ps6XYh04HNQ3vKf0CVko62/EhRg= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= @@ -530,7 +526,6 @@ github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1: github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -695,8 +690,9 @@ github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= @@ -763,7 +759,6 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f h1:2+myh5ml7lgEU/51gbeLHfKGNfgEQQIWrlbdaOsidbQ= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= @@ -840,7 +835,6 @@ github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+v github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= -github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -856,7 +850,6 @@ github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prY github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= @@ -869,7 +862,6 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= @@ -877,7 +869,6 @@ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= @@ -926,8 +917,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1034,11 +1026,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -1212,8 +1201,8 @@ golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y= -golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0= +golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1231,8 +1220,8 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 h1:zwrSfklXn0gxyLRX/aR+q6cgHbV/ItVyzbPlbA+dkAw= -golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92 h1:oVlhw3Oe+1reYsE2Nqu19PDJfLzwdU3QUUrG86rLK68= +golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1266,7 +1255,6 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1340,8 +1328,8 @@ golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1677,20 +1665,25 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY= k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ= -k8s.io/apiextensions-apiserver v0.24.1 h1:5yBh9+ueTq/kfnHQZa0MAo6uNcPrtxPMpNQgorBaKS0= -k8s.io/apiextensions-apiserver v0.24.1/go.mod h1:A6MHfaLDGfjOc/We2nM7uewD5Oa/FnEbZ6cD7g2ca4Q= -k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I= +k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI= +k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg= +k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k= +k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ= k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.24.1/go.mod h1:dQWNMx15S8NqJMp0gpYfssyvhYnkilc1LpExd/dkLh0= +k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM= +k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apiserver v0.24.2/go.mod h1:pSuKzr3zV+L+MWqsEo0kHHYwCo77AT5qXbFXP2jbvFI= k8s.io/cli-runtime v0.24.1 h1:IW6L8dRBq+pPTzvXcB+m/hOabzbqXy57Bqo4XxmW7DY= k8s.io/cli-runtime v0.24.1/go.mod h1:14aVvCTqkA7dNXY51N/6hRY3GUjchyWDOwW84qmR3bs= -k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E= k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8= +k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA= +k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30= k8s.io/code-generator v0.24.1/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.24.1 h1:APv6W/YmfOWZfo+XJ1mZwep/f7g7Tpwvdbo9CQLDuts= +k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.24.1/go.mod h1:DW5vQGYVCog8WYpNob3PMmmsY8A3L9QZNg4j/dV3s38= +k8s.io/component-base v0.24.2 h1:kwpQdoSfbcH+8MPN4tALtajLDfSfYxBDYlXobNWI6OU= +k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM= k8s.io/component-helpers v0.24.1/go.mod h1:q5Z1pWV/QfX9ThuNeywxasiwkLw9KsR4Q9TAOdb/Y3s= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= @@ -1701,8 +1694,9 @@ k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661 h1:nqYOUleKLC/0P1zbU29F5q6aoezM6MOAVz+iyfQbZ5M= k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661/go.mod h1:daOouuuwd9JXpv1L7Y34iV3yf6nxzipkKMWWlqlvK9M= +k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6 h1:nBQrWPlrNIiw0BsX6a6MKr1itkm0ZS0Nl97kNLitFfI= +k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6/go.mod h1:daOouuuwd9JXpv1L7Y34iV3yf6nxzipkKMWWlqlvK9M= k8s.io/kubectl v0.24.1 h1:gxcjHrnwntV1c+G/BHWVv4Mtk8CQJ0WTraElLBG+ddk= k8s.io/kubectl v0.24.1/go.mod h1:NzFqQ50B004fHYWOfhHTrAm4TY6oGF5FAAL13LEaeUI= k8s.io/metrics v0.24.1/go.mod h1:vMs5xpcOyY9D+/XVwlaw8oUHYCo6JTGBCZfyXOOkAhE= @@ -1721,8 +1715,9 @@ sigs.k8s.io/cli-utils v0.31.2 h1:0yX0GPyvbc+yAEWwWlhgHlPF7JtvlLco6HjolSWewt4= sigs.k8s.io/cli-utils v0.31.2/go.mod h1:g/zB9hJ5eUN7zIEBIxrO0CwhXU4YISJ+BkLJzvWwlEs= sigs.k8s.io/controller-runtime v0.11.2 h1:H5GTxQl0Mc9UjRJhORusqfJCIjBO8UtUxGggCwL1rLA= sigs.k8s.io/controller-runtime v0.11.2/go.mod h1:P6QCzrEjLaZGqHsfd+os7JQ+WFZhvB8MRFsn4dWF7O4= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 h1:2sgAQQcY0dEW2SsQwTXhQV4vO6+rSslYx8K3XmM5hqQ= +sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= sigs.k8s.io/kustomize/api v0.11.5 h1:vLDp++YAX7iy2y2CVPJNy9pk9CY8XaUKgHkjbVtnWag= sigs.k8s.io/kustomize/api v0.11.5/go.mod h1:2UDpxS6AonWXow2ZbySd4AjUxmdXLeTlvGBC46uSiq8= diff --git a/internal/oci/build.go b/internal/oci/build.go deleted file mode 100644 index 3deb3fc69d..0000000000 --- a/internal/oci/build.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "archive/tar" - "compress/gzip" - "fmt" - "io" - "os" - "path/filepath" - "time" -) - -// Build archives the given directory as a tarball to the given local path. -// While archiving, any environment specific data (for example, the user and group name) is stripped from file headers. -func Build(artifactPath, sourceDir string) (err error) { - if f, err := os.Stat(sourceDir); os.IsNotExist(err) || !f.IsDir() { - return fmt.Errorf("invalid source dir path: %s", sourceDir) - } - - tf, err := os.CreateTemp(filepath.Split(sourceDir)) - if err != nil { - return err - } - tmpName := tf.Name() - defer func() { - if err != nil { - os.Remove(tmpName) - } - }() - - sz := &writeCounter{} - mw := io.MultiWriter(tf, sz) - - gw := gzip.NewWriter(mw) - tw := tar.NewWriter(gw) - if err := filepath.Walk(sourceDir, func(p string, fi os.FileInfo, err error) error { - if err != nil { - return err - } - - // Ignore anything that is not a file or directories e.g. symlinks - if m := fi.Mode(); !(m.IsRegular() || m.IsDir()) { - return nil - } - - header, err := tar.FileInfoHeader(fi, p) - if err != nil { - return err - } - // The name needs to be modified to maintain directory structure - // as tar.FileInfoHeader only has access to the base name of the file. - // Ref: https://golang.org/src/archive/tar/common.go?#L626 - relFilePath := p - if filepath.IsAbs(sourceDir) { - relFilePath, err = filepath.Rel(sourceDir, p) - if err != nil { - return err - } - } - header.Name = relFilePath - - // Remove any environment specific data. - header.Gid = 0 - header.Uid = 0 - header.Uname = "" - header.Gname = "" - header.ModTime = time.Time{} - header.AccessTime = time.Time{} - header.ChangeTime = time.Time{} - - if err := tw.WriteHeader(header); err != nil { - return err - } - - if !fi.Mode().IsRegular() { - return nil - } - f, err := os.Open(p) - if err != nil { - f.Close() - return err - } - if _, err := io.Copy(tw, f); err != nil { - f.Close() - return err - } - return f.Close() - }); err != nil { - tw.Close() - gw.Close() - tf.Close() - return err - } - - if err := tw.Close(); err != nil { - gw.Close() - tf.Close() - return err - } - if err := gw.Close(); err != nil { - tf.Close() - return err - } - if err := tf.Close(); err != nil { - return err - } - - if err := os.Chmod(tmpName, 0o640); err != nil { - return err - } - - return os.Rename(tmpName, artifactPath) -} - -type writeCounter struct { - written int64 -} - -func (wc *writeCounter) Write(p []byte) (int, error) { - n := len(p) - wc.written += int64(n) - return n, nil -} diff --git a/internal/oci/build_test.go b/internal/oci/build_test.go deleted file mode 100644 index 2f6c561678..0000000000 --- a/internal/oci/build_test.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "os" - "path/filepath" - "testing" - - . "github.com/onsi/gomega" -) - -func TestBuild(t *testing.T) { - g := NewWithT(t) - testDir := "./testdata/build" - - tmpDir := t.TempDir() - artifactPath := filepath.Join(tmpDir, "files.tar.gz") - - // test with non-existent path - err := Build(artifactPath, "testdata/non-existent") - g.Expect(err).To(HaveOccurred()) - - err = Build(artifactPath, testDir) - g.Expect(err).ToNot(HaveOccurred()) - - if _, err := os.Stat(artifactPath); err != nil { - g.Expect(err).ToNot(HaveOccurred()) - } -} diff --git a/internal/oci/list.go b/internal/oci/list.go deleted file mode 100644 index 9901d1d826..0000000000 --- a/internal/oci/list.go +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "bytes" - "context" - "fmt" - "sort" - "strings" - - "github.com/google/go-containerregistry/pkg/crane" - gcrv1 "github.com/google/go-containerregistry/pkg/v1" -) - -// List fetches the tags and their manifests for a given OCI repository. -func List(ctx context.Context, url string) ([]Metadata, error) { - metas := make([]Metadata, 0) - tags, err := crane.ListTags(url, craneOptions(ctx)...) - if err != nil { - return nil, fmt.Errorf("listing tags failed: %w", err) - } - - sort.Slice(tags, func(i, j int) bool { return tags[i] > tags[j] }) - - for _, tag := range tags { - // exclude cosign signatures - if strings.HasSuffix(tag, ".sig") { - continue - } - - meta := Metadata{ - URL: fmt.Sprintf("%s:%s", url, tag), - } - - manifestJSON, err := crane.Manifest(meta.URL, craneOptions(ctx)...) - if err != nil { - return nil, fmt.Errorf("fetching manifest failed: %w", err) - } - - manifest, err := gcrv1.ParseManifest(bytes.NewReader(manifestJSON)) - if err != nil { - return nil, fmt.Errorf("parsing manifest failed: %w", err) - } - - if m, err := MetadataFromAnnotations(manifest.Annotations); err == nil { - meta.Revision = m.Revision - meta.Source = m.Source - } - - digest, err := crane.Digest(meta.URL, craneOptions(ctx)...) - if err != nil { - return nil, fmt.Errorf("fetching digest failed: %w", err) - } - meta.Digest = digest - - metas = append(metas, meta) - } - - return metas, nil -} diff --git a/internal/oci/list_test.go b/internal/oci/list_test.go deleted file mode 100644 index c67a3a6cf3..0000000000 --- a/internal/oci/list_test.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "context" - "fmt" - "testing" - - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/name" - gcrv1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/mutate" - "github.com/google/go-containerregistry/pkg/v1/random" - . "github.com/onsi/gomega" -) - -func Test_List(t *testing.T) { - g := NewWithT(t) - ctx := context.Background() - repo := "test-list" + randStringRunes(5) - tags := []string{"v0.0.1", "v0.0.2", "v0.0.3"} - source := "github.com/fluxcd/fluxv2" - rev := "rev" - m := Metadata{ - Source: source, - Revision: rev, - } - - for _, tag := range tags { - dst := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag) - img, err := random.Image(1024, 1) - g.Expect(err).ToNot(HaveOccurred()) - img = mutate.Annotations(img, m.ToAnnotations()).(gcrv1.Image) - err = crane.Push(img, dst, craneOptions(ctx)...) - g.Expect(err).ToNot(HaveOccurred()) - } - - metadata, err := List(ctx, fmt.Sprintf("%s/%s", dockerReg, repo)) - g.Expect(err).ToNot(HaveOccurred()) - - g.Expect(len(metadata)).To(Equal(len(tags))) - for _, meta := range metadata { - tag, err := name.NewTag(meta.URL) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(tag.TagStr()).Should(BeElementOf(tags)) - - g.Expect(meta.ToAnnotations()).To(Equal(m.ToAnnotations())) - - digest, err := crane.Digest(meta.URL, craneOptions(ctx)...) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(meta.Digest).To(Equal(digest)) - } -} diff --git a/internal/oci/meta.go b/internal/oci/meta.go deleted file mode 100644 index c1a43fa457..0000000000 --- a/internal/oci/meta.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "fmt" -) - -const ( - SourceAnnotation = "org.opencontainers.image.source" - RevisionAnnotation = "org.opencontainers.image.revision" -) - -type Metadata struct { - Source string `json:"source_url"` - Revision string `json:"source_revision"` - Digest string `json:"digest"` - URL string `json:"url"` -} - -func (m *Metadata) ToAnnotations() map[string]string { - annotations := map[string]string{ - SourceAnnotation: m.Source, - RevisionAnnotation: m.Revision, - } - - return annotations -} - -func MetadataFromAnnotations(annotations map[string]string) (*Metadata, error) { - source, ok := annotations[SourceAnnotation] - if !ok { - return nil, fmt.Errorf("'%s' annotation not found", SourceAnnotation) - } - - revision, ok := annotations[RevisionAnnotation] - if !ok { - return nil, fmt.Errorf("'%s' annotation not found", RevisionAnnotation) - } - - m := Metadata{ - Source: source, - Revision: revision, - } - - return &m, nil -} diff --git a/internal/oci/pull.go b/internal/oci/pull.go deleted file mode 100644 index f08c0e345d..0000000000 --- a/internal/oci/pull.go +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "context" - "fmt" - - "github.com/fluxcd/pkg/untar" - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/name" -) - -// Pull downloads an artifact from an OCI repository and extracts the content to the given directory. -func Pull(ctx context.Context, url, outDir string) (*Metadata, error) { - ref, err := name.ParseReference(url) - if err != nil { - return nil, fmt.Errorf("invalid URL: %w", err) - } - - img, err := crane.Pull(url, craneOptions(ctx)...) - if err != nil { - return nil, err - } - - digest, err := img.Digest() - if err != nil { - return nil, fmt.Errorf("parsing digest failed: %w", err) - } - - manifest, err := img.Manifest() - if err != nil { - return nil, fmt.Errorf("parsing manifest failed: %w", err) - } - - meta, err := MetadataFromAnnotations(manifest.Annotations) - if err != nil { - return nil, err - } - meta.Digest = ref.Context().Digest(digest.String()).String() - - layers, err := img.Layers() - if err != nil { - return nil, fmt.Errorf("failed to list layers: %w", err) - } - - if len(layers) < 1 { - return nil, fmt.Errorf("no layers found in artifact") - } - - blob, err := layers[0].Compressed() - if err != nil { - return nil, fmt.Errorf("extracting first layer failed: %w", err) - } - - if _, err = untar.Untar(blob, outDir); err != nil { - return nil, fmt.Errorf("failed to untar first layer: %w", err) - } - - return meta, nil -} diff --git a/internal/oci/push.go b/internal/oci/push.go deleted file mode 100644 index 30d572c99c..0000000000 --- a/internal/oci/push.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "context" - "fmt" - "os" - "path/filepath" - - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/name" - gcrv1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/empty" - "github.com/google/go-containerregistry/pkg/v1/mutate" -) - -// Push creates an artifact from the given directory, uploads the artifact -// to the given OCI repository and returns the digest. -func Push(ctx context.Context, url, sourceDir string, meta Metadata) (string, error) { - ref, err := name.ParseReference(url) - if err != nil { - return "", fmt.Errorf("invalid URL: %w", err) - } - - tmpDir, err := os.MkdirTemp("", "oci") - if err != nil { - return "", err - } - defer os.RemoveAll(tmpDir) - - tmpFile := filepath.Join(tmpDir, "artifact.tgz") - - if err := Build(tmpFile, sourceDir); err != nil { - return "", err - } - - img, err := crane.Append(empty.Image, tmpFile) - if err != nil { - return "", fmt.Errorf("appeding content to artifact failed: %w", err) - } - - img = mutate.Annotations(img, meta.ToAnnotations()).(gcrv1.Image) - - if err := crane.Push(img, url, craneOptions(ctx)...); err != nil { - return "", fmt.Errorf("pushing artifact failed: %w", err) - } - - digest, err := img.Digest() - if err != nil { - return "", fmt.Errorf("parsing artifact digest failed: %w", err) - } - - return ref.Context().Digest(digest.String()).String(), err -} - -func craneOptions(ctx context.Context) []crane.Option { - return []crane.Option{ - crane.WithContext(ctx), - crane.WithUserAgent("flux/v2"), - crane.WithPlatform(&gcrv1.Platform{ - Architecture: "flux", - OS: "flux", - OSVersion: "v2", - }), - } -} diff --git a/internal/oci/push_pull_test.go b/internal/oci/push_pull_test.go deleted file mode 100644 index 1083dcddda..0000000000 --- a/internal/oci/push_pull_test.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "context" - "fmt" - "io/fs" - "os" - "path/filepath" - "testing" - - "github.com/google/go-containerregistry/pkg/crane" - . "github.com/onsi/gomega" -) - -func Test_Push_Pull(t *testing.T) { - g := NewWithT(t) - ctx := context.Background() - tag := "v0.0.1" - repo := "test-push" + randStringRunes(5) - - url := fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag) - metadata := Metadata{ - Source: "github.com/fluxcd/flux2", - Revision: "rev", - } - annotations := metadata.ToAnnotations() - - testDir := "testdata/build" - _, err := Push(ctx, url, testDir, metadata) - g.Expect(err).ToNot(HaveOccurred()) - - tags, err := crane.ListTags(fmt.Sprintf("%s/%s", dockerReg, repo)) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(tags)).To(BeEquivalentTo(1)) - - image, err := crane.Pull(fmt.Sprintf("%s/%s:%s", dockerReg, repo, tag)) - g.Expect(err).ToNot(HaveOccurred()) - - manifest, err := image.Manifest() - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(manifest.Annotations).To(BeEquivalentTo(annotations)) - - tmpDir := t.TempDir() - _, err = Pull(ctx, url, tmpDir) - g.Expect(err).ToNot(HaveOccurred()) - - // Walk directory the test directory and check that all paths exists in the extracted archive - err = filepath.Walk(testDir, func(path string, info fs.FileInfo, err error) error { - tmpPath := filepath.Join(tmpDir, path) - if _, err := os.Stat(tmpPath); err != nil && os.IsNotExist(err) { - return fmt.Errorf("path '%s' doesn't exist in archive", path) - } - - return nil - }) -} diff --git a/internal/oci/suite_test.go b/internal/oci/suite_test.go deleted file mode 100644 index c611e1ab5c..0000000000 --- a/internal/oci/suite_test.go +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "context" - "fmt" - "math/rand" - "os" - "testing" - "time" - - ctrl "sigs.k8s.io/controller-runtime" - - "github.com/distribution/distribution/v3/configuration" - "github.com/distribution/distribution/v3/registry" - _ "github.com/distribution/distribution/v3/registry/auth/htpasswd" - _ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory" - "github.com/phayes/freeport" -) - -var ( - dockerReg string -) - -func init() { - rand.Seed(time.Now().UnixNano()) -} - -func setupRegistryServer(ctx context.Context) error { - // Registry config - config := &configuration.Configuration{} - port, err := freeport.GetFreePort() - if err != nil { - return fmt.Errorf("failed to get free port: %s", err) - } - - dockerReg = fmt.Sprintf("localhost:%d", port) - config.HTTP.Addr = fmt.Sprintf("127.0.0.1:%d", port) - config.HTTP.DrainTimeout = time.Duration(10) * time.Second - config.Storage = map[string]configuration.Parameters{"inmemory": map[string]interface{}{}} - dockerRegistry, err := registry.NewRegistry(ctx, config) - if err != nil { - return fmt.Errorf("failed to create docker registry: %w", err) - } - - // Start Docker registry - go dockerRegistry.ListenAndServe() - - return nil -} - -func TestMain(m *testing.M) { - ctx := ctrl.SetupSignalHandler() - err := setupRegistryServer(ctx) - if err != nil { - panic(fmt.Sprintf("failed to start docker registry: %s", err)) - } - - code := m.Run() - os.Exit(code) -} - -var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890") - -func randStringRunes(n int) string { - b := make([]rune, n) - for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] - } - return string(b) -} diff --git a/internal/oci/tag.go b/internal/oci/tag.go deleted file mode 100644 index 8e0140f66b..0000000000 --- a/internal/oci/tag.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "context" - "fmt" - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/name" -) - -// Tag creates a new tag for the given artifact using the same OCI repository as the origin. -func Tag(ctx context.Context, url, tag string) (string, error) { - ref, err := name.ParseReference(url) - if err != nil { - return "", fmt.Errorf("invalid URL: %w", err) - } - - if err := crane.Tag(url, tag, craneOptions(ctx)...); err != nil { - return "", err - } - - dst := ref.Context().Tag(tag) - - return dst.Name(), nil -} diff --git a/internal/oci/tag_test.go b/internal/oci/tag_test.go deleted file mode 100644 index 81cbebb11e..0000000000 --- a/internal/oci/tag_test.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "context" - "fmt" - "testing" - - "github.com/google/go-containerregistry/pkg/crane" - "github.com/google/go-containerregistry/pkg/v1/random" - . "github.com/onsi/gomega" -) - -func Test_Tag(t *testing.T) { - g := NewWithT(t) - ctx := context.Background() - testRepo := "test-tag" - url := fmt.Sprintf("%s/%s:v0.0.1", dockerReg, testRepo) - img, err := random.Image(1024, 1) - g.Expect(err).ToNot(HaveOccurred()) - err = crane.Push(img, url, craneOptions(ctx)...) - g.Expect(err).ToNot(HaveOccurred()) - - _, err = Tag(ctx, url, "v0.0.2") - g.Expect(err).ToNot(HaveOccurred()) - - tags, err := crane.ListTags(fmt.Sprintf("%s/%s", dockerReg, testRepo)) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(tags)).To(BeEquivalentTo(2)) - g.Expect(tags).To(BeEquivalentTo([]string{"v0.0.1", "v0.0.2"})) -} diff --git a/internal/oci/testdata/build/deployment.yaml b/internal/oci/testdata/build/deployment.yaml deleted file mode 100644 index 007ecd317d..0000000000 --- a/internal/oci/testdata/build/deployment.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx-deployment - labels: - app: nginx -spec: - replicas: 3 - selector: - matchLabels: - app: nginx - template: - metadata: - labels: - app: nginx - spec: - containers: - - name: nginx - image: nginx:1.14.2 - ports: - - containerPort: 80 diff --git a/internal/oci/testdata/build/somedir/repo.yaml b/internal/oci/testdata/build/somedir/repo.yaml deleted file mode 100644 index 253b76323e..0000000000 --- a/internal/oci/testdata/build/somedir/repo.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: source.toolkit.fluxcd.io/v1beta1 -kind: HelmRepository -metadata: - name: podinfo - namespace: flux-system -spec: - interval: 2m - url: https://stefanprodan.github.io/podinfo diff --git a/internal/oci/url.go b/internal/oci/url.go deleted file mode 100644 index 38dafb1f50..0000000000 --- a/internal/oci/url.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2022 The Flux authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package oci - -import ( - "fmt" - "strings" - - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" - "github.com/google/go-containerregistry/pkg/name" -) - -// ParseArtifactURL validates the OCI URL and returns the address of the artifact. -func ParseArtifactURL(ociURL string) (string, error) { - if !strings.HasPrefix(ociURL, sourcev1.OCIRepositoryPrefix) { - return "", fmt.Errorf("URL must be in format 'oci:////'") - } - - url := strings.TrimPrefix(ociURL, sourcev1.OCIRepositoryPrefix) - if _, err := name.ParseReference(url); err != nil { - return "", fmt.Errorf("'%s' invalid URL: %w", ociURL, err) - } - - return url, nil -} - -// ParseRepositoryURL validates the OCI URL and returns the address of the artifact repository. -func ParseRepositoryURL(ociURL string) (string, error) { - if !strings.HasPrefix(ociURL, sourcev1.OCIRepositoryPrefix) { - return "", fmt.Errorf("URL must be in format 'oci:////'") - } - - url := strings.TrimPrefix(ociURL, sourcev1.OCIRepositoryPrefix) - ref, err := name.ParseReference(url) - if err != nil { - return "", fmt.Errorf("'%s' invalid URL: %w", ociURL, err) - } - - return ref.Context().Name(), nil -} From ac9b3d193d88e07120e957fcaafb6eaa770317ea Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Mon, 8 Aug 2022 20:24:32 +0300 Subject: [PATCH 28/32] Update controllers with OCI support Signed-off-by: Stefan Prodan --- .../testdata/oci/create_source_oci.golden | 2 +- cmd/flux/testdata/oci/get_oci.golden | 2 +- cmd/flux/testdata/oci/reconcile_oci.golden | 2 +- cmd/flux/testdata/oci/resume_oci.golden | 2 +- go.mod | 26 ++++----- go.sum | 56 +++++++++---------- .../kustomize-controller/kustomization.yaml | 10 +--- .../kustomization.yaml | 4 +- .../source-controller/kustomization.yaml | 10 +--- 9 files changed, 53 insertions(+), 61 deletions(-) diff --git a/cmd/flux/testdata/oci/create_source_oci.golden b/cmd/flux/testdata/oci/create_source_oci.golden index 6b2563c914..af1125c85c 100644 --- a/cmd/flux/testdata/oci/create_source_oci.golden +++ b/cmd/flux/testdata/oci/create_source_oci.golden @@ -2,4 +2,4 @@ ✔ OCIRepository created ◎ waiting for OCIRepository reconciliation ✔ OCIRepository reconciliation completed -✔ fetched revision: ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 +✔ fetched revision: dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3 diff --git a/cmd/flux/testdata/oci/get_oci.golden b/cmd/flux/testdata/oci/get_oci.golden index 3d5a8a1cb7..ae582c8cf5 100644 --- a/cmd/flux/testdata/oci/get_oci.golden +++ b/cmd/flux/testdata/oci/get_oci.golden @@ -1,2 +1,2 @@ NAME REVISION SUSPENDED READY MESSAGE -thrfg ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 False True stored artifact for digest 'ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59' +thrfg dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3 False True stored artifact for digest 'dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3' diff --git a/cmd/flux/testdata/oci/reconcile_oci.golden b/cmd/flux/testdata/oci/reconcile_oci.golden index c0223e8d20..832c329465 100644 --- a/cmd/flux/testdata/oci/reconcile_oci.golden +++ b/cmd/flux/testdata/oci/reconcile_oci.golden @@ -1,4 +1,4 @@ ► annotating OCIRepository thrfg in {{ .ns }} namespace ✔ OCIRepository annotated ◎ waiting for OCIRepository reconciliation -✔ fetched revision ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 +✔ fetched revision dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3 diff --git a/cmd/flux/testdata/oci/resume_oci.golden b/cmd/flux/testdata/oci/resume_oci.golden index 0851c4877e..b4341a5d2f 100644 --- a/cmd/flux/testdata/oci/resume_oci.golden +++ b/cmd/flux/testdata/oci/resume_oci.golden @@ -2,4 +2,4 @@ ✔ source oci resumed ◎ waiting for OCIRepository reconciliation ✔ OCIRepository reconciliation completed -✔ fetched revision ad1869cb84deb98917c06d93de0fe0ec56297473694d42b45b6adf1c84692d59 +✔ fetched revision dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3 diff --git a/go.mod b/go.mod index 9a8e80f8d8..6b025c1048 100644 --- a/go.mod +++ b/go.mod @@ -10,17 +10,17 @@ require ( github.com/fluxcd/helm-controller/api v0.22.2 github.com/fluxcd/image-automation-controller/api v0.23.5 github.com/fluxcd/image-reflector-controller/api v0.19.4 - github.com/fluxcd/kustomize-controller/api v0.26.3 - github.com/fluxcd/notification-controller/api v0.24.1 + github.com/fluxcd/kustomize-controller/api v0.27.0 + github.com/fluxcd/notification-controller/api v0.25.0 github.com/fluxcd/pkg/apis/meta v0.14.2 github.com/fluxcd/pkg/kustomize v0.5.2 - github.com/fluxcd/pkg/oci v0.2.0 + github.com/fluxcd/pkg/oci v0.3.0 github.com/fluxcd/pkg/runtime v0.16.2 github.com/fluxcd/pkg/ssa v0.17.0 github.com/fluxcd/pkg/ssh v0.5.0 github.com/fluxcd/pkg/untar v0.1.0 github.com/fluxcd/pkg/version v0.1.0 - github.com/fluxcd/source-controller/api v0.25.10-0.20220803075204-d95db9403032 + github.com/fluxcd/source-controller/api v0.26.0 github.com/go-git/go-git/v5 v5.4.2 github.com/gonvenience/bunt v1.3.4 github.com/gonvenience/ytbx v1.4.4 @@ -38,16 +38,16 @@ require ( github.com/theckman/yacspin v0.13.12 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 - k8s.io/api v0.24.2 - k8s.io/apiextensions-apiserver v0.24.2 - k8s.io/apimachinery v0.24.2 + k8s.io/api v0.24.3 + k8s.io/apiextensions-apiserver v0.24.3 + k8s.io/apimachinery v0.24.3 k8s.io/cli-runtime v0.24.1 - k8s.io/client-go v0.24.2 + k8s.io/client-go v0.24.3 k8s.io/kubectl v0.24.1 - sigs.k8s.io/cli-utils v0.31.2 + sigs.k8s.io/cli-utils v0.32.0 sigs.k8s.io/controller-runtime v0.11.2 - sigs.k8s.io/kustomize/api v0.11.5 - sigs.k8s.io/kustomize/kyaml v0.13.7 + sigs.k8s.io/kustomize/api v0.12.1 + sigs.k8s.io/kustomize/kyaml v0.13.9 sigs.k8s.io/yaml v1.3.0 ) @@ -155,7 +155,7 @@ require ( github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 // indirect github.com/xanzy/go-gitlab v0.58.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect - github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect + github.com/xlab/treeprint v1.1.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92 // indirect @@ -170,7 +170,7 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/component-base v0.24.2 // indirect + k8s.io/component-base v0.24.3 // indirect k8s.io/klog/v2 v2.60.1 // indirect k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6 // indirect k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect diff --git a/go.sum b/go.sum index b38fa82b90..18b8d0c5ca 100644 --- a/go.sum +++ b/go.sum @@ -277,10 +277,10 @@ github.com/fluxcd/image-automation-controller/api v0.23.5 h1:haMWilXLHXQGn4YXwm7 github.com/fluxcd/image-automation-controller/api v0.23.5/go.mod h1:v/sRqXwo0jNyXK0f4oUY7GZt8NgcNy5twP3OVEsoAt0= github.com/fluxcd/image-reflector-controller/api v0.19.4 h1:SnqJS7vhm+jWHsArjMluCdVydu6jY+m3M2mi+oSHh94= github.com/fluxcd/image-reflector-controller/api v0.19.4/go.mod h1:QFRYeJTfUQY9l3r+PqGGAlr7KzJRCKN7Lsvg9nXaWHk= -github.com/fluxcd/kustomize-controller/api v0.26.3 h1:RTrRM9N+YWIX8M690x/rDq/ryiEkhnOaq9Sj1AeWcNQ= -github.com/fluxcd/kustomize-controller/api v0.26.3/go.mod h1:Zwvl6iBKbR6SKl5W8APK5hvHfH55S50zAqFLJ/188LQ= -github.com/fluxcd/notification-controller/api v0.24.1 h1:aGe4AEPmCW/8gIRCRhOosppXb2mqZYgfftt16Q05/30= -github.com/fluxcd/notification-controller/api v0.24.1/go.mod h1:hqn/1JsYiv8Gg3xjBYkLJQhez3hbYj2v57ATfSo637M= +github.com/fluxcd/kustomize-controller/api v0.27.0 h1:mhaw15noK7cGFoMkFUCjBgkpqYrKPJ6JoqlmbpLU6nc= +github.com/fluxcd/kustomize-controller/api v0.27.0/go.mod h1:qNL44xfm+E2ng8/TqheZZ4bXilWtvVtDYjlKCiMbfM0= +github.com/fluxcd/notification-controller/api v0.25.0 h1:ZAFAfRs+cPcepPjdjbDvl6fOWc1aOoM4r6lozOAxWhw= +github.com/fluxcd/notification-controller/api v0.25.0/go.mod h1:hqn/1JsYiv8Gg3xjBYkLJQhez3hbYj2v57ATfSo637M= github.com/fluxcd/pkg/apis/acl v0.0.3 h1:Lw0ZHdpnO4G7Zy9KjrzwwBmDZQuy4qEjaU/RvA6k1lc= github.com/fluxcd/pkg/apis/acl v0.0.3/go.mod h1:XPts6lRJ9C9fIF9xVWofmQwftvhY25n1ps7W9xw0XLU= github.com/fluxcd/pkg/apis/kustomize v0.4.2 h1:5mC/t+OndouK7poFaG4soWLqvHqOxJ3HCsbxu8qyt30= @@ -289,8 +289,8 @@ github.com/fluxcd/pkg/apis/meta v0.14.2 h1:/Hf7I/Vz01vv3m7Qx7DtQvrzAL1oVt0MJcLb/ github.com/fluxcd/pkg/apis/meta v0.14.2/go.mod h1:ijZ61VG/8T3U17gj0aFL3fdtZL+mulD6V8VrLLUCAgM= github.com/fluxcd/pkg/kustomize v0.5.2 h1:Nhaw/Tqwt588Cp4PYa83nj45t3mGgojMl23zhq/t/fM= github.com/fluxcd/pkg/kustomize v0.5.2/go.mod h1:X3Uls1l13giFPwig1NDoXvrF53yyXUemSyR3nYGw28s= -github.com/fluxcd/pkg/oci v0.2.0 h1:pvLF6iKmSj9u48Da7qlBDVIiH2NLOrbFUFE4Yr431Lc= -github.com/fluxcd/pkg/oci v0.2.0/go.mod h1:c1pj9E/G5927gSa6ooACAyZe+HwjgmPk9johL7oXDHw= +github.com/fluxcd/pkg/oci v0.3.0 h1:GFn6JZeg5fV2K4vsQ0s5lJFid6qrpA4RybLXL+7qUbQ= +github.com/fluxcd/pkg/oci v0.3.0/go.mod h1:c1pj9E/G5927gSa6ooACAyZe+HwjgmPk9johL7oXDHw= github.com/fluxcd/pkg/runtime v0.16.2 h1:CexfMmJK+r12sHTvKWyAax0pcPomjd6VnaHXcxjUrRY= github.com/fluxcd/pkg/runtime v0.16.2/go.mod h1:OHSKsrO+T+Ym8WZRS2oidrnauWRARuE2nfm8ewevm7M= github.com/fluxcd/pkg/ssa v0.17.0 h1:iO4EQ+/xIbd79VKrh+8fvsAvq3RlmgAdWtnzOAUxD5s= @@ -301,8 +301,8 @@ github.com/fluxcd/pkg/untar v0.1.0 h1:k97V/xV5hFrAkIkVPuv5AVhyxh1ZzzAKba/lbDfGo6 github.com/fluxcd/pkg/untar v0.1.0/go.mod h1:aGswNyzB1mlz/T/kpOS58mITBMxMKc9tlJBH037A2HY= github.com/fluxcd/pkg/version v0.1.0 h1:v+SmCanmCB5Tj2Cx9TXlj+kNRfPGbAvirkeqsp7ZEAQ= github.com/fluxcd/pkg/version v0.1.0/go.mod h1:V7Z/w8dxLQzv0FHqa5ox5TeyOd2zOd49EeuWFgnwyj4= -github.com/fluxcd/source-controller/api v0.25.10-0.20220803075204-d95db9403032 h1:qJgj+/LGV4bjxutw5ENVLHgAe1MpdfMASC00Qb75NIY= -github.com/fluxcd/source-controller/api v0.25.10-0.20220803075204-d95db9403032/go.mod h1:1W0Xx/GpZ14Z/sOltxjsQKXeCv8zxAqSivbX9e4s+H8= +github.com/fluxcd/source-controller/api v0.26.0 h1:DOf9R7YLV0lNiIRnaYg5bh8fGbIB6zGbK5vFqejeSAk= +github.com/fluxcd/source-controller/api v0.26.0/go.mod h1:1W0Xx/GpZ14Z/sOltxjsQKXeCv8zxAqSivbX9e4s+H8= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -1010,8 +1010,9 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= +github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc= @@ -1666,24 +1667,24 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ= -k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI= -k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg= -k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k= -k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ= +k8s.io/api v0.24.3 h1:tt55QEmKd6L2k5DP6G/ZzdMQKvG5ro4H4teClqm0sTY= +k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= +k8s.io/apiextensions-apiserver v0.24.3 h1:kyx+Tmro1qEsTUr07ZGQOfvTsF61yn+AxnxytBWq8As= +k8s.io/apiextensions-apiserver v0.24.3/go.mod h1:cL0xkmUefpYM4f6IuOau+6NMFEIh6/7wXe/O4vPVJ8A= k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM= -k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.24.2/go.mod h1:pSuKzr3zV+L+MWqsEo0kHHYwCo77AT5qXbFXP2jbvFI= +k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg= +k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apiserver v0.24.3/go.mod h1:aXfwtIn4U27B7lYs5f2BKgz6DRbgWy+HJeYReN1jLJ8= k8s.io/cli-runtime v0.24.1 h1:IW6L8dRBq+pPTzvXcB+m/hOabzbqXy57Bqo4XxmW7DY= k8s.io/cli-runtime v0.24.1/go.mod h1:14aVvCTqkA7dNXY51N/6hRY3GUjchyWDOwW84qmR3bs= k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8= -k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA= -k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30= +k8s.io/client-go v0.24.3 h1:Nl1840+6p4JqkFWEW2LnMKU667BUxw03REfLAVhuKQY= +k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= k8s.io/code-generator v0.24.1/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= +k8s.io/code-generator v0.24.3/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= k8s.io/component-base v0.24.1/go.mod h1:DW5vQGYVCog8WYpNob3PMmmsY8A3L9QZNg4j/dV3s38= -k8s.io/component-base v0.24.2 h1:kwpQdoSfbcH+8MPN4tALtajLDfSfYxBDYlXobNWI6OU= -k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM= +k8s.io/component-base v0.24.3 h1:u99WjuHYCRJjS1xeLOx72DdRaghuDnuMgueiGMFy1ec= +k8s.io/component-base v0.24.3/go.mod h1:bqom2IWN9Lj+vwAkPNOv2TflsP1PeVDIwIN0lRthxYY= k8s.io/component-helpers v0.24.1/go.mod h1:q5Z1pWV/QfX9ThuNeywxasiwkLw9KsR4Q9TAOdb/Y3s= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= @@ -1694,7 +1695,6 @@ k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220401212409-b28bf2818661/go.mod h1:daOouuuwd9JXpv1L7Y34iV3yf6nxzipkKMWWlqlvK9M= k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6 h1:nBQrWPlrNIiw0BsX6a6MKr1itkm0ZS0Nl97kNLitFfI= k8s.io/kube-openapi v0.0.0-20220413171646-5e7f5fdc6da6/go.mod h1:daOouuuwd9JXpv1L7Y34iV3yf6nxzipkKMWWlqlvK9M= k8s.io/kubectl v0.24.1 h1:gxcjHrnwntV1c+G/BHWVv4Mtk8CQJ0WTraElLBG+ddk= @@ -1711,21 +1711,21 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/cli-utils v0.31.2 h1:0yX0GPyvbc+yAEWwWlhgHlPF7JtvlLco6HjolSWewt4= -sigs.k8s.io/cli-utils v0.31.2/go.mod h1:g/zB9hJ5eUN7zIEBIxrO0CwhXU4YISJ+BkLJzvWwlEs= +sigs.k8s.io/cli-utils v0.32.0 h1:776y8z6gbBFTxfJ78lkHK6tbzK+MZTH6+ycP1gh16aw= +sigs.k8s.io/cli-utils v0.32.0/go.mod h1:g/zB9hJ5eUN7zIEBIxrO0CwhXU4YISJ+BkLJzvWwlEs= sigs.k8s.io/controller-runtime v0.11.2 h1:H5GTxQl0Mc9UjRJhORusqfJCIjBO8UtUxGggCwL1rLA= sigs.k8s.io/controller-runtime v0.11.2/go.mod h1:P6QCzrEjLaZGqHsfd+os7JQ+WFZhvB8MRFsn4dWF7O4= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 h1:2sgAQQcY0dEW2SsQwTXhQV4vO6+rSslYx8K3XmM5hqQ= sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= -sigs.k8s.io/kustomize/api v0.11.5 h1:vLDp++YAX7iy2y2CVPJNy9pk9CY8XaUKgHkjbVtnWag= -sigs.k8s.io/kustomize/api v0.11.5/go.mod h1:2UDpxS6AonWXow2ZbySd4AjUxmdXLeTlvGBC46uSiq8= +sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= +sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= -sigs.k8s.io/kustomize/kyaml v0.13.7 h1:/EZ/nPaLUzeJKF/BuJ4QCuMVJWiEVoI8iftOHY3g3tk= -sigs.k8s.io/kustomize/kyaml v0.13.7/go.mod h1:6K+IUOuir3Y7nucPRAjw9yth04KSWBnP5pqUTGwj/qU= +sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= +sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= diff --git a/manifests/bases/kustomize-controller/kustomization.yaml b/manifests/bases/kustomize-controller/kustomization.yaml index 2ae59c8a81..b6a455932a 100644 --- a/manifests/bases/kustomize-controller/kustomization.yaml +++ b/manifests/bases/kustomize-controller/kustomization.yaml @@ -1,9 +1,8 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -# TODO: remove the hardcoded branch when OCIRepository is released resources: -- https://github.com/fluxcd/kustomize-controller/config/crd?ref=oci -- https://github.com/fluxcd/kustomize-controller/releases/download/v0.26.1/kustomize-controller.deployment.yaml +- https://github.com/fluxcd/kustomize-controller/releases/download/v0.27.0/kustomize-controller.crds.yaml +- https://github.com/fluxcd/kustomize-controller/releases/download/v0.27.0/kustomize-controller.deployment.yaml - account.yaml patchesJson6902: - target: @@ -12,7 +11,4 @@ patchesJson6902: kind: Deployment name: kustomize-controller path: patch.yaml -# TODO: remove the hardcoded image when OCIRepository is released -images: - - name: fluxcd/kustomize-controller - newTag: oci-7681bda9 + diff --git a/manifests/bases/notification-controller/kustomization.yaml b/manifests/bases/notification-controller/kustomization.yaml index febba4e0cb..afbaf63a2b 100644 --- a/manifests/bases/notification-controller/kustomization.yaml +++ b/manifests/bases/notification-controller/kustomization.yaml @@ -1,8 +1,8 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: -- https://github.com/fluxcd/notification-controller/releases/download/v0.24.1/notification-controller.crds.yaml -- https://github.com/fluxcd/notification-controller/releases/download/v0.24.1/notification-controller.deployment.yaml +- https://github.com/fluxcd/notification-controller/releases/download/v0.25.0/notification-controller.crds.yaml +- https://github.com/fluxcd/notification-controller/releases/download/v0.25.0/notification-controller.deployment.yaml - account.yaml patchesJson6902: - target: diff --git a/manifests/bases/source-controller/kustomization.yaml b/manifests/bases/source-controller/kustomization.yaml index 2e882adaa6..01ba758407 100644 --- a/manifests/bases/source-controller/kustomization.yaml +++ b/manifests/bases/source-controller/kustomization.yaml @@ -1,9 +1,8 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -# TODO: remove the hardcoded branch when OCIRepository is released resources: -- https://github.com/fluxcd/source-controller/config/crd?ref=oci -- https://github.com/fluxcd/source-controller/releases/download/v0.25.5/source-controller.deployment.yaml +- https://github.com/fluxcd/source-controller/releases/download/v0.26.0/source-controller.crds.yaml +- https://github.com/fluxcd/source-controller/releases/download/v0.26.0/source-controller.deployment.yaml - account.yaml patchesJson6902: - target: @@ -12,7 +11,4 @@ patchesJson6902: kind: Deployment name: source-controller path: patch.yaml -# TODO: remove the hardcoded image when OCIRepository is released -images: - - name: fluxcd/source-controller - newTag: oci-d95db940 + From d4718f6ff41cd63c7191087b1d316da6bb828b89 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 9 Aug 2022 13:27:45 +0300 Subject: [PATCH 29/32] Improve artifact commands docs Signed-off-by: Stefan Prodan --- cmd/flux/build_artifact.go | 7 +++++-- cmd/flux/list_artifact.go | 6 +++--- cmd/flux/push_artifact.go | 18 +++++++++++++----- cmd/flux/tag_artifact.go | 6 +++--- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/cmd/flux/build_artifact.go b/cmd/flux/build_artifact.go index a2b6eaa4ff..a7db13f66a 100644 --- a/cmd/flux/build_artifact.go +++ b/cmd/flux/build_artifact.go @@ -29,8 +29,11 @@ var buildArtifactCmd = &cobra.Command{ Use: "artifact", Short: "Build artifact", Long: `The build artifact command creates an tgz file with the manifests from the given directory.`, - Example: `# Build the given manifests directory into an artifact -flux build artifact --path ./path/to/local/manifests --output ./path/to/artifact.tgz + Example: ` # Build the given manifests directory into an artifact + flux build artifact --path ./path/to/local/manifests --output ./path/to/artifact.tgz + + # List the files bundles in the artifact + tar -ztvf ./path/to/artifact.tgz `, RunE: buildArtifactCmdRun, } diff --git a/cmd/flux/list_artifact.go b/cmd/flux/list_artifact.go index 6632c1a377..eb0d4127a0 100644 --- a/cmd/flux/list_artifact.go +++ b/cmd/flux/list_artifact.go @@ -31,9 +31,9 @@ var listArtifactsCmd = &cobra.Command{ Use: "artifacts", Short: "list artifacts", Long: `The list command fetches the tags and their metadata from a remote OCI repository. -The list command uses the credentials from '~/.docker/config.json'.`, - Example: `# list the artifacts stored in an OCI repository -flux list artifact oci://ghcr.io/org/manifests/app +The command uses the credentials from '~/.docker/config.json'.`, + Example: ` # List the artifacts stored in an OCI repository + flux list artifact oci://ghcr.io/org/config/app `, RunE: listArtifactsCmdRun, } diff --git a/cmd/flux/push_artifact.go b/cmd/flux/push_artifact.go index f16ee98d15..009ba437b4 100644 --- a/cmd/flux/push_artifact.go +++ b/cmd/flux/push_artifact.go @@ -29,13 +29,21 @@ import ( var pushArtifactCmd = &cobra.Command{ Use: "artifact", Short: "Push artifact", - Long: `The push artifact command creates a tarball from the given directory and uploads the artifact to a OCI repository. -The push command uses the credentials from '~/.docker/config.json'.`, - Example: `# Push the local manifests to GHCR -flux push artifact oci://ghcr.io/org/manifests/app:v0.0.1 \ + Long: `The push artifact command creates a tarball from the given directory and uploads the artifact to an OCI repository. +The command uses the credentials from '~/.docker/config.json'.`, + Example: ` # Push manifests to GHCR using the short Git SHA as the OCI artifact tag + echo $GITHUB_PAT | docker login ghcr.io --username flux --password-stdin + flux push artifact oci://ghcr.io/org/config/app:$(git rev-parse --short HEAD) \ --path="./path/to/local/manifests" \ --source="$(git config --get remote.origin.url)" \ --revision="$(git branch --show-current)/$(git rev-parse HEAD)" + + # Push manifests to Docker Hub using the Git tag as the OCI artifact tag + echo $DOCKER_PAT | docker login --username flux --password-stdin + flux push artifact oci://docker.io/org/app-config:$(git tag --points-at HEAD) \ + --path="./path/to/local/manifests" \ + --source="$(git config --get remote.origin.url)" \ + --revision="$(git tag --points-at HEAD)/$(git rev-parse HEAD)" `, RunE: pushArtifactCmdRun, } @@ -50,7 +58,7 @@ var pushArtifactArgs pushArtifactFlags func init() { pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.") - pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.source, "source", "", "The source address, e.g. Git URL.") + pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.source, "source", "", "The source address, e.g. the Git URL.") pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.revision, "revision", "", "The source revision in the format '/'") pushCmd.AddCommand(pushArtifactCmd) } diff --git a/cmd/flux/tag_artifact.go b/cmd/flux/tag_artifact.go index 4f82bf7f23..4cfed85177 100644 --- a/cmd/flux/tag_artifact.go +++ b/cmd/flux/tag_artifact.go @@ -29,9 +29,9 @@ var tagArtifactCmd = &cobra.Command{ Use: "artifact", Short: "Tag artifact", Long: `The tag artifact command creates tags for the given OCI artifact. -The tag command uses the credentials from '~/.docker/config.json'.`, - Example: `# Tag an artifact version as latest -flux tag artifact oci://ghcr.io/org/manifests/app:v0.0.1 --tag latest +The command uses the credentials from '~/.docker/config.json'.`, + Example: ` # Tag an artifact version as latest + flux tag artifact oci://ghcr.io/org/manifests/app:v0.0.1 --tag latest `, RunE: tagArtifactCmdRun, } From d4c5a137a1650bb4dec3d03973526f3ab5ef8d3f Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 9 Aug 2022 13:50:27 +0300 Subject: [PATCH 30/32] Add examples for pushing artifacts with GH Actions Signed-off-by: Stefan Prodan --- action/README.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/action/README.md b/action/README.md index 7a432d6bfd..f2871b76d1 100644 --- a/action/README.md +++ b/action/README.md @@ -32,7 +32,7 @@ You can download a specific version with: - name: Setup Flux CLI uses: fluxcd/flux2/action@main with: - version: 0.8.0 + version: 0.32.0 ``` ### Automate Flux updates @@ -74,6 +74,86 @@ jobs: ${{ steps.update.outputs.flux_version }} ``` +### Push Kubernetes manifests to container registries + +Example workflow for publishing Kubernetes manifests bundled as OCI artifacts to GitHub Container Registry: + +```yaml +name: push-artifact-staging + +on: + push: + branches: + - 'main' + +permissions: + packages: write # needed for ghcr.io access + +env: + OCI_REPO: "oci://ghcr.io/my-org/manifests/${{ github.event.repository.name }}" + +jobs: + kubernetes: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Flux CLI + uses: fluxcd/flux2/action@main + - name: Generate manifests + run: | + kustomize build ./manifests/staging > ./deploy/app.yaml + - name: Push manifests + run: | + flux push artifact $OCI_REPO:$(git rev-parse --short HEAD) \ + --path="./deploy" \ + --source="$(git config --get remote.origin.url)" \ + --revision="$(git branch --show-current)/$(git rev-parse HEAD)" + - name: Deploy manifests to staging + run: | + flux tag artifact $OCI_REPO:$(git rev-parse --short HEAD) --tag staging +``` + +Example workflow for publishing Kubernetes manifests bundled as OCI artifacts to Docker Hub: + +```yaml +name: push-artifact-production + +on: + push: + tags: + - '*' + +env: + OCI_REPO: "oci://docker.io/my-org/app-config" + +jobs: + kubernetes: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Flux CLI + uses: fluxcd/flux2/action@main + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Generate manifests + run: | + kustomize build ./manifests/production > ./deploy/app.yaml + - name: Push manifests + run: | + flux push artifact $OCI_REPO:$(git tag --points-at HEAD) \ + --path="./deploy" \ + --source="$(git config --get remote.origin.url)" \ + --revision="$(git tag --points-at HEAD)/$(git rev-parse HEAD)" + - name: Deploy manifests to production + run: | + flux tag artifact $OCI_REPO:$(git tag --points-at HEAD) --tag production +``` + ### End-to-end testing Example workflow for running Flux in Kubernetes Kind: From 75a879c77030b8444b4b3f1a31b6f612f468e7ac Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Wed, 10 Aug 2022 11:51:11 +0300 Subject: [PATCH 31/32] OCI docs improvements Co-authored-by: Kingdon Barrett Co-authored-by: Sunny Signed-off-by: Stefan Prodan --- action/README.md | 10 ++++++++-- cmd/flux/build_artifact.go | 8 ++++---- cmd/flux/create_secret_oci.go | 6 +++--- cmd/flux/create_source_oci.go | 2 +- cmd/flux/delete_source_oci.go | 2 +- cmd/flux/get_source_oci.go | 2 +- cmd/flux/list.go | 2 +- cmd/flux/pull_artifact.go | 6 +++--- cmd/flux/push.go | 2 +- cmd/flux/push_artifact.go | 6 +++--- cmd/flux/reconcile_source_oci.go | 2 +- cmd/flux/resume_source_oci.go | 2 +- cmd/flux/suspend_source_oci.go | 2 +- cmd/flux/tag.go | 2 +- cmd/flux/tag_artifact.go | 2 +- 15 files changed, 31 insertions(+), 25 deletions(-) diff --git a/action/README.md b/action/README.md index f2871b76d1..daeada31c5 100644 --- a/action/README.md +++ b/action/README.md @@ -97,9 +97,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Flux CLI uses: fluxcd/flux2/action@main + - name: Login to GHCR + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Generate manifests run: | kustomize build ./manifests/staging > ./deploy/app.yaml @@ -132,7 +138,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Flux CLI uses: fluxcd/flux2/action@main - name: Login to Docker Hub diff --git a/cmd/flux/build_artifact.go b/cmd/flux/build_artifact.go index a7db13f66a..bf523fa016 100644 --- a/cmd/flux/build_artifact.go +++ b/cmd/flux/build_artifact.go @@ -28,11 +28,11 @@ import ( var buildArtifactCmd = &cobra.Command{ Use: "artifact", Short: "Build artifact", - Long: `The build artifact command creates an tgz file with the manifests from the given directory.`, + Long: `The build artifact command creates a tgz file with the manifests from the given directory.`, Example: ` # Build the given manifests directory into an artifact flux build artifact --path ./path/to/local/manifests --output ./path/to/artifact.tgz - # List the files bundles in the artifact + # List the files bundled in the artifact tar -ztvf ./path/to/artifact.tgz `, RunE: buildArtifactCmdRun, @@ -47,7 +47,7 @@ var buildArtifactArgs buildArtifactFlags func init() { buildArtifactCmd.Flags().StringVar(&buildArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.") - buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.output, "output", "0", "artifact.tgz", "Path to where the artifact tgz file should be written.") + buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.output, "output", "o", "artifact.tgz", "Path to where the artifact tgz file should be written.") buildCmd.AddCommand(buildArtifactCmd) } @@ -57,7 +57,7 @@ func buildArtifactCmdRun(cmd *cobra.Command, args []string) error { } if fs, err := os.Stat(buildArtifactArgs.path); err != nil || !fs.IsDir() { - return fmt.Errorf("invalid path %q", buildArtifactArgs.path) + return fmt.Errorf("invalid path '%s', must point to an existing directory", buildArtifactArgs.path) } logger.Actionf("building artifact from %s", buildArtifactArgs.path) diff --git a/cmd/flux/create_secret_oci.go b/cmd/flux/create_secret_oci.go index 2e86f4618f..b7cb34490c 100644 --- a/cmd/flux/create_secret_oci.go +++ b/cmd/flux/create_secret_oci.go @@ -30,8 +30,8 @@ import ( var createSecretOCICmd = &cobra.Command{ Use: "oci [name]", - Short: "Create or update a Kubernetes secret for OCI Registry authentication", - Long: `The create secret oci command generates a Kubernetes secret with `, + Short: "Create or update a Kubernetes image pull secret", + Long: `The create secret oci command generates a Kubernetes secret that can be used for OCIRepository authentication`, Example: ` # Create an OCI authentication secret on disk and encrypt it with Mozilla SOPS flux create secret oci podinfo-auth \ --url=ghcr.io \ @@ -39,7 +39,7 @@ var createSecretOCICmd = &cobra.Command{ --password=password \ --export > repo-auth.yaml - sops --encrypt --encrypted-regex '^(data|stringData)$' \ + sops --encrypt --encrypted-regex '^(data|stringData)$' \ --in-place repo-auth.yaml `, RunE: createSecretOCICmdRun, diff --git a/cmd/flux/create_source_oci.go b/cmd/flux/create_source_oci.go index 2481fe7d03..75372a35ce 100644 --- a/cmd/flux/create_source_oci.go +++ b/cmd/flux/create_source_oci.go @@ -71,7 +71,7 @@ func newSourceOCIFlags() sourceOCIRepositoryFlags { } func init() { - createSourceOCIRepositoryCmd.Flags().Var(&sourceOCIRepositoryArgs.provider, "provider", sourceBucketArgs.provider.Description()) + createSourceOCIRepositoryCmd.Flags().Var(&sourceOCIRepositoryArgs.provider, "provider", sourceOCIRepositoryArgs.provider.Description()) createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.url, "url", "", "the OCI repository URL") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.tag, "tag", "", "the OCI artifact tag") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.semver, "tag-semver", "", "the OCI artifact tag semver range") diff --git a/cmd/flux/delete_source_oci.go b/cmd/flux/delete_source_oci.go index 1d641bbf51..8d98e5b03e 100644 --- a/cmd/flux/delete_source_oci.go +++ b/cmd/flux/delete_source_oci.go @@ -24,7 +24,7 @@ import ( var deleteSourceOCIRepositoryCmd = &cobra.Command{ Use: "oci [name]", - Short: "Delete a OCIRepository source", + Short: "Delete an OCIRepository source", Long: "The delete source oci command deletes the given OCIRepository from the cluster.", Example: ` # Delete an OCIRepository flux delete source oci podinfo`, diff --git a/cmd/flux/get_source_oci.go b/cmd/flux/get_source_oci.go index 8f948d8122..b79f73f826 100644 --- a/cmd/flux/get_source_oci.go +++ b/cmd/flux/get_source_oci.go @@ -34,7 +34,7 @@ var getSourceOCIRepositoryCmd = &cobra.Command{ Example: ` # List all OCIRepositories and their status flux get sources oci - # List OCIRepositories from all namespaces + # List OCIRepositories from all namespaces flux get sources oci --all-namespaces`, ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/flux/list.go b/cmd/flux/list.go index e89dc14963..240e69d085 100644 --- a/cmd/flux/list.go +++ b/cmd/flux/list.go @@ -1,5 +1,5 @@ /* -Copyright 2021 The Flux authors +Copyright 2022 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/cmd/flux/pull_artifact.go b/cmd/flux/pull_artifact.go index 7f508e5366..f36ab3d0c0 100644 --- a/cmd/flux/pull_artifact.go +++ b/cmd/flux/pull_artifact.go @@ -31,8 +31,8 @@ var pullArtifactCmd = &cobra.Command{ Short: "Pull artifact", Long: `The pull artifact command downloads and extracts the OCI artifact content to the given path. The pull command uses the credentials from '~/.docker/config.json'.`, - Example: `# Pull an OCI artifact created by flux from GHCR -flux pull artifact oci://ghcr.io/org/manifests/app:v0.0.1 --output ./path/to/local/manifests + Example: ` # Pull an OCI artifact created by flux from GHCR + flux pull artifact oci://ghcr.io/org/manifests/app:v0.0.1 --output ./path/to/local/manifests `, RunE: pullArtifactCmdRun, } @@ -44,7 +44,7 @@ type pullArtifactFlags struct { var pullArtifactArgs pullArtifactFlags func init() { - pullArtifactCmd.Flags().StringVarP(&pullArtifactArgs.output, "output", "o", "", "Path where the artifact content should be extracted.") + pullArtifactCmd.Flags().StringVarP(&pullArtifactArgs.output, "output", "o", "", "path where the artifact content should be extracted.") pullCmd.AddCommand(pullArtifactCmd) } diff --git a/cmd/flux/push.go b/cmd/flux/push.go index 481c6ae9ae..eec4882ddc 100644 --- a/cmd/flux/push.go +++ b/cmd/flux/push.go @@ -1,5 +1,5 @@ /* -Copyright 2021 The Flux authors +Copyright 2022 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/cmd/flux/push_artifact.go b/cmd/flux/push_artifact.go index 009ba437b4..6f3186025e 100644 --- a/cmd/flux/push_artifact.go +++ b/cmd/flux/push_artifact.go @@ -57,9 +57,9 @@ type pushArtifactFlags struct { var pushArtifactArgs pushArtifactFlags func init() { - pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.") - pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.source, "source", "", "The source address, e.g. the Git URL.") - pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.revision, "revision", "", "The source revision in the format '/'") + pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.path, "path", "", "path to the directory where the Kubernetes manifests are located") + pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.source, "source", "", "the source address, e.g. the Git URL") + pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.revision, "revision", "", "the source revision in the format '/'") pushCmd.AddCommand(pushArtifactCmd) } diff --git a/cmd/flux/reconcile_source_oci.go b/cmd/flux/reconcile_source_oci.go index 17df7174f8..ffc649f9b3 100644 --- a/cmd/flux/reconcile_source_oci.go +++ b/cmd/flux/reconcile_source_oci.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Flux authors +Copyright 2022 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/cmd/flux/resume_source_oci.go b/cmd/flux/resume_source_oci.go index 42ad48ab1d..3c121c4733 100644 --- a/cmd/flux/resume_source_oci.go +++ b/cmd/flux/resume_source_oci.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Flux authors +Copyright 2022 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/cmd/flux/suspend_source_oci.go b/cmd/flux/suspend_source_oci.go index 06ab4c6c35..d656dbf23c 100644 --- a/cmd/flux/suspend_source_oci.go +++ b/cmd/flux/suspend_source_oci.go @@ -24,7 +24,7 @@ import ( var suspendSourceOCIRepositoryCmd = &cobra.Command{ Use: "oci [name]", - Short: "Suspend reconciliation of a OCIRepository", + Short: "Suspend reconciliation of an OCIRepository", Long: "The suspend command disables the reconciliation of an OCIRepository resource.", Example: ` # Suspend reconciliation for an existing OCIRepository flux suspend source oci podinfo`, diff --git a/cmd/flux/tag.go b/cmd/flux/tag.go index 56c9485fb0..966acef6f7 100644 --- a/cmd/flux/tag.go +++ b/cmd/flux/tag.go @@ -1,5 +1,5 @@ /* -Copyright 2021 The Flux authors +Copyright 2022 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/cmd/flux/tag_artifact.go b/cmd/flux/tag_artifact.go index 4cfed85177..65ba121887 100644 --- a/cmd/flux/tag_artifact.go +++ b/cmd/flux/tag_artifact.go @@ -43,7 +43,7 @@ type tagArtifactFlags struct { var tagArtifactArgs tagArtifactFlags func init() { - tagArtifactCmd.Flags().StringSliceVar(&tagArtifactArgs.tags, "tag", nil, "Tag name.") + tagArtifactCmd.Flags().StringSliceVar(&tagArtifactArgs.tags, "tag", nil, "tag name") tagCmd.AddCommand(tagArtifactCmd) } From b810aea6ccb7b2f3ad9f5b049b1609b5463b1975 Mon Sep 17 00:00:00 2001 From: Max Jonas Werner Date: Wed, 10 Aug 2022 14:27:23 +0200 Subject: [PATCH 32/32] Make `flux trace` work with OCIRepository * Added support for OCIRepositories to `flux trace` * Changed indentation to compensate new, longer field name "Source Revision" * Added unit tests for the new output closes #2970 Signed-off-by: Max Jonas Werner --- .../testdata/trace/helmrelease-oci.golden | 21 ++++ cmd/flux/testdata/trace/helmrelease-oci.yaml | 92 ++++++++++++++ cmd/flux/testdata/trace/helmrelease.golden | 32 ++--- cmd/flux/trace.go | 119 +++++++++++++----- cmd/flux/trace_test.go | 12 ++ 5 files changed, 228 insertions(+), 48 deletions(-) create mode 100644 cmd/flux/testdata/trace/helmrelease-oci.golden create mode 100644 cmd/flux/testdata/trace/helmrelease-oci.yaml diff --git a/cmd/flux/testdata/trace/helmrelease-oci.golden b/cmd/flux/testdata/trace/helmrelease-oci.golden new file mode 100644 index 0000000000..768c46165c --- /dev/null +++ b/cmd/flux/testdata/trace/helmrelease-oci.golden @@ -0,0 +1,21 @@ + +Object: HelmRelease/podinfo +Namespace: {{ .ns }} +Status: Managed by Flux +--- +Kustomization: infrastructure +Namespace: {{ .fluxns }} +Path: ./infrastructure +Revision: main/696f056df216eea4f9401adbee0ff744d4df390f +Status: Last reconciled at {{ .kustomizationLastReconcile }} +Message: Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f +--- +OCIRepository: flux-system +Namespace: {{ .fluxns }} +URL: oci://ghcr.io/example/repo +Tag: 1.2.3 +Revision: dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3 +Origin Revision: 6.1.6/450796ddb2ab6724ee1cc32a4be56da032d1cca0 +Origin Source: https://github.com/stefanprodan/podinfo.git +Status: Last reconciled at {{ .ociRepositoryLastReconcile }} +Message: stored artifact for digest 'dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3' diff --git a/cmd/flux/testdata/trace/helmrelease-oci.yaml b/cmd/flux/testdata/trace/helmrelease-oci.yaml new file mode 100644 index 0000000000..7c3fa2da6c --- /dev/null +++ b/cmd/flux/testdata/trace/helmrelease-oci.yaml @@ -0,0 +1,92 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .fluxns }} +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .ns }} +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + labels: + kustomize.toolkit.fluxcd.io/name: infrastructure + kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }} + name: podinfo + namespace: {{ .ns }} +spec: + chart: + spec: + chart: podinfo + sourceRef: + kind: HelmRepository + name: podinfo + namespace: {{ .fluxns }} + interval: 5m +status: + conditions: + - lastTransitionTime: "2021-07-16T15:42:20Z" + message: Release reconciliation succeeded + reason: ReconciliationSucceeded + status: "True" + type: Ready + helmChart: {{ .fluxns }}/podinfo-podinfo + lastAppliedRevision: 6.0.0 + lastAttemptedRevision: 6.0.0 + lastAttemptedValuesChecksum: c31db75d05b7515eba2eef47bd71038c74b2e531 +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +kind: Kustomization +metadata: + name: infrastructure + namespace: {{ .fluxns }} +spec: + path: ./infrastructure + sourceRef: + kind: OCIRepository + name: flux-system + validation: client + interval: 5m + prune: false +status: + conditions: + - lastTransitionTime: "2021-08-01T04:52:56Z" + message: 'Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f' + reason: ReconciliationSucceeded + status: "True" + type: Ready + lastAppliedRevision: main/696f056df216eea4f9401adbee0ff744d4df390f +--- +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: OCIRepository +metadata: + labels: + kustomize.toolkit.fluxcd.io/name: flux-system + kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }} + name: flux-system + namespace: {{ .fluxns }} +spec: + interval: 10m0s + provider: generic + ref: + tag: 1.2.3 + timeout: 60s + url: oci://ghcr.io/example/repo +status: + artifact: + lastUpdateTime: "2022-08-10T10:07:59Z" + metadata: + org.opencontainers.image.revision: 6.1.6/450796ddb2ab6724ee1cc32a4be56da032d1cca0 + org.opencontainers.image.source: https://github.com/stefanprodan/podinfo.git + path: "example" + revision: dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3 + url: "example" + conditions: + - lastTransitionTime: "2021-07-20T00:48:16Z" + message: "stored artifact for digest 'dbdb109711ffb3be77504d2670dbe13c24dd63d8d7f1fb489d350e5bfe930dd3'" + reason: Succeed + status: "True" + type: Ready diff --git a/cmd/flux/testdata/trace/helmrelease.golden b/cmd/flux/testdata/trace/helmrelease.golden index cd775bad6c..310d219257 100644 --- a/cmd/flux/testdata/trace/helmrelease.golden +++ b/cmd/flux/testdata/trace/helmrelease.golden @@ -1,19 +1,19 @@ -Object: HelmRelease/podinfo -Namespace: {{ .ns }} -Status: Managed by Flux +Object: HelmRelease/podinfo +Namespace: {{ .ns }} +Status: Managed by Flux --- -Kustomization: infrastructure -Namespace: {{ .fluxns }} -Path: ./infrastructure -Revision: main/696f056df216eea4f9401adbee0ff744d4df390f -Status: Last reconciled at {{ .kustomizationLastReconcile }} -Message: Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f +Kustomization: infrastructure +Namespace: {{ .fluxns }} +Path: ./infrastructure +Revision: main/696f056df216eea4f9401adbee0ff744d4df390f +Status: Last reconciled at {{ .kustomizationLastReconcile }} +Message: Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f --- -GitRepository: flux-system -Namespace: {{ .fluxns }} -URL: ssh://git@github.com/example/repo -Branch: main -Revision: main/696f056df216eea4f9401adbee0ff744d4df390f -Status: Last reconciled at {{ .gitRepositoryLastReconcile }} -Message: Fetched revision: main/696f056df216eea4f9401adbee0ff744d4df390f +GitRepository: flux-system +Namespace: {{ .fluxns }} +URL: ssh://git@github.com/example/repo +Branch: main +Revision: main/696f056df216eea4f9401adbee0ff744d4df390f +Status: Last reconciled at {{ .gitRepositoryLastReconcile }} +Message: Fetched revision: main/696f056df216eea4f9401adbee0ff744d4df390f diff --git a/cmd/flux/trace.go b/cmd/flux/trace.go index 926b60165b..1a9e0acdb6 100644 --- a/cmd/flux/trace.go +++ b/cmd/flux/trace.go @@ -37,6 +37,7 @@ import ( helmv2 "github.com/fluxcd/helm-controller/api/v2beta1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" fluxmeta "github.com/fluxcd/pkg/apis/meta" + "github.com/fluxcd/pkg/oci" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" ) @@ -219,10 +220,12 @@ func traceKustomization(ctx context.Context, kubeClient client.Client, ksName ty } ksReady := meta.FindStatusCondition(ks.Status.Conditions, fluxmeta.ReadyCondition) - var ksRepository *sourcev1.GitRepository + var gitRepository *sourcev1.GitRepository + var ociRepository *sourcev1.OCIRepository var ksRepositoryReady *metav1.Condition - if ks.Spec.SourceRef.Kind == sourcev1.GitRepositoryKind { - ksRepository = &sourcev1.GitRepository{} + switch ks.Spec.SourceRef.Kind { + case sourcev1.GitRepositoryKind: + gitRepository = &sourcev1.GitRepository{} sourceNamespace := ks.Namespace if ks.Spec.SourceRef.Namespace != "" { sourceNamespace = ks.Spec.SourceRef.Namespace @@ -230,61 +233,109 @@ func traceKustomization(ctx context.Context, kubeClient client.Client, ksName ty err = kubeClient.Get(ctx, types.NamespacedName{ Namespace: sourceNamespace, Name: ks.Spec.SourceRef.Name, - }, ksRepository) + }, gitRepository) if err != nil { return "", fmt.Errorf("failed to find GitRepository: %w", err) } - ksRepositoryReady = meta.FindStatusCondition(ksRepository.Status.Conditions, fluxmeta.ReadyCondition) + ksRepositoryReady = meta.FindStatusCondition(gitRepository.Status.Conditions, fluxmeta.ReadyCondition) + case sourcev1.OCIRepositoryKind: + ociRepository = &sourcev1.OCIRepository{} + sourceNamespace := ks.Namespace + if ks.Spec.SourceRef.Namespace != "" { + sourceNamespace = ks.Spec.SourceRef.Namespace + } + err = kubeClient.Get(ctx, types.NamespacedName{ + Namespace: sourceNamespace, + Name: ks.Spec.SourceRef.Name, + }, ociRepository) + if err != nil { + return "", fmt.Errorf("failed to find OCIRepository: %w", err) + } + ksRepositoryReady = meta.FindStatusCondition(ociRepository.Status.Conditions, fluxmeta.ReadyCondition) } var traceTmpl = ` -Object: {{.ObjectName}} +Object: {{.ObjectName}} {{- if .ObjectNamespace }} -Namespace: {{.ObjectNamespace}} +Namespace: {{.ObjectNamespace}} {{- end }} -Status: Managed by Flux +Status: Managed by Flux {{- if .Kustomization }} --- -Kustomization: {{.Kustomization.Name}} -Namespace: {{.Kustomization.Namespace}} +Kustomization: {{.Kustomization.Name}} +Namespace: {{.Kustomization.Namespace}} {{- if .Kustomization.Spec.TargetNamespace }} -Target: {{.Kustomization.Spec.TargetNamespace}} +Target: {{.Kustomization.Spec.TargetNamespace}} {{- end }} -Path: {{.Kustomization.Spec.Path}} -Revision: {{.Kustomization.Status.LastAppliedRevision}} +Path: {{.Kustomization.Spec.Path}} +Revision: {{.Kustomization.Status.LastAppliedRevision}} {{- if .KustomizationReady }} -Status: Last reconciled at {{.KustomizationReady.LastTransitionTime}} -Message: {{.KustomizationReady.Message}} +Status: Last reconciled at {{.KustomizationReady.LastTransitionTime}} +Message: {{.KustomizationReady.Message}} {{- else }} -Status: Unknown +Status: Unknown {{- end }} {{- end }} {{- if .GitRepository }} --- -GitRepository: {{.GitRepository.Name}} -Namespace: {{.GitRepository.Namespace}} -URL: {{.GitRepository.Spec.URL}} +GitRepository: {{.GitRepository.Name}} +Namespace: {{.GitRepository.Namespace}} +URL: {{.GitRepository.Spec.URL}} {{- if .GitRepository.Spec.Reference }} {{- if .GitRepository.Spec.Reference.Tag }} -Tag: {{.GitRepository.Spec.Reference.Tag}} +Tag: {{.GitRepository.Spec.Reference.Tag}} {{- else if .GitRepository.Spec.Reference.SemVer }} -Tag: {{.GitRepository.Spec.Reference.SemVer}} +Tag: {{.GitRepository.Spec.Reference.SemVer}} {{- else if .GitRepository.Spec.Reference.Branch }} -Branch: {{.GitRepository.Spec.Reference.Branch}} +Branch: {{.GitRepository.Spec.Reference.Branch}} {{- end }} {{- end }} {{- if .GitRepository.Status.Artifact }} -Revision: {{.GitRepository.Status.Artifact.Revision}} +Revision: {{.GitRepository.Status.Artifact.Revision}} {{- end }} -{{- if .GitRepositoryReady }} -{{- if eq .GitRepositoryReady.Status "False" }} -Status: Last reconciliation failed at {{.GitRepositoryReady.LastTransitionTime}} +{{- if .RepositoryReady }} +{{- if eq .RepositoryReady.Status "False" }} +Status: Last reconciliation failed at {{.RepositoryReady.LastTransitionTime}} {{- else }} -Status: Last reconciled at {{.GitRepositoryReady.LastTransitionTime}} +Status: Last reconciled at {{.RepositoryReady.LastTransitionTime}} {{- end }} -Message: {{.GitRepositoryReady.Message}} +Message: {{.RepositoryReady.Message}} {{- else }} -Status: Unknown +Status: Unknown +{{- end }} +{{- end }} +{{- if .OCIRepository }} +--- +OCIRepository: {{.OCIRepository.Name}} +Namespace: {{.OCIRepository.Namespace}} +URL: {{.OCIRepository.Spec.URL}} +{{- if .OCIRepository.Spec.Reference }} +{{- if .OCIRepository.Spec.Reference.Tag }} +Tag: {{.OCIRepository.Spec.Reference.Tag}} +{{- else if .OCIRepository.Spec.Reference.SemVer }} +Tag: {{.OCIRepository.Spec.Reference.SemVer}} +{{- else if .OCIRepository.Spec.Reference.Digest }} +Digest: {{.OCIRepository.Spec.Reference.Digest}} +{{- end }} +{{- end }} +{{- if .OCIRepository.Status.Artifact }} +Revision: {{.OCIRepository.Status.Artifact.Revision}} +{{- if .OCIRepository.Status.Artifact.Metadata }} +{{- $metadata := .OCIRepository.Status.Artifact.Metadata }} +{{- range $k, $v := .Annotations }} +{{ with (index $metadata $v) }}{{ $k }}{{ . }}{{ end }} +{{- end }} +{{- end }} +{{- end }} +{{- if .RepositoryReady }} +{{- if eq .RepositoryReady.Status "False" }} +Status: Last reconciliation failed at {{.RepositoryReady.LastTransitionTime}} +{{- else }} +Status: Last reconciled at {{.RepositoryReady.LastTransitionTime}} +{{- end }} +Message: {{.RepositoryReady.Message}} +{{- else }} +Status: Unknown {{- end }} {{- end }} ` @@ -295,14 +346,18 @@ Status: Unknown Kustomization *kustomizev1.Kustomization KustomizationReady *metav1.Condition GitRepository *sourcev1.GitRepository - GitRepositoryReady *metav1.Condition + OCIRepository *sourcev1.OCIRepository + RepositoryReady *metav1.Condition + Annotations map[string]string }{ ObjectName: obj.GetKind() + "/" + obj.GetName(), ObjectNamespace: obj.GetNamespace(), Kustomization: ks, KustomizationReady: ksReady, - GitRepository: ksRepository, - GitRepositoryReady: ksRepositoryReady, + GitRepository: gitRepository, + OCIRepository: ociRepository, + RepositoryReady: ksRepositoryReady, + Annotations: map[string]string{"Origin Source: ": oci.SourceAnnotation, "Origin Revision: ": oci.RevisionAnnotation}, } t, err := template.New("tmpl").Parse(traceTmpl) diff --git a/cmd/flux/trace_test.go b/cmd/flux/trace_test.go index 1f3dd8892f..8020e1a8ac 100644 --- a/cmd/flux/trace_test.go +++ b/cmd/flux/trace_test.go @@ -57,6 +57,18 @@ func TestTrace(t *testing.T) { "gitRepositoryLastReconcile": toLocalTime(t, "2021-07-20T00:48:16Z"), }, }, + { + "HelmRelease from OCI registry", + "trace podinfo --kind HelmRelease --api-version=helm.toolkit.fluxcd.io/v2beta1", + "testdata/trace/helmrelease-oci.yaml", + "testdata/trace/helmrelease-oci.golden", + map[string]string{ + "ns": allocateNamespace("podinfo"), + "fluxns": allocateNamespace("flux-system"), + "kustomizationLastReconcile": toLocalTime(t, "2021-08-01T04:52:56Z"), + "ociRepositoryLastReconcile": toLocalTime(t, "2021-07-20T00:48:16Z"), + }, + }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) {