Update digest of latest image
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
This commit is contained in:
parent
4addc4e215
commit
806d41081a
|
|
@ -6,7 +6,7 @@ require (
|
|||
github.com/fluxcd/pkg/apis/meta v1.12.0
|
||||
github.com/fluxcd/source-controller/api v1.5.0
|
||||
k8s.io/apimachinery v0.33.0
|
||||
sigs.k8s.io/controller-runtime v0.20.4
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -18,6 +18,7 @@ require (
|
|||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
|
|
|
|||
14
api/go.sum
14
api/go.sum
|
|
@ -1,8 +1,7 @@
|
|||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
|
||||
|
|
@ -40,8 +39,9 @@ github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg
|
|||
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
|
||||
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
|
|
@ -94,16 +94,16 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
|||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
|
||||
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
|
||||
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
|
||||
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
|
||||
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
|
||||
sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
|
||||
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
|
||||
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@ limitations under the License.
|
|||
|
||||
package v1beta2
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CrossNamespaceSourceReference contains enough information to let you locate the
|
||||
// typed Kubernetes resource object at cluster level.
|
||||
|
|
@ -55,10 +57,15 @@ type ImageRef struct {
|
|||
// Tag is the image's tag.
|
||||
// +required
|
||||
Tag string `json:"tag"`
|
||||
// Digest is the image's digest.
|
||||
// +optional
|
||||
Digest string `json:"digest,omitempty"`
|
||||
}
|
||||
|
||||
// String combines the components of ImageRef to construct a string
|
||||
// representation of the image reference.
|
||||
func (r ImageRef) String() string {
|
||||
return r.Name + ":" + r.Tag
|
||||
func (in *ImageRef) String() string {
|
||||
res := in.Name + ":" + in.Tag
|
||||
if in.Digest != "" {
|
||||
res += "@" + in.Digest
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
|
|||
|
|
@ -691,6 +691,9 @@ spec:
|
|||
additionalProperties:
|
||||
description: ImageRef represents an image reference.
|
||||
properties:
|
||||
digest:
|
||||
description: Digest is the image's digest.
|
||||
type: string
|
||||
name:
|
||||
description: Name is the bare image's name.
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -332,6 +332,18 @@ string
|
|||
<p>Tag is the image’s tag.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>digest</code><br>
|
||||
<em>
|
||||
string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Digest is the image’s digest.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -672,6 +672,59 @@ spec:
|
|||
|
||||
## Working with ImageUpdateAutomation
|
||||
|
||||
### Marking images for update
|
||||
|
||||
In order to tell ImageUpdateAutomation to update images in a manifest, the
|
||||
images must be marked with *setters*. A setter is a comment at the end of a
|
||||
line telling exactly which ImagePolicy to use for that line, and optionally
|
||||
also which field of the image elected as latest by the policy to update in
|
||||
that line. This is useful for example in Helm charts, where images are often
|
||||
defined by multiple values, such as the repository URL, a tag, and optionally
|
||||
a digest.
|
||||
|
||||
For example, if you want to use the ImagePolicy `my-policy` from the
|
||||
`flux-system` namespace, you could use it in a Deployment like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: my-app
|
||||
namespace: default
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: my-app
|
||||
image: ghcr.io/my-org/my-app:4.0.6 # {"$imagepolicy": "flux-system:my-policy"}
|
||||
```
|
||||
|
||||
Deployments expect the image to be fully specified, including tag
|
||||
and optionally digest, so for Deployments the setter is the basic
|
||||
one, not specifying any fields of the image.
|
||||
|
||||
If your app is instead deployed by a Flux HelmRelease whose chart
|
||||
supports image fields, you can use the image fields like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: my-app
|
||||
namespace: default
|
||||
spec:
|
||||
values:
|
||||
image:
|
||||
repository: ghcr.io/my-org/my-app # {"$imagepolicy": "flux-system:my-policy:name"}
|
||||
tag: 4.0.6 # {"$imagepolicy": "flux-system:my-policy:tag"}
|
||||
digest: sha256:6129bb944cada32b4662eafd13fd9904d34c77286bf2ec4523eaedb711757cb0 # {"$imagepolicy": "flux-system:my-policy:digest"}
|
||||
```
|
||||
|
||||
**Note:** For the `digest` field to be available in the ImagePolicy status,
|
||||
the `.spec.digestReflectionPolicy` field of the ImagePolicy must be set to
|
||||
`IfNotPresent` or `Always`. For a complete guide on digest reflection,
|
||||
see these [docs](/flux/guides/image-update/#digest-pinning).
|
||||
|
||||
### Triggering a reconciliation
|
||||
|
||||
To manually tell the image-automation-controller to reconcile an
|
||||
|
|
|
|||
20
go.mod
20
go.mod
|
|
@ -16,16 +16,16 @@ require (
|
|||
github.com/ProtonMail/go-crypto v1.2.0
|
||||
github.com/cyphar/filepath-securejoin v0.4.1
|
||||
github.com/fluxcd/image-automation-controller/api v0.40.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.34.0
|
||||
github.com/fluxcd/image-reflector-controller/api v0.35.0
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0
|
||||
github.com/fluxcd/pkg/auth v0.14.0
|
||||
github.com/fluxcd/pkg/auth v0.16.0
|
||||
github.com/fluxcd/pkg/cache v0.9.0
|
||||
github.com/fluxcd/pkg/git v0.31.0
|
||||
github.com/fluxcd/pkg/git/gogit v0.33.0
|
||||
github.com/fluxcd/pkg/gittestserver v0.17.0
|
||||
github.com/fluxcd/pkg/runtime v0.59.0
|
||||
github.com/fluxcd/pkg/runtime v0.60.0
|
||||
github.com/fluxcd/pkg/ssh v0.18.0
|
||||
github.com/fluxcd/source-controller/api v1.5.0
|
||||
github.com/go-git/go-billy/v5 v5.6.2
|
||||
|
|
@ -40,7 +40,7 @@ require (
|
|||
k8s.io/client-go v0.33.0
|
||||
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e
|
||||
sigs.k8s.io/controller-runtime v0.20.4
|
||||
sigs.k8s.io/controller-runtime v0.21.0
|
||||
sigs.k8s.io/kustomize/kyaml v0.19.0
|
||||
)
|
||||
|
||||
|
|
@ -152,13 +152,13 @@ require (
|
|||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/oauth2 v0.29.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/term v0.31.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
|
|
|
|||
40
go.sum
40
go.sum
|
|
@ -110,16 +110,16 @@ github.com/fluxcd/cli-utils v0.36.0-flux.13 h1:2X5yjz/rk9mg7+bMFBDZKGKzeZpAmY2s6
|
|||
github.com/fluxcd/cli-utils v0.36.0-flux.13/go.mod h1:b2iSoIeDTtjfCB0IKtGgqlhhvWa1oux3e90CjOf81oA=
|
||||
github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg=
|
||||
github.com/fluxcd/gitkit v0.6.0/go.mod h1:svOHuKi0fO9HoawdK4HfHAJJseZDHHjk7I3ihnCIqNo=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.34.0 h1:+0AGoaYzHYXzVDQO9xq2eGZKkPl81Bfz6xFI7rElBzs=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.34.0/go.mod h1:C6742RYyZVt2KIyJv16lb4gYbsK+P1RGQeaQ8C8huec=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.35.0 h1:PYPqDmo8BOu3B2vtNkp/KIdGotYAN1zwVJ0+7wumhaE=
|
||||
github.com/fluxcd/image-reflector-controller/api v0.35.0/go.mod h1:mjpokoQhFs2RxfFjY4rHpn3ZAUvee8TiELyROFN4wiA=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0 h1:dMhZJH+g6ZRPjs4zVOAN9vHBd1DcavFgcIFkg5ooOE0=
|
||||
github.com/fluxcd/pkg/apis/acl v0.7.0/go.mod h1:uv7pXXR/gydiX4MUwlQa7vS8JONEDztynnjTvY3JxKQ=
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0 h1:foEINE++pCJlWVhWjYDXfkVmGKu8mQ4BDBlbYi5NU7M=
|
||||
github.com/fluxcd/pkg/apis/event v0.17.0/go.mod h1:0fLhLFiHlRTDKPDXdRnv+tS7mCMIQ0fJxnEfmvGM/5A=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0 h1:XW15TKZieC2b7MN8VS85stqZJOx+/b8jATQ/xTUhVYg=
|
||||
github.com/fluxcd/pkg/apis/meta v1.12.0/go.mod h1:+son1Va60x2eiDcTwd7lcctbI6C+K3gM7R+ULmEq1SI=
|
||||
github.com/fluxcd/pkg/auth v0.14.0 h1:AA9nmbFzTN5jcGROJK51LvQoDetMrXJLAo4Sd6WHpFI=
|
||||
github.com/fluxcd/pkg/auth v0.14.0/go.mod h1:o91WIZZshLooBALXY/MVn0mmdUw3eATrqGXrG1M7nTE=
|
||||
github.com/fluxcd/pkg/auth v0.16.0 h1:YEjSaNqlpYoXfoFAGhU/Z8y0322nGsT24W6zCh+sbGw=
|
||||
github.com/fluxcd/pkg/auth v0.16.0/go.mod h1:+BRnAO61Nr6fACEjJS6eNRdOk1nXhX/FCPylYn1ypNc=
|
||||
github.com/fluxcd/pkg/cache v0.9.0 h1:EGKfOLMG3fOwWnH/4Axl5xd425mxoQbZzlZoLfd8PDk=
|
||||
github.com/fluxcd/pkg/cache v0.9.0/go.mod h1:jMwabjWfsC5lW8hE7NM3wtGNwSJ38Javx6EKbEi7INU=
|
||||
github.com/fluxcd/pkg/git v0.31.0 h1:hVUJcRujNa+GA5zrjrMpuVcgHbCBjfq0CZIZJqJl22I=
|
||||
|
|
@ -128,8 +128,8 @@ github.com/fluxcd/pkg/git/gogit v0.33.0 h1:JYKa3XqA91AX7/sKEgARO9VzkwouXWjUgpwud
|
|||
github.com/fluxcd/pkg/git/gogit v0.33.0/go.mod h1:EvsVYcB3KjfhpdoyU1sO9HuMH5Xt0cVhW49kFlZcFLY=
|
||||
github.com/fluxcd/pkg/gittestserver v0.17.0 h1:JlBvWZQTDOI+np5Z+084m3DkeAH1hMusEybyRUDF63k=
|
||||
github.com/fluxcd/pkg/gittestserver v0.17.0/go.mod h1:E/40EmLoXcMqd6gLuLDC9F6KJxqHVGbBBeMNKk5XdxU=
|
||||
github.com/fluxcd/pkg/runtime v0.59.0 h1:3OrFkMJB39NcQ2vhhoxqls59sQVSn8U+thhyLbsQoA4=
|
||||
github.com/fluxcd/pkg/runtime v0.59.0/go.mod h1:MFbfyNyyoYRgPxpdwC9/dCOkzo7Yxhu/cQ9NKyhvqc0=
|
||||
github.com/fluxcd/pkg/runtime v0.60.0 h1:d++EkV3FlycB+bzakB5NumwY4J8xts8i7lbvD6jBLeU=
|
||||
github.com/fluxcd/pkg/runtime v0.60.0/go.mod h1:UeU0/eZLErYC/1bTmgzBfNXhiHy9fuQzjfLK0HxRgxY=
|
||||
github.com/fluxcd/pkg/ssh v0.18.0 h1:SB0RrZ/YZIla3chTUulsfVmiCzJv5pEWfHM3dHMC8AU=
|
||||
github.com/fluxcd/pkg/ssh v0.18.0/go.mod h1:G5o0ZD7iR3KFoG5gPnFelX243ciI/PIiVW7J4eBrt5Y=
|
||||
github.com/fluxcd/pkg/version v0.7.0 h1:jZT5I6WFy1KlM40nHCSqlHmjC1VT1/DfmbAdOkIVVJc=
|
||||
|
|
@ -349,8 +349,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
|
|
@ -358,15 +358,15 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -378,16 +378,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
@ -441,8 +441,8 @@ k8s.io/kubectl v0.33.0 h1:HiRb1yqibBSCqic4pRZP+viiOBAnIdwYDpzUFejs07g=
|
|||
k8s.io/kubectl v0.33.0/go.mod h1:gAlGBuS1Jq1fYZ9AjGWbI/5Vk3M/VW2DK4g10Fpyn/0=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
|
||||
sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
|
||||
sigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=
|
||||
sigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ=
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2025 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package constants
|
||||
|
||||
const (
|
||||
// SetterShortHand is a shorthand that can be used to mark
|
||||
// setters; instead of
|
||||
// # { "$ref": "#/definitions/
|
||||
SetterShortHand = "$imagepolicy"
|
||||
)
|
||||
|
|
@ -20,7 +20,6 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -331,10 +330,14 @@ func (r *ImageUpdateAutomationReconciler) reconcile(ctx context.Context, sp *pat
|
|||
conditions.MarkUnknown(obj, meta.ReadyCondition, meta.ProgressingReason, "reconciliation in progress")
|
||||
}
|
||||
|
||||
observedPolicies, err := observedPolicies(policies)
|
||||
if err != nil {
|
||||
result, retErr = ctrl.Result{}, err
|
||||
return
|
||||
// Index the policies by their name.
|
||||
observedPolicies := imagev1.ObservedPolicies{}
|
||||
for _, policy := range policies {
|
||||
observedPolicies[policy.Name] = imagev1.ImageRef{
|
||||
Name: policy.Status.LatestRef.Name,
|
||||
Tag: policy.Status.LatestRef.Tag,
|
||||
Digest: policy.Status.LatestRef.Digest,
|
||||
}
|
||||
}
|
||||
|
||||
// If the policies have changed, require a full sync.
|
||||
|
|
@ -547,7 +550,7 @@ func getPolicies(ctx context.Context, kclient client.Client, namespace string, s
|
|||
readyPolicies := []imagev1_reflect.ImagePolicy{}
|
||||
for _, policy := range policies.Items {
|
||||
// Ignore the policies that don't have a latest image.
|
||||
if policy.Status.LatestImage == "" {
|
||||
if policy.Status.LatestRef == nil {
|
||||
continue
|
||||
}
|
||||
readyPolicies = append(readyPolicies, policy)
|
||||
|
|
@ -556,31 +559,6 @@ func getPolicies(ctx context.Context, kclient client.Client, namespace string, s
|
|||
return readyPolicies, nil
|
||||
}
|
||||
|
||||
// observedPolicies takes a list of ImagePolicies and returns an
|
||||
// ObservedPolicies with all the policies in it.
|
||||
func observedPolicies(policies []imagev1_reflect.ImagePolicy) (imagev1.ObservedPolicies, error) {
|
||||
observedPolicies := imagev1.ObservedPolicies{}
|
||||
for _, policy := range policies {
|
||||
name, tag := splitByLastColon(policy.Status.LatestImage)
|
||||
if name == "" || tag == "" {
|
||||
return nil, fmt.Errorf("failed parsing image: %s", policy.Status.LatestImage)
|
||||
}
|
||||
observedPolicies[policy.Name] = imagev1.ImageRef{
|
||||
Name: name,
|
||||
Tag: tag,
|
||||
}
|
||||
}
|
||||
return observedPolicies, nil
|
||||
}
|
||||
|
||||
func splitByLastColon(latestImage string) (string, string) {
|
||||
idx := strings.LastIndex(latestImage, ":")
|
||||
if idx == -1 {
|
||||
return latestImage, ""
|
||||
}
|
||||
return latestImage[:idx], latestImage[idx+1:]
|
||||
}
|
||||
|
||||
// observedPoliciesChanged returns if the previous and current observedPolicies
|
||||
// have changed.
|
||||
func observedPoliciesChanged(previous, current imagev1.ObservedPolicies) bool {
|
||||
|
|
|
|||
|
|
@ -1532,7 +1532,7 @@ func Test_getPolicies(t *testing.T) {
|
|||
aPolicy.Name = p.name
|
||||
aPolicy.Namespace = p.namespace
|
||||
aPolicy.Status = imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: p.latestImage,
|
||||
LatestRef: testutil.ImageToRef(p.latestImage),
|
||||
}
|
||||
aPolicy.Labels = p.labels
|
||||
testObjects = append(testObjects, aPolicy)
|
||||
|
|
@ -1555,65 +1555,6 @@ func Test_getPolicies(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_observedPolicies(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
policyWithImage map[string]string
|
||||
want imagev1.ObservedPolicies
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "good policies",
|
||||
policyWithImage: map[string]string{
|
||||
"p1": "aaa:bbb",
|
||||
"p2": "ccc:ddd",
|
||||
"p3": "eee:latest",
|
||||
"p4": "registry.localhost:5000/sample-web:0.1.0",
|
||||
},
|
||||
want: imagev1.ObservedPolicies{
|
||||
"p1": imagev1.ImageRef{Name: "aaa", Tag: "bbb"},
|
||||
"p2": imagev1.ImageRef{Name: "ccc", Tag: "ddd"},
|
||||
"p3": imagev1.ImageRef{Name: "eee", Tag: "latest"},
|
||||
"p4": imagev1.ImageRef{Name: "registry.localhost:5000/sample-web", Tag: "0.1.0"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad policy image with no tag",
|
||||
policyWithImage: map[string]string{
|
||||
"p1": "aaa",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "no policy",
|
||||
want: imagev1.ObservedPolicies{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := NewWithT(t)
|
||||
|
||||
policies := []imagev1_reflect.ImagePolicy{}
|
||||
for name, image := range tt.policyWithImage {
|
||||
aPolicy := imagev1_reflect.ImagePolicy{}
|
||||
aPolicy.Name = name
|
||||
aPolicy.Status = imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: image,
|
||||
}
|
||||
policies = append(policies, aPolicy)
|
||||
}
|
||||
|
||||
result, err := observedPolicies(policies)
|
||||
if (err != nil) != tt.wantErr {
|
||||
g.Fail(fmt.Sprintf("unexpected error: %v", err))
|
||||
}
|
||||
if err == nil {
|
||||
g.Expect(result).To(Equal(tt.want))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_observedPoliciesChanged(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
@ -1902,7 +1843,7 @@ func createImagePolicyWithLatestImageForSpec(ctx context.Context, kClient client
|
|||
return err
|
||||
}
|
||||
patch := client.MergeFrom(policy.DeepCopy())
|
||||
policy.Status.LatestImage = latest
|
||||
policy.Status.LatestRef = testutil.ImageToRef(latest)
|
||||
return kClient.Status().Patch(ctx, policy, patch)
|
||||
}
|
||||
|
||||
|
|
@ -1916,7 +1857,7 @@ func updateImagePolicyWithLatestImage(ctx context.Context, kClient client.Client
|
|||
return err
|
||||
}
|
||||
patch := client.MergeFrom(policy.DeepCopy())
|
||||
policy.Status.LatestImage = latest
|
||||
policy.Status.LatestRef = testutil.ImageToRef(latest)
|
||||
return kClient.Status().Patch(ctx, policy, patch)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,11 @@ func (latestImageChangePredicate) Update(e event.UpdateEvent) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if oldSource.Status.LatestImage != newSource.Status.LatestImage {
|
||||
if newSource.Status.LatestRef == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if oldSource.Status.LatestRef == nil || *oldSource.Status.LatestRef != *newSource.Status.LatestRef {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,24 +35,24 @@ func Test_latestImageChangePredicate_Update(t *testing.T) {
|
|||
{
|
||||
name: "no latest image",
|
||||
beforeFunc: func(oldObj, newObj *imagev1_reflect.ImagePolicy) {
|
||||
oldObj.Status.LatestImage = ""
|
||||
newObj.Status.LatestImage = ""
|
||||
oldObj.Status.LatestRef = nil
|
||||
newObj.Status.LatestRef = nil
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "new image, no old image",
|
||||
beforeFunc: func(oldObj, newObj *imagev1_reflect.ImagePolicy) {
|
||||
oldObj.Status.LatestImage = ""
|
||||
newObj.Status.LatestImage = "foo"
|
||||
oldObj.Status.LatestRef = nil
|
||||
newObj.Status.LatestRef = &imagev1_reflect.ImageRef{Name: "foo"}
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "different old and new image",
|
||||
beforeFunc: func(oldObj, newObj *imagev1_reflect.ImagePolicy) {
|
||||
oldObj.Status.LatestImage = "bar"
|
||||
newObj.Status.LatestImage = "foo"
|
||||
oldObj.Status.LatestRef = &imagev1_reflect.ImageRef{Name: "bar"}
|
||||
newObj.Status.LatestRef = &imagev1_reflect.ImageRef{Name: "foo"}
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ func Test_applyPolicies(t *testing.T) {
|
|||
policy.Name = name
|
||||
policy.Namespace = testNS
|
||||
policy.Status = imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: image,
|
||||
LatestRef: testutil.ImageToRef(image),
|
||||
}
|
||||
policyList = append(policyList, *policy)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -640,7 +640,7 @@ Testing: value
|
|||
imgPolicy.Name = "policy1"
|
||||
imgPolicy.Namespace = testNS
|
||||
imgPolicy.Status = imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: tt.latestImage,
|
||||
LatestRef: testutil.ImageToRef(tt.latestImage),
|
||||
}
|
||||
testObjects = append(testObjects, imgPolicy)
|
||||
policyKey := client.ObjectKeyFromObject(imgPolicy)
|
||||
|
|
@ -865,7 +865,7 @@ func test_pushBranchUpdateScenarios(t *testing.T, proto string, srcOpts []Source
|
|||
imgPolicy.Name = "policy1"
|
||||
imgPolicy.Namespace = testNS
|
||||
imgPolicy.Status = imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: latestImage,
|
||||
LatestRef: testutil.ImageToRef(latestImage),
|
||||
}
|
||||
testObjects = append(testObjects, imgPolicy)
|
||||
// Take the policyKey to update the setter marker with.
|
||||
|
|
@ -966,7 +966,7 @@ func test_pushBranchUpdateScenarios(t *testing.T, proto string, srcOpts []Source
|
|||
|
||||
// Update latest image.
|
||||
latestImage = "helloworld:v1.3.0"
|
||||
imgPolicy.Status.LatestImage = latestImage
|
||||
imgPolicy.Status.LatestRef = testutil.ImageToRef(latestImage)
|
||||
g.Expect(kClient.Update(ctx, imgPolicy)).To(Succeed())
|
||||
|
||||
policies = []imagev1_reflect.ImagePolicy{*imgPolicy}
|
||||
|
|
@ -1014,7 +1014,7 @@ func test_pushBranchUpdateScenarios(t *testing.T, proto string, srcOpts []Source
|
|||
|
||||
// Update latest image.
|
||||
latestImage = "helloworld:v1.3.1"
|
||||
imgPolicy.Status.LatestImage = latestImage
|
||||
imgPolicy.Status.LatestRef = testutil.ImageToRef(latestImage)
|
||||
g.Expect(kClient.Update(ctx, imgPolicy)).To(Succeed())
|
||||
|
||||
policies = []imagev1_reflect.ImagePolicy{*imgPolicy}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
|
|
@ -43,7 +44,8 @@ import (
|
|||
|
||||
"github.com/fluxcd/pkg/gittestserver"
|
||||
|
||||
"github.com/fluxcd/image-automation-controller/pkg/update"
|
||||
"github.com/fluxcd/image-automation-controller/internal/constants"
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -80,7 +82,7 @@ func ReplaceMarkerWithMarker(path string, policyKey types.NamespacedName, marker
|
|||
}
|
||||
|
||||
func setterRef(name types.NamespacedName) string {
|
||||
return fmt.Sprintf(`{"%s": "%s:%s"}`, update.SetterShortHand, name.Namespace, name.Name)
|
||||
return fmt.Sprintf(`{"%s": "%s:%s"}`, constants.SetterShortHand, name.Namespace, name.Name)
|
||||
}
|
||||
|
||||
func CommitInRepo(ctx context.Context, g *WithT, repoURL, branch, remote, msg string, changeFiles func(path string)) plumbing.Hash {
|
||||
|
|
@ -456,3 +458,23 @@ func GetSigningKeyPair(g *WithT, passphrase string) (*openpgp.Entity, []byte) {
|
|||
|
||||
return pgpEntity, b.Bytes()
|
||||
}
|
||||
|
||||
func ImageToRef(image string) *imagev1_reflect.ImageRef {
|
||||
var digest string
|
||||
|
||||
if idx := strings.LastIndex(image, "@"); idx != -1 {
|
||||
image, digest = image[:idx], image[idx+1:]
|
||||
}
|
||||
|
||||
var tag string
|
||||
|
||||
if idx := strings.LastIndex(image, ":"); idx != -1 {
|
||||
image, tag = image[:idx], image[idx+1:]
|
||||
}
|
||||
|
||||
return &imagev1_reflect.ImageRef{
|
||||
Name: image,
|
||||
Tag: tag,
|
||||
Digest: digest,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ package update
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
|
|
@ -31,21 +30,17 @@ import (
|
|||
"sigs.k8s.io/kustomize/kyaml/sets"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
"github.com/fluxcd/image-automation-controller/internal/constants"
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
const (
|
||||
// This is preserved from setters2
|
||||
K8sCliExtensionKey = "x-k8s-cli"
|
||||
|
||||
// SetterShortHand is a shorthand that can be used to mark
|
||||
// setters; instead of
|
||||
// # { "$ref": "#/definitions/
|
||||
SetterShortHand = "$imagepolicy"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fieldmeta.SetShortHandRef(SetterShortHand)
|
||||
fieldmeta.SetShortHandRef(constants.SetterShortHand)
|
||||
// this prevents the global schema, should it be initialised, from
|
||||
// parsing all the Kubernetes openAPI definitions, which is not
|
||||
// necessary.
|
||||
|
|
@ -144,7 +139,7 @@ func UpdateV2WithSetters(tracelog logr.Logger, inpath, outpath string, policies
|
|||
}
|
||||
result.Files[file] = fileres
|
||||
}
|
||||
objres, ok := fileres.Objects[oid]
|
||||
objres := fileres.Objects[oid]
|
||||
for _, n := range objres {
|
||||
if n == ref {
|
||||
return
|
||||
|
|
@ -156,7 +151,7 @@ func UpdateV2WithSetters(tracelog logr.Logger, inpath, outpath string, policies
|
|||
|
||||
defs := map[string]spec.Schema{}
|
||||
for _, policy := range policies {
|
||||
if policy.Status.LatestImage == "" {
|
||||
if policy.Status.LatestRef == nil {
|
||||
continue
|
||||
}
|
||||
// Using strict validation would mean any image that omits the
|
||||
|
|
@ -165,10 +160,10 @@ func UpdateV2WithSetters(tracelog logr.Logger, inpath, outpath string, policies
|
|||
// filled in. Usually this would mean the tag would end up
|
||||
// being `latest` if empty in the input; but I'm assuming here
|
||||
// that the policy won't have a tagless ref.
|
||||
image := policy.Status.LatestImage
|
||||
image := policy.Status.LatestRef.String()
|
||||
r, err := name.ParseReference(image, name.WeakValidation)
|
||||
if err != nil {
|
||||
return ResultV2{}, fmt.Errorf("encountered invalid image ref %q: %w", policy.Status.LatestImage, err)
|
||||
return ResultV2{}, fmt.Errorf("encountered invalid image ref %q: %w", image, err)
|
||||
}
|
||||
ref := imageRef{
|
||||
Reference: r,
|
||||
|
|
@ -178,15 +173,13 @@ func UpdateV2WithSetters(tracelog logr.Logger, inpath, outpath string, policies
|
|||
},
|
||||
}
|
||||
|
||||
tag := ref.Identifier()
|
||||
// annoyingly, neither the library imported above, nor an
|
||||
// alternative I found, will yield the original image name;
|
||||
// this is an easy way to get it
|
||||
name := strings.TrimSuffix(image, ":"+tag)
|
||||
tag := policy.Status.LatestRef.Tag
|
||||
name := policy.Status.LatestRef.Name
|
||||
digest := policy.Status.LatestRef.Digest
|
||||
|
||||
imageSetter := fmt.Sprintf("%s:%s", policy.GetNamespace(), policy.GetName())
|
||||
tracelog.Info("adding setter", "name", imageSetter)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+imageSetter] = setterSchema(imageSetter, policy.Status.LatestImage)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+imageSetter] = setterSchema(imageSetter, image)
|
||||
imageRefs[imageSetter] = ref
|
||||
|
||||
tagSetter := imageSetter + ":tag"
|
||||
|
|
@ -194,11 +187,15 @@ func UpdateV2WithSetters(tracelog logr.Logger, inpath, outpath string, policies
|
|||
defs[fieldmeta.SetterDefinitionPrefix+tagSetter] = setterSchema(tagSetter, tag)
|
||||
imageRefs[tagSetter] = ref
|
||||
|
||||
// Context().Name() gives the image repository _as supplied_
|
||||
nameSetter := imageSetter + ":name"
|
||||
tracelog.Info("adding setter", "name", nameSetter)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+nameSetter] = setterSchema(nameSetter, name)
|
||||
imageRefs[nameSetter] = ref
|
||||
|
||||
digestSetter := imageSetter + ":digest"
|
||||
tracelog.Info("adding setter", "name", digestSetter)
|
||||
defs[fieldmeta.SetterDefinitionPrefix+digestSetter] = setterSchema(digestSetter, digest)
|
||||
imageRefs[digestSetter] = ref
|
||||
}
|
||||
|
||||
settersSchema.Definitions = defs
|
||||
|
|
@ -206,7 +203,7 @@ func UpdateV2WithSetters(tracelog logr.Logger, inpath, outpath string, policies
|
|||
// get ready with the reader and writer
|
||||
reader := &ScreeningLocalReader{
|
||||
Path: inpath,
|
||||
Token: fmt.Sprintf("%q", SetterShortHand),
|
||||
Token: fmt.Sprintf("%q", constants.SetterShortHand),
|
||||
Trace: tracelog,
|
||||
}
|
||||
writer := &kio.LocalPackageWriter{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ images:
|
|||
- name: container
|
||||
newName: index.repo.fake/updated # {"$imagepolicy": "automation-ns:policy:name"}
|
||||
newTag: v1.0.1 # {"$imagepolicy": "automation-ns:policy:tag"}
|
||||
newDigest: sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be # {"$imagepolicy": "automation-ns:policy-with-digest:digest"}
|
||||
# Prove fix for https://github.com/fluxcd/flux2/issues/3284
|
||||
patches:
|
||||
- patch: |
|
||||
|
|
@ -24,3 +25,4 @@ patches:
|
|||
version: v1
|
||||
kind: Deployment
|
||||
name: sxxxxdadminservice
|
||||
image: image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be # {"$imagepolicy": "automation-ns:policy-with-digest"}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ images:
|
|||
- name: container
|
||||
newName: replaced # {"$imagepolicy": "automation-ns:policy:name"}
|
||||
newTag: v1 # {"$imagepolicy": "automation-ns:policy:tag"}
|
||||
newDigest: sha256:1234567890abcdef # {"$imagepolicy": "automation-ns:policy-with-digest:digest"}
|
||||
# Prove fix for https://github.com/fluxcd/flux2/issues/3284
|
||||
patches:
|
||||
- patch: |
|
||||
|
|
@ -24,3 +25,4 @@ patches:
|
|||
version: v1
|
||||
kind: Deployment
|
||||
name: sxxxxdadminservice
|
||||
image: image # {"$imagepolicy": "automation-ns:policy-with-digest"}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
|
||||
"github.com/fluxcd/image-automation-controller/internal/testutil"
|
||||
"github.com/fluxcd/image-automation-controller/pkg/test"
|
||||
imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1beta2"
|
||||
)
|
||||
|
|
@ -35,21 +36,30 @@ func TestUpdateWithSetters(t *testing.T) {
|
|||
|
||||
policies := []imagev1_reflect.ImagePolicy{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{ // name matches marker used in testdata/setters/{original,expected}
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "automation-ns",
|
||||
Name: "policy",
|
||||
},
|
||||
Status: imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: "index.repo.fake/updated:v1.0.1",
|
||||
LatestRef: testutil.ImageToRef("index.repo.fake/updated:v1.0.1"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{ // name matches marker used in testdata/setters/{original,expected}
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "automation-ns",
|
||||
Name: "unchanged",
|
||||
},
|
||||
Status: imagev1_reflect.ImagePolicyStatus{
|
||||
LatestImage: "image:v1.0.0",
|
||||
LatestRef: testutil.ImageToRef("image:v1.0.0"),
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "automation-ns",
|
||||
Name: "policy-with-digest",
|
||||
},
|
||||
Status: imagev1_reflect.ImagePolicyStatus{
|
||||
LatestRef: testutil.ImageToRef("image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -75,18 +85,26 @@ func TestUpdateWithSetters(t *testing.T) {
|
|||
Name: "foo",
|
||||
},
|
||||
}}
|
||||
|
||||
r, _ := name.ParseReference("index.repo.fake/updated:v1.0.1")
|
||||
expectedImageRef := imageRef{r, types.NamespacedName{
|
||||
Name: "policy",
|
||||
Namespace: "automation-ns",
|
||||
}}
|
||||
|
||||
r, _ = name.ParseReference("image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be")
|
||||
expectedImageRefDigest := imageRef{r, types.NamespacedName{
|
||||
Name: "policy-with-digest",
|
||||
Namespace: "automation-ns",
|
||||
}}
|
||||
|
||||
expectedResult := Result{
|
||||
Files: map[string]FileResult{
|
||||
"kustomization.yml": {
|
||||
Objects: map[ObjectIdentifier][]ImageRef{
|
||||
kustomizeResourceID: {
|
||||
expectedImageRef,
|
||||
expectedImageRefDigest,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -130,6 +148,16 @@ func TestUpdateWithSetters(t *testing.T) {
|
|||
NewValue: "v1.0.1",
|
||||
Setter: "automation-ns:policy:tag",
|
||||
},
|
||||
{
|
||||
OldValue: "sha256:1234567890abcdef",
|
||||
NewValue: "sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be",
|
||||
Setter: "automation-ns:policy-with-digest:digest",
|
||||
},
|
||||
{
|
||||
OldValue: "image",
|
||||
NewValue: "image:v1.0.0@sha256:6745aaad46d795c9836632e1fb62f24b7e7f4c843144da8e47a5465c411a14be",
|
||||
Setter: "automation-ns:policy-with-digest",
|
||||
},
|
||||
},
|
||||
},
|
||||
"Kustomization": {
|
||||
|
|
|
|||
Loading…
Reference in New Issue