From acc95d8c50cbc39ff51fe3d30a7114d632035ba2 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Thu, 28 Jul 2022 15:04:52 +0300 Subject: [PATCH] Add upstream source and revision to logs and events Enrich the successful reconciliation event message with the upstream opencontainers annotations Signed-off-by: Stefan Prodan --- api/v1beta2/ocirepository_types.go | 3 --- controllers/ocirepository_controller.go | 22 +++++++++++++++++--- controllers/ocirepository_controller_test.go | 20 +++++++++++------- docs/spec/v1beta2/ocirepositories.md | 6 +++--- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/api/v1beta2/ocirepository_types.go b/api/v1beta2/ocirepository_types.go index 2c6df091..e788d44b 100644 --- a/api/v1beta2/ocirepository_types.go +++ b/api/v1beta2/ocirepository_types.go @@ -141,9 +141,6 @@ type OCIRepositoryStatus struct { } const ( - // OCIOperationSucceedReason signals that a Git operation (e.g. pull) succeeded. - OCIOperationSucceedReason string = "OCIOperationSucceeded" - // OCIOperationFailedReason signals that an OCI operation (e.g. pull) failed. OCIOperationFailedReason string = "OCIOperationFailed" ) diff --git a/controllers/ocirepository_controller.go b/controllers/ocirepository_controller.go index 54355c94..4170254e 100644 --- a/controllers/ocirepository_controller.go +++ b/controllers/ocirepository_controller.go @@ -65,9 +65,11 @@ import ( ) const ( - ClientCert = "certFile" - ClientKey = "keyFile" - CACert = "caFile" + ClientCert = "certFile" + ClientKey = "keyFile" + CACert = "caFile" + OCISourceKey = "org.opencontainers.image.source" + OCIRevisionKey = "org.opencontainers.image.revision" ) // ociRepositoryReadyCondition contains the information required to summarize a @@ -829,6 +831,20 @@ func (r *OCIRepositoryReconciler) notify(ctx context.Context, message := fmt.Sprintf("stored artifact with digest '%s' from '%s'", newObj.Status.Artifact.Revision, newObj.Spec.URL) + // enrich message with upstream annotations if found + if info := newObj.GetArtifact().Metadata; info != nil { + var source, revision string + if val, ok := info[OCISourceKey]; ok { + source = val + } + if val, ok := info[OCIRevisionKey]; ok { + revision = val + } + if source != "" && revision != "" { + message = fmt.Sprintf("%s, origin source '%s', origin revision '%s'", message, source, revision) + } + } + // Notify on new artifact and failure recovery. if oldChecksum != newObj.GetArtifact().Checksum { r.AnnotatedEventf(newObj, annotations, corev1.EventTypeNormal, diff --git a/controllers/ocirepository_controller_test.go b/controllers/ocirepository_controller_test.go index eb1ce3fe..311f8b20 100644 --- a/controllers/ocirepository_controller_test.go +++ b/controllers/ocirepository_controller_test.go @@ -172,8 +172,8 @@ func TestOCIRepository_Reconcile(t *testing.T) { g.Expect(obj.Status.Artifact.Revision).To(Equal(tt.digest)) // Check if the metadata matches the expected annotations - g.Expect(obj.Status.Artifact.Metadata["org.opencontainers.image.source"]).To(ContainSubstring("podinfo")) - g.Expect(obj.Status.Artifact.Metadata["org.opencontainers.image.revision"]).To(ContainSubstring(tt.tag)) + g.Expect(obj.Status.Artifact.Metadata[OCISourceKey]).To(ContainSubstring("podinfo")) + g.Expect(obj.Status.Artifact.Metadata[OCIRevisionKey]).To(ContainSubstring(tt.tag)) // Check if the artifact storage path matches the expected file path localPath := testStorage.LocalPath(*obj.Status.Artifact) @@ -534,7 +534,6 @@ func TestOCIRepository_reconcileSource_authStrategy(t *testing.T) { } g.Expect(got).To(Equal(tt.want)) g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(tt.assertConditions)) - }) } } @@ -1263,9 +1262,16 @@ func TestOCIRepositoryReconciler_notify(t *testing.T) { resErr: nil, newObjBeforeFunc: func(obj *sourcev1.OCIRepository) { obj.Spec.URL = "oci://newurl.io" - obj.Status.Artifact = &sourcev1.Artifact{Revision: "xxx", Checksum: "yyy"} + obj.Status.Artifact = &sourcev1.Artifact{ + Revision: "xxx", + Checksum: "yyy", + Metadata: map[string]string{ + OCISourceKey: "https://github.com/stefanprodan/podinfo", + OCIRevisionKey: "6.1.8/b3b00fe35424a45d373bf4c7214178bc36fd7872", + }, + } }, - wantEvent: "Normal NewArtifact stored artifact with digest 'xxx' from 'oci://newurl.io'", + wantEvent: "Normal NewArtifact stored artifact with digest 'xxx' from 'oci://newurl.io', origin source 'https://github.com/stefanprodan/podinfo', origin revision '6.1.8/b3b00fe35424a45d373bf4c7214178bc36fd7872'", }, { name: "recovery from failure", @@ -1432,8 +1438,8 @@ func pushMultiplePodinfoImages(serverURL string, versions ...string) (map[string func setPodinfoImageAnnotations(img gcrv1.Image, tag string) gcrv1.Image { metadata := map[string]string{ - "org.opencontainers.image.source": "https://github.com/stefanprodan/podinfo", - "org.opencontainers.image.revision": fmt.Sprintf("%s/SHA", tag), + OCISourceKey: "https://github.com/stefanprodan/podinfo", + OCIRevisionKey: fmt.Sprintf("%s/SHA", tag), } return mutate.Annotations(img, metadata).(gcrv1.Image) } diff --git a/docs/spec/v1beta2/ocirepositories.md b/docs/spec/v1beta2/ocirepositories.md index 3b394dfa..18e129ff 100644 --- a/docs/spec/v1beta2/ocirepositories.md +++ b/docs/spec/v1beta2/ocirepositories.md @@ -31,7 +31,7 @@ In the above example: by the `.spec.interval` field. - It pulls the `latest` tag of the `ghcr.io/stefanprodan/manifests/podinfo` repository, indicated by the `.spec.ref.tag` and `.spec.url` fields. -- The specified tag and resolved digest are used as the Artifact +- The resolved SHA256 digest is used as the Artifact revision, reported in-cluster in the `.status.artifact.revision` field. - When the current OCIRepository digest differs from the latest fetched digest, a new Artifact is archived. @@ -49,7 +49,7 @@ You can run this example by saving the manifest into `ocirepository.yaml`. ```console NAME URL AGE READY STATUS - podinfo oci://ghcr.io/stefanprodan/manifests/podinfo 5s True stored artifact for revision '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' + podinfo oci://ghcr.io/stefanprodan/manifests/podinfo 5s True stored artifact with digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' ``` 3. Run `kubectl describe ocirepository podinfo` to see the [Artifact](#artifact) @@ -63,7 +63,7 @@ You can run this example by saving the manifest into `ocirepository.yaml`. Last Update Time: 2022-06-14T11:23:36Z Path: ocirepository/default/podinfo/3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de.tar.gz Revision: 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de - URL: http://source-controller.flux-system.svc.cluster.local./ocirepository/oci/podinfo/3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de.tar.g + URL: http://source-controller.flux-system.svc.cluster.local./ocirepository/oci/podinfo/3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de.tar.gz Conditions: Last Transition Time: 2022-06-14T11:23:36Z Message: stored artifact for digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de'