From b070d3bea568bbe1cfbe0ff2d3f85a8a74f41b7a Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Mon, 9 Aug 2021 13:20:02 +0100 Subject: [PATCH 1/6] Update fluxcd/pkg/runtime to v0.13.0-rc.2 Signed-off-by: Michael Bridgen --- go.mod | 4 ++-- go.sum | 39 +++++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 5fb47216..63ba7e27 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,8 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/dgraph-io/badger/v3 v3.2103.1 github.com/fluxcd/image-reflector-controller/api v0.11.1 - github.com/fluxcd/pkg/apis/meta v0.10.0 - github.com/fluxcd/pkg/runtime v0.12.0 + github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1 + github.com/fluxcd/pkg/runtime v0.13.0-rc.2 github.com/fluxcd/pkg/version v0.1.0 github.com/go-logr/logr v0.4.0 github.com/google/go-containerregistry v0.4.0 diff --git a/go.sum b/go.sum index d8bc628a..a3f0e10d 100644 --- a/go.sum +++ b/go.sum @@ -130,10 +130,11 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fluxcd/pkg/apis/meta v0.10.0 h1:N7wVGHC1cyPdT87hrDC7UwCwRwnZdQM46PBSLjG2rlE= github.com/fluxcd/pkg/apis/meta v0.10.0/go.mod h1:CW9X9ijMTpNe7BwnokiUOrLl/h13miwVr/3abEQLbKE= -github.com/fluxcd/pkg/runtime v0.12.0 h1:BPZZ8bBkimpqGAPXqOf3LTaw+tcw6HgbWyCuzbbsJGs= -github.com/fluxcd/pkg/runtime v0.12.0/go.mod h1:EyaTR2TOYcjL5U//C4yH3bt2tvTgIOSXpVRbWxUn/C4= +github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1 h1:RHHrztAFv9wmjM+Pk7Svt1UdD+1SdnQSp76MWFiM7Hg= +github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1/go.mod h1:yUblM2vg+X8TE3A2VvJfdhkGmg+uqBlSPkLk7dxi0UM= +github.com/fluxcd/pkg/runtime v0.13.0-rc.2 h1:+4uTEg+CU++hlr7NpOP4KYp60MtHDOgYvpz/74tbATg= +github.com/fluxcd/pkg/runtime v0.13.0-rc.2/go.mod h1:TmvE2cJl1QkgZNmmlr7XUKoWDQwUiM5/wTUxXsQVoc8= 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/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -470,6 +471,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/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= 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= @@ -536,6 +538,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -571,8 +574,10 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= +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-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -588,8 +593,9 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -635,9 +641,12 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -658,6 +667,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb 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-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -705,8 +715,9 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -819,24 +830,25 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= -k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= +k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU= k8s.io/api v0.21.3 h1:cblWILbLO8ar+Fj6xdDGr603HRsf8Wu9E9rngJeprZQ= k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= -k8s.io/apiextensions-apiserver v0.21.1/go.mod h1:KESQFCGjqVcVsZ9g0xX5bacMjyX5emuWcS2arzdEouA= +k8s.io/apiextensions-apiserver v0.21.2/go.mod h1:+Axoz5/l3AYpGLlhJDfcVQzCerVYq3K3CvDMvw6X1RA= k8s.io/apiextensions-apiserver v0.21.3 h1:+B6biyUWpqt41kz5x6peIsljlsuwvNAp/oFax/j2/aY= k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM= k8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII= k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= -k8s.io/apiserver v0.21.1/go.mod h1:nLLYZvMWn35glJ4/FZRhzLG/3MPxAaZTgV4FJZdr+tY= +k8s.io/apiserver v0.21.2/go.mod h1:lN4yBoGyiNT7SC1dmNk0ue6a5Wi6O3SWOIw91TsucQw= k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= -k8s.io/client-go v0.21.1/go.mod h1:/kEw4RgW+3xnBGzvp9IWxKSNA+lXn3A7AuH3gdOAzLs= +k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA= k8s.io/client-go v0.21.3 h1:J9nxZTOmvkInRDCzcSNQmPJbDYN/PjlxXT9Mos3HcLg= k8s.io/client-go v0.21.3/go.mod h1:+VPhCgTsaFmGILxR/7E1N0S+ryO010QBeNCv5JwRGYU= k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= -k8s.io/code-generator v0.21.1/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= +k8s.io/code-generator v0.21.2/go.mod h1:8mXJDCB7HcRo1xiEQstcguZkbxZaqeUOrO9SsicWs3U= k8s.io/code-generator v0.21.3/go.mod h1:K3y0Bv9Cz2cOW2vXUrNZlFbflhuPvuadW6JdnN6gGKo= -k8s.io/component-base v0.21.1/go.mod h1:NgzFZ2qu4m1juby4TnrmpR8adRk6ka62YdH5DkIIyKA= +k8s.io/component-base v0.21.2/go.mod h1:9lvmIThzdlrJj5Hp8Z/TOgIkdfsNARQ1pT+3PByuiuc= k8s.io/component-base v0.21.3 h1:4WuuXY3Npa+iFfi2aDRiOz+anhNvRfye0859ZgfC5Og= k8s.io/component-base v0.21.3/go.mod h1:kkuhtfEHeZM6LkX0saqSK8PbdO7A0HigUngmhhrwfGQ= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= @@ -857,9 +869,8 @@ k8s.io/utils v0.0.0-20210722164352-7f3ee0f31471/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ 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.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/controller-runtime v0.9.0/go.mod h1:TgkfvrhhEw3PlI0BRL/5xM+89y3/yc0ZDfdbTl84si8= +sigs.k8s.io/controller-runtime v0.9.2/go.mod h1:TxzMCHyEUpaeuOiZx/bIdc2T81vfs/aKdvJt9wuu0zk= sigs.k8s.io/controller-runtime v0.9.5 h1:WThcFE6cqctTn2jCZprLICO6BaKZfhsT37uAapTNfxc= sigs.k8s.io/controller-runtime v0.9.5/go.mod h1:q6PpkM5vqQubEKUKOM6qr06oXGzOBcCby1DA9FbyZeA= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= From 795c363895e30a8136719eba9d2ae9eca1ad89e5 Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Wed, 11 Aug 2021 12:24:18 +0100 Subject: [PATCH 2/6] Port to fluxcd/pkg/runtime/conditions The helpers for conditions have changed in runtime v0.13.0-rc.2; this commit is near to a mechanical rewrite of the conditions-hamdling code in the controllers. It removes `Set*Readiness` from all api/*/, since it it only a thin shim, and would now need pkg/runtime to be imported. These were exported funcs, but unlikely to be used outside of the controller code, and anyway it's <1.0. meta.DependencyNotReadyReason was removed from pkg/apis/meta, and gets a more specific replacement `ImageRepositoryNotReadyReason` here. One more thing: I went through and checked each MarkFalse (i.e., not ready) to see if it should be a MarkStalled (i.e., add stalled condition, and also not ready). I think for now it is OK to stick with being ready or not ready, and consider what might lead to being stalled later. Signed-off-by: Michael Bridgen --- api/go.mod | 2 +- api/go.sum | 8 ++-- api/v1alpha1/imagepolicy_types.go | 6 --- api/v1alpha1/imagerepository_types.go | 6 --- api/v1alpha2/imagepolicy_types.go | 6 --- api/v1alpha2/imagerepository_types.go | 6 --- api/v1beta1/imagepolicy_types.go | 19 ++++++--- api/v1beta1/imagerepository_types.go | 15 ++++--- ...image.toolkit.fluxcd.io_imagepolicies.yaml | 6 +-- ...e.toolkit.fluxcd.io_imagerepositories.yaml | 18 ++++---- controllers/imagepolicy_controller.go | 33 ++++++++------- controllers/imagerepository_controller.go | 41 ++++++++++--------- controllers/scan_test.go | 2 +- go.sum | 3 -- 14 files changed, 79 insertions(+), 92 deletions(-) diff --git a/api/go.mod b/api/go.mod index 1d5d783f..812241d5 100644 --- a/api/go.mod +++ b/api/go.mod @@ -3,7 +3,7 @@ module github.com/fluxcd/image-reflector-controller/api go 1.16 require ( - github.com/fluxcd/pkg/apis/meta v0.10.0 + github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1 k8s.io/apimachinery v0.21.3 sigs.k8s.io/controller-runtime v0.9.5 ) diff --git a/api/go.sum b/api/go.sum index 4b8ebacb..d9846c5a 100644 --- a/api/go.sum +++ b/api/go.sum @@ -91,8 +91,8 @@ github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMi github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fluxcd/pkg/apis/meta v0.10.0 h1:N7wVGHC1cyPdT87hrDC7UwCwRwnZdQM46PBSLjG2rlE= -github.com/fluxcd/pkg/apis/meta v0.10.0/go.mod h1:CW9X9ijMTpNe7BwnokiUOrLl/h13miwVr/3abEQLbKE= +github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1 h1:RHHrztAFv9wmjM+Pk7Svt1UdD+1SdnQSp76MWFiM7Hg= +github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1/go.mod h1:yUblM2vg+X8TE3A2VvJfdhkGmg+uqBlSPkLk7dxi0UM= github.com/form3tech-oss/jwt-go v3.2.2+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 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= @@ -159,7 +159,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -510,7 +509,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -677,7 +675,7 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 k8s.io/api v0.21.3 h1:cblWILbLO8ar+Fj6xdDGr603HRsf8Wu9E9rngJeprZQ= k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= -k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM= k8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII= k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= k8s.io/apiserver v0.21.3/go.mod h1:eDPWlZG6/cCCMj/JBcEpDoK+I+6i3r9GsChYBHSbAzU= diff --git a/api/v1alpha1/imagepolicy_types.go b/api/v1alpha1/imagepolicy_types.go index 12c7bdb3..e27899d5 100644 --- a/api/v1alpha1/imagepolicy_types.go +++ b/api/v1alpha1/imagepolicy_types.go @@ -115,12 +115,6 @@ func (p *ImagePolicy) GetStatusConditions() *[]metav1.Condition { return &p.Status.Conditions } -// SetImageRepositoryReadiness sets the ready condition with the given status, reason and message. -func SetImagePolicyReadiness(p *ImagePolicy, status metav1.ConditionStatus, reason, message string) { - p.Status.ObservedGeneration = p.ObjectMeta.Generation - meta.SetResourceCondition(p, meta.ReadyCondition, status, reason, message) -} - // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="LatestImage",type=string,JSONPath=`.status.latestImage` diff --git a/api/v1alpha1/imagerepository_types.go b/api/v1alpha1/imagerepository_types.go index 02748322..dec33f78 100644 --- a/api/v1alpha1/imagerepository_types.go +++ b/api/v1alpha1/imagerepository_types.go @@ -96,12 +96,6 @@ type ImageRepositoryStatus struct { meta.ReconcileRequestStatus `json:",inline"` } -// SetImageRepositoryReadiness sets the ready condition with the given status, reason and message. -func SetImageRepositoryReadiness(ir *ImageRepository, status metav1.ConditionStatus, reason, message string) { - ir.Status.ObservedGeneration = ir.ObjectMeta.Generation - meta.SetResourceCondition(ir, meta.ReadyCondition, status, reason, message) -} - // GetStatusConditions returns a pointer to the Status.Conditions slice func (in *ImageRepository) GetStatusConditions() *[]metav1.Condition { return &in.Status.Conditions diff --git a/api/v1alpha2/imagepolicy_types.go b/api/v1alpha2/imagepolicy_types.go index b5140cc1..6ec875db 100644 --- a/api/v1alpha2/imagepolicy_types.go +++ b/api/v1alpha2/imagepolicy_types.go @@ -115,12 +115,6 @@ func (p *ImagePolicy) GetStatusConditions() *[]metav1.Condition { return &p.Status.Conditions } -// SetImageRepositoryReadiness sets the ready condition with the given status, reason and message. -func SetImagePolicyReadiness(p *ImagePolicy, status metav1.ConditionStatus, reason, message string) { - p.Status.ObservedGeneration = p.ObjectMeta.Generation - meta.SetResourceCondition(p, meta.ReadyCondition, status, reason, message) -} - // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="LatestImage",type=string,JSONPath=`.status.latestImage` diff --git a/api/v1alpha2/imagerepository_types.go b/api/v1alpha2/imagerepository_types.go index f0cdb760..82facb0f 100644 --- a/api/v1alpha2/imagerepository_types.go +++ b/api/v1alpha2/imagerepository_types.go @@ -96,12 +96,6 @@ type ImageRepositoryStatus struct { meta.ReconcileRequestStatus `json:",inline"` } -// SetImageRepositoryReadiness sets the ready condition with the given status, reason and message. -func SetImageRepositoryReadiness(ir *ImageRepository, status metav1.ConditionStatus, reason, message string) { - ir.Status.ObservedGeneration = ir.ObjectMeta.Generation - meta.SetResourceCondition(ir, meta.ReadyCondition, status, reason, message) -} - // GetStatusConditions returns a pointer to the Status.Conditions slice func (in *ImageRepository) GetStatusConditions() *[]metav1.Condition { return &in.Status.Conditions diff --git a/api/v1beta1/imagepolicy_types.go b/api/v1beta1/imagepolicy_types.go index e09c5e5c..21acb9a4 100644 --- a/api/v1beta1/imagepolicy_types.go +++ b/api/v1beta1/imagepolicy_types.go @@ -111,14 +111,21 @@ type ImagePolicyStatus struct { Conditions []metav1.Condition `json:"conditions,omitempty"` } -func (p *ImagePolicy) GetStatusConditions() *[]metav1.Condition { - return &p.Status.Conditions +// GetConditions returns the slice of status conditions for the object. +func (in ImagePolicy) GetConditions() []metav1.Condition { + return in.Status.Conditions +} + +// SetConditions sets the slice of status conditions for the object. +func (in *ImagePolicy) SetConditions(conditions []metav1.Condition) { + in.Status.Conditions = conditions } -// SetImageRepositoryReadiness sets the ready condition with the given status, reason and message. -func SetImagePolicyReadiness(p *ImagePolicy, status metav1.ConditionStatus, reason, message string) { - p.Status.ObservedGeneration = p.ObjectMeta.Generation - meta.SetResourceCondition(p, meta.ReadyCondition, status, reason, message) +// GetStatusConditions returns a pointer to the slice of status +// conditions. Deprecated: use GetConditions (and possibly +// SetConditions) instead. +func (p *ImagePolicy) GetStatusConditions() *[]metav1.Condition { + return &p.Status.Conditions } // +kubebuilder:storageversion diff --git a/api/v1beta1/imagerepository_types.go b/api/v1beta1/imagerepository_types.go index afc904e1..fe9f17ca 100644 --- a/api/v1beta1/imagerepository_types.go +++ b/api/v1beta1/imagerepository_types.go @@ -109,13 +109,18 @@ type ImageRepositoryStatus struct { meta.ReconcileRequestStatus `json:",inline"` } -// SetImageRepositoryReadiness sets the ready condition with the given status, reason and message. -func SetImageRepositoryReadiness(ir *ImageRepository, status metav1.ConditionStatus, reason, message string) { - ir.Status.ObservedGeneration = ir.ObjectMeta.Generation - meta.SetResourceCondition(ir, meta.ReadyCondition, status, reason, message) +// GetConditions returns the slice of status conditions for the object. +func (in ImageRepository) GetConditions() []metav1.Condition { + return in.Status.Conditions } -// GetStatusConditions returns a pointer to the Status.Conditions slice +// SetConditions sets the slice of status conditions for the object. +func (in *ImageRepository) SetConditions(conditions []metav1.Condition) { + in.Status.Conditions = conditions +} + +// GetStatusConditions returns a pointer to the Status.Conditions +// slice. Deprecated: use GetConditions (then SetConditions) instead. func (in *ImageRepository) GetStatusConditions() *[]metav1.Condition { return &in.Status.Conditions } diff --git a/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml b/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml index 0efb411e..dbeb1db4 100644 --- a/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml +++ b/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml @@ -50,7 +50,7 @@ spec: description: ImageRepositoryRef points at the object specifying the image being scanned properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -186,7 +186,7 @@ spec: description: ImageRepositoryRef points at the object specifying the image being scanned properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -322,7 +322,7 @@ spec: description: ImageRepositoryRef points at the object specifying the image being scanned properties: name: - description: Name of the referent + description: Name of the referent. type: string namespace: description: Namespace of the referent, when not specified it acts as LocalObjectReference diff --git a/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml b/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml index e36a297c..4ff7cffc 100644 --- a/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml +++ b/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml @@ -43,7 +43,7 @@ spec: description: "CertSecretRef can be given the name of a secret containing either or both of \n - a PEM-encoded client certificate (`certFile`) and private key (`keyFile`); - a PEM-encoded CA certificate (`caFile`) \n and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate." properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -58,7 +58,7 @@ spec: description: SecretRef can be given the name of a secret containing credentials to use for the image registry. The secret should be created with `kubectl create secret docker-registry`, or the equivalent. properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -120,7 +120,7 @@ spec: type: object type: array lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change can be detected. + description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string lastScanResult: description: LastScanResult contains the number of fetched tags. @@ -170,7 +170,7 @@ spec: description: "CertSecretRef can be given the name of a secret containing either or both of \n - a PEM-encoded client certificate (`certFile`) and private key (`keyFile`); - a PEM-encoded CA certificate (`caFile`) \n and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate." properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -185,7 +185,7 @@ spec: description: SecretRef can be given the name of a secret containing credentials to use for the image registry. The secret should be created with `kubectl create secret docker-registry`, or the equivalent. properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -247,7 +247,7 @@ spec: type: object type: array lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change can be detected. + description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string lastScanResult: description: LastScanResult contains the number of fetched tags. @@ -310,7 +310,7 @@ spec: description: "CertSecretRef can be given the name of a secret containing either or both of \n - a PEM-encoded client certificate (`certFile`) and private key (`keyFile`); - a PEM-encoded CA certificate (`caFile`) \n and whichever are supplied, will be used for connecting to the registry. The client cert and key are useful if you are authenticating with a certificate; the CA cert is useful if you are using a self-signed server certificate." properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -325,7 +325,7 @@ spec: description: SecretRef can be given the name of a secret containing credentials to use for the image registry. The secret should be created with `kubectl create secret docker-registry`, or the equivalent. properties: name: - description: Name of the referent + description: Name of the referent. type: string required: - name @@ -387,7 +387,7 @@ spec: type: object type: array lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change can be detected. + description: LastHandledReconcileAt holds the value of the most recent reconcile request value, so a change of the annotation value can be detected. type: string lastScanResult: description: LastScanResult contains the number of fetched tags. diff --git a/controllers/imagepolicy_controller.go b/controllers/imagepolicy_controller.go index 34cdd177..0c557e2c 100644 --- a/controllers/imagepolicy_controller.go +++ b/controllers/imagepolicy_controller.go @@ -38,6 +38,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" "github.com/fluxcd/pkg/apis/meta" + "github.com/fluxcd/pkg/runtime/conditions" "github.com/fluxcd/pkg/runtime/events" "github.com/fluxcd/pkg/runtime/metrics" @@ -45,6 +46,8 @@ import ( "github.com/fluxcd/image-reflector-controller/internal/policy" ) +const ImageRepositoryNotReadyReason = "ImageRepositoryNotReady" + // this is used as the key for the index of policy->repository; the // string is arbitrary and acts as a reminder where the value comes // from. @@ -100,10 +103,10 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) } if err := r.Get(ctx, repoNamespacedName, &repo); err != nil { if client.IgnoreNotFound(err) == nil { - imagev1.SetImagePolicyReadiness( + conditions.MarkFalse( &pol, - metav1.ConditionFalse, - meta.DependencyNotReadyReason, + meta.ReadyCondition, + ImageRepositoryNotReadyReason, err.Error(), ) if err := r.patchStatus(ctx, req, pol.Status); err != nil { @@ -133,10 +136,10 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) // if the image repo hasn't been scanned, don't bother if repo.Status.CanonicalImageName == "" { msg := "referenced ImageRepository has not been scanned yet" - imagev1.SetImagePolicyReadiness( + conditions.MarkFalse( &pol, - metav1.ConditionFalse, - meta.DependencyNotReadyReason, + meta.ReadyCondition, + ImageRepositoryNotReadyReason, msg, ) if err := r.patchStatus(ctx, req, pol.Status); err != nil { @@ -172,10 +175,10 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) } if err != nil { - imagev1.SetImagePolicyReadiness( + conditions.MarkFalse( &pol, - metav1.ConditionFalse, - meta.ReconciliationFailedReason, + meta.ReadyCondition, + meta.FailedReason, err.Error(), ) if err := r.patchStatus(ctx, req, pol.Status); err != nil { @@ -188,10 +191,10 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) if latest == "" { msg := fmt.Sprintf("Cannot determine latest tag for policy: %s", err.Error()) pol.Status.LatestImage = "" - imagev1.SetImagePolicyReadiness( + conditions.MarkFalse( &pol, - metav1.ConditionFalse, - meta.ReconciliationFailedReason, + meta.ReadyCondition, + meta.FailedReason, msg, ) @@ -204,10 +207,10 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) msg := fmt.Sprintf("Latest image tag for '%s' resolved to: %s", repo.Spec.Image, latest) pol.Status.LatestImage = repo.Spec.Image + ":" + latest - imagev1.SetImagePolicyReadiness( + conditions.MarkTrue( &pol, - metav1.ConditionTrue, - meta.ReconciliationSucceededReason, + meta.ReadyCondition, + meta.SucceededReason, msg, ) diff --git a/controllers/imagerepository_controller.go b/controllers/imagerepository_controller.go index 006b4695..5cd454c0 100644 --- a/controllers/imagerepository_controller.go +++ b/controllers/imagerepository_controller.go @@ -46,6 +46,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "github.com/fluxcd/pkg/apis/meta" + "github.com/fluxcd/pkg/runtime/conditions" "github.com/fluxcd/pkg/runtime/events" "github.com/fluxcd/pkg/runtime/metrics" "github.com/fluxcd/pkg/runtime/predicates" @@ -108,9 +109,9 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ if imageRepo.Spec.Suspend { msg := "ImageRepository is suspended, skipping reconciliation" - imagev1.SetImageRepositoryReadiness( + conditions.MarkFalse( &imageRepo, - metav1.ConditionFalse, + meta.ReadyCondition, meta.SuspendedReason, msg, ) @@ -135,9 +136,9 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ ref, err := name.ParseReference(imageRepo.Spec.Image) if err != nil { - imagev1.SetImageRepositoryReadiness( + conditions.MarkFalse( &imageRepo, - metav1.ConditionFalse, + meta.ReadyCondition, imagev1.ImageURLInvalidReason, err.Error(), ) @@ -171,7 +172,7 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{Requeue: true}, reconcileErr } // emit successful scan event - if rc := apimeta.FindStatusCondition(imageRepo.Status.Conditions, meta.ReconciliationSucceededReason); rc != nil { + if rc := apimeta.FindStatusCondition(imageRepo.Status.Conditions, meta.SucceededReason); rc != nil { r.event(ctx, imageRepo, events.EventSeverityInfo, rc.Message) } } @@ -196,20 +197,20 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo *imagev1 Namespace: imageRepo.GetNamespace(), Name: imageRepo.Spec.SecretRef.Name, }, &authSecret); err != nil { - imagev1.SetImageRepositoryReadiness( + conditions.MarkFalse( imageRepo, - metav1.ConditionFalse, - meta.ReconciliationFailedReason, + meta.ReadyCondition, + meta.FailedReason, err.Error(), ) return err } auth, err := authFromSecret(authSecret, ref) if err != nil { - imagev1.SetImageRepositoryReadiness( + conditions.MarkFalse( imageRepo, - metav1.ConditionFalse, - meta.ReconciliationFailedReason, + meta.ReadyCondition, + meta.FailedReason, err.Error(), ) return err @@ -226,10 +227,10 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo *imagev1 Namespace: imageRepo.GetNamespace(), Name: imageRepo.Spec.CertSecretRef.Name, }, &certSecret); err != nil { - imagev1.SetImageRepositoryReadiness( + conditions.MarkFalse( imageRepo, - metav1.ConditionFalse, - meta.ReconciliationFailedReason, + meta.ReadyCondition, + meta.FailedReason, err.Error(), ) return err @@ -245,10 +246,10 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo *imagev1 tags, err := remote.ListWithContext(ctx, ref.Context(), options...) if err != nil { - imagev1.SetImageRepositoryReadiness( + conditions.MarkFalse( imageRepo, - metav1.ConditionFalse, - meta.ReconciliationFailedReason, + meta.ReadyCondition, + meta.FailedReason, err.Error(), ) return err @@ -272,10 +273,10 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo *imagev1 imageRepo.Status.SetLastHandledReconcileRequest(token) } - imagev1.SetImageRepositoryReadiness( + conditions.MarkTrue( imageRepo, - metav1.ConditionTrue, - meta.ReconciliationSucceededReason, + meta.ReadyCondition, + meta.SucceededReason, fmt.Sprintf("successful scan, found %v tags", len(tags)), ) diff --git a/controllers/scan_test.go b/controllers/scan_test.go index 9bfd6cfe..7f8bf9a4 100644 --- a/controllers/scan_test.go +++ b/controllers/scan_test.go @@ -188,7 +188,7 @@ var _ = Describe("ImageRepository controller", func() { lastScanTime := repo.Status.LastScanResult.ScanTime repo.Annotations = map[string]string{ - meta.ReconcileAtAnnotation: requestToken, + meta.ReconcileRequestAnnotation: requestToken, } Expect(r.Update(ctx, &repo)).To(Succeed()) Eventually(func() bool { diff --git a/go.sum b/go.sum index a3f0e10d..92075493 100644 --- a/go.sum +++ b/go.sum @@ -130,7 +130,6 @@ github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fluxcd/pkg/apis/meta v0.10.0/go.mod h1:CW9X9ijMTpNe7BwnokiUOrLl/h13miwVr/3abEQLbKE= github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1 h1:RHHrztAFv9wmjM+Pk7Svt1UdD+1SdnQSp76MWFiM7Hg= github.com/fluxcd/pkg/apis/meta v0.11.0-rc.1/go.mod h1:yUblM2vg+X8TE3A2VvJfdhkGmg+uqBlSPkLk7dxi0UM= github.com/fluxcd/pkg/runtime v0.13.0-rc.2 h1:+4uTEg+CU++hlr7NpOP4KYp60MtHDOgYvpz/74tbATg= @@ -640,7 +639,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w 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-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -836,7 +834,6 @@ k8s.io/api v0.21.3/go.mod h1:hUgeYHUbBp23Ue4qdX9tR8/ANi/g3ehylAqDn9NWVOg= k8s.io/apiextensions-apiserver v0.21.2/go.mod h1:+Axoz5/l3AYpGLlhJDfcVQzCerVYq3K3CvDMvw6X1RA= k8s.io/apiextensions-apiserver v0.21.3 h1:+B6biyUWpqt41kz5x6peIsljlsuwvNAp/oFax/j2/aY= k8s.io/apiextensions-apiserver v0.21.3/go.mod h1:kl6dap3Gd45+21Jnh6utCx8Z2xxLm8LGDkprcd+KbsE= -k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJumM= k8s.io/apimachinery v0.21.3 h1:3Ju4nvjCngxxMYby0BimUk+pQHPOQp3eCGChk5kfVII= k8s.io/apimachinery v0.21.3/go.mod h1:H/IM+5vH9kZRNJ4l3x/fXP/5bOPJaVP/guptnZPeCFI= From 25711ed4f360da85e7cc35dabaac43e8fa870aa5 Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Thu, 12 Aug 2021 15:57:06 +0100 Subject: [PATCH 3/6] Use patch.Helper for updating ImageRepository This uses the patch helper from pkg/runtime. The deferred func is a lot simpler than the example given in https://pkg.go.dev/github.com/fluxcd/pkg/runtime/patch#Helper because I do not use extra conditions, or try to infer the status from the return values. Signed-off-by: Michael Bridgen --- controllers/imagerepository_controller.go | 43 ++++++++--------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/controllers/imagerepository_controller.go b/controllers/imagerepository_controller.go index 5cd454c0..bd7698d8 100644 --- a/controllers/imagerepository_controller.go +++ b/controllers/imagerepository_controller.go @@ -38,6 +38,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + kerrors "k8s.io/apimachinery/pkg/util/errors" kuberecorder "k8s.io/client-go/tools/record" "k8s.io/client-go/tools/reference" ctrl "sigs.k8s.io/controller-runtime" @@ -49,6 +50,7 @@ import ( "github.com/fluxcd/pkg/runtime/conditions" "github.com/fluxcd/pkg/runtime/events" "github.com/fluxcd/pkg/runtime/metrics" + "github.com/fluxcd/pkg/runtime/patch" "github.com/fluxcd/pkg/runtime/predicates" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1" @@ -90,7 +92,7 @@ type dockerConfig struct { // +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch // +kubebuilder:rbac:groups="",resources=events,verbs=create;patch -func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) { reconcileStart := time.Now() // NB: In general, if an error is returned then controller-runtime @@ -103,6 +105,18 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, client.IgnoreNotFound(err) } + patcher, err := patch.NewHelper(&imageRepo, r.Client) + if err != nil { + return ctrl.Result{Requeue: true}, err + } + defer func() { + if err := patcher.Patch(ctx, &imageRepo, patch.WithOwnedConditions{ + Conditions: []string{meta.ReadyCondition}, + }, patch.WithStatusObservedGeneration{}); err != nil { + retErr = kerrors.NewAggregate([]error{retErr, err}) + } + }() + defer r.recordSuspension(ctx, imageRepo) log := logr.FromContext(ctx) @@ -115,11 +129,6 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ meta.SuspendedReason, msg, ) - if err := r.patchStatus(ctx, req, imageRepo.Status); err != nil { - log.Error(err, "unable to update status") - return ctrl.Result{Requeue: true}, err - } - log.Info(msg) return ctrl.Result{}, nil } @@ -142,9 +151,6 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ imagev1.ImageURLInvalidReason, err.Error(), ) - if err := r.patchStatus(ctx, req, imageRepo.Status); err != nil { - return ctrl.Result{Requeue: true}, err - } log.Error(err, "Unable to parse image name", "imageName", imageRepo.Spec.Image) return ctrl.Result{Requeue: true}, err } @@ -152,9 +158,6 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ // Set CanonicalImageName based on the parsed reference if c := ref.Context().String(); imageRepo.Status.CanonicalImageName != c { imageRepo.Status.CanonicalImageName = c - if err = r.patchStatus(ctx, req, imageRepo.Status); err != nil { - return ctrl.Result{Requeue: true}, err - } } // Throttle scans based on spec Interval @@ -164,9 +167,6 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ } if ok { reconcileErr := r.scan(ctx, &imageRepo, ref) - if err := r.patchStatus(ctx, req, imageRepo.Status); err != nil { - return ctrl.Result{Requeue: true}, err - } if reconcileErr != nil { r.event(ctx, imageRepo, events.EventSeverityError, reconcileErr.Error()) return ctrl.Result{Requeue: true}, reconcileErr @@ -455,19 +455,6 @@ func (r *ImageRepositoryReconciler) recordSuspension(ctx context.Context, imageR } } -func (r *ImageRepositoryReconciler) patchStatus(ctx context.Context, req ctrl.Request, - newStatus imagev1.ImageRepositoryStatus) error { - var res imagev1.ImageRepository - if err := r.Get(ctx, req.NamespacedName, &res); err != nil { - return err - } - - patch := client.MergeFrom(res.DeepCopy()) - res.Status = newStatus - - return r.Status().Patch(ctx, &res, patch) -} - func parseAuthMap(config dockerConfig) (map[string]authn.AuthConfig, error) { auth := map[string]authn.AuthConfig{} for url, entry := range config.Auths { From d253b65fd06bd1dd2b2a79581d8cf0bb78c7026a Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Thu, 12 Aug 2021 16:32:40 +0100 Subject: [PATCH 4/6] Use patch.Helper for ImagePolicy This replaces all the individual patchStatus calls with a single defer. Signed-off-by: Michael Bridgen --- controllers/imagepolicy_controller.go | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/controllers/imagepolicy_controller.go b/controllers/imagepolicy_controller.go index 0c557e2c..2ffb5811 100644 --- a/controllers/imagepolicy_controller.go +++ b/controllers/imagepolicy_controller.go @@ -28,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + kerrors "k8s.io/apimachinery/pkg/util/errors" kuberecorder "k8s.io/client-go/tools/record" "k8s.io/client-go/tools/reference" ctrl "sigs.k8s.io/controller-runtime" @@ -41,6 +42,7 @@ import ( "github.com/fluxcd/pkg/runtime/conditions" "github.com/fluxcd/pkg/runtime/events" "github.com/fluxcd/pkg/runtime/metrics" + "github.com/fluxcd/pkg/runtime/patch" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1" "github.com/fluxcd/image-reflector-controller/internal/policy" @@ -73,7 +75,7 @@ type ImagePolicyReconcilerOptions struct { // +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch // +kubebuilder:rbac:groups="",resources=events,verbs=create;patch -func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { +func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) { reconcileStart := time.Now() var pol imagev1.ImagePolicy @@ -83,6 +85,18 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) log := logr.FromContext(ctx) + patcher, err := patch.NewHelper(&pol, r.Client) + if err != nil { + return ctrl.Result{Requeue: true}, err + } + defer func() { + if err := patcher.Patch(ctx, &pol, patch.WithOwnedConditions{ + Conditions: []string{meta.ReadyCondition}, + }, patch.WithStatusObservedGeneration{}); err != nil { + retErr = kerrors.NewAggregate([]error{retErr, err}) + } + }() + // record reconciliation duration if r.MetricsRecorder != nil { objRef, err := reference.GetReference(r.Scheme, &pol) @@ -109,9 +123,6 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) ImageRepositoryNotReadyReason, err.Error(), ) - if err := r.patchStatus(ctx, req, pol.Status); err != nil { - return ctrl.Result{Requeue: true}, err - } log.Error(err, "referenced ImageRepository does not exist") return ctrl.Result{}, nil } @@ -142,14 +153,10 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) ImageRepositoryNotReadyReason, msg, ) - if err := r.patchStatus(ctx, req, pol.Status); err != nil { - return ctrl.Result{Requeue: true}, err - } log.Info(msg) return ctrl.Result{}, nil } - var err error policer, err := policy.PolicerFromSpec(pol.Spec.Policy) var latest string @@ -181,9 +188,6 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) meta.FailedReason, err.Error(), ) - if err := r.patchStatus(ctx, req, pol.Status); err != nil { - return ctrl.Result{Requeue: true}, err - } r.event(ctx, pol, events.EventSeverityError, err.Error()) return ctrl.Result{}, err } @@ -197,10 +201,6 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) meta.FailedReason, msg, ) - - if err := r.patchStatus(ctx, req, pol.Status); err != nil { - return ctrl.Result{}, err - } r.event(ctx, pol, events.EventSeverityError, msg) return ctrl.Result{}, nil } From e0e6fa21b5a1c5f7a0f34e8e9778ea6e6e18e984 Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Tue, 17 Aug 2021 12:04:25 +0100 Subject: [PATCH 5/6] Use events and metrics helpers in controllers Signed-off-by: Michael Bridgen --- ...image.toolkit.fluxcd.io_imagepolicies.yaml | 2 +- controllers/imagepolicy_controller.go | 108 ++++------------ controllers/imagerepository_controller.go | 116 ++++-------------- main.go | 26 ++-- 4 files changed, 67 insertions(+), 185 deletions(-) diff --git a/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml b/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml index dbeb1db4..a80c6cb4 100644 --- a/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml +++ b/config/crd/bases/image.toolkit.fluxcd.io_imagepolicies.yaml @@ -325,7 +325,7 @@ spec: description: Name of the referent. type: string namespace: - description: Namespace of the referent, when not specified it acts as LocalObjectReference + description: Namespace of the referent, when not specified it acts as LocalObjectReference. type: string required: - name diff --git a/controllers/imagepolicy_controller.go b/controllers/imagepolicy_controller.go index 2ffb5811..3e029476 100644 --- a/controllers/imagepolicy_controller.go +++ b/controllers/imagepolicy_controller.go @@ -23,14 +23,11 @@ import ( "github.com/go-logr/logr" v1 "k8s.io/api/core/v1" - apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" kerrors "k8s.io/apimachinery/pkg/util/errors" - kuberecorder "k8s.io/client-go/tools/record" - "k8s.io/client-go/tools/reference" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -40,15 +37,23 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/runtime/conditions" + helpers "github.com/fluxcd/pkg/runtime/controller" "github.com/fluxcd/pkg/runtime/events" - "github.com/fluxcd/pkg/runtime/metrics" "github.com/fluxcd/pkg/runtime/patch" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1" "github.com/fluxcd/image-reflector-controller/internal/policy" ) -const ImageRepositoryNotReadyReason = "ImageRepositoryNotReady" +const ( + ImageRepositoryNotReadyReason = "ImageRepositoryNotReady" + AccessDeniedReason = "AccessDenied" +) + +const ( + EventReasonRefFound = "ImageRefFound" + EventReasonCannotCalculate = "CannotCalculate" +) // this is used as the key for the index of policy->repository; the // string is arbitrary and acts as a reminder where the value comes @@ -58,11 +63,11 @@ const imageRepoKey = ".spec.imageRepository.name" // ImagePolicyReconciler reconciles a ImagePolicy object type ImagePolicyReconciler struct { client.Client - Scheme *runtime.Scheme - EventRecorder kuberecorder.EventRecorder - ExternalEventRecorder *events.Recorder - MetricsRecorder *metrics.Recorder - Database DatabaseReader + Scheme *runtime.Scheme + Database DatabaseReader + + helpers.Events + helpers.Metrics } type ImagePolicyReconcilerOptions struct { @@ -95,17 +100,11 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) }, patch.WithStatusObservedGeneration{}); err != nil { retErr = kerrors.NewAggregate([]error{retErr, err}) } - }() - // record reconciliation duration - if r.MetricsRecorder != nil { - objRef, err := reference.GetReference(r.Scheme, &pol) - if err != nil { - return ctrl.Result{}, err - } - defer r.MetricsRecorder.RecordDuration(*objRef, reconcileStart) - } - defer r.recordReadinessMetric(ctx, &pol) + // Always record readiness and duration metrics + r.RecordReadiness(ctx, &pol) + r.RecordDuration(ctx, &pol, reconcileStart) + }() var repo imagev1.ImageRepository repoNamespacedName := types.NamespacedName{ @@ -131,15 +130,12 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) // check if we are allowed to use the referenced ImageRepository if _, err := r.hasAccessToRepository(ctx, req, pol.Spec.ImageRepositoryRef, repo.Spec.AccessFrom); err != nil { - imagev1.SetImagePolicyReadiness( + conditions.MarkFalse( &pol, - metav1.ConditionFalse, - "AccessDenied", + meta.ReadyCondition, + AccessDeniedReason, err.Error(), ) - if err := r.patchStatus(ctx, req, pol.Status); err != nil { - return ctrl.Result{Requeue: true}, err - } log.Error(err, "access denied") return ctrl.Result{}, nil } @@ -188,7 +184,7 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) meta.FailedReason, err.Error(), ) - r.event(ctx, pol, events.EventSeverityError, err.Error()) + r.Event(ctx, &pol, events.EventSeverityError, EventReasonCannotCalculate, err.Error()) return ctrl.Result{}, err } @@ -201,7 +197,7 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) meta.FailedReason, msg, ) - r.event(ctx, pol, events.EventSeverityError, msg) + r.Event(ctx, &pol, events.EventSeverityError, EventReasonCannotCalculate, msg) return ctrl.Result{}, nil } @@ -213,11 +209,7 @@ func (r *ImagePolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) meta.SucceededReason, msg, ) - - if err := r.patchStatus(ctx, req, pol.Status); err != nil { - return ctrl.Result{}, err - } - r.event(ctx, pol, events.EventSeverityInfo, msg) + r.Event(ctx, &pol, events.EventSeverityInfo, EventReasonRefFound, msg) return ctrl.Result{}, err } @@ -261,56 +253,6 @@ func (r *ImagePolicyReconciler) imagePoliciesForRepository(obj client.Object) [] return reqs } -// event emits a Kubernetes event and forwards the event to notification controller if configured -func (r *ImagePolicyReconciler) event(ctx context.Context, policy imagev1.ImagePolicy, severity, msg string) { - if r.EventRecorder != nil { - r.EventRecorder.Event(&policy, "Normal", severity, msg) - } - if r.ExternalEventRecorder != nil { - objRef, err := reference.GetReference(r.Scheme, &policy) - if err == nil { - err = r.ExternalEventRecorder.Eventf(*objRef, nil, severity, severity, msg) - } - if err != nil { - logr.FromContext(ctx).Error(err, "unable to send event") - return - } - } -} - -func (r *ImagePolicyReconciler) recordReadinessMetric(ctx context.Context, policy *imagev1.ImagePolicy) { - if r.MetricsRecorder == nil { - return - } - - objRef, err := reference.GetReference(r.Scheme, policy) - if err != nil { - logr.FromContext(ctx).Error(err, "unable to record readiness metric") - return - } - if rc := apimeta.FindStatusCondition(policy.Status.Conditions, meta.ReadyCondition); rc != nil { - r.MetricsRecorder.RecordCondition(*objRef, *rc, !policy.DeletionTimestamp.IsZero()) - } else { - r.MetricsRecorder.RecordCondition(*objRef, metav1.Condition{ - Type: meta.ReadyCondition, - Status: metav1.ConditionUnknown, - }, !policy.DeletionTimestamp.IsZero()) - } -} - -func (r *ImagePolicyReconciler) patchStatus(ctx context.Context, req ctrl.Request, - newStatus imagev1.ImagePolicyStatus) error { - var res imagev1.ImagePolicy - if err := r.Get(ctx, req.NamespacedName, &res); err != nil { - return err - } - - patch := client.MergeFrom(res.DeepCopy()) - res.Status = newStatus - - return r.Status().Patch(ctx, &res, patch) -} - func (r *ImagePolicyReconciler) hasAccessToRepository(ctx context.Context, policy ctrl.Request, repo meta.NamespacedObjectReference, acl *imagev1.AccessFrom) (bool, error) { // grant access if the policy is in the same namespace as the repository if repo.Namespace == "" || policy.Namespace == repo.Namespace { diff --git a/controllers/imagerepository_controller.go b/controllers/imagerepository_controller.go index bd7698d8..0e929159 100644 --- a/controllers/imagerepository_controller.go +++ b/controllers/imagerepository_controller.go @@ -39,8 +39,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" kerrors "k8s.io/apimachinery/pkg/util/errors" - kuberecorder "k8s.io/client-go/tools/record" - "k8s.io/client-go/tools/reference" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -48,8 +46,8 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/runtime/conditions" + helpers "github.com/fluxcd/pkg/runtime/controller" "github.com/fluxcd/pkg/runtime/events" - "github.com/fluxcd/pkg/runtime/metrics" "github.com/fluxcd/pkg/runtime/patch" "github.com/fluxcd/pkg/runtime/predicates" @@ -66,17 +64,22 @@ const ( CACert = "caFile" ) +const ( + EventReasonScanFailed = "ScanFailed" + EventReasonScanSucceeded = "ScanSucceeded" +) + // ImageRepositoryReconciler reconciles a ImageRepository object type ImageRepositoryReconciler struct { client.Client - Scheme *runtime.Scheme - EventRecorder kuberecorder.EventRecorder - ExternalEventRecorder *events.Recorder - MetricsRecorder *metrics.Recorder - Database interface { + Scheme *runtime.Scheme + Database interface { DatabaseWriter DatabaseReader } + + helpers.Events + helpers.Metrics } type ImageRepositoryReconcilerOptions struct { @@ -105,21 +108,30 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, client.IgnoreNotFound(err) } + r.RecordSuspend(ctx, &imageRepo, imageRepo.Spec.Suspend) + patcher, err := patch.NewHelper(&imageRepo, r.Client) if err != nil { return ctrl.Result{Requeue: true}, err } defer func() { + // if the reconcile request annotation was set, consider it + // handled (NB it doesn't matter here if it was changed since last + // time) + if token, ok := meta.ReconcileAnnotationValue(imageRepo.GetAnnotations()); ok { + imageRepo.Status.SetLastHandledReconcileRequest(token) + } + if err := patcher.Patch(ctx, &imageRepo, patch.WithOwnedConditions{ Conditions: []string{meta.ReadyCondition}, }, patch.WithStatusObservedGeneration{}); err != nil { retErr = kerrors.NewAggregate([]error{retErr, err}) } - }() - - defer r.recordSuspension(ctx, imageRepo) - log := logr.FromContext(ctx) + // Always record readiness and duration metrics + r.RecordReadiness(ctx, &imageRepo) + r.RecordDuration(ctx, &imageRepo, reconcileStart) + }() if imageRepo.Spec.Suspend { msg := "ImageRepository is suspended, skipping reconciliation" @@ -132,16 +144,7 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, nil } - // Record readiness metric - defer r.recordReadinessMetric(ctx, &imageRepo) - // Record reconciliation duration - if r.MetricsRecorder != nil { - objRef, err := reference.GetReference(r.Scheme, &imageRepo) - if err != nil { - return ctrl.Result{}, err - } - defer r.MetricsRecorder.RecordDuration(*objRef, reconcileStart) - } + log := logr.FromContext(ctx) ref, err := name.ParseReference(imageRepo.Spec.Image) if err != nil { @@ -168,12 +171,12 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ if ok { reconcileErr := r.scan(ctx, &imageRepo, ref) if reconcileErr != nil { - r.event(ctx, imageRepo, events.EventSeverityError, reconcileErr.Error()) + r.Event(ctx, &imageRepo, events.EventSeverityError, EventReasonScanFailed, reconcileErr.Error()) return ctrl.Result{Requeue: true}, reconcileErr } // emit successful scan event if rc := apimeta.FindStatusCondition(imageRepo.Status.Conditions, meta.SucceededReason); rc != nil { - r.event(ctx, imageRepo, events.EventSeverityInfo, rc.Message) + r.Event(ctx, &imageRepo, events.EventSeverityInfo, EventReasonScanSucceeded, rc.Message) } } @@ -266,13 +269,6 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo *imagev1 ScanTime: scanTime, } - // if the reconcile request annotation was set, consider it - // handled (NB it doesn't matter here if it was changed since last - // time) - if token, ok := meta.ReconcileAnnotationValue(imageRepo.GetAnnotations()); ok { - imageRepo.Status.SetLastHandledReconcileRequest(token) - } - conditions.MarkTrue( imageRepo, meta.ReadyCondition, @@ -397,64 +393,6 @@ func authFromSecret(secret corev1.Secret, ref name.Reference) (authn.Authenticat } } -// event emits a Kubernetes event and forwards the event to notification controller if configured -func (r *ImageRepositoryReconciler) event(ctx context.Context, repo imagev1.ImageRepository, severity, msg string) { - if r.EventRecorder != nil { - r.EventRecorder.Eventf(&repo, "Normal", severity, msg) - } - if r.ExternalEventRecorder != nil { - objRef, err := reference.GetReference(r.Scheme, &repo) - if err != nil { - logr.FromContext(ctx).Error(err, "unable to send event") - return - } - - if err := r.ExternalEventRecorder.Eventf(*objRef, nil, severity, severity, msg); err != nil { - logr.FromContext(ctx).Error(err, "unable to send event") - return - } - } -} - -func (r *ImageRepositoryReconciler) recordReadinessMetric(ctx context.Context, repo *imagev1.ImageRepository) { - if r.MetricsRecorder == nil { - return - } - - objRef, err := reference.GetReference(r.Scheme, repo) - if err != nil { - logr.FromContext(ctx).Error(err, "unable to record readiness metric") - return - } - if rc := apimeta.FindStatusCondition(repo.Status.Conditions, meta.ReadyCondition); rc != nil { - r.MetricsRecorder.RecordCondition(*objRef, *rc, !repo.DeletionTimestamp.IsZero()) - } else { - r.MetricsRecorder.RecordCondition(*objRef, metav1.Condition{ - Type: meta.ReadyCondition, - Status: metav1.ConditionUnknown, - }, !repo.DeletionTimestamp.IsZero()) - } -} - -func (r *ImageRepositoryReconciler) recordSuspension(ctx context.Context, imageRepo imagev1.ImageRepository) { - if r.MetricsRecorder == nil { - return - } - log := logr.FromContext(ctx) - - objRef, err := reference.GetReference(r.Scheme, &imageRepo) - if err != nil { - log.Error(err, "unable to record suspended metric") - return - } - - if !imageRepo.DeletionTimestamp.IsZero() { - r.MetricsRecorder.RecordSuspend(*objRef, false) - } else { - r.MetricsRecorder.RecordSuspend(*objRef, imageRepo.Spec.Suspend) - } -} - func parseAuthMap(config dockerConfig) (map[string]authn.AuthConfig, error) { auth := map[string]authn.AuthConfig{} for url, entry := range config.Auths { diff --git a/main.go b/main.go index 511d8eee..0eadc678 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,7 @@ import ( crtlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics" "github.com/fluxcd/pkg/runtime/client" + helpers "github.com/fluxcd/pkg/runtime/controller" "github.com/fluxcd/pkg/runtime/events" "github.com/fluxcd/pkg/runtime/leaderelection" "github.com/fluxcd/pkg/runtime/logger" @@ -137,13 +138,15 @@ func main() { probes.SetupChecks(mgr, setupLog) pprof.SetupHandlers(mgr, setupLog) + events := helpers.MakeEvents(mgr, controllerName, eventRecorder) + metrics := helpers.MustMakeMetrics(mgr) + if err = (&controllers.ImageRepositoryReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - EventRecorder: mgr.GetEventRecorderFor(controllerName), - ExternalEventRecorder: eventRecorder, - MetricsRecorder: metricsRecorder, - Database: db, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Database: db, + Events: events, + Metrics: metrics, }).SetupWithManager(mgr, controllers.ImageRepositoryReconcilerOptions{ MaxConcurrentReconciles: concurrent, }); err != nil { @@ -151,12 +154,11 @@ func main() { os.Exit(1) } if err = (&controllers.ImagePolicyReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - EventRecorder: mgr.GetEventRecorderFor(controllerName), - ExternalEventRecorder: eventRecorder, - MetricsRecorder: metricsRecorder, - Database: db, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Database: db, + Events: events, + Metrics: metrics, }).SetupWithManager(mgr, controllers.ImagePolicyReconcilerOptions{ MaxConcurrentReconciles: concurrent, }); err != nil { From 650775e07995e451746f18494d1b86f70cbacdd6 Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Tue, 17 Aug 2021 13:52:59 +0100 Subject: [PATCH 6/6] Exit early when resource is suspended The contract for .spec.suspend is (I'm told) to not take any actions, including not updating the status. Signed-off-by: Michael Bridgen --- controllers/imagerepository_controller.go | 14 +++---------- controllers/scan_test.go | 24 +++++++++++------------ 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/controllers/imagerepository_controller.go b/controllers/imagerepository_controller.go index 0e929159..405fee83 100644 --- a/controllers/imagerepository_controller.go +++ b/controllers/imagerepository_controller.go @@ -109,6 +109,9 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ } r.RecordSuspend(ctx, &imageRepo, imageRepo.Spec.Suspend) + if imageRepo.Spec.Suspend { + return ctrl.Result{}, nil + } patcher, err := patch.NewHelper(&imageRepo, r.Client) if err != nil { @@ -133,17 +136,6 @@ func (r *ImageRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Requ r.RecordDuration(ctx, &imageRepo, reconcileStart) }() - if imageRepo.Spec.Suspend { - msg := "ImageRepository is suspended, skipping reconciliation" - conditions.MarkFalse( - &imageRepo, - meta.ReadyCondition, - meta.SuspendedReason, - msg, - ) - return ctrl.Result{}, nil - } - log := logr.FromContext(ctx) ref, err := name.ParseReference(imageRepo.Spec.Image) diff --git a/controllers/scan_test.go b/controllers/scan_test.go index 7f8bf9a4..f5a6754a 100644 --- a/controllers/scan_test.go +++ b/controllers/scan_test.go @@ -29,6 +29,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + ctrl "sigs.k8s.io/controller-runtime" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1" // +kubebuilder:scaffold:imports @@ -135,21 +136,18 @@ var _ = Describe("ImageRepository controller", func() { ctx, cancel := context.WithTimeout(context.Background(), contextTimeout) defer cancel() - r := imageRepoReconciler + Expect(k8sClient.Create(ctx, &repo)).To(Succeed()) - err := r.Create(ctx, &repo) - Expect(err).ToNot(HaveOccurred()) + // call this explicitly, since suspend by definition will + // not change anything we can observe + res, err := imageRepoReconciler.Reconcile(ctx, ctrl.Request{NamespacedName: imageRepoName}) + Expect(err).To(BeNil()) + Expect(res.Requeue).ToNot(BeTrue()) - Eventually(func() bool { - err := r.Get(ctx, imageRepoName, &repo) - return err == nil && len(repo.Status.Conditions) > 0 - }, timeout, interval).Should(BeTrue()) - Expect(repo.Status.CanonicalImageName).To(Equal("")) - cond := repo.Status.Conditions[0] - Expect(cond.Message).To( - Equal("ImageRepository is suspended, skipping reconciliation")) - Expect(cond.Reason).To( - Equal(meta.SuspendedReason)) + // make sure no status was written + var ir imagev1.ImageRepository + Expect(k8sClient.Get(ctx, imageRepoName, &ir)).To(Succeed()) + Expect(ir.Status.CanonicalImageName).To(Equal("")) }) })