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 <stefan.prodan@gmail.com>
This commit is contained in:
Stefan Prodan 2022-07-28 15:04:52 +03:00
parent 799d7df457
commit acc95d8c50
No known key found for this signature in database
GPG Key ID: 3299AEB0E4085BAF
4 changed files with 35 additions and 16 deletions

View File

@ -141,9 +141,6 @@ type OCIRepositoryStatus struct {
} }
const ( 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 signals that an OCI operation (e.g. pull) failed.
OCIOperationFailedReason string = "OCIOperationFailed" OCIOperationFailedReason string = "OCIOperationFailed"
) )

View File

@ -65,9 +65,11 @@ import (
) )
const ( const (
ClientCert = "certFile" ClientCert = "certFile"
ClientKey = "keyFile" ClientKey = "keyFile"
CACert = "caFile" CACert = "caFile"
OCISourceKey = "org.opencontainers.image.source"
OCIRevisionKey = "org.opencontainers.image.revision"
) )
// ociRepositoryReadyCondition contains the information required to summarize a // 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) 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. // Notify on new artifact and failure recovery.
if oldChecksum != newObj.GetArtifact().Checksum { if oldChecksum != newObj.GetArtifact().Checksum {
r.AnnotatedEventf(newObj, annotations, corev1.EventTypeNormal, r.AnnotatedEventf(newObj, annotations, corev1.EventTypeNormal,

View File

@ -172,8 +172,8 @@ func TestOCIRepository_Reconcile(t *testing.T) {
g.Expect(obj.Status.Artifact.Revision).To(Equal(tt.digest)) g.Expect(obj.Status.Artifact.Revision).To(Equal(tt.digest))
// Check if the metadata matches the expected annotations // 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[OCISourceKey]).To(ContainSubstring("podinfo"))
g.Expect(obj.Status.Artifact.Metadata["org.opencontainers.image.revision"]).To(ContainSubstring(tt.tag)) g.Expect(obj.Status.Artifact.Metadata[OCIRevisionKey]).To(ContainSubstring(tt.tag))
// Check if the artifact storage path matches the expected file path // Check if the artifact storage path matches the expected file path
localPath := testStorage.LocalPath(*obj.Status.Artifact) 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(got).To(Equal(tt.want))
g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(tt.assertConditions)) g.Expect(obj.Status.Conditions).To(conditions.MatchConditions(tt.assertConditions))
}) })
} }
} }
@ -1263,9 +1262,16 @@ func TestOCIRepositoryReconciler_notify(t *testing.T) {
resErr: nil, resErr: nil,
newObjBeforeFunc: func(obj *sourcev1.OCIRepository) { newObjBeforeFunc: func(obj *sourcev1.OCIRepository) {
obj.Spec.URL = "oci://newurl.io" 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", 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 { func setPodinfoImageAnnotations(img gcrv1.Image, tag string) gcrv1.Image {
metadata := map[string]string{ metadata := map[string]string{
"org.opencontainers.image.source": "https://github.com/stefanprodan/podinfo", OCISourceKey: "https://github.com/stefanprodan/podinfo",
"org.opencontainers.image.revision": fmt.Sprintf("%s/SHA", tag), OCIRevisionKey: fmt.Sprintf("%s/SHA", tag),
} }
return mutate.Annotations(img, metadata).(gcrv1.Image) return mutate.Annotations(img, metadata).(gcrv1.Image)
} }

View File

@ -31,7 +31,7 @@ In the above example:
by the `.spec.interval` field. by the `.spec.interval` field.
- It pulls the `latest` tag of the `ghcr.io/stefanprodan/manifests/podinfo` - It pulls the `latest` tag of the `ghcr.io/stefanprodan/manifests/podinfo`
repository, indicated by the `.spec.ref.tag` and `.spec.url` fields. 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. revision, reported in-cluster in the `.status.artifact.revision` field.
- When the current OCIRepository digest differs from the latest fetched - When the current OCIRepository digest differs from the latest fetched
digest, a new Artifact is archived. digest, a new Artifact is archived.
@ -49,7 +49,7 @@ You can run this example by saving the manifest into `ocirepository.yaml`.
```console ```console
NAME URL AGE READY STATUS 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) 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 Last Update Time: 2022-06-14T11:23:36Z
Path: ocirepository/default/podinfo/3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de.tar.gz Path: ocirepository/default/podinfo/3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de.tar.gz
Revision: 3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de 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: Conditions:
Last Transition Time: 2022-06-14T11:23:36Z Last Transition Time: 2022-06-14T11:23:36Z
Message: stored artifact for digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de' Message: stored artifact for digest '3b6cdcc7adcc9a84d3214ee1c029543789d90b5ae69debe9efa3f66e982875de'