diff --git a/config/crd/bases/sets.gitops.pro_gitopssets.yaml b/config/crd/bases/sets.gitops.pro_gitopssets.yaml index 5ff4c106..dc90caaa 100644 --- a/config/crd/bases/sets.gitops.pro_gitopssets.yaml +++ b/config/crd/bases/sets.gitops.pro_gitopssets.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 + controller-gen.kubebuilder.io/version: v0.19.0 name: gitopssets.sets.gitops.pro spec: group: sets.gitops.pro diff --git a/controllers/gitopsset_controller.go b/controllers/gitopsset_controller.go index 6d594597..6506c53d 100644 --- a/controllers/gitopsset_controller.go +++ b/controllers/gitopsset_controller.go @@ -7,7 +7,7 @@ import ( "sort" "time" - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1" fluxMeta "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/runtime/conditions" diff --git a/examples/imagepolicy/policy-resources.yaml b/examples/imagepolicy/policy-resources.yaml index ec92745f..fa3e6bd5 100644 --- a/examples/imagepolicy/policy-resources.yaml +++ b/examples/imagepolicy/policy-resources.yaml @@ -1,5 +1,5 @@ --- -apiVersion: image.toolkit.fluxcd.io/v1beta2 +apiVersion: image.toolkit.fluxcd.io/v1 kind: ImageRepository metadata: name: podinfo @@ -9,7 +9,7 @@ spec: interval: 1h provider: generic --- -apiVersion: image.toolkit.fluxcd.io/v1beta2 +apiVersion: image.toolkit.fluxcd.io/v1b kind: ImagePolicy metadata: name: podinfo diff --git a/go.mod b/go.mod index 583192da..d48d166d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( dario.cat/mergo v1.0.2 github.com/Masterminds/sprig/v3 v3.3.0 github.com/cyphar/filepath-securejoin v0.4.1 - github.com/fluxcd/image-reflector-controller/api v0.35.2 + github.com/fluxcd/image-reflector-controller/api v1.0.0 github.com/fluxcd/kustomize-controller/api v1.6.1 github.com/fluxcd/pkg/apis/event v0.19.0 github.com/fluxcd/pkg/apis/meta v1.21.0 @@ -108,13 +108,13 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/net v0.43.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/net v0.44.0 // indirect golang.org/x/oauth2 v0.31.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/term v0.34.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.12.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect google.golang.org/protobuf v1.36.7 // indirect @@ -126,8 +126,8 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect k8s.io/kubectl v0.34.0 // indirect - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect - sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d // indirect + sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/kustomize/api v0.20.1 // indirect sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect diff --git a/go.sum b/go.sum index 70ae4f22..5cc9dcdd 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fluxcd/cli-utils v0.36.0-flux.15 h1:Et5QLnIpRjj+oZtM9gEybkAaoNsjysHq0y1253Ai94Y= github.com/fluxcd/cli-utils v0.36.0-flux.15/go.mod h1:AqRUmWIfNE7cdL6NWSGF0bAlypGs+9x5UQ2qOtlEzv4= -github.com/fluxcd/image-reflector-controller/api v0.35.2 h1:EzjtUpyx8kbTFx7ugdi5LRMaCpQW4kX/vjFCIPpPD38= -github.com/fluxcd/image-reflector-controller/api v0.35.2/go.mod h1:mjpokoQhFs2RxfFjY4rHpn3ZAUvee8TiELyROFN4wiA= +github.com/fluxcd/image-reflector-controller/api v1.0.0 h1:dJEu2FKphDmrMe4GsNNg6752cv8pogUqqNWt9ZQPED8= +github.com/fluxcd/image-reflector-controller/api v1.0.0/go.mod h1:J562aKopNq0H2m0Hnz2M9kOwwyLjjwPwJgNBiIlNHQo= github.com/fluxcd/kustomize-controller/api v1.6.1 h1:8AOD+BWQwCLT+u5jgtGryZWkCeslgr+cnQAfUzgWmGk= github.com/fluxcd/kustomize-controller/api v1.6.1/go.mod h1:b0i/KVz28tV8iuqlNHx7MW6ZtTcIbBELGLoKdaK+X8M= github.com/fluxcd/pkg/apis/acl v0.9.0 h1:wBpgsKT+jcyZEcM//OmZr9RiF8klL3ebrDp2u2ThsnA= @@ -259,8 +259,8 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -269,28 +269,28 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 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.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= 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.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= 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.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -338,14 +338,14 @@ k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOP k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts= k8s.io/kubectl v0.34.0 h1:NcXz4TPTaUwhiX4LU+6r6udrlm0NsVnSkP3R9t0dmxs= k8s.io/kubectl v0.34.0/go.mod h1:bmd0W5i+HuG7/p5sqicr0Li0rR2iIhXL0oUyLF3OjR4= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0= +k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/cli-utils v0.37.2 h1:GOfKw5RV2HDQZDJlru5KkfLO1tbxqMoyn1IYUxqBpNg= sigs.k8s.io/cli-utils v0.37.2/go.mod h1:V+IZZr4UoGj7gMJXklWBg6t5xbdThFBcpj4MrZuCYco= sigs.k8s.io/controller-runtime v0.22.1 h1:Ah1T7I+0A7ize291nJZdS1CabF/lB4E++WizgV24Eqg= sigs.k8s.io/controller-runtime v0.22.1/go.mod h1:FwiwRjkRPbiN+zp2QRp7wlTCzbUXxZ/D4OzuQUDwBHY= -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/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= +sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= diff --git a/pkg/generators/imagepolicy/image_policy.go b/pkg/generators/imagepolicy/image_policy.go index 826895e5..f5b0fb05 100644 --- a/pkg/generators/imagepolicy/image_policy.go +++ b/pkg/generators/imagepolicy/image_policy.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" templatesv1 "github.com/gitops-tools/gitopssets-controller/api/v1alpha1" "github.com/gitops-tools/gitopssets-controller/pkg/generators" "github.com/go-logr/logr" @@ -56,7 +56,7 @@ func (g *ImagePolicyGenerator) Generate(ctx context.Context, sg *templatesv1.Git result := []map[string]any{} - if imagePolicy.Status.LatestImage == "" { + if imagePolicy.Status.LatestRef == nil { g.Logger.Info("image policy has not calculated the latest image") return nil, generators.ArtifactError("ImagePolicy", types.NamespacedName{ @@ -65,19 +65,22 @@ func (g *ImagePolicyGenerator) Generate(ctx context.Context, sg *templatesv1.Git }) } - latestTag, err := name.NewTag(imagePolicy.Status.LatestImage) + latestTag, err := name.NewTag(imagePolicy.Status.LatestRef.String()) if err != nil { - return nil, err + return nil, fmt.Errorf("parsing latest ref tag: %w", err) } - g.Logger.Info("image policy", "latestImage", imagePolicy.Status.LatestImage, "latestTag", latestTag.TagStr(), "previousImage", imagePolicy.Status.ObservedPreviousImage) + g.Logger.Info("image policy", + "latestImage", imageRefString(imagePolicy.Status.LatestRef), + "latestTag", latestTag.TagStr(), + "previousImage", imageRefString(imagePolicy.Status.ObservedPreviousRef)) - // This stores empty strings the for the previous tag if it's empty because + // This stores empty strings for the previous tag if it's empty because // that saves users having to check for the existence of the fields in their // templates. previousTag := "" - if imagePolicy.Status.ObservedPreviousImage != "" { - parsedTag, err := name.NewTag(imagePolicy.Status.ObservedPreviousImage) + if imagePolicy.Status.ObservedPreviousRef != nil { + parsedTag, err := name.NewTag(imagePolicy.Status.ObservedPreviousRef.String()) if err != nil { return nil, err } @@ -86,10 +89,10 @@ func (g *ImagePolicyGenerator) Generate(ctx context.Context, sg *templatesv1.Git } generated := map[string]any{ - "latestImage": imagePolicy.Status.LatestImage, + "latestImage": imageRefString(imagePolicy.Status.LatestRef), "image": latestTag.Repository.Name(), "latestTag": latestTag.TagStr(), - "previousImage": imagePolicy.Status.ObservedPreviousImage, + "previousImage": imageRefString(imagePolicy.Status.ObservedPreviousRef), "previousTag": previousTag, } @@ -104,3 +107,11 @@ func (g *ImagePolicyGenerator) Generate(ctx context.Context, sg *templatesv1.Git func (g *ImagePolicyGenerator) Interval(sg *templatesv1.GitOpsSetGenerator) time.Duration { return generators.NoRequeueInterval } + +func imageRefString(s *imagev1.ImageRef) string { + if s == nil { + return "" + } + + return s.String() +} diff --git a/pkg/generators/imagepolicy/image_policy_test.go b/pkg/generators/imagepolicy/image_policy_test.go index 445c7d5f..cc0b4267 100644 --- a/pkg/generators/imagepolicy/image_policy_test.go +++ b/pkg/generators/imagepolicy/image_policy_test.go @@ -3,7 +3,7 @@ package imagepolicy import ( "testing" - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" "github.com/go-logr/logr" "github.com/google/go-cmp/cmp" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -42,7 +42,7 @@ func TestGenerate(t *testing.T) { &templatesv1.ImagePolicyGenerator{ PolicyRef: "test-policy", }, - []runtime.Object{test.NewImagePolicy(withImages("ghcr.io/testing/test:v0.30.0", "ghcr.io/testing/test:v0.29.0"))}, + []runtime.Object{test.NewImagePolicy(withImages("ghcr.io/testing/test", "v0.30.0", "ghcr.io/testing/test", "v0.29.0"))}, []map[string]any{ { "image": "ghcr.io/testing/test", @@ -58,7 +58,7 @@ func TestGenerate(t *testing.T) { &templatesv1.ImagePolicyGenerator{ PolicyRef: "test-policy", }, - []runtime.Object{test.NewImagePolicy(withImages("ghcr.io/testing/test:v0.30.0", ""))}, + []runtime.Object{test.NewImagePolicy(withImages("ghcr.io/testing/test", "v0.30.0", "", ""))}, []map[string]any{ { "image": "ghcr.io/testing/test", @@ -140,8 +140,8 @@ func TestGenerate_errors(t *testing.T) { generator: &templatesv1.ImagePolicyGenerator{ PolicyRef: "test-policy", }, - objects: []runtime.Object{test.NewImagePolicy(withImages("testing/test::", "testing/test:v0.29.0"))}, - wantErr: "repository can only contain the characters `abcdefghijklmnopqrstuvwxyz0123456789_-.", + objects: []runtime.Object{test.NewImagePolicy(withImages("testing/test", ":", "testing/test", "v0.29.0"))}, + wantErr: "must specify a tag name after the colon", }, } @@ -170,10 +170,20 @@ func TestGenerate_errors(t *testing.T) { } } -func withImages(latestImage, previousImage string) func(*imagev1.ImagePolicy) { +func withImages(latestName, latestTag, previousName, previousTag string) func(*imagev1.ImagePolicy) { return func(ip *imagev1.ImagePolicy) { - ip.Status.LatestImage = latestImage - ip.Status.ObservedPreviousImage = previousImage + if latestName != "" && latestTag != "" { + ip.Status.LatestRef = &imagev1.ImageRef{ + Name: latestName, + Tag: latestTag, + } + } + if previousName != "" && previousTag != "" { + ip.Status.ObservedPreviousRef = &imagev1.ImageRef{ + Name: previousName, + Tag: previousTag, + } + } } } diff --git a/pkg/setup/generators.go b/pkg/setup/generators.go index 9501507a..1035463d 100644 --- a/pkg/setup/generators.go +++ b/pkg/setup/generators.go @@ -8,7 +8,7 @@ import ( // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2" clustersv1 "github.com/weaveworks/cluster-controller/api/v1alpha1" diff --git a/pkg/setup/generators_test.go b/pkg/setup/generators_test.go index fb2cb5ce..60632243 100644 --- a/pkg/setup/generators_test.go +++ b/pkg/setup/generators_test.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" templatesv1 "github.com/gitops-tools/gitopssets-controller/api/v1alpha1" clustersv1 "github.com/weaveworks/cluster-controller/api/v1alpha1" diff --git a/test/resources.go b/test/resources.go index ba739795..e8440179 100644 --- a/test/resources.go +++ b/test/resources.go @@ -1,7 +1,7 @@ package test import ( - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -13,7 +13,7 @@ const testNamespace = "default" func NewImagePolicy(opts ...func(*imagev1.ImagePolicy)) *imagev1.ImagePolicy { ip := &imagev1.ImagePolicy{ TypeMeta: metav1.TypeMeta{ - APIVersion: "image.toolkit.fluxcd.io/v1beta2", + APIVersion: "image.toolkit.fluxcd.io/v1", Kind: "ImagePolicy", }, ObjectMeta: metav1.ObjectMeta{ diff --git a/tests/e2e/gitopsset_controller_test.go b/tests/e2e/gitopsset_controller_test.go index 84d627c3..07755c1e 100644 --- a/tests/e2e/gitopsset_controller_test.go +++ b/tests/e2e/gitopsset_controller_test.go @@ -6,7 +6,7 @@ import ( "sort" "testing" - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" "github.com/fluxcd/pkg/apis/meta" sourcev1 "github.com/fluxcd/source-controller/api/v1" @@ -300,7 +300,10 @@ func TestReconcilingUpdatingImagePolicy(t *testing.T) { defer deleteObject(t, testEnv, ip) ip = waitForResource[*imagev1.ImagePolicy](t, testEnv, ip) - ip.Status.LatestImage = "testing/test:v0.30.0" + ip.Status.LatestRef = &imagev1.ImageRef{ + Name: "testing/test", + Tag: "v0.30.0", + } test.AssertNoError(t, testEnv.Status().Update(ctx, ip)) gs := &templatesv1.GitOpsSet{ @@ -336,7 +339,10 @@ func TestReconcilingUpdatingImagePolicy(t *testing.T) { defer deleteGitOpsSetAndWaitForNotFound(t, testEnv, gs) ip = waitForResource[*imagev1.ImagePolicy](t, testEnv, ip) - ip.Status.LatestImage = "testing/test:v0.31.0" + ip.Status.LatestRef = &imagev1.ImageRef{ + Name: "testing/test", + Tag: "v0.31.0", + } test.AssertNoError(t, testEnv.Status().Update(ctx, ip)) waitForGitOpsSetCondition(t, testEnv, gs, "1 resources created") @@ -360,7 +366,10 @@ func TestReconcilingUpdatingImagePolicy_in_matrix(t *testing.T) { defer deleteObject(t, testEnv, ip) test.AssertNoError(t, testEnv.Get(ctx, client.ObjectKeyFromObject(ip), ip)) - ip.Status.LatestImage = "testing/test:v0.30.0" + ip.Status.LatestRef = &imagev1.ImageRef{ + Name: "testing/test", + Tag: "v0.30.0", + } test.AssertNoError(t, testEnv.Status().Update(ctx, ip)) gs := &templatesv1.GitOpsSet{ diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index 816bbaf5..8a3e4795 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" + imagev1 "github.com/fluxcd/image-reflector-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" "github.com/fluxcd/pkg/http/fetch" "github.com/fluxcd/pkg/runtime/testenv" diff --git a/tests/e2e/testdata/crds/image.toolkit.fluxcd.io_imagepolicies.yaml b/tests/e2e/testdata/crds/image.toolkit.fluxcd.io_imagepolicies.yaml index 915c5d77..3967f5ae 100644 --- a/tests/e2e/testdata/crds/image.toolkit.fluxcd.io_imagepolicies.yaml +++ b/tests/e2e/testdata/crds/image.toolkit.fluxcd.io_imagepolicies.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 + controller-gen.kubebuilder.io/version: v0.19.0 name: imagepolicies.image.toolkit.fluxcd.io spec: group: image.toolkit.fluxcd.io @@ -11,14 +11,29 @@ spec: kind: ImagePolicy listKind: ImagePolicyList plural: imagepolicies + shortNames: + - imgpol + - imagepol singular: imagepolicy scope: Namespaced versions: - additionalPrinterColumns: - - jsonPath: .status.latestImage - name: LatestImage + - jsonPath: .status.latestRef.name + name: Image type: string - name: v1beta1 + - jsonPath: .status.latestRef.tag + name: Tag + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 schema: openAPIV3Schema: description: ImagePolicy is the Schema for the imagepolicies API @@ -43,8 +58,27 @@ spec: spec: description: |- ImagePolicySpec defines the parameters for calculating the - ImagePolicy + ImagePolicy. properties: + digestReflectionPolicy: + default: Never + description: |- + DigestReflectionPolicy governs the setting of the `.status.latestRef.digest` field. + + Never: The digest field will always be set to the empty string. + + IfNotPresent: The digest field will be set to the digest of the elected + latest image if the field is empty and the image did not change. + + Always: The digest field will always be set to the digest of the elected + latest image. + + Default: Never. + enum: + - Always + - IfNotPresent + - Never + type: string filterTags: description: |- FilterTags enables filtering for only a subset of tags based on a set of @@ -77,6 +111,15 @@ spec: required: - name type: object + interval: + description: |- + Interval is the length of time to wait between + refreshing the digest of the latest tag when the + reflection policy is set to "Always". + + Defaults to 10m. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string policy: description: |- Policy gives the particulars of the policy to be followed in @@ -126,10 +169,24 @@ spec: - range type: object type: object + suspend: + description: |- + This flag tells the controller to suspend subsequent policy reconciliations. + It does not apply to already started reconciliations. Defaults to false. + type: boolean required: - imageRepositoryRef - policy type: object + x-kubernetes-validations: + - message: spec.interval is only accepted when spec.digestReflectionPolicy + is set to 'Always' + rule: '!has(self.interval) || (has(self.digestReflectionPolicy) && self.digestReflectionPolicy + == ''Always'')' + - message: spec.interval must be set when spec.digestReflectionPolicy + is set to 'Always' + rule: has(self.interval) || !has(self.digestReflectionPolicy) || self.digestReflectionPolicy + != 'Always' status: default: observedGeneration: -1 @@ -191,25 +248,76 @@ spec: - type type: object type: array - latestImage: + lastHandledReconcileAt: description: |- - LatestImage gives the first in the list of images scanned by - the image repository, when filtered and ordered according to - the policy. + LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value + can be detected. type: string + latestRef: + description: |- + LatestRef gives the first in the list of images scanned by + the image repository, when filtered and ordered according + to the policy. + properties: + digest: + description: Digest is the image's digest. + type: string + name: + description: Name is the bare image's name. + type: string + tag: + description: Tag is the image's tag. + type: string + required: + - name + - tag + type: object observedGeneration: format: int64 type: integer + observedPreviousRef: + description: |- + ObservedPreviousRef is the observed previous LatestRef. It is used + to keep track of the previous and current images. + properties: + digest: + description: Digest is the image's digest. + type: string + name: + description: Name is the bare image's name. + type: string + tag: + description: Tag is the image's tag. + type: string + required: + - name + - tag + type: object type: object type: object served: true - storage: false + storage: true subresources: status: {} - additionalPrinterColumns: - - jsonPath: .status.latestImage - name: LatestImage + - jsonPath: .status.latestRef.name + name: Image + type: string + - jsonPath: .status.latestRef.tag + name: Tag + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: v1beta2 ImagePolicy is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: @@ -237,6 +345,25 @@ spec: ImagePolicySpec defines the parameters for calculating the ImagePolicy. properties: + digestReflectionPolicy: + default: Never + description: |- + DigestReflectionPolicy governs the setting of the `.status.latestRef.digest` field. + + Never: The digest field will always be set to the empty string. + + IfNotPresent: The digest field will be set to the digest of the elected + latest image if the field is empty and the image did not change. + + Always: The digest field will always be set to the digest of the elected + latest image. + + Default: Never. + enum: + - Always + - IfNotPresent + - Never + type: string filterTags: description: |- FilterTags enables filtering for only a subset of tags based on a set of @@ -269,6 +396,15 @@ spec: required: - name type: object + interval: + description: |- + Interval is the length of time to wait between + refreshing the digest of the latest tag when the + reflection policy is set to "Always". + + Defaults to 10m. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string policy: description: |- Policy gives the particulars of the policy to be followed in @@ -318,10 +454,24 @@ spec: - range type: object type: object + suspend: + description: |- + This flag tells the controller to suspend subsequent policy reconciliations. + It does not apply to already started reconciliations. Defaults to false. + type: boolean required: - imageRepositoryRef - policy type: object + x-kubernetes-validations: + - message: spec.interval is only accepted when spec.digestReflectionPolicy + is set to 'Always' + rule: '!has(self.interval) || (has(self.digestReflectionPolicy) && self.digestReflectionPolicy + == ''Always'')' + - message: spec.interval must be set when spec.digestReflectionPolicy + is set to 'Always' + rule: has(self.interval) || !has(self.digestReflectionPolicy) || self.digestReflectionPolicy + != 'Always' status: default: observedGeneration: -1 @@ -383,23 +533,55 @@ spec: - type type: object type: array - latestImage: + lastHandledReconcileAt: description: |- - LatestImage gives the first in the list of images scanned by - the image repository, when filtered and ordered according to - the policy. + LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value + can be detected. type: string + latestRef: + description: |- + LatestRef gives the first in the list of images scanned by + the image repository, when filtered and ordered according + to the policy. + properties: + digest: + description: Digest is the image's digest. + type: string + name: + description: Name is the bare image's name. + type: string + tag: + description: Tag is the image's tag. + type: string + required: + - name + - tag + type: object observedGeneration: format: int64 type: integer - observedPreviousImage: + observedPreviousRef: description: |- - ObservedPreviousImage is the observed previous LatestImage. It is used + ObservedPreviousRef is the observed previous LatestRef. It is used to keep track of the previous and current images. - type: string + properties: + digest: + description: Digest is the image's digest. + type: string + name: + description: Name is the bare image's name. + type: string + tag: + description: Tag is the image's tag. + type: string + required: + - name + - tag + type: object type: object type: object served: true - storage: true + storage: false subresources: status: {} diff --git a/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_gitrepositories.yaml b/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_gitrepositories.yaml index 9d01fbd5..10663e47 100644 --- a/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_gitrepositories.yaml +++ b/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_gitrepositories.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 + controller-gen.kubebuilder.io/version: v0.19.0 name: gitrepositories.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io @@ -105,11 +105,12 @@ spec: type: string provider: description: |- - Provider used for authentication, can be 'azure', 'generic'. + Provider used for authentication, can be 'azure', 'github', 'generic'. When not specified, defaults to 'generic'. enum: - generic - azure + - github type: string proxySecretRef: description: |- @@ -173,6 +174,19 @@ spec: required: - name type: object + serviceAccountName: + description: |- + ServiceAccountName is the name of the Kubernetes ServiceAccount used to + authenticate to the GitRepository. This field is only supported for 'azure' provider. + type: string + sparseCheckout: + description: |- + SparseCheckout specifies a list of directories to checkout when cloning + the repository. If specified, only these directories are included in the + Artifact produced for this GitRepository. + items: + type: string + type: array suspend: description: |- Suspend tells the controller to suspend the reconciliation of this @@ -226,6 +240,10 @@ spec: - interval - url type: object + x-kubernetes-validations: + - message: serviceAccountName can only be set when provider is 'azure' + rule: '!has(self.serviceAccountName) || (has(self.provider) && self.provider + == ''azure'')' status: default: observedGeneration: -1 @@ -272,6 +290,7 @@ spec: consumption, e.g. by another controller applying the Artifact contents. type: string required: + - digest - lastUpdateTime - path - revision @@ -380,6 +399,7 @@ spec: consumption, e.g. by another controller applying the Artifact contents. type: string required: + - digest - lastUpdateTime - path - revision @@ -442,6 +462,13 @@ spec: ObservedRecurseSubmodules is the observed resource submodules configuration used to produce the current Artifact. type: boolean + observedSparseCheckout: + description: |- + ObservedSparseCheckout is the observed list of directories used to + produce the current Artifact. + items: + type: string + type: array sourceVerificationMode: description: |- SourceVerificationMode is the last used verification mode indicating @@ -453,343 +480,6 @@ spec: storage: true subresources: status: {} - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - deprecated: true - deprecationWarning: v1beta1 GitRepository is deprecated, upgrade to v1 - name: v1beta1 - schema: - openAPIV3Schema: - description: GitRepository is the Schema for the gitrepositories API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: GitRepositorySpec defines the desired state of a Git repository. - properties: - accessFrom: - description: AccessFrom defines an Access Control List for allowing - cross-namespace references to this object. - properties: - namespaceSelectors: - description: |- - NamespaceSelectors is the list of namespace selectors to which this ACL applies. - Items in this list are evaluated using a logical OR operation. - items: - description: |- - NamespaceSelector selects the namespaces to which this ACL applies. - An empty map of MatchLabels matches all namespaces in a cluster. - properties: - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - type: array - required: - - namespaceSelectors - type: object - gitImplementation: - default: go-git - description: |- - Determines which git client library to use. - Defaults to go-git, valid values are ('go-git', 'libgit2'). - enum: - - go-git - - libgit2 - type: string - ignore: - description: |- - Ignore overrides the set of excluded patterns in the .sourceignore format - (which is the same as .gitignore). If not provided, a default will be used, - consult the documentation for your version to find out what those are. - type: string - include: - description: Extra git repositories to map into the repository - items: - description: GitRepositoryInclude defines a source with a from and - to path. - properties: - fromPath: - description: The path to copy contents from, defaults to the - root directory. - type: string - repository: - description: Reference to a GitRepository to include. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - toPath: - description: The path to copy contents to, defaults to the name - of the source ref. - type: string - required: - - repository - type: object - type: array - interval: - description: The interval at which to check for repository updates. - type: string - recurseSubmodules: - description: |- - When enabled, after the clone is created, initializes all submodules within, - using their default settings. - This option is available only when using the 'go-git' GitImplementation. - type: boolean - ref: - description: |- - The Git reference to checkout and monitor for changes, defaults to - master branch. - properties: - branch: - description: The Git branch to checkout, defaults to master. - type: string - commit: - description: The Git commit SHA to checkout, if specified Tag - filters will be ignored. - type: string - semver: - description: The Git tag semver expression, takes precedence over - Tag. - type: string - tag: - description: The Git tag to checkout, takes precedence over Branch. - type: string - type: object - secretRef: - description: |- - The secret name containing the Git credentials. - For HTTPS repositories the secret must contain username and password - fields. - For SSH repositories the secret must contain identity and known_hosts - fields. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - suspend: - description: This flag tells the controller to suspend the reconciliation - of this source. - type: boolean - timeout: - default: 60s - description: The timeout for remote Git operations like cloning, defaults - to 60s. - type: string - url: - description: The repository URL, can be a HTTP/S or SSH address. - pattern: ^(http|https|ssh)://.*$ - type: string - verify: - description: Verify OpenPGP signature for the Git commit HEAD points - to. - properties: - mode: - description: Mode describes what git object should be verified, - currently ('head'). - enum: - - head - type: string - secretRef: - description: The secret name containing the public keys of all - trusted Git authors. - properties: - name: - description: Name of the referent. - type: string - required: - - name - type: object - required: - - mode - type: object - required: - - interval - - url - type: object - status: - default: - observedGeneration: -1 - description: GitRepositoryStatus defines the observed state of a Git repository. - properties: - artifact: - description: Artifact represents the output of the last successful - repository sync. - properties: - checksum: - description: Checksum is the SHA256 checksum of the artifact. - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of this - artifact. - format: date-time - type: string - path: - description: Path is the relative file path of this artifact. - type: string - revision: - description: |- - Revision is a human readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm index timestamp, a Helm - chart version, etc. - type: string - url: - description: URL is the HTTP address of this artifact. - type: string - required: - - lastUpdateTime - - path - - url - type: object - conditions: - description: Conditions holds the conditions for the GitRepository. - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - includedArtifacts: - description: IncludedArtifacts represents the included artifacts from - the last successful repository sync. - items: - description: Artifact represents the output of a source synchronisation. - properties: - checksum: - description: Checksum is the SHA256 checksum of the artifact. - type: string - lastUpdateTime: - description: |- - LastUpdateTime is the timestamp corresponding to the last update of this - artifact. - format: date-time - type: string - path: - description: Path is the relative file path of this artifact. - type: string - revision: - description: |- - Revision is a human readable identifier traceable in the origin source - system. It can be a Git commit SHA, Git tag, a Helm index timestamp, a Helm - chart version, etc. - type: string - url: - description: URL is the HTTP address of this artifact. - type: string - required: - - lastUpdateTime - - path - - url - type: object - type: array - lastHandledReconcileAt: - description: |- - LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change of the annotation value - can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - url: - description: |- - URL is the download link for the artifact output of the last repository - sync. - type: string - type: object - type: object - served: true - storage: false - subresources: - status: {} - additionalPrinterColumns: - jsonPath: .spec.url name: URL @@ -1058,6 +748,7 @@ spec: consumption, e.g. by another controller applying the Artifact contents. type: string required: + - digest - lastUpdateTime - path - revision @@ -1181,6 +872,7 @@ spec: consumption, e.g. by another controller applying the Artifact contents. type: string required: + - digest - lastUpdateTime - path - revision diff --git a/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_ocirepositories.yaml b/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_ocirepositories.yaml index a60b7b41..05b7b96a 100644 --- a/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_ocirepositories.yaml +++ b/tests/e2e/testdata/crds/source.toolkit.fluxcd.io_ocirepositories.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 + controller-gen.kubebuilder.io/version: v0.19.0 name: ocirepositories.source.toolkit.fluxcd.io spec: group: source.toolkit.fluxcd.io @@ -29,6 +29,401 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date + name: v1 + schema: + openAPIV3Schema: + description: OCIRepository is the Schema for the ocirepositories API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OCIRepositorySpec defines the desired state of OCIRepository + properties: + certSecretRef: + description: |- + CertSecretRef can be given the name of a Secret containing + either or both of + + - a PEM-encoded client certificate (`tls.crt`) and private + key (`tls.key`); + - a PEM-encoded CA certificate (`ca.crt`) + + 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. The Secret must + be of type `Opaque` or `kubernetes.io/tls`. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + ignore: + description: |- + Ignore overrides the set of excluded patterns in the .sourceignore format + (which is the same as .gitignore). If not provided, a default will be used, + consult the documentation for your version to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS HTTP container + registry. + type: boolean + interval: + description: |- + Interval at which the OCIRepository URL is checked for updates. + This interval is approximate and may be subject to jitter to ensure + efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + layerSelector: + description: |- + LayerSelector specifies which layer should be extracted from the OCI artifact. + When not specified, the first layer found in the artifact is selected. + properties: + mediaType: + description: |- + MediaType specifies the OCI media type of the layer + which should be extracted from the OCI Artifact. The + first layer matching this type is selected. + type: string + operation: + description: |- + Operation specifies how the selected layer should be processed. + By default, the layer compressed content is extracted to storage. + When the operation is set to 'copy', the layer compressed content + is persisted to storage as it is. + enum: + - extract + - copy + type: string + type: object + provider: + default: generic + description: |- + The provider used for authentication, can be 'aws', 'azure', 'gcp' or 'generic'. + When not specified, defaults to 'generic'. + enum: + - generic + - aws + - azure + - gcp + type: string + proxySecretRef: + description: |- + ProxySecretRef specifies the Secret containing the proxy configuration + to use while communicating with the container registry. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + ref: + description: |- + The OCI reference to pull and monitor for changes, + defaults to the latest tag. + properties: + digest: + description: |- + Digest is the image digest to pull, takes precedence over SemVer. + The value should be in the format 'sha256:'. + type: string + semver: + description: |- + SemVer is the range of tags to pull selecting the latest within + the range, takes precedence over Tag. + type: string + semverFilter: + description: SemverFilter is a regex pattern to filter the tags + within the SemVer range. + type: string + tag: + description: Tag is the image tag to pull, defaults to latest. + type: string + type: object + secretRef: + description: |- + SecretRef contains the secret name containing the registry login + credentials to resolve image metadata. + The secret must be of type kubernetes.io/dockerconfigjson. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + serviceAccountName: + description: |- + ServiceAccountName is the name of the Kubernetes ServiceAccount used to authenticate + the image pull if the service account has attached pull secrets. For more information: + https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account + type: string + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout for remote OCI Repository operations like + pulling, defaults to 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + url: + description: |- + URL is a reference to an OCI artifact repository hosted + on a remote container registry. + pattern: ^oci://.*$ + type: string + verify: + description: |- + Verify contains the secret name containing the trusted public keys + used to verify the signature and specifies which provider to use to check + whether OCI image is authentic. + properties: + matchOIDCIdentity: + description: |- + MatchOIDCIdentity specifies the identity matching criteria to use + while verifying an OCI artifact which was signed using Cosign keyless + signing. The artifact's identity is deemed to be verified if any of the + specified matchers match against the identity. + items: + description: |- + OIDCIdentityMatch specifies options for verifying the certificate identity, + i.e. the issuer and the subject of the certificate. + properties: + issuer: + description: |- + Issuer specifies the regex pattern to match against to verify + the OIDC issuer in the Fulcio certificate. The pattern must be a + valid Go regular expression. + type: string + subject: + description: |- + Subject specifies the regex pattern to match against to verify + the identity subject in the Fulcio certificate. The pattern must + be a valid Go regular expression. + type: string + required: + - issuer + - subject + type: object + type: array + provider: + default: cosign + description: Provider specifies the technology used to sign the + OCI Artifact. + enum: + - cosign + - notation + type: string + secretRef: + description: |- + SecretRef specifies the Kubernetes Secret containing the + trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: OCIRepositoryStatus defines the observed state of OCIRepository + properties: + artifact: + description: Artifact represents the output of the last successful + OCI Repository sync. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: |- + LastUpdateTime is the timestamp corresponding to the last update of the + Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: |- + Path is the relative file path of the Artifact. It can be used to locate + the file in the root of the Artifact storage on the local file system of + the controller managing the Source. + type: string + revision: + description: |- + Revision is a human-readable identifier traceable in the origin source + system. It can be a Git commit SHA, Git tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: |- + URL is the HTTP address of the Artifact as exposed by the controller + managing the Source. It can be used to retrieve the Artifact for + consumption, e.g. by another controller applying the Artifact contents. + type: string + required: + - digest + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the OCIRepository. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: |- + LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value + can be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + observedIgnore: + description: |- + ObservedIgnore is the observed exclusion patterns used for constructing + the source artifact. + type: string + observedLayerSelector: + description: |- + ObservedLayerSelector is the observed layer selector used for constructing + the source artifact. + properties: + mediaType: + description: |- + MediaType specifies the OCI media type of the layer + which should be extracted from the OCI Artifact. The + first layer matching this type is selected. + type: string + operation: + description: |- + Operation specifies how the selected layer should be processed. + By default, the layer compressed content is extracted to storage. + When the operation is set to 'copy', the layer compressed content + is persisted to storage as it is. + enum: + - extract + - copy + type: string + type: object + url: + description: URL is the download link for the artifact output of the + last OCI Repository sync. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: v1beta2 OCIRepository is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: @@ -302,6 +697,7 @@ spec: consumption, e.g. by another controller applying the Artifact contents. type: string required: + - digest - lastUpdateTime - path - revision @@ -422,6 +818,6 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: status: {}