summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod6
-rw-r--r--go.sum41
-rw-r--r--pkg/argocd/update_test.go29
-rw-r--r--pkg/image/credentials.go4
-rw-r--r--pkg/registry/client.go220
-rw-r--r--pkg/registry/client_test.go82
-rw-r--r--pkg/registry/mocks/RegistryClient.go78
-rw-r--r--pkg/registry/registry.go20
-rw-r--r--pkg/registry/registry_test.go147
9 files changed, 330 insertions, 297 deletions
diff --git a/go.mod b/go.mod
index 85d07c7..2dc5679 100644
--- a/go.mod
+++ b/go.mod
@@ -7,17 +7,19 @@ require (
github.com/argoproj/argo-cd/v2 v2.1.2
github.com/argoproj/gitops-engine v0.4.1
github.com/argoproj/pkg v0.9.1
+ github.com/distribution/distribution/v3 v3.0.0-20210820130019-1cdeff259b9d
github.com/docker/distribution v2.7.1+incompatible
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
- github.com/nokia/docker-registry-client v0.0.0-20201015093031-af1a6d3b4fb1
+ github.com/opencontainers/go-digest v1.0.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/prometheus/client_golang v1.7.1
- github.com/sirupsen/logrus v1.7.0
+ github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
go.uber.org/ratelimit v0.1.1-0.20201110185707-e86515f0dda9
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
+ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v2 v2.4.0
diff --git a/go.sum b/go.sum
index 44f54be..6bb3152 100644
--- a/go.sum
+++ b/go.sum
@@ -35,9 +35,11 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
+github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
@@ -67,6 +69,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/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d/go.mod h1:WML6KOYjeU8N6YyusMjj2qRvaPNUEvrQvaxuFcMRFJY=
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
@@ -104,6 +107,7 @@ github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:l
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM=
github.com/aws/aws-sdk-go v1.33.16/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.34.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -111,14 +115,20 @@ 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/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU=
+github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/bombsimon/logrusr v1.0.0 h1:CTCkURYAt5nhCCnKH9eLShYayj2/8Kn/4Qg3QfiU+Ro=
github.com/bombsimon/logrusr v1.0.0/go.mod h1:Jq0nHtvxabKE5EMwAAdgTaz7dfWE8C4i11NOltxGQpc=
github.com/bradleyfalzon/ghinstallation v1.1.1 h1:pmBXkxgM1WeF8QYvDLT5kuQiHMcmf+X015GI0KM/E3I=
github.com/bradleyfalzon/ghinstallation v1.1.1/go.mod h1:vyCmHTciHx/uuyN82Zc3rXN3X2KTK8nUTCrTMwAhcug=
+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/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
+github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
+github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
github.com/caddyserver/caddy v1.0.3/go.mod h1:G+ouvOY32gENkJC+jhgl62TyhvqEsFaDiZ4uw0RzP1E=
github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
@@ -178,6 +188,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
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/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
+github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
@@ -185,14 +197,20 @@ github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
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-20210820130019-1cdeff259b9d h1:tU9uEoN7IVTXTznsS/5jUn+Jt7xY9UWTyy9Jp9Rmzc0=
+github.com/distribution/distribution/v3 v3.0.0-20210820130019-1cdeff259b9d/go.mod h1:gt38b7cvVKazi5XkHvINNytZXgTEntyhtyM3HQz46Nk=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v20.10.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+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/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
@@ -339,6 +357,7 @@ github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3K
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
+github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -510,6 +529,7 @@ github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/malexdev/utfutil v0.0.0-20180510171754-00c8d4a8e7a8/go.mod h1:UtpLyb/EupVKXF/N0b4NRe1DNg+QYJsnsHQ038romhM=
github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
+github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
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=
@@ -544,6 +564,7 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
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/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
@@ -569,10 +590,9 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
+github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/nokia/docker-registry-client v0.0.0-20201015093031-af1a6d3b4fb1 h1:QNZos2cYVSeT7m1IEQupD3dWJG3ELuThKQMP3WRDZVE=
-github.com/nokia/docker-registry-client v0.0.0-20201015093031-af1a6d3b4fb1/go.mod h1:0DpUaZpSvIXrsvYc6Wb+fKwjhKz0Lu1NHwMziqTqqvA=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
@@ -626,6 +646,7 @@ github.com/pquerna/cachecontrol v0.0.0-20180306154005-525d0eb5f91d/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 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -636,6 +657,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 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -643,6 +665,7 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/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.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
@@ -672,8 +695,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
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 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
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/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@@ -751,6 +775,9 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da h1:NimzV1aGyq29m5ukMK0AMWEhFaL/lrEOaephfuoiARg=
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
+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/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
+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.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
@@ -796,6 +823,7 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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=
@@ -901,8 +929,9 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 h1:3B43BWw0xEBsLZ/NO1VALz6fppU3481pik+2Ksv45z8=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw=
+golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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=
@@ -939,6 +968,7 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/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=
@@ -1075,6 +1105,7 @@ gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
+google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
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=
@@ -1100,6 +1131,7 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
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/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/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=
@@ -1143,6 +1175,7 @@ google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
diff --git a/pkg/argocd/update_test.go b/pkg/argocd/update_test.go
index d3b9fdc..6cbe6df 100644
--- a/pkg/argocd/update_test.go
+++ b/pkg/argocd/update_test.go
@@ -33,9 +33,10 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Test successful update", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
- regMock.On("Tags", mock.MatchedBy(func(s string) bool {
+ regMock.On("NewRepository", mock.MatchedBy(func(s string) bool {
return s == "jannfis/foobar"
- })).Return([]string{"1.0.1"}, nil)
+ })).Return(nil)
+ regMock.On("Tags").Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -91,7 +92,10 @@ func Test_UpdateApplication(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
assert.Equal(t, endpoint.RegistryPrefix, "quay.io")
- regMock.On("Tags", mock.Anything).Return([]string{"1.0.1"}, nil)
+ regMock.On("NewRepository", mock.MatchedBy(func(s string) bool {
+ return s == "jannfis/foobar"
+ })).Return(nil)
+ regMock.On("Tags").Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -152,9 +156,10 @@ func Test_UpdateApplication(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
assert.Equal(t, endpoint.RegistryPrefix, "quay.io")
- regMock.On("Tags", mock.MatchedBy(func(s string) bool {
+ regMock.On("NewRepository", mock.MatchedBy(func(s string) bool {
return s == "someorg/foobar"
- })).Return([]string{"1.0.1"}, nil)
+ })).Return(nil)
+ regMock.On("Tags").Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -214,6 +219,7 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Test successful update when no tag is set in running workload", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -271,6 +277,7 @@ func Test_UpdateApplication(t *testing.T) {
regMock := regmock.RegistryClient{}
assert.Equal(t, "myuser", username)
assert.Equal(t, "mypass", password)
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -384,6 +391,7 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Test skip because of image up-to-date", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -439,6 +447,7 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Test update because of image registry changed", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -497,6 +506,7 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Test not updated because kustomize image is the same", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -569,8 +579,9 @@ func Test_UpdateApplication(t *testing.T) {
called := 0
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"one", "two", "three", "four"}, nil)
- regMock.On("ManifestV1", mock.Anything).Return(meta[called], nil)
+ regMock.On("Manifest", mock.Anything).Return(meta[called], nil)
called += 1
return &regMock, nil
}
@@ -644,8 +655,9 @@ func Test_UpdateApplication(t *testing.T) {
called := 0
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"one", "two", "three", "four"}, nil)
- regMock.On("ManifestV1", mock.Anything).Return(meta[called], nil)
+ regMock.On("Manifest", mock.Anything).Return(meta[called], nil)
called += 1
return &regMock, nil
}
@@ -705,6 +717,7 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Error - unknown registry", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"1.0.1"}, nil)
return &regMock, nil
}
@@ -813,6 +826,7 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Test error on failure to list tags", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return(nil, errors.New("some error"))
return &regMock, nil
}
@@ -868,6 +882,7 @@ func Test_UpdateApplication(t *testing.T) {
t.Run("Test error on improper semver in tag", func(t *testing.T) {
mockClientFn := func(endpoint *registry.RegistryEndpoint, username, password string) (registry.RegistryClient, error) {
regMock := regmock.RegistryClient{}
+ regMock.On("NewRepository", mock.Anything).Return(nil)
regMock.On("Tags", mock.Anything).Return([]string{"1.0.0", "1.0.1"}, nil)
return &regMock, nil
}
diff --git a/pkg/image/credentials.go b/pkg/image/credentials.go
index 2eb1062..50c3f37 100644
--- a/pkg/image/credentials.go
+++ b/pkg/image/credentials.go
@@ -229,9 +229,7 @@ func parseDockerConfigJson(registryURL string, jsonSource string) (string, strin
regPrefix = registryURL
}
- if strings.HasSuffix(regPrefix, "/") {
- regPrefix = strings.TrimSuffix(regPrefix, "/")
- }
+ regPrefix = strings.TrimSuffix(regPrefix, "/")
for registry, authConf := range auths {
if !strings.HasPrefix(registry, registryURL) && !strings.HasPrefix(registry, regPrefix) {
diff --git a/pkg/registry/client.go b/pkg/registry/client.go
index b4dc380..83197e2 100644
--- a/pkg/registry/client.go
+++ b/pkg/registry/client.go
@@ -1,41 +1,75 @@
package registry
import (
- "bytes"
+ "context"
"crypto/sha256"
- "crypto/tls"
- "encoding/json"
"fmt"
- "net/http"
- "strings"
- "time"
+
+ "github.com/argoproj/pkg/json"
"github.com/argoproj-labs/argocd-image-updater/pkg/log"
"github.com/argoproj-labs/argocd-image-updater/pkg/metrics"
"github.com/argoproj-labs/argocd-image-updater/pkg/tag"
- "github.com/docker/distribution"
- "github.com/docker/distribution/manifest/schema1"
- "github.com/docker/distribution/manifest/schema2"
- "github.com/nokia/docker-registry-client/registry"
+ "github.com/distribution/distribution/v3"
+ "github.com/distribution/distribution/v3/manifest/ocischema"
+ "github.com/distribution/distribution/v3/manifest/schema1"
+ "github.com/distribution/distribution/v3/manifest/schema2"
+ "github.com/distribution/distribution/v3/reference"
+ "github.com/distribution/distribution/v3/registry/client"
+ "github.com/distribution/distribution/v3/registry/client/auth"
+ "github.com/distribution/distribution/v3/registry/client/auth/challenge"
+ "github.com/distribution/distribution/v3/registry/client/transport"
+
+ "github.com/opencontainers/go-digest"
+
"go.uber.org/ratelimit"
+
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
)
// TODO: Check image's architecture and OS
// RegistryClient defines the methods we need for querying container registries
type RegistryClient interface {
- Tags(nameInRepository string) ([]string, error)
- ManifestV1(repository string, reference string) (*schema1.SignedManifest, error)
- ManifestV2(repository string, reference string) (*schema2.DeserializedManifest, error)
- TagMetadata(repository string, manifest distribution.Manifest) (*tag.TagInfo, error)
+ NewRepository(nameInRepository string) error
+ Tags() ([]string, error)
+ Manifest(tagStr string) (distribution.Manifest, error)
+ TagMetadata(manifest distribution.Manifest) (*tag.TagInfo, error)
}
type NewRegistryClient func(*RegistryEndpoint, string, string) (RegistryClient, error)
// Helper type for registry clients
type registryClient struct {
- regClient *registry.Registry
+ regClient distribution.Repository
+ endpoint *RegistryEndpoint
+ creds credentials
+}
+
+// credentials is an implementation of distribution/V3/session struct
+// to mangage registry credentials and token
+type credentials struct {
+ username string
+ password string
+ refreshTokens map[string]string
+}
+
+func (c credentials) Basic(url *url.URL) (string, string) {
+ return c.username, c.password
+}
+
+func (c credentials) RefreshToken(url *url.URL, service string) string {
+ return c.refreshTokens[service]
+}
+
+func (c credentials) SetRefreshToken(realm *url.URL, service, token string) {
+ if c.refreshTokens != nil {
+ c.refreshTokens[service] = token
+ }
}
// rateLimitTransport encapsulates our custom HTTP round tripper with rate
@@ -55,90 +89,84 @@ func (rlt *rateLimitTransport) RoundTrip(r *http.Request) (*http.Response, error
return resp, err
}
-// newRegistry is a wrapper for creating a registry client that is possibly
+// NewRepository is a wrapper for creating a registry client that is possibly
// rate-limited by using a custom HTTP round tripper method.
-func newRegistry(ep *RegistryEndpoint, opts registry.Options) (*registry.Registry, error) {
- url := strings.TrimSuffix(ep.RegistryAPI, "/")
- var transport http.RoundTripper
- if opts.Insecure {
- transport = &http.Transport{
- TLSClientConfig: &tls.Config{
- InsecureSkipVerify: true,
- },
- }
- } else {
- transport = http.DefaultTransport
+func (clt *registryClient) NewRepository(nameInRepository string) error {
+ urlToCall := strings.TrimSuffix(clt.endpoint.RegistryAPI, "/")
+ challengeManager1 := challenge.NewSimpleManager()
+ _, err := ping(challengeManager1, clt.endpoint.RegistryAPI+"/v2/", "")
+ if err != nil {
+ return err
}
- transport = registry.WrapTransport(transport, url, opts)
+ var transport http.RoundTripper = transport.NewTransport(
+ nil, auth.NewAuthorizer(
+ challengeManager1,
+ auth.NewTokenHandler(nil, clt.creds, nameInRepository, "pull")))
rlt := &rateLimitTransport{
- limiter: ep.Limiter,
+ limiter: clt.endpoint.Limiter,
transport: transport,
- endpoint: ep.RegistryAPI,
+ endpoint: clt.endpoint.RegistryAPI,
}
- logf := opts.Logf
- if logf == nil {
- logf = registry.Log
- }
- registry := &registry.Registry{
- URL: url,
- Client: &http.Client{
- Transport: rlt,
- },
- Logf: logf,
+ named, err := reference.WithName(nameInRepository)
+ if err != nil {
+ return err
}
- if opts.DoInitialPing {
- if err := registry.Ping(); err != nil {
- return nil, err
- }
+ clt.regClient, err = client.NewRepository(named, urlToCall, rlt)
+ if err != nil {
+ return err
}
- return registry, nil
-
+ return nil
}
// NewClient returns a new RegistryClient for the given endpoint information
func NewClient(endpoint *RegistryEndpoint, username, password string) (RegistryClient, error) {
-
if username == "" && endpoint.Username != "" {
username = endpoint.Username
}
if password == "" && endpoint.Password != "" {
password = endpoint.Password
}
-
- client, err := newRegistry(endpoint, registry.Options{
- DoInitialPing: endpoint.Ping,
- Logf: registry.Quiet,
- Username: username,
- Password: password,
- Insecure: endpoint.Insecure,
- })
- if err != nil {
- return nil, err
+ creds := credentials{
+ username: username,
+ password: password,
}
return &registryClient{
- regClient: client,
+ creds: creds,
+ endpoint: endpoint,
}, nil
}
// Tags returns a list of tags for given name in repository
-func (client *registryClient) Tags(nameInRepository string) ([]string, error) {
- return client.regClient.Tags(nameInRepository)
-}
-
-// ManifestV1 returns a signed V1 manifest for a given tag in given repository
-func (client *registryClient) ManifestV1(repository string, reference string) (*schema1.SignedManifest, error) {
- return client.regClient.ManifestV1(repository, reference)
+func (clt *registryClient) Tags() ([]string, error) {
+ tagService := clt.regClient.Tags(context.Background())
+ tTags, err := tagService.All(context.Background())
+ if err != nil {
+ return nil, err
+ }
+ return tTags, nil
}
-// ManifestV2 returns a deserialized V2 manifest for a given tag in given repository
-func (client *registryClient) ManifestV2(repository string, reference string) (*schema2.DeserializedManifest, error) {
- return client.regClient.ManifestV2(repository, reference)
+// Manifest returns a Manifest for a given tag in repository
+func (clt *registryClient) Manifest(tagStr string) (distribution.Manifest, error) {
+ manService, err := clt.regClient.Manifests(context.Background())
+ if err != nil {
+ return nil, err
+ }
+ mediaType := []string{ocischema.SchemaVersion.MediaType, schema1.SchemaVersion.MediaType, schema2.SchemaVersion.MediaType}
+ manifest, err := manService.Get(
+ context.Background(),
+ digest.FromString(tagStr),
+ distribution.WithTag(tagStr), distribution.WithManifestMediaTypes(mediaType))
+ if err != nil {
+ return nil, err
+ }
+ return manifest, nil
}
-// GetTagInfo retrieves metadata for a given manifest of given repository
-func (client *registryClient) TagMetadata(repository string, manifest distribution.Manifest) (*tag.TagInfo, error) {
+// TagMetadata retrieves metadata for a given manifest of given repository
+func (client *registryClient) TagMetadata(manifest distribution.Manifest) (*tag.TagInfo, error) {
ti := &tag.TagInfo{}
var info struct {
@@ -146,8 +174,8 @@ func (client *registryClient) TagMetadata(repository string, manifest distributi
Created string `json:"created"`
OS string `json:"os"`
}
-
- // We support both V1 and V2 manifest schemas. Everything else will trigger
+ //
+ // We support both V1,V2 AND OCI manifest schemas. Everything else will trigger
// an error.
switch deserialized := manifest.(type) {
@@ -177,26 +205,37 @@ func (client *registryClient) TagMetadata(repository string, manifest distributi
// The data we require from a V2 manifest is in a blob that we need to
// fetch from the registry.
- _, err := client.regClient.BlobMetadata(repository, man.Config.Digest)
+ blobReader, err := client.regClient.Blobs(context.Background()).Get(context.Background(), man.Config.Digest)
if err != nil {
- return nil, fmt.Errorf("could not get metadata: %v", err)
+ return nil, err
}
- blobReader, err := client.regClient.DownloadBlob(repository, man.Config.Digest)
- if err != nil {
+ if err := json.Unmarshal(blobReader, &info); err != nil {
+ return nil, err
+ }
+
+ if ti.CreatedAt, err = time.Parse(time.RFC3339Nano, info.Created); err != nil {
return nil, err
}
- defer blobReader.Close()
- blobBytes := bytes.Buffer{}
- n, err := blobBytes.ReadFrom(blobReader)
+ _, mBytes, err := manifest.Payload()
if err != nil {
return nil, err
}
+ ti.Digest = sha256.Sum256(mBytes)
+ log.Tracef("v2 SHA digest is %s", fmt.Sprintf("sha256:%x", ti.Digest))
+ return ti, nil
+ case *ocischema.DeserializedManifest:
+ var man ocischema.Manifest = deserialized.Manifest
- log.Tracef("read %d bytes of blob data for %s", n, repository)
+ // The data we require from a V2 manifest is in a blob that we need to
+ // fetch from the registry.
+ blobReader, err := client.regClient.Blobs(context.Background()).Get(context.Background(), man.Config.Digest)
+ if err != nil {
+ return nil, err
+ }
- if err := json.Unmarshal(blobBytes.Bytes(), &info); err != nil {
+ if err := json.Unmarshal(blobReader, &info); err != nil {
return nil, err
}
@@ -209,10 +248,25 @@ func (client *registryClient) TagMetadata(repository string, manifest distributi
return nil, err
}
ti.Digest = sha256.Sum256(mBytes)
- log.Tracef("v2 SHA digest is %s", fmt.Sprintf("sha256:%x", ti.Digest))
+ log.Tracef("oci SHA digest is %s", fmt.Sprintf("sha256:%x", ti.Digest))
return ti, nil
-
default:
return nil, fmt.Errorf("invalid manifest type")
}
}
+
+// Implementation of ping method to intialize the challenge list
+// Without this, tokenHandler and AuthorizationHandler won't work
+func ping(manager challenge.Manager, endpoint, versionHeader string) ([]auth.APIVersion, error) {
+ resp, err := http.Get(endpoint)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ if err := manager.AddResponse(resp); err != nil {
+ return nil, err
+ }
+
+ return auth.APIVersions(resp, versionHeader), err
+}
diff --git a/pkg/registry/client_test.go b/pkg/registry/client_test.go
new file mode 100644
index 0000000..7d0c3a0
--- /dev/null
+++ b/pkg/registry/client_test.go
@@ -0,0 +1,82 @@
+package registry
+
+import (
+ "testing"
+
+ "github.com/distribution/distribution/v3/manifest/schema1"
+ "github.com/stretchr/testify/require"
+)
+
+func Test_TagMetadata(t *testing.T) {
+ t.Run("Check for correct error handling when manifest contains no history", func(t *testing.T) {
+ meta1 := &schema1.SignedManifest{
+ Manifest: schema1.Manifest{
+ History: []schema1.History{},
+ },
+ }
+ ep, err := GetRegistryEndpoint("")
+ require.NoError(t, err)
+ client, err := NewClient(ep, "", "")
+ require.NoError(t, err)
+ _, err = client.TagMetadata(meta1)
+ require.Error(t, err)
+ })
+
+ t.Run("Check for correct error handling when manifest contains invalid history", func(t *testing.T) {
+ meta1 := &schema1.SignedManifest{
+ Manifest: schema1.Manifest{
+ History: []schema1.History{
+ {
+ V1Compatibility: `{"created": {"something": "notastring"}}`,
+ },
+ },
+ },
+ }
+
+ ep, err := GetRegistryEndpoint("")
+ require.NoError(t, err)
+ client, err := NewClient(ep, "", "")
+ require.NoError(t, err)
+ _, err = client.TagMetadata(meta1)
+ require.Error(t, err)
+ })
+
+ t.Run("Check for correct error handling when manifest contains invalid history", func(t *testing.T) {
+ meta1 := &schema1.SignedManifest{
+ Manifest: schema1.Manifest{
+ History: []schema1.History{
+ {
+ V1Compatibility: `{"something": "something"}`,
+ },
+ },
+ },
+ }
+
+ ep, err := GetRegistryEndpoint("")
+ require.NoError(t, err)
+ client, err := NewClient(ep, "", "")
+ require.NoError(t, err)
+ _, err = client.TagMetadata(meta1)
+ require.Error(t, err)
+
+ })
+
+ t.Run("Check for correct error handling when time stamp cannot be parsed", func(t *testing.T) {
+ ts := "invalid"
+ meta1 := &schema1.SignedManifest{
+ Manifest: schema1.Manifest{
+ History: []schema1.History{
+ {
+ V1Compatibility: `{"created":"` + ts + `"}`,
+ },
+ },
+ },
+ }
+ ep, err := GetRegistryEndpoint("")
+ require.NoError(t, err)
+ client, err := NewClient(ep, "", "")
+ require.NoError(t, err)
+ _, err = client.TagMetadata(meta1)
+ require.Error(t, err)
+ })
+}
diff --git a/pkg/registry/mocks/RegistryClient.go b/pkg/registry/mocks/RegistryClient.go
index 6352903..c6cdb72 100644
--- a/pkg/registry/mocks/RegistryClient.go
+++ b/pkg/registry/mocks/RegistryClient.go
@@ -3,13 +3,8 @@
package mocks
import (
- distribution "github.com/docker/distribution"
+ distribution "github.com/distribution/distribution/v3"
mock "github.com/stretchr/testify/mock"
-
- schema1 "github.com/docker/distribution/manifest/schema1"
-
- schema2 "github.com/docker/distribution/manifest/schema2"
-
tag "github.com/argoproj-labs/argocd-image-updater/pkg/tag"
)
@@ -18,22 +13,21 @@ type RegistryClient struct {
mock.Mock
}
-// ManifestV1 provides a mock function with given fields: repository, reference
-func (_m *RegistryClient) ManifestV1(repository string, reference string) (*schema1.SignedManifest, error) {
- ret := _m.Called(repository, reference)
+func (_m *RegistryClient) TagMetadata(manifest distribution.Manifest) (*tag.TagInfo, error) {
+ ret := _m.Called(manifest)
- var r0 *schema1.SignedManifest
- if rf, ok := ret.Get(0).(func(string, string) *schema1.SignedManifest); ok {
- r0 = rf(repository, reference)
+ var r0 *tag.TagInfo
+ if rf, ok := ret.Get(0).(func(distribution.Manifest) *tag.TagInfo); ok {
+ r0 = rf(manifest)
} else {
if ret.Get(0) != nil {
- r0 = ret.Get(0).(*schema1.SignedManifest)
+ r0 = ret.Get(0).(*tag.TagInfo)
}
}
var r1 error
- if rf, ok := ret.Get(1).(func(string, string) error); ok {
- r1 = rf(repository, reference)
+ if rf, ok := ret.Get(1).(func(distribution.Manifest) error); ok {
+ r1 = rf(manifest)
} else {
r1 = ret.Error(1)
}
@@ -41,22 +35,21 @@ func (_m *RegistryClient) ManifestV1(repository string, reference string) (*sche
return r0, r1
}
-// ManifestV2 provides a mock function with given fields: repository, reference
-func (_m *RegistryClient) ManifestV2(repository string, reference string) (*schema2.DeserializedManifest, error) {
- ret := _m.Called(repository, reference)
-
- var r0 *schema2.DeserializedManifest
- if rf, ok := ret.Get(0).(func(string, string) *schema2.DeserializedManifest); ok {
- r0 = rf(repository, reference)
+// Tags provides a mock function with given fields: nameInRepository
+func (_m *RegistryClient) Tags() ([]string, error) {
+ ret := _m.Called()
+ var r0 []string
+ if rf, ok := ret.Get(0).(func() []string); ok {
+ r0 = rf()
} else {
if ret.Get(0) != nil {
- r0 = ret.Get(0).(*schema2.DeserializedManifest)
+ r0 = ret.Get(0).([]string)
}
}
var r1 error
- if rf, ok := ret.Get(1).(func(string, string) error); ok {
- r1 = rf(repository, reference)
+ if rf, ok := ret.Get(1).(func() error); ok {
+ r1 = rf()
} else {
r1 = ret.Error(1)
}
@@ -64,22 +57,21 @@ func (_m *RegistryClient) ManifestV2(repository string, reference string) (*sche
return r0, r1
}
-// TagMetadata provides a mock function with given fields: repository, manifest
-func (_m *RegistryClient) TagMetadata(repository string, manifest distribution.Manifest) (*tag.TagInfo, error) {
- ret := _m.Called(repository, manifest)
+func (_m *RegistryClient) Manifest(tagStr string) (distribution.Manifest, error) {
+ ret := _m.Called(tagStr)
- var r0 *tag.TagInfo
- if rf, ok := ret.Get(0).(func(string, distribution.Manifest) *tag.TagInfo); ok {
- r0 = rf(repository, manifest)
+ var r0 distribution.Manifest
+ if rf, ok := ret.Get(0).(func(string) distribution.Manifest); ok {
+ r0 = rf(tagStr)
} else {
if ret.Get(0) != nil {
- r0 = ret.Get(0).(*tag.TagInfo)
+ r0 = ret.Get(0).(distribution.Manifest)
}
}
var r1 error
- if rf, ok := ret.Get(1).(func(string, distribution.Manifest) error); ok {
- r1 = rf(repository, manifest)
+ if rf, ok := ret.Get(1).(func(string) error); ok {
+ r1 = rf(tagStr)
} else {
r1 = ret.Error(1)
}
@@ -87,25 +79,15 @@ func (_m *RegistryClient) TagMetadata(repository string, manifest distribution.M
return r0, r1
}
-// Tags provides a mock function with given fields: nameInRepository
-func (_m *RegistryClient) Tags(nameInRepository string) ([]string, error) {
+func (_m *RegistryClient) NewRepository(nameInRepository string) (error){
ret := _m.Called(nameInRepository)
- var r0 []string
- if rf, ok := ret.Get(0).(func(string) []string); ok {
- r0 = rf(nameInRepository)
- } else {
- if ret.Get(0) != nil {
- r0 = ret.Get(0).([]string)
- }
- }
-
var r1 error
- if rf, ok := ret.Get(1).(func(string) error); ok {
+ if rf, ok := ret.Get(0).(func(string) error); ok {
r1 = rf(nameInRepository)
} else {
- r1 = ret.Error(1)
+ r1 = ret.Error(0)
}
- return r0, r1
+ return r1
}
diff --git a/pkg/registry/registry.go b/pkg/registry/registry.go
index e39f0d3..c26fe2a 100644
--- a/pkg/registry/registry.go
+++ b/pkg/registry/registry.go
@@ -12,7 +12,8 @@ import (
"sync"
"time"
- "github.com/docker/distribution"
+ "github.com/distribution/distribution/v3"
+
"golang.org/x/sync/semaphore"
"github.com/argoproj-labs/argocd-image-updater/pkg/image"
@@ -39,7 +40,11 @@ func (endpoint *RegistryEndpoint) GetTags(img *image.ContainerImage, regClient R
} else {
nameInRegistry = img.ImageName
}
- tTags, err := regClient.Tags(nameInRegistry)
+ err = regClient.NewRepository(nameInRegistry)
+ if err != nil {
+ return nil, err
+ }
+ tTags, err := regClient.Tags()
if err != nil {
return nil, err
}
@@ -131,17 +136,14 @@ func (endpoint *RegistryEndpoint) GetTags(img *image.ContainerImage, regClient R
// We first try to fetch a V2 manifest, and if that's not available we fall
// back to fetching V1 manifest. If that fails also, we just skip this tag.
- if ml, err = regClient.ManifestV2(nameInRegistry, tagStr); err != nil {
- log.Debugf("No V2 manifest for %s:%s, fetching V1 (%v)", nameInRegistry, tagStr, err)
- if ml, err = regClient.ManifestV1(nameInRegistry, tagStr); err != nil {
- log.Errorf("Error fetching metadata for %s:%s - neither V1 or V2 manifest returned by registry: %v", nameInRegistry, tagStr, err)
- return
- }
+ if ml, err = regClient.Manifest(tagStr); err != nil {
+ log.Errorf("Error fetching metadata for %s:%s - neither V1 or V2 or OCI manifest returned by registry: %v", nameInRegistry, tagStr, err)
+ return
}
// Parse required meta data from the manifest. The metadata contains all
// information needed to decide whether to consider this tag or not.
- ti, err := regClient.TagMetadata(nameInRegistry, ml)
+ ti, err := regClient.TagMetadata(ml)
if err != nil {
log.Errorf("error fetching metadata for %s:%s: %v", nameInRegistry, tagStr, err)
return
diff --git a/pkg/registry/registry_test.go b/pkg/registry/registry_test.go
index bf52748..fb61077 100644
--- a/pkg/registry/registry_test.go
+++ b/pkg/registry/registry_test.go
@@ -1,7 +1,6 @@
package registry
import (
- "fmt"
"os"
"testing"
"time"
@@ -10,8 +9,7 @@ import (
"github.com/argoproj-labs/argocd-image-updater/pkg/registry/mocks"
"github.com/argoproj-labs/argocd-image-updater/pkg/tag"
- "github.com/docker/distribution/manifest/schema1"
- "github.com/docker/distribution/manifest/schema2"
+ "github.com/distribution/distribution/v3/manifest/schema1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
@@ -21,6 +19,7 @@ func Test_GetTags(t *testing.T) {
t.Run("Check for correctly returned tags with semver sort", func(t *testing.T) {
regClient := mocks.RegistryClient{}
+ regClient.On("NewRepository", mock.Anything).Return(nil)
regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
ep, err := GetRegistryEndpoint("")
@@ -39,6 +38,7 @@ func Test_GetTags(t *testing.T) {
t.Run("Check for correctly returned tags with filter function applied", func(t *testing.T) {
regClient := mocks.RegistryClient{}
+ regClient.On("NewRepository", mock.Anything).Return(nil)
regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
ep, err := GetRegistryEndpoint("")
@@ -58,6 +58,7 @@ func Test_GetTags(t *testing.T) {
t.Run("Check for correctly returned tags with name sort", func(t *testing.T) {
regClient := mocks.RegistryClient{}
+ regClient.On("NewRepository", mock.Anything).Return(nil)
regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
ep, err := GetRegistryEndpoint("")
@@ -85,14 +86,11 @@ func Test_GetTags(t *testing.T) {
},
},
}
- meta2 := &schema2.DeserializedManifest{
- Manifest: schema2.Manifest{},
- }
regClient := mocks.RegistryClient{}
+ regClient.On("NewRepository", mock.Anything).Return(nil)
regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
- regClient.On("ManifestV1", mock.Anything, mock.Anything).Return(meta1, nil)
- regClient.On("ManifestV2", mock.Anything, mock.Anything).Return(meta2, nil)
+ regClient.On("Manifest", mock.Anything, mock.Anything).Return(meta1, nil)
regClient.On("TagMetadata", mock.Anything, mock.Anything).Return(&tag.TagInfo{}, nil)
ep, err := GetRegistryEndpoint("")
@@ -110,139 +108,6 @@ func Test_GetTags(t *testing.T) {
require.Equal(t, "1.2.1", tag.TagName)
})
- t.Run("Check for correct error handling when manifest contains no history", func(t *testing.T) {
- meta1 := &schema1.SignedManifest{
- Manifest: schema1.Manifest{
- History: []schema1.History{},
- },
- }
- meta2 := &schema2.DeserializedManifest{
- Manifest: schema2.Manifest{},
- }
-
- regClient := mocks.RegistryClient{}
- regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
- regClient.On("ManifestV1", mock.Anything, mock.Anything).Return(meta1, nil)
- regClient.On("ManifestV2", mock.Anything, mock.Anything).Return(meta2, fmt.Errorf("not implemented"))
- regClient.On("TagMetadata", mock.Anything, mock.Anything).Return(nil, nil)
-
- ep, err := GetRegistryEndpoint("")
- require.NoError(t, err)
- ep.Cache.ClearCache()
-
- img := image.NewFromIdentifier("foo/bar:1.2.0")
- tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{SortMode: image.VersionSortLatest})
- require.NoError(t, err)
- assert.Empty(t, tl.Tags())
-
- tag, err := ep.Cache.GetTag("foo/bar", "1.2.1")
- require.NoError(t, err)
- require.Nil(t, tag)
- })
-
- t.Run("Check for correct error handling when manifest contains invalid history", func(t *testing.T) {
- meta1 := &schema1.SignedManifest{
- Manifest: schema1.Manifest{
- History: []schema1.History{
- {
- V1Compatibility: `{"created": {"something": "notastring"}}`,
- },
- },
- },
- }
- meta2 := &schema2.DeserializedManifest{
- Manifest: schema2.Manifest{},
- }
-
- regClient := mocks.RegistryClient{}
- regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
- regClient.On("ManifestV1", mock.Anything, mock.Anything).Return(meta1, nil)
- regClient.On("ManifestV2", mock.Anything, mock.Anything).Return(meta2, fmt.Errorf("not implemented"))
- regClient.On("TagMetadata", mock.Anything, mock.Anything).Return(nil, nil)
-
- ep, err := GetRegistryEndpoint("")
- require.NoError(t, err)
- ep.Cache.ClearCache()
-
- img := image.NewFromIdentifier("foo/bar:1.2.0")
- tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{SortMode: image.VersionSortLatest})
- require.NoError(t, err)
- assert.Empty(t, tl.Tags())
-
- tag, err := ep.Cache.GetTag("foo/bar", "1.2.1")
- require.NoError(t, err)
- require.Nil(t, tag)
- })
-
- t.Run("Check for correct error handling when manifest contains invalid history", func(t *testing.T) {
- meta1 := &schema1.SignedManifest{
- Manifest: schema1.Manifest{
- History: []schema1.History{
- {
- V1Compatibility: `{"something": "something"}`,
- },
- },
- },
- }
- meta2 := &schema2.DeserializedManifest{
- Manifest: schema2.Manifest{},
- }
-
- regClient := mocks.RegistryClient{}
- regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
- regClient.On("ManifestV1", mock.Anything, mock.Anything).Return(meta1, nil)
- regClient.On("ManifestV2", mock.Anything, mock.Anything).Return(meta2, fmt.Errorf("not implemented"))
- regClient.On("TagMetadata", mock.Anything, mock.Anything).Return(nil, nil)
-
- ep, err := GetRegistryEndpoint("")
- require.NoError(t, err)
- ep.Cache.ClearCache()
-
- img := image.NewFromIdentifier("foo/bar:1.2.0")
- tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{SortMode: image.VersionSortLatest})
- require.NoError(t, err)
- assert.Empty(t, tl.Tags())
-
- tag, err := ep.Cache.GetTag("foo/bar", "1.2.1")
- require.NoError(t, err)
- require.Nil(t, tag)
- })
-
- t.Run("Check for correct error handling when time stamp cannot be parsed", func(t *testing.T) {
- ts := "invalid"
- meta1 := &schema1.SignedManifest{
- Manifest: schema1.Manifest{
- History: []schema1.History{
- {
- V1Compatibility: `{"created":"` + ts + `"}`,
- },
- },
- },
- }
- meta2 := &schema2.DeserializedManifest{
- Manifest: schema2.Manifest{},
- }
-
- regClient := mocks.RegistryClient{}
- regClient.On("Tags", mock.Anything).Return([]string{"1.2.0", "1.2.1", "1.2.2"}, nil)
- regClient.On("ManifestV1", mock.Anything, mock.Anything).Return(meta1, nil)
- regClient.On("ManifestV2", mock.Anything, mock.Anything).Return(meta2, fmt.Errorf("not implemented"))
- regClient.On("TagMetadata", mock.Anything, mock.Anything).Return(nil, nil)
-
- ep, err := GetRegistryEndpoint("")
- require.NoError(t, err)
- ep.Cache.ClearCache()
-
- img := image.NewFromIdentifier("foo/bar:1.2.0")
- tl, err := ep.GetTags(img, &regClient, &image.VersionConstraint{SortMode: image.VersionSortLatest})
- require.NoError(t, err)
- assert.Empty(t, tl.Tags())
-
- tag, err := ep.Cache.GetTag("foo/bar", "1.2.1")
- require.NoError(t, err)
- require.Nil(t, tag)
- })
-
}
func Test_ExpireCredentials(t *testing.T) {