Update digest of latest image

Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
This commit is contained in:
Matheus Pimenta 2025-05-10 13:22:01 +01:00
parent 4addc4e215
commit 806d41081a
No known key found for this signature in database
GPG Key ID: DE594AAD698A94DE
20 changed files with 247 additions and 173 deletions

View File

@ -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

View File

@ -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=

View File

@ -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
}

View File

@ -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

View File

@ -332,6 +332,18 @@ string
<p>Tag is the image&rsquo;s tag.</p>
</td>
</tr>
<tr>
<td>
<code>digest</code><br>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Digest is the image&rsquo;s digest.</p>
</td>
</tr>
</tbody>
</table>
</div>

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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"
)

View File

@ -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 {

View File

@ -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)
}

View File

@ -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
}

View File

@ -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,
},

View File

@ -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)
}

View File

@ -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}

View File

@ -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,
}
}

View File

@ -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{

View File

@ -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"}

View File

@ -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"}

View File

@ -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": {