From ff3bc7bdbd95978f96a70564bd2a52bf979ad80e Mon Sep 17 00:00:00 2001 From: Ilya Khandamirov Date: Tue, 4 Mar 2025 17:52:39 +0100 Subject: [PATCH] omit snapshot --- PROJECT | 9 -- api/v1alpha1/common_types.go | 15 ++ api/v1alpha1/component_types.go | 31 ++-- api/v1alpha1/configuredresource_types.go | 11 +- api/v1alpha1/constants.go | 4 +- api/v1alpha1/localizedresource_types.go | 14 +- api/v1alpha1/resource_types.go | 8 +- api/v1alpha1/snapshot_types.go | 101 ------------ api/v1alpha1/zz_generated.deepcopy.go | 145 +++++------------- cmd/main.go | 2 +- .../delivery.ocm.software_components.yaml | 44 ++++-- ...very.ocm.software_configuredresources.yaml | 46 ++++-- ...ivery.ocm.software_localizedresources.yaml | 49 ++++-- .../delivery.ocm.software_resources.yaml | 54 +++++-- .../delivery.ocm.software_snapshots.yaml | 2 +- .../component/component_controller.go | 76 ++++----- .../component/component_controller_test.go | 123 +++++---------- internal/controller/component/suite_test.go | 2 +- .../controller/configuration/client/client.go | 2 +- .../configuration/configuration_controller.go | 4 +- .../configuration_controller_test.go | 2 +- .../controller/configuration/configure.go | 4 +- .../controller/configuration/suite_test.go | 4 +- .../types/configuration_reference.go | 8 +- .../controller/localization/client/client.go | 12 +- .../localization/localization_controller.go | 10 +- .../localization_controller_test.go | 2 +- .../controller/localization/suite_test.go | 4 +- .../types/localization_reference.go | 10 +- .../resource/resource_controller.go | 8 +- .../resource/resource_controller_test.go | 12 +- internal/controller/resource/suite_test.go | 4 +- internal/controller/snapshot/controller.go | 12 +- .../object_config.go | 2 +- pkg/{snapshot => ociartifact}/registry.go | 2 +- pkg/{snapshot => ociartifact}/repository.go | 18 +-- pkg/{snapshot => ociartifact}/resource.go | 4 +- pkg/ocm/snapshot.go | 6 +- pkg/snapshot/snapshot.go | 84 ---------- pkg/test/component.go | 10 +- pkg/test/resource.go | 10 +- pkg/test/zot-registry.go | 6 +- 42 files changed, 374 insertions(+), 602 deletions(-) delete mode 100644 api/v1alpha1/snapshot_types.go rename pkg/{snapshot => ociartifact}/object_config.go (98%) rename pkg/{snapshot => ociartifact}/registry.go (97%) rename pkg/{snapshot => ociartifact}/repository.go (94%) rename pkg/{snapshot => ociartifact}/resource.go (98%) delete mode 100644 pkg/snapshot/snapshot.go diff --git a/PROJECT b/PROJECT index f172fb06..08a89d0e 100644 --- a/PROJECT +++ b/PROJECT @@ -71,13 +71,4 @@ resources: kind: Replication path: github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1 version: v1alpha1 -- api: - crdVersion: v1 - namespaced: true - controller: true - domain: ocm.software - group: delivery - kind: Snapshot - path: github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1 - version: v1alpha1 version: "3" diff --git a/api/v1alpha1/common_types.go b/api/v1alpha1/common_types.go index 861c058f..902ce1f8 100644 --- a/api/v1alpha1/common_types.go +++ b/api/v1alpha1/common_types.go @@ -125,3 +125,18 @@ type BlobInfo struct { // Can be used to determine how to file should be handled when downloaded (memory/disk) Size int64 `json:"size"` } + +// OCIArtifactInfo contains information on how to locate an OCI Artifact. +type OCIArtifactInfo struct { + // OCI repository name + // +required + Repository string `json:"repository"` + + // Manifest digest (required to delete the manifest and prepare OCI artifact for GC) + // +required + Digest string `json:"digest"` + + // Blob + // +required + Blob *BlobInfo `json:"blob"` +} diff --git a/api/v1alpha1/component_types.go b/api/v1alpha1/component_types.go index 3fa2d179..3e147513 100644 --- a/api/v1alpha1/component_types.go +++ b/api/v1alpha1/component_types.go @@ -20,7 +20,6 @@ import ( "fmt" "time" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -100,12 +99,6 @@ type ComponentStatus struct { // +optional Conditions []metav1.Condition `json:"conditions,omitempty"` - // SnapshotRef references the generated snapshot containing a list of - // component descriptors. This list can be used by other controllers to - // avoid re-downloading (and potentially also re-verifying) the components. - // +optional - SnapshotRef corev1.LocalObjectReference `json:"snapshotRef,omitempty"` - // Component specifies the concrete version of the component that was // fetched after based on the semver constraints during the last successful // reconciliation. @@ -117,6 +110,12 @@ type ComponentStatus struct { // in the order the configuration data was applied. // +optional EffectiveOCMConfig []OCMConfiguration `json:"effectiveOCMConfig,omitempty"` + + // OCIArtifact references the generated OCI artifact containing a list of + // component descriptors. This list can be used by other controllers to + // avoid re-downloading (and potentially also re-verifying) the components. + // +optional + OCIArtifact *OCIArtifactInfo `json:"ociArtifact,omitempty"` } // +kubebuilder:object:root=true @@ -180,8 +179,22 @@ func (in *Component) GetVerifications() []Verification { return in.Spec.Verify } -func (in *Component) GetSnapshotName() string { - return in.Status.SnapshotRef.Name +// GetOCIRepository returns the name of the OCI repository of the OCI artifact in which the component +// descriptors are stored. +func (in *Component) GetOCIRepository() string { + return in.Status.OCIArtifact.Repository +} + +// GetManifestDigest returns the manifest digest of the OCI artifact, in which the component descriptors +// are stored. +func (in *Component) GetManifestDigest() string { + return in.Status.OCIArtifact.Digest +} + +// GetBlobDigest returns the blob digest of the OCI artifact, in which the component descriptors +// are stored. +func (in *Component) GetBlobDigest() string { + return in.Status.OCIArtifact.Blob.Digest } // +kubebuilder:object:root=true diff --git a/api/v1alpha1/configuredresource_types.go b/api/v1alpha1/configuredresource_types.go index 587661df..5a70bcf4 100644 --- a/api/v1alpha1/configuredresource_types.go +++ b/api/v1alpha1/configuredresource_types.go @@ -21,7 +21,6 @@ import ( "github.com/fluxcd/pkg/apis/meta" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -91,10 +90,10 @@ type ConfiguredResourceStatus struct { ObservedGeneration int64 `json:"observedGeneration,omitempty"` Conditions []metav1.Condition `json:"conditions,omitempty"` - // The configuration reconcile loop generates a snapshot, which contains the + // The configuration reconcile loop generates an OCI artifact, which contains the // ConfiguredResourceSpec.Target ConfigurationReference after configuration. - // It is filled once the Snapshot is created and the configuration completed. - SnapshotRef corev1.LocalObjectReference `json:"snapshotRef,omitempty"` + // It is filled once the OCI artifact is created and the configuration completed. + OCIArtifact *OCIArtifactInfo `json:"ociArtifact,omitempty"` } // +kubebuilder:object:root=true @@ -109,10 +108,6 @@ type ConfiguredResource struct { Status ConfiguredResourceStatus `json:"status,omitempty"` } -func (in *ConfiguredResource) GetSnapshotName() string { - return in.Status.SnapshotRef.Name -} - // +kubebuilder:object:root=true // ConfiguredResourceList contains a list of ConfiguredResource. diff --git a/api/v1alpha1/constants.go b/api/v1alpha1/constants.go index d467e152..f788eb92 100644 --- a/api/v1alpha1/constants.go +++ b/api/v1alpha1/constants.go @@ -34,8 +34,8 @@ const ( // Finalizers for controllers. const ( - // SnapshotFinalizer is the finalizter that is added to snapshot created by the ocm controllers. - SnapshotFinalizer = "finalizers.ocm.software/snapshot" + // ArtifactFinalizer is the finalizer that is added to an object that handles the lifecycle of an artifact created by the ocm controllers. + ArtifactFinalizer = "finalizers.ocm.software/artifact" ) // OCI related constants. diff --git a/api/v1alpha1/localizedresource_types.go b/api/v1alpha1/localizedresource_types.go index 029b6a12..41cb7f93 100644 --- a/api/v1alpha1/localizedresource_types.go +++ b/api/v1alpha1/localizedresource_types.go @@ -3,7 +3,6 @@ package v1alpha1 import ( "fmt" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -74,10 +73,6 @@ func (in *LocalizedResource) SetTarget(v *ConfigurationReference) { v.DeepCopyInto(&in.Spec.Target) } -func (in *LocalizedResource) GetSnapshotName() string { - return in.Status.SnapshotRef.Name -} - type LocalizedResourceSpec struct { // Target that is to be localized Target ConfigurationReference `json:"target"` @@ -96,15 +91,16 @@ type LocalizedResourceStatus struct { ObservedGeneration int64 `json:"observedGeneration,omitempty"` Conditions []metav1.Condition `json:"conditions,omitempty"` - // The LocalizedResource reports an SnapshotRef which contains the content of the Resource after Localization - SnapshotRef corev1.LocalObjectReference `json:"snapshotRef,omitempty"` + // The OCIArtifact contains the information where to find the OCI artifact which contains + // the content of the Resource after Localization + OCIArtifact *OCIArtifactInfo `json:"ociArtifact,omitempty"` // The LocalizedResource reports a ConfiguredResourceRef which contains a reference to the ConfiguredResource - // that is responsible for generating the SnapshotRef. + // that is responsible for generating the OCI artifact. ConfiguredResourceRef *ObjectKey `json:"configuredResourceRef,omitempty"` // ConfigRef is a reference to the Configuration that was generated by the Localization process - // and is used to setup the ConfiguredResource responsible for generating the SnapshotRef. + // and is used to setup the ConfiguredResource responsible for generating the OCI artifact. ConfigRef *ObjectKey `json:"configRef,omitempty"` // A unique digest of the combination of the config and target resources applied through a LocalizationStrategy diff --git a/api/v1alpha1/resource_types.go b/api/v1alpha1/resource_types.go index 8fd47664..255219b1 100644 --- a/api/v1alpha1/resource_types.go +++ b/api/v1alpha1/resource_types.go @@ -62,10 +62,10 @@ type ResourceStatus struct { // +optional Conditions []metav1.Condition `json:"conditions,omitempty"` - // SnapshotRef points to the Snapshot which represents the output of the + // OCIArtifact points to the OCI artifact which represents the output of the // last successful Resource sync. // +optional - SnapshotRef corev1.LocalObjectReference `json:"snapshotRef,omitempty"` + OCIArtifact *OCIArtifactInfo `json:"ociArtifact,omitempty"` // +optional Resource *ResourceInfo `json:"resource,omitempty"` @@ -131,10 +131,6 @@ func (in *Resource) GetEffectiveOCMConfig() []OCMConfiguration { return in.Status.EffectiveOCMConfig } -func (in *Resource) GetSnapshotName() string { - return in.Status.SnapshotRef.Name -} - // +kubebuilder:object:root=true // ResourceList contains a list of Resource. diff --git a/api/v1alpha1/snapshot_types.go b/api/v1alpha1/snapshot_types.go deleted file mode 100644 index 975d545e..00000000 --- a/api/v1alpha1/snapshot_types.go +++ /dev/null @@ -1,101 +0,0 @@ -package v1alpha1 - -import ( - "fmt" - - "sigs.k8s.io/controller-runtime/pkg/client" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// SnapshotWriter defines any object which produces a snapshot -// +k8s:deepcopy-gen=false -type SnapshotWriter interface { - client.Object - GetSnapshotName() string - GetKind() string -} - -// SnapshotSpec defines the desired state of Snapshot. -type SnapshotSpec struct { - // OCI repository name - // +required - Repository string `json:"repository"` - - // Manifest digest (required to delete the manifest and prepare OCI artifact for GC) - // +required - Digest string `json:"digest"` - - // Blob - // +required - Blob *BlobInfo `json:"blob"` - - // Suspend stops all operations on this object. - // +optional - Suspend bool `json:"suspend,omitempty"` -} - -// SnapshotStatus defines the observed state of Snapshot. -type SnapshotStatus struct { - // +optional - Conditions []metav1.Condition `json:"conditions,omitempty"` - - // ObservedGeneration is the last reconciled generation. - // +optional - ObservedGeneration int64 `json:"observedGeneration,omitempty"` -} - -func (in *Snapshot) GetVID() map[string]string { - vid := fmt.Sprintf("%s:%s", in.GetNamespace(), in.GetName()) - metadata := make(map[string]string) - metadata[GroupVersion.Group+"/snapshot_version"] = vid - - return metadata -} - -func (in *Snapshot) SetObservedGeneration(v int64) { - in.Status.ObservedGeneration = v -} - -// GetDigest returns the last reconciled digest for the snapshot. -func (in Snapshot) GetDigest() string { - return in.Spec.Digest -} - -// GetConditions returns the status conditions of the object. -func (in Snapshot) GetConditions() []metav1.Condition { - return in.Status.Conditions -} - -// SetConditions sets the status conditions on the object. -func (in *Snapshot) SetConditions(conditions []metav1.Condition) { - in.Status.Conditions = conditions -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:shortName=snap -// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="" -// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="" - -// Snapshot is the Schema for the snapshots API. -type Snapshot struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SnapshotSpec `json:"spec,omitempty"` - Status SnapshotStatus `json:"status,omitempty"` -} - -//+kubebuilder:object:root=true - -// SnapshotList contains a list of Snapshot. -type SnapshotList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Snapshot `json:"items"` -} - -func init() { - SchemeBuilder.Register(&Snapshot{}, &SnapshotList{}) -} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 636a6712..dad944ed 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -142,13 +142,17 @@ func (in *ComponentStatus) DeepCopyInto(out *ComponentStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - out.SnapshotRef = in.SnapshotRef in.Component.DeepCopyInto(&out.Component) if in.EffectiveOCMConfig != nil { in, out := &in.EffectiveOCMConfig, &out.EffectiveOCMConfig *out = make([]OCMConfiguration, len(*in)) copy(*out, *in) } + if in.OCIArtifact != nil { + in, out := &in.OCIArtifact, &out.OCIArtifact + *out = new(OCIArtifactInfo) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentStatus. @@ -394,7 +398,11 @@ func (in *ConfiguredResourceStatus) DeepCopyInto(out *ConfiguredResourceStatus) (*in)[i].DeepCopyInto(&(*out)[i]) } } - out.SnapshotRef = in.SnapshotRef + if in.OCIArtifact != nil { + in, out := &in.OCIArtifact, &out.OCIArtifact + *out = new(OCIArtifactInfo) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfiguredResourceStatus. @@ -721,7 +729,11 @@ func (in *LocalizedResourceStatus) DeepCopyInto(out *LocalizedResourceStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - out.SnapshotRef = in.SnapshotRef + if in.OCIArtifact != nil { + in, out := &in.OCIArtifact, &out.OCIArtifact + *out = new(OCIArtifactInfo) + (*in).DeepCopyInto(*out) + } if in.ConfiguredResourceRef != nil { in, out := &in.ConfiguredResourceRef, &out.ConfiguredResourceRef *out = new(ObjectKey) @@ -744,6 +756,26 @@ func (in *LocalizedResourceStatus) DeepCopy() *LocalizedResourceStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OCIArtifactInfo) DeepCopyInto(out *OCIArtifactInfo) { + *out = *in + if in.Blob != nil { + in, out := &in.Blob, &out.Blob + *out = new(BlobInfo) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OCIArtifactInfo. +func (in *OCIArtifactInfo) DeepCopy() *OCIArtifactInfo { + if in == nil { + return nil + } + out := new(OCIArtifactInfo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OCMConfiguration) DeepCopyInto(out *OCMConfiguration) { *out = *in @@ -1254,7 +1286,11 @@ func (in *ResourceStatus) DeepCopyInto(out *ResourceStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - out.SnapshotRef = in.SnapshotRef + if in.OCIArtifact != nil { + in, out := &in.OCIArtifact, &out.OCIArtifact + *out = new(OCIArtifactInfo) + (*in).DeepCopyInto(*out) + } if in.Resource != nil { in, out := &in.Resource, &out.Resource *out = new(ResourceInfo) @@ -1277,107 +1313,6 @@ func (in *ResourceStatus) DeepCopy() *ResourceStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Snapshot) DeepCopyInto(out *Snapshot) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Snapshot. -func (in *Snapshot) DeepCopy() *Snapshot { - if in == nil { - return nil - } - out := new(Snapshot) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Snapshot) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SnapshotList) DeepCopyInto(out *SnapshotList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Snapshot, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotList. -func (in *SnapshotList) DeepCopy() *SnapshotList { - if in == nil { - return nil - } - out := new(SnapshotList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SnapshotList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SnapshotSpec) DeepCopyInto(out *SnapshotSpec) { - *out = *in - if in.Blob != nil { - in, out := &in.Blob, &out.Blob - *out = new(BlobInfo) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotSpec. -func (in *SnapshotSpec) DeepCopy() *SnapshotSpec { - if in == nil { - return nil - } - out := new(SnapshotSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SnapshotStatus) DeepCopyInto(out *SnapshotStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SnapshotStatus. -func (in *SnapshotStatus) DeepCopy() *SnapshotStatus { - if in == nil { - return nil - } - out := new(SnapshotStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TransferStatus) DeepCopyInto(out *TransferStatus) { *out = *in diff --git a/cmd/main.go b/cmd/main.go index bed80e92..04ef5ef7 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -48,8 +48,8 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/replication" "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/resource" "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/snapshot" + snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" ) var ( diff --git a/config/crd/bases/delivery.ocm.software_components.yaml b/config/crd/bases/delivery.ocm.software_components.yaml index 5a092f95..a8f02601 100644 --- a/config/crd/bases/delivery.ocm.software_components.yaml +++ b/config/crd/bases/delivery.ocm.software_components.yaml @@ -310,23 +310,45 @@ spec: object. format: int64 type: integer - snapshotRef: + ociArtifact: description: |- - SnapshotRef references the generated snapshot containing a list of + OCIArtifact references the generated OCI artifact containing a list of component descriptors. This list can be used by other controllers to avoid re-downloading (and potentially also re-verifying) the components. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + blob: + description: Blob + properties: + digest: + description: Digest is the digest of the blob in the form + of ':'. + type: string + size: + description: |- + Size is the number of bytes of the blob. + Can be used to determine how to file should be handled when downloaded (memory/disk) + format: int64 + type: integer + tag: + description: Tag/Version of the blob + type: string + required: + - digest + - size + - tag + type: object + digest: + description: Manifest digest (required to delete the manifest + and prepare OCI artifact for GC) + type: string + repository: + description: OCI repository name type: string + required: + - blob + - digest + - repository type: object - x-kubernetes-map-type: atomic type: object required: - spec diff --git a/config/crd/bases/delivery.ocm.software_configuredresources.yaml b/config/crd/bases/delivery.ocm.software_configuredresources.yaml index 5c7c91d4..4ea1e58b 100644 --- a/config/crd/bases/delivery.ocm.software_configuredresources.yaml +++ b/config/crd/bases/delivery.ocm.software_configuredresources.yaml @@ -158,23 +158,45 @@ spec: observedGeneration: format: int64 type: integer - snapshotRef: + ociArtifact: description: |- - The configuration reconcile loop generates a snapshot, which contains the + The configuration reconcile loop generates an OCI artifact, which contains the ConfiguredResourceSpec.Target ConfigurationReference after configuration. - It is filled once the Snapshot is created and the configuration completed. + It is filled once the OCI artifact is created and the configuration completed. properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + blob: + description: Blob + properties: + digest: + description: Digest is the digest of the blob in the form + of ':'. + type: string + size: + description: |- + Size is the number of bytes of the blob. + Can be used to determine how to file should be handled when downloaded (memory/disk) + format: int64 + type: integer + tag: + description: Tag/Version of the blob + type: string + required: + - digest + - size + - tag + type: object + digest: + description: Manifest digest (required to delete the manifest + and prepare OCI artifact for GC) + type: string + repository: + description: OCI repository name type: string + required: + - blob + - digest + - repository type: object - x-kubernetes-map-type: atomic type: object type: object served: true diff --git a/config/crd/bases/delivery.ocm.software_localizedresources.yaml b/config/crd/bases/delivery.ocm.software_localizedresources.yaml index a3a814a8..bf78941b 100644 --- a/config/crd/bases/delivery.ocm.software_localizedresources.yaml +++ b/config/crd/bases/delivery.ocm.software_localizedresources.yaml @@ -157,7 +157,7 @@ spec: configRef: description: |- ConfigRef is a reference to the Configuration that was generated by the Localization process - and is used to setup the ConfiguredResource responsible for generating the SnapshotRef. + and is used to setup the ConfiguredResource responsible for generating the OCI artifact. properties: name: type: string @@ -169,7 +169,7 @@ spec: configuredResourceRef: description: |- The LocalizedResource reports a ConfiguredResourceRef which contains a reference to the ConfiguredResource - that is responsible for generating the SnapshotRef. + that is responsible for generating the OCI artifact. properties: name: type: string @@ -185,21 +185,44 @@ spec: observedGeneration: format: int64 type: integer - snapshotRef: - description: The LocalizedResource reports an SnapshotRef which contains + ociArtifact: + description: |- + The OCIArtifact contains the information where to find the OCI artifact which contains the content of the Resource after Localization properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + blob: + description: Blob + properties: + digest: + description: Digest is the digest of the blob in the form + of ':'. + type: string + size: + description: |- + Size is the number of bytes of the blob. + Can be used to determine how to file should be handled when downloaded (memory/disk) + format: int64 + type: integer + tag: + description: Tag/Version of the blob + type: string + required: + - digest + - size + - tag + type: object + digest: + description: Manifest digest (required to delete the manifest + and prepare OCI artifact for GC) type: string + repository: + description: OCI repository name + type: string + required: + - blob + - digest + - repository type: object - x-kubernetes-map-type: atomic type: object type: object served: true diff --git a/config/crd/bases/delivery.ocm.software_resources.yaml b/config/crd/bases/delivery.ocm.software_resources.yaml index 877d74e6..a180b58b 100644 --- a/config/crd/bases/delivery.ocm.software_resources.yaml +++ b/config/crd/bases/delivery.ocm.software_resources.yaml @@ -262,6 +262,44 @@ spec: object. format: int64 type: integer + ociArtifact: + description: |- + OCIArtifact points to the OCI artifact which represents the output of the + last successful Resource sync. + properties: + blob: + description: Blob + properties: + digest: + description: Digest is the digest of the blob in the form + of ':'. + type: string + size: + description: |- + Size is the number of bytes of the blob. + Can be used to determine how to file should be handled when downloaded (memory/disk) + format: int64 + type: integer + tag: + description: Tag/Version of the blob + type: string + required: + - digest + - size + - tag + type: object + digest: + description: Manifest digest (required to delete the manifest + and prepare OCI artifact for GC) + type: string + repository: + description: OCI repository name + type: string + required: + - blob + - digest + - repository + type: object resource: properties: access: @@ -284,22 +322,6 @@ spec: - name - type type: object - snapshotRef: - description: |- - SnapshotRef points to the Snapshot which represents the output of the - last successful Resource sync. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic type: object required: - spec diff --git a/config/crd/bases/delivery.ocm.software_snapshots.yaml b/config/crd/bases/delivery.ocm.software_snapshots.yaml index 5afbb696..9b171ca6 100644 --- a/config/crd/bases/delivery.ocm.software_snapshots.yaml +++ b/config/crd/bases/delivery.ocm.software_snapshots.yaml @@ -13,7 +13,7 @@ spec: plural: snapshots shortNames: - snap - singular: snapshot + singular: ociartifact scope: Namespaced versions: - additionalPrinterColumns: diff --git a/internal/controller/component/component_controller.go b/internal/controller/component/component_controller.go index 3ebe5718..b556b1bf 100644 --- a/internal/controller/component/component_controller.go +++ b/internal/controller/component/component_controller.go @@ -39,23 +39,19 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/yaml" - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" ocmctx "ocm.software/ocm/api/ocm" ctrl "sigs.k8s.io/controller-runtime" "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/status" ) -const SnapshotFinalizer = "snapshot-finalizer" - // Reconciler reconciles a Component object. type Reconciler struct { *ocm.BaseReconciler - Registry snapshot.RegistryType + Registry ociartifact.RegistryType } var _ ocm.Reconciler = (*Reconciler)(nil) @@ -86,7 +82,6 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&v1alpha1.Component{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). Watches(&v1alpha1.OCMRepository{}, handler.EnqueueRequestsFromMapFunc(r.findOCMRepositories(ocmRepositoryKey))). - Owns(&v1alpha1.Snapshot{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). Complete(r) } @@ -153,21 +148,27 @@ func (r *Reconciler) reconcileExists(ctx context.Context, component *v1alpha1.Co if !component.GetDeletionTimestamp().IsZero() { logger.Info("component is being deleted and cannot be used", "name", component.Name) - if component.Status.SnapshotRef.Name != "" { - snap := &v1alpha1.Snapshot{} - snap.SetNamespace(component.GetNamespace()) - snap.SetName(component.Status.SnapshotRef.Name) - err := r.Get(ctx, client.ObjectKeyFromObject(snap), snap) - if err == nil { - err = r.Delete(ctx, snap) + ociRepositoryName := component.GetOCIRepository() + if ociRepositoryName != "" { + ociRepository, err := r.Registry.NewRepository(ctx, ociRepositoryName) + if err != nil { + return ctrl.Result{}, err + } + + exists, err := ociRepository.ExistsArtifact(ctx, component.GetManifestDigest()) + if err != nil { + return ctrl.Result{}, err } - if err != nil && !k8serrors.IsNotFound(err) { - return ctrl.Result{}, fmt.Errorf("failed to delete snapshot: %w", err) + + if exists { + err = ociRepository.DeleteArtifact(ctx, component.GetManifestDigest()) + if err != nil { + return ctrl.Result{}, err + } } - logger.Info("referenced snapshot deleted", "name", snap.GetName()) } - if updated := controllerutil.RemoveFinalizer(component, SnapshotFinalizer); updated { + if updated := controllerutil.RemoveFinalizer(component, v1alpha1.ArtifactFinalizer); updated { if err := r.Update(ctx, component); err != nil { return ctrl.Result{}, fmt.Errorf("failed to remove finalizer: %w", err) } @@ -176,7 +177,7 @@ func (r *Reconciler) reconcileExists(ctx context.Context, component *v1alpha1.Co return ctrl.Result{Requeue: true}, nil } - if updated := controllerutil.AddFinalizer(component, SnapshotFinalizer); updated { + if updated := controllerutil.AddFinalizer(component, v1alpha1.ArtifactFinalizer); updated { if err := r.Update(ctx, component); err != nil { return ctrl.Result{}, fmt.Errorf("failed to add finalizer: %w", err) } @@ -325,7 +326,7 @@ func (r *Reconciler) reconcileComponent(ctx context.Context, octx ocmctx.Context // Store descriptors and create snapshot logger.Info("pushing descriptors to storage") - ociRepositoryName, err := snapshot.CreateRepositoryName(component.Spec.RepositoryRef.Name, component.GetName()) + ociRepositoryName, err := ociartifact.CreateRepositoryName(component.Spec.RepositoryRef.Name, component.GetName()) if err != nil { status.MarkNotReady(r.EventRecorder, component, v1alpha1.CreateOCIRepositoryNameFailedReason, err.Error()) @@ -346,47 +347,26 @@ func (r *Reconciler) reconcileComponent(ctx context.Context, octx ocmctx.Context return ctrl.Result{}, err } - manifestDigest, err := ociRepository.PushSnapshot(ctx, version, descriptorsBytes) + manifestDigest, err := ociRepository.PushArtifact(ctx, version, descriptorsBytes) if err != nil { status.MarkNotReady(r.EventRecorder, component, v1alpha1.PushSnapshotFailedReason, err.Error()) return ctrl.Result{}, err } - logger.Info("creating snapshot") - snapshotCR := snapshot.Create( - component, - ociRepositoryName, - manifestDigest.String(), - &v1alpha1.BlobInfo{ + ociArtifact := v1alpha1.OCIArtifactInfo{ + Repository: ociRepositoryName, + Digest: manifestDigest.String(), + Blob: &v1alpha1.BlobInfo{ Digest: digest.FromBytes(descriptorsBytes).String(), Tag: version, Size: int64(len(descriptorsBytes)), }, - ) - snapshotCopy := snapshotCR.DeepCopy() - - result, err := controllerutil.CreateOrUpdate(ctx, r.GetClient(), snapshotCR, func() error { - if err := controllerutil.SetControllerReference(component, snapshotCR, r.GetScheme()); err != nil { - return fmt.Errorf("failed to set controller reference: %w", err) - } - - snapshotCR.Spec = snapshotCopy.Spec - - component.Status.SnapshotRef = corev1.LocalObjectReference{ - Name: snapshotCR.GetName(), - } - - return nil - }) - if err != nil { - status.MarkNotReady(r.EventRecorder, component, v1alpha1.CreateSnapshotFailedReason, err.Error()) - - return ctrl.Result{}, err } - logger.Info(fmt.Sprintf("snapshot %s", result), "operation", result) logger.Info("updating status") + component.Status.OCIArtifact = &ociArtifact + component.Status.Component = v1alpha1.ComponentInfo{ RepositorySpec: repository.Spec.RepositorySpec, Component: component.Spec.Component, diff --git a/internal/controller/component/component_controller_test.go b/internal/controller/component/component_controller_test.go index 193d26a4..45088bad 100644 --- a/internal/controller/component/component_controller_test.go +++ b/internal/controller/component/component_controller_test.go @@ -46,7 +46,6 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - snapshotpkg "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" ) const ( @@ -126,9 +125,7 @@ var _ = Describe("Component Controller", func() { Expect(k8sClient.List(ctx, components, client.InNamespace(namespace.GetName()))).To(Succeed()) Expect(components.Items).To(HaveLen(0)) - snapshots := &v1alpha1.SnapshotList{} - Expect(k8sClient.List(ctx, snapshots, client.InNamespace(namespace.GetName()))).To(Succeed()) - Expect(snapshots.Items).To(HaveLen(0)) + // TODO: test if OCI artifact was deleted }) It("reconcileComponent a component", func(ctx SpecContext) { @@ -153,12 +150,10 @@ var _ = Describe("Component Controller", func() { By("checking that the component has been reconciled successfully") waitUntilComponentIsReady(ctx, component, "1.0.0") - - By("checking that the snapshot has been created successfully") - snapshot := validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("delete resources manually") - deleteComponentWithSnapshot(ctx, component, snapshot) + deleteComponent(ctx, component) }) It("does not reconcile when the repository is not ready", func(ctx SpecContext) { @@ -197,17 +192,7 @@ var _ = Describe("Component Controller", func() { }, "15s").WithContext(ctx).Should(BeTrue()) By("checking that reference to snapshot has not been created") - Expect(component).To(HaveField("Status.SnapshotRef.Name", BeEmpty())) - - By("checking that the snapshot has not been created") - snapshot := &v1alpha1.Snapshot{ - ObjectMeta: metav1.ObjectMeta{ - Name: snapshotpkg.GenerateName(component), - Namespace: component.GetNamespace(), - }, - } - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(snapshot), snapshot) - Expect(errors.IsNotFound(err)).To(BeTrue()) + Expect(component).To(HaveField("Status.OCIArtifact", BeNil())) By("deleting the resources manually") Expect(k8sClient.Delete(ctx, component)).To(Succeed()) @@ -240,7 +225,7 @@ var _ = Describe("Component Controller", func() { By("checking that the component has been reconciled successfully") waitUntilComponentIsReady(ctx, component, Version1) - snapshot := validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("increasing the component version") env.OCMCommonTransport(ctfpath, accessio.FormatDirectory, func() { @@ -256,10 +241,10 @@ var _ = Describe("Component Controller", func() { waitUntilComponentIsReady(ctx, component, Version2) By("checking that increased version is reflected in the snapshot") - snapshot = validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("delete resources manually") - deleteComponentWithSnapshot(ctx, component, snapshot) + deleteComponent(ctx, component) }) It("grabs lower version if downgrade is allowed", func(ctx SpecContext) { @@ -297,7 +282,7 @@ var _ = Describe("Component Controller", func() { By("checking that the component has been reconciled successfully") waitUntilComponentIsReady(ctx, component, "0.0.3") - snapshot := validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("decreasing the component version") component.Spec.Semver = "0.0.2" @@ -305,12 +290,10 @@ var _ = Describe("Component Controller", func() { By("checking that the decreased version has been discovered successfully") waitUntilComponentIsReady(ctx, component, "0.0.2") - - By("checking that decreased version is reflected in the snapshot") - snapshot = validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("delete resources manually") - deleteComponentWithSnapshot(ctx, component, snapshot) + deleteComponent(ctx, component) }) It("does not grab lower version if downgrade is denied", func(ctx SpecContext) { @@ -347,7 +330,7 @@ var _ = Describe("Component Controller", func() { By("checking that the component has been reconciled successfully") waitUntilComponentIsReady(ctx, component, "0.0.3") - snapshot := validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("trying to decrease component version") component.Spec.Semver = "0.0.2" @@ -361,12 +344,10 @@ var _ = Describe("Component Controller", func() { return cond.Message == "terminal error: component version cannot be downgraded from version 0.0.3 to version 0.0.2" }).WithTimeout(15 * time.Second).Should(BeTrue()) Expect(component.Status.Component.Version).To(Equal("0.0.3")) - snapshot = &v1alpha1.Snapshot{} - Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: component.GetNamespace(), Name: component.GetSnapshotName()}, snapshot)).To(Succeed()) - Expect(snapshot.Spec.Blob.Tag).To(Equal("0.0.3")) + Expect(component.Status.OCIArtifact.Blob.Tag).To(Equal("0.0.3")) By("delete resources manually") - deleteComponentWithSnapshot(ctx, component, snapshot) + deleteComponent(ctx, component) }) It("can force downgrade even if not allowed by the component", func(ctx SpecContext) { @@ -400,7 +381,7 @@ var _ = Describe("Component Controller", func() { By("checking that the component has been reconciled successfully") waitUntilComponentIsReady(ctx, component, "0.0.3") - snapshot := validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("decreasing the component version") component.Spec.Semver = "0.0.2" @@ -408,12 +389,10 @@ var _ = Describe("Component Controller", func() { By("checking that the decreased version has been discovered successfully") waitUntilComponentIsReady(ctx, component, "0.0.2") - - By("checking that decreased version is reflected in the snapshot") - snapshot = validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("delete resources manually") - deleteComponentWithSnapshot(ctx, component, snapshot) + deleteComponent(ctx, component) }) }) @@ -592,12 +571,8 @@ var _ = Describe("Component Controller", func() { g.Expect(k8sClient.List(ctx, components, client.InNamespace(namespace.GetName()))).To(Succeed()) g.Expect(components.Items).To(HaveLen(0)) }, "15s").WithContext(ctx).Should(Succeed()) - By("ensuring no snapshots are left") - Eventually(func(g Gomega, ctx SpecContext) { - snapshots := &v1alpha1.SnapshotList{} - g.Expect(k8sClient.List(ctx, snapshots, client.InNamespace(namespace.GetName()))).To(Succeed()) - g.Expect(snapshots.Items).To(HaveLen(0)) - }, "15s").WithContext(ctx).Should(Succeed()) + + // TODO: check that the OCI artifact is not in the registry anymore }) It("component resolves and propagates config from repository", func(ctx SpecContext) { @@ -633,7 +608,7 @@ var _ = Describe("Component Controller", func() { By("checking that the component has been reconciled successfully") waitUntilComponentIsReady(ctx, component, "1.0.0") - snapshot := validateSnapshot(ctx, component, env, ctfpath) + validateArtifact(ctx, component, env, ctfpath) By("checking component's effective OCM config") Eventually(komega.Object(component), "15s").Should( @@ -660,7 +635,7 @@ var _ = Describe("Component Controller", func() { ) By("delete resources manually") - deleteComponentWithSnapshot(ctx, component, snapshot) + deleteComponent(ctx, component) }) }) }) @@ -678,58 +653,30 @@ func waitUntilComponentIsReady(ctx context.Context, component *v1alpha1.Componen }, "15s").WithContext(ctx).Should(BeTrue()) } -func validateSnapshot(ctx context.Context, component *v1alpha1.Component, env *Builder, ctfpath string) *v1alpha1.Snapshot { +func validateArtifact(ctx context.Context, component *v1alpha1.Component, env *Builder, ctfpath string) { GinkgoHelper() - By("checking that component has a reference to snapshot") + By("checking that component has a reference to OCI artifact") Eventually(komega.Object(component), "15s").Should( - HaveField("Status.SnapshotRef.Name", Not(BeEmpty()))) - - By("checking that the snapshot resource has been created successfully") - snapshot := &v1alpha1.Snapshot{} - Eventually(func(g Gomega, ctx context.Context) bool { - err := k8sClient.Get(ctx, types.NamespacedName{ - Namespace: component.GetNamespace(), - Name: component.Status.SnapshotRef.Name, - }, snapshot) - if err != nil { - return false - } - g.Expect(snapshot).Should(HaveField("Spec.Digest", Not(BeEmpty()))) - g.Expect(snapshot).Should(HaveField("Spec.Blob", Not(BeNil()))) - - return snapshot.Spec.Digest != "" && snapshot.Spec.Blob != nil - }, "15s").WithContext(ctx).Should(BeTrue()) - - By("validating the snapshot's owner references") - ownersReference := snapshot.GetOwnerReferences() - Expect(len(ownersReference)).To(Equal(1), "expected only one ownersReference") - Expect(ownersReference[0].Name).To(Equal(component.GetName()), "expected to be a ownersReference of the component") - - By("checking that the snapshot contains the correct content") - snapshotRepository := Must(registry.NewRepository(ctx, snapshot.Spec.Repository)) - snapshotComponentContent := Must(snapshotRepository.FetchSnapshot(ctx, snapshot.GetDigest())) - - snapshotDescriptors := &ocm.Descriptors{} - MustBeSuccessful(yaml.Unmarshal(snapshotComponentContent, snapshotDescriptors)) - repo := Must(ctf.Open(env, accessobj.ACC_WRITABLE, ctfpath, vfs.FileMode(vfs.O_RDWR), env)) - cv := Must(repo.LookupComponentVersion(component.Status.Component.Component, component.Status.Component.Version)) - expectedDescriptors := Must(ocm.ListComponentDescriptors(ctx, cv, repo)) - Expect(snapshotDescriptors).To(YAMLEqual(expectedDescriptors)) - - return snapshot + HaveField("Status.OCIArtifact", Not(BeNil()))) + + By("checking that the OCI artifact contains the correct content") + ociRepo := Must(registry.NewRepository(ctx, component.GetOCIRepository())) + componentContent := Must(ociRepo.FetchArtifact(ctx, component.GetManifestDigest())) + + descriptors := &ocm.Descriptors{} + MustBeSuccessful(yaml.Unmarshal(componentContent, descriptors)) + ctfRepo := Must(ctf.Open(env, accessobj.ACC_WRITABLE, ctfpath, vfs.FileMode(vfs.O_RDWR), env)) + cv := Must(ctfRepo.LookupComponentVersion(component.Status.Component.Component, component.Status.Component.Version)) + expectedDescriptors := Must(ocm.ListComponentDescriptors(ctx, cv, ctfRepo)) + Expect(descriptors).To(YAMLEqual(expectedDescriptors)) } -func deleteComponentWithSnapshot(ctx context.Context, component *v1alpha1.Component, snapshot *v1alpha1.Snapshot) { +func deleteComponent(ctx context.Context, component *v1alpha1.Component) { GinkgoHelper() Expect(k8sClient.Delete(ctx, component)).To(Succeed()) - Eventually(func(ctx context.Context) bool { - err := k8sClient.Get(ctx, client.ObjectKeyFromObject(snapshot), snapshot) - return errors.IsNotFound(err) - }, "15s").WithContext(ctx).Should(BeTrue()) - // Snapshot deletion was triggered by the Component reconciler Eventually(func(ctx context.Context) bool { err := k8sClient.Get(ctx, client.ObjectKeyFromObject(component), component) return errors.IsNotFound(err) diff --git a/internal/controller/component/suite_test.go b/internal/controller/component/suite_test.go index f63934b4..37d2147c 100644 --- a/internal/controller/component/suite_test.go +++ b/internal/controller/component/suite_test.go @@ -37,8 +37,8 @@ import ( metricserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" + snapshotPkg "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - snapshotPkg "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/test" ) diff --git a/internal/controller/configuration/client/client.go b/internal/controller/configuration/client/client.go index eddec93d..3a5187a9 100644 --- a/internal/controller/configuration/client/client.go +++ b/internal/controller/configuration/client/client.go @@ -10,7 +10,7 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/configuration/types" - snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" ) type Client interface { diff --git a/internal/controller/configuration/configuration_controller.go b/internal/controller/configuration/configuration_controller.go index c302d56b..9138101e 100644 --- a/internal/controller/configuration/configuration_controller.go +++ b/internal/controller/configuration/configuration_controller.go @@ -36,8 +36,8 @@ import ( configurationclient "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/configuration/client" "github.com/open-component-model/ocm-k8s-toolkit/pkg/compression" "github.com/open-component-model/ocm-k8s-toolkit/pkg/index" + snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/status" ) @@ -218,7 +218,7 @@ func (r *Reconciler) reconcileExists(ctx context.Context, configuration *v1alpha // - HelmRelease (FluxCD) requires the OCI artifact to have the same tag as the helm chart itself // - But how to get the helm chart version? (User input, parse from content) tag := "dummy" - manifestDigest, err := repository.PushSnapshot(ctx, tag, dataTGZ) + manifestDigest, err := repository.PushArtifact(ctx, tag, dataTGZ) if err != nil { status.MarkNotReady(r.EventRecorder, configuration, v1alpha1.ConfigurationFailedReason, err.Error()) diff --git a/internal/controller/configuration/configuration_controller_test.go b/internal/controller/configuration/configuration_controller_test.go index 3d863d44..62349fbe 100644 --- a/internal/controller/configuration/configuration_controller_test.go +++ b/internal/controller/configuration/configuration_controller_test.go @@ -159,7 +159,7 @@ var _ = Describe("ConfiguredResource Controller", func() { snapshotRepository, err := registry.NewRepository(ctx, snapshotResource.Spec.Repository) Expect(err).NotTo(HaveOccurred()) - snapshotResourceContent, err := snapshotRepository.FetchSnapshot(ctx, snapshotResource.GetDigest()) + snapshotResourceContent, err := snapshotRepository.FetchArtifact(ctx, snapshotResource.GetDigest()) Expect(err).NotTo(HaveOccurred()) dataExtracted, err := compression.ExtractDataFromTGZ(snapshotResourceContent) Expect(err).NotTo(HaveOccurred()) diff --git a/internal/controller/configuration/configure.go b/internal/controller/configuration/configure.go index 667da711..e4febe66 100644 --- a/internal/controller/configuration/configure.go +++ b/internal/controller/configuration/configure.go @@ -18,7 +18,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/substitute" "github.com/open-component-model/ocm-k8s-toolkit/pkg/substitute/steps" "github.com/open-component-model/ocm-k8s-toolkit/pkg/util" @@ -55,7 +55,7 @@ func Configure(ctx context.Context, ) (string, error) { logger := log.FromContext(ctx) targetDir := filepath.Join(basePath, "target") - if err := target.UnpackIntoDirectory(targetDir); errors.Is(err, snapshot.ErrAlreadyUnpacked) { + if err := target.UnpackIntoDirectory(targetDir); errors.Is(err, ociartifact.ErrAlreadyUnpacked) { logger.Info("target was already present, reusing existing directory", "path", targetDir) } else if err != nil { return "", fmt.Errorf("failed to get target directory: %w", err) diff --git a/internal/controller/configuration/suite_test.go b/internal/controller/configuration/suite_test.go index 05825b14..9b133cb9 100644 --- a/internal/controller/configuration/suite_test.go +++ b/internal/controller/configuration/suite_test.go @@ -39,8 +39,8 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" cfgclient "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/configuration/client" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/test" ) @@ -55,7 +55,7 @@ var k8sManager ctrl.Manager var testEnv *envtest.Environment var recorder record.EventRecorder var zotCmd *exec.Cmd -var registry *snapshot.Registry +var registry *ociartifact.Registry var zotRootDir string func TestControllers(t *testing.T) { diff --git a/internal/controller/configuration/types/configuration_reference.go b/internal/controller/configuration/types/configuration_reference.go index 42b5f8bb..f0222e94 100644 --- a/internal/controller/configuration/types/configuration_reference.go +++ b/internal/controller/configuration/types/configuration_reference.go @@ -1,7 +1,7 @@ package types import ( - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" ) // ConfigurationReference can be used both as a source (ConfigurationSource), @@ -12,12 +12,12 @@ type ConfigurationReference interface { } // ConfigurationSource is a source of localization. -// It contains instructions on how to localize an snapshot.Content. +// It contains instructions on how to localize an ociartifact.Content. type ConfigurationSource interface { - snapshot.Content + ociartifact.Content } // ConfigurationTarget is a target for configuration. type ConfigurationTarget interface { - snapshot.Content + ociartifact.Content } diff --git a/internal/controller/localization/client/client.go b/internal/controller/localization/client/client.go index 4d36f318..a3b831af 100644 --- a/internal/controller/localization/client/client.go +++ b/internal/controller/localization/client/client.go @@ -10,7 +10,7 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/localization/types" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" ) type Client interface { @@ -26,7 +26,7 @@ type Client interface { GetLocalizationConfig(ctx context.Context, ref v1alpha1.ConfigurationReference) (source types.LocalizationConfig, err error) } -func NewClientWithRegistry(c client.Client, registry *snapshot.Registry, scheme *runtime.Scheme) Client { +func NewClientWithRegistry(c client.Client, registry *ociartifact.Registry, scheme *runtime.Scheme) Client { factory := serializer.NewCodecFactory(scheme) info, _ := runtime.SerializerInfoForMediaType(factory.SupportedMediaTypes(), runtime.ContentTypeYAML) encoder := factory.EncoderForVersion(info.Serializer, v1alpha1.GroupVersion) @@ -41,7 +41,7 @@ func NewClientWithRegistry(c client.Client, registry *snapshot.Registry, scheme type localStorageBackedClient struct { client.Client - Registry *snapshot.Registry + Registry *ociartifact.Registry scheme *runtime.Scheme encoder runtime.Encoder } @@ -62,7 +62,7 @@ func (clnt *localStorageBackedClient) GetLocalizationTarget( case v1alpha1.KindLocalizedResource: fallthrough case v1alpha1.KindResource: - return snapshot.GetContentBackedBySnapshotFromComponent(ctx, clnt.Client, clnt.Registry, &ref) + return ociartifact.GetContentBackedBySnapshotFromComponent(ctx, clnt.Client, clnt.Registry, &ref) default: return nil, fmt.Errorf("unsupported localization target kind: %s", ref.Kind) } @@ -74,7 +74,7 @@ func (clnt *localStorageBackedClient) GetLocalizationConfig( ) (types.LocalizationConfig, error) { switch ref.Kind { case v1alpha1.KindResource: - return snapshot.GetContentBackedBySnapshotFromComponent(ctx, clnt.Client, clnt.Registry, &ref) + return ociartifact.GetContentBackedBySnapshotFromComponent(ctx, clnt.Client, clnt.Registry, &ref) case v1alpha1.KindLocalizationConfig: return GetLocalizationConfigFromKubernetes(ctx, clnt.Client, clnt.encoder, ref) default: @@ -98,5 +98,5 @@ func GetLocalizationConfigFromKubernetes(ctx context.Context, clnt client.Reader return nil, fmt.Errorf("failed to fetch localization config %s: %w", reference.Name, err) } - return &snapshot.ObjectConfig{Object: &cfg, Encoder: encoder}, nil + return &ociartifact.ObjectConfig{Object: &cfg, Encoder: encoder}, nil } diff --git a/internal/controller/localization/localization_controller.go b/internal/controller/localization/localization_controller.go index 0967f38c..231a7805 100644 --- a/internal/controller/localization/localization_controller.go +++ b/internal/controller/localization/localization_controller.go @@ -32,8 +32,8 @@ import ( localizationclient "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/localization/client" "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/localization/types" "github.com/open-component-model/ocm-k8s-toolkit/pkg/index" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/status" "github.com/open-component-model/ocm-k8s-toolkit/pkg/util" ) @@ -42,7 +42,7 @@ import ( type Reconciler struct { *ocm.BaseReconciler LocalizationClient localizationclient.Client - Registry snapshot.RegistryType + Registry ociartifact.RegistryType } var _ ocm.Reconciler = (*Reconciler)(nil) @@ -274,7 +274,7 @@ func (r *Reconciler) reconcileExists(ctx context.Context, localization *v1alpha1 func localizeRules( ctx context.Context, c client.Client, - r snapshot.RegistryType, + r ociartifact.RegistryType, content LocalizableSnapshotContent, cfg types.LocalizationConfig, ) ( @@ -336,7 +336,7 @@ func localizeRules( // LocalizableSnapshotContent is an artifact content that is backed by a component and resource, allowing it // to be localized (by resolving relative references from the resource & component into absolute values). type LocalizableSnapshotContent interface { - snapshot.Content + ociartifact.Content GetComponent() *v1alpha1.Component GetResource() *v1alpha1.Resource } @@ -344,7 +344,7 @@ type LocalizableSnapshotContent interface { func ComponentDescriptorAndSetFromResource( ctx context.Context, reader client.Reader, - registry snapshot.RegistryType, + registry ociartifact.RegistryType, baseComponent *v1alpha1.Component, ) (compdesc.ComponentVersionResolver, *compdesc.ComponentDescriptor, error) { snapshotResource := &v1alpha1.Snapshot{} diff --git a/internal/controller/localization/localization_controller_test.go b/internal/controller/localization/localization_controller_test.go index a2c863a2..8333111d 100644 --- a/internal/controller/localization/localization_controller_test.go +++ b/internal/controller/localization/localization_controller_test.go @@ -140,7 +140,7 @@ var _ = Describe("Localization Controller", func() { repository, err := registry.NewRepository(ctx, snapshotLocalization.Spec.Repository) Expect(err).ToNot(HaveOccurred()) - data, err := repository.FetchSnapshot(ctx, snapshotLocalization.GetDigest()) + data, err := repository.FetchArtifact(ctx, snapshotLocalization.GetDigest()) Expect(err).ToNot(HaveOccurred()) memFs := vfs.New(memoryfs.New()) diff --git a/internal/controller/localization/suite_test.go b/internal/controller/localization/suite_test.go index 070d6e7a..1e71fdeb 100644 --- a/internal/controller/localization/suite_test.go +++ b/internal/controller/localization/suite_test.go @@ -43,8 +43,8 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/configuration" cfgclient "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/configuration/client" locclient "github.com/open-component-model/ocm-k8s-toolkit/internal/controller/localization/client" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/test" ) @@ -59,7 +59,7 @@ var k8sManager ctrl.Manager var testEnv *envtest.Environment var recorder record.EventRecorder var zotCmd *exec.Cmd -var registry *snapshot.Registry +var registry *ociartifact.Registry var zotRootDir string var ctx context.Context var cancel context.CancelFunc diff --git a/internal/controller/localization/types/localization_reference.go b/internal/controller/localization/types/localization_reference.go index 61764d19..997951d0 100644 --- a/internal/controller/localization/types/localization_reference.go +++ b/internal/controller/localization/types/localization_reference.go @@ -1,7 +1,7 @@ package types import ( - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" ) // LocalizationReference can be used both as a source (LocalizationConfig), @@ -11,12 +11,12 @@ type LocalizationReference interface { LocalizationTarget } -// LocalizationConfig is a configuration on how to localize an snapshot.Content. +// LocalizationConfig is a configuration on how to localize an ociartifact.Content. type LocalizationConfig interface { - snapshot.Content + ociartifact.Content } -// LocalizationTarget is a target snapshot.Content for localization. +// LocalizationTarget is a target ociartifact.Content for localization. type LocalizationTarget interface { - snapshot.Content + ociartifact.Content } diff --git a/internal/controller/resource/resource_controller.go b/internal/controller/resource/resource_controller.go index 5aeb8971..c55fdf85 100644 --- a/internal/controller/resource/resource_controller.go +++ b/internal/controller/resource/resource_controller.go @@ -48,14 +48,14 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" "github.com/open-component-model/ocm-k8s-toolkit/pkg/compression" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/status" ) type Reconciler struct { *ocm.BaseReconciler - Registry snapshot.RegistryType + Registry ociartifact.RegistryType } var _ ocm.Reconciler = (*Reconciler)(nil) @@ -370,7 +370,7 @@ func (r *Reconciler) reconcileResource(ctx context.Context, octx ocmctx.Context, return ctrl.Result{}, fmt.Errorf("failed to auto compress data: %w", err) } - manifestDigest, err = repositoryResource.PushSnapshot(ctx, resourceAccess.Meta().GetVersion(), resourceContentCompressed) + manifestDigest, err = repositoryResource.PushArtifact(ctx, resourceAccess.Meta().GetVersion(), resourceContentCompressed) if err != nil { status.MarkNotReady(r.GetEventRecorder(), resource, v1alpha1.PushSnapshotFailedReason, err.Error()) @@ -381,7 +381,7 @@ func (r *Reconciler) reconcileResource(ctx context.Context, octx ocmctx.Context, } // Create respective snapshot CR - snapshotCR := snapshot.Create( + snapshotCR := ociartifact.Create( resource, repositoryResourceName, manifestDigest.String(), diff --git a/internal/controller/resource/resource_controller_test.go b/internal/controller/resource/resource_controller_test.go index d9b10f40..b669aed2 100644 --- a/internal/controller/resource/resource_controller_test.go +++ b/internal/controller/resource/resource_controller_test.go @@ -173,7 +173,7 @@ var _ = Describe("Resource Controller", func() { By("checking that the snapshot contains the correct content") snapshotRepository, err := registry.NewRepository(ctx, snapshotResource.Spec.Repository) Expect(err).NotTo(HaveOccurred()) - snapshotResourceContentCompressed, err := snapshotRepository.FetchSnapshot(ctx, snapshotResource.GetDigest()) + snapshotResourceContentCompressed, err := snapshotRepository.FetchArtifact(ctx, snapshotResource.GetDigest()) Expect(err).NotTo(HaveOccurred()) gzipReader, err := gzip.NewReader(bytes.NewReader(snapshotResourceContentCompressed)) Expect(err).NotTo(HaveOccurred()) @@ -291,7 +291,7 @@ var _ = Describe("Resource Controller", func() { By("checking that the snapshot contains the correct content") snapshotRepository, err := registry.NewRepository(ctx, snapshotResource.Spec.Repository) Expect(err).NotTo(HaveOccurred()) - snapshotResourceContentCompressed, err := snapshotRepository.FetchSnapshot(ctx, snapshotResource.GetDigest()) + snapshotResourceContentCompressed, err := snapshotRepository.FetchArtifact(ctx, snapshotResource.GetDigest()) Expect(err).NotTo(HaveOccurred()) gzipReader, err := gzip.NewReader(bytes.NewReader(snapshotResourceContentCompressed)) Expect(err).NotTo(HaveOccurred()) @@ -322,7 +322,7 @@ var _ = Describe("Resource Controller", func() { Expect(k8sClient.Delete(ctx, snapshotComponent)).To(Succeed()) }) - It("can reconcile a resource: OCIArtifact", func() { + It("can reconcile a resource: OCIArtifactInfo", func() { testComponent := fmt.Sprintf("%s-%d", ComponentObj, testNumber) testResource := fmt.Sprintf("%s-%d", ResourceObj, testNumber) resourceType := artifacttypes.OCI_ARTIFACT @@ -330,10 +330,10 @@ var _ = Describe("Resource Controller", func() { By("creating an OCI artifact") repository, err := registry.NewRepository(ctx, testResource) Expect(err).NotTo(HaveOccurred()) - manifestDigest, err := repository.PushSnapshot(ctx, ResourceVersion, []byte(ResourceContent)) + manifestDigest, err := repository.PushArtifact(ctx, ResourceVersion, []byte(ResourceContent)) Expect(err).ToNot(HaveOccurred()) DeferCleanup(func(ctx SpecContext) { - Expect(repository.DeleteSnapshot(ctx, manifestDigest.String())).To(Succeed()) + Expect(repository.DeleteArtifact(ctx, manifestDigest.String())).To(Succeed()) }) By("creating an ocm resource from an OCI artifact") @@ -415,7 +415,7 @@ var _ = Describe("Resource Controller", func() { By("checking that the snapshot contains the correct content") snapshotRepository, err := registry.NewRepository(ctx, snapshotResource.Spec.Repository) Expect(err).NotTo(HaveOccurred()) - snapshotResourceContent, err := snapshotRepository.FetchSnapshot(ctx, snapshotResource.GetDigest()) + snapshotResourceContent, err := snapshotRepository.FetchArtifact(ctx, snapshotResource.GetDigest()) Expect(err).NotTo(HaveOccurred()) Expect(string(snapshotResourceContent)).To(Equal(ResourceContent)) diff --git a/internal/controller/resource/suite_test.go b/internal/controller/resource/suite_test.go index daa447fb..ca69b7c7 100644 --- a/internal/controller/resource/suite_test.go +++ b/internal/controller/resource/suite_test.go @@ -39,8 +39,8 @@ import ( metricserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/test" ) @@ -55,7 +55,7 @@ var k8sManager ctrl.Manager var testEnv *envtest.Environment var recorder record.EventRecorder var zotCmd *exec.Cmd -var registry *snapshot.Registry +var registry *ociartifact.Registry var zotRootDir string var ctx context.Context var cancel context.CancelFunc diff --git a/internal/controller/snapshot/controller.go b/internal/controller/snapshot/controller.go index bc061510..7149c043 100644 --- a/internal/controller/snapshot/controller.go +++ b/internal/controller/snapshot/controller.go @@ -16,8 +16,8 @@ import ( ctrl "sigs.k8s.io/controller-runtime" deliveryv1alpha1 "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" + snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/ocm" - snapshotRegistry "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" "github.com/open-component-model/ocm-k8s-toolkit/pkg/status" ) @@ -78,7 +78,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re return ctrl.Result{}, fmt.Errorf("failed to create a repository: %w", err) } - exists, err := repository.ExistsSnapshot(ctx, snapshotResource.GetDigest()) + exists, err := repository.ExistsArtifact(ctx, snapshotResource.GetDigest()) if err != nil { status.MarkNotReady(r.EventRecorder, snapshotResource, deliveryv1alpha1.OCIRepositoryExistsFailedReason, err.Error()) @@ -86,14 +86,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re } if exists { - if err := repository.DeleteSnapshot(ctx, snapshotResource.GetDigest()); err != nil { + if err := repository.DeleteArtifact(ctx, snapshotResource.GetDigest()); err != nil { status.MarkNotReady(r.EventRecorder, snapshotResource, deliveryv1alpha1.DeleteSnapshotFailedReason, err.Error()) return ctrl.Result{}, fmt.Errorf("failed to delete snapshot: %w", err) } } - if removed := controllerutil.RemoveFinalizer(snapshotResource, deliveryv1alpha1.SnapshotFinalizer); removed { + if removed := controllerutil.RemoveFinalizer(snapshotResource, deliveryv1alpha1.ArtifactFinalizer); removed { if err := r.Update(ctx, snapshotResource); err != nil { return ctrl.Result{}, fmt.Errorf("failed to remove finalizer: %w", err) } @@ -102,7 +102,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re return ctrl.Result{Requeue: true}, nil } - if added := controllerutil.AddFinalizer(snapshotResource, deliveryv1alpha1.SnapshotFinalizer); added { + if added := controllerutil.AddFinalizer(snapshotResource, deliveryv1alpha1.ArtifactFinalizer); added { err := r.Update(ctx, snapshotResource) if err != nil { return ctrl.Result{}, fmt.Errorf("failed to add finalizer: %w", err) @@ -119,7 +119,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Re return ctrl.Result{}, fmt.Errorf("failed to create a repository: %w", err) } - exists, err := repository.ExistsSnapshot(ctx, snapshotResource.GetDigest()) + exists, err := repository.ExistsArtifact(ctx, snapshotResource.GetDigest()) if err != nil { status.MarkNotReady(r.EventRecorder, snapshotResource, deliveryv1alpha1.OCIRepositoryExistsFailedReason, err.Error()) diff --git a/pkg/snapshot/object_config.go b/pkg/ociartifact/object_config.go similarity index 98% rename from pkg/snapshot/object_config.go rename to pkg/ociartifact/object_config.go index 97e93458..a52ce1b3 100644 --- a/pkg/snapshot/object_config.go +++ b/pkg/ociartifact/object_config.go @@ -1,4 +1,4 @@ -package snapshot +package ociartifact import ( "bytes" diff --git a/pkg/snapshot/registry.go b/pkg/ociartifact/registry.go similarity index 97% rename from pkg/snapshot/registry.go rename to pkg/ociartifact/registry.go index 850bc448..28a4d14b 100644 --- a/pkg/snapshot/registry.go +++ b/pkg/ociartifact/registry.go @@ -1,4 +1,4 @@ -package snapshot +package ociartifact import ( "context" diff --git a/pkg/snapshot/repository.go b/pkg/ociartifact/repository.go similarity index 94% rename from pkg/snapshot/repository.go rename to pkg/ociartifact/repository.go index 358fdb44..65d327dd 100644 --- a/pkg/snapshot/repository.go +++ b/pkg/ociartifact/repository.go @@ -1,4 +1,4 @@ -package snapshot +package ociartifact import ( "bytes" @@ -31,17 +31,17 @@ type RepositoryType interface { // PushSnapshot is a wrapper to push a single layer OCI artifact with an empty config and a single data layer // containing the blob. As all snapshots are produced and consumed by us, we do not have to care about the // configuration. - PushSnapshot(ctx context.Context, reference string, blob []byte) (digest.Digest, error) + PushArtifact(ctx context.Context, reference string, blob []byte) (digest.Digest, error) // FetchSnapshot is a wrapper to fetch a single layer OCI artifact with a manifest digest. It expects and returns // the single data layer. - FetchSnapshot(ctx context.Context, reference string) ([]byte, error) + FetchArtifact(ctx context.Context, reference string) ([]byte, error) // DeleteSnapshot is a wrapper to delete a single layer OCI artifact with a manifest digest. - DeleteSnapshot(ctx context.Context, digest string) error + DeleteArtifact(ctx context.Context, digest string) error // ExistsSnapshot is a wrapper to check if an OCI repository exists using the manifest digest. - ExistsSnapshot(ctx context.Context, manifestDigest string) (bool, error) + ExistsArtifact(ctx context.Context, manifestDigest string) (bool, error) // CopyOCIArtifactForResourceAccess is a wrapper to copy an OCI artifact from an OCM resource access. CopyOCIArtifactForResourceAccess(ctx context.Context, access ocmctx.ResourceAccess) (digest.Digest, error) @@ -63,7 +63,7 @@ func (r *Repository) GetName() string { return r.Reference.Repository } -func (r *Repository) PushSnapshot(ctx context.Context, tag string, blob []byte) (digest.Digest, error) { +func (r *Repository) PushArtifact(ctx context.Context, tag string, blob []byte) (digest.Digest, error) { logger := log.FromContext(ctx) // Prepare and upload blob @@ -139,7 +139,7 @@ func (r *Repository) PushSnapshot(ctx context.Context, tag string, blob []byte) return manifestDigest, nil } -func (r *Repository) FetchSnapshot(ctx context.Context, manifestDigest string) ([]byte, error) { +func (r *Repository) FetchArtifact(ctx context.Context, manifestDigest string) ([]byte, error) { // Fetch manifest descriptor to get manifest. manifestDescriptor, _, err := r.FetchReference(ctx, manifestDigest) if err != nil { @@ -169,7 +169,7 @@ func (r *Repository) FetchSnapshot(ctx context.Context, manifestDigest string) ( return io.ReadAll(reader) } -func (r *Repository) DeleteSnapshot(ctx context.Context, manifestDigest string) error { +func (r *Repository) DeleteArtifact(ctx context.Context, manifestDigest string) error { manifestDescriptor, _, err := r.FetchReference(ctx, manifestDigest) if err != nil { return fmt.Errorf("error fetching manifest: %w", err) @@ -178,7 +178,7 @@ func (r *Repository) DeleteSnapshot(ctx context.Context, manifestDigest string) return r.Delete(ctx, manifestDescriptor) } -func (r *Repository) ExistsSnapshot(ctx context.Context, manifestDigest string) (bool, error) { +func (r *Repository) ExistsArtifact(ctx context.Context, manifestDigest string) (bool, error) { manifestDescriptor, _, err := r.FetchReference(ctx, manifestDigest) if err != nil { return false, fmt.Errorf("error fetching manifest: %w", err) diff --git a/pkg/snapshot/resource.go b/pkg/ociartifact/resource.go similarity index 98% rename from pkg/snapshot/resource.go rename to pkg/ociartifact/resource.go index 7544111e..7700a075 100644 --- a/pkg/snapshot/resource.go +++ b/pkg/ociartifact/resource.go @@ -1,4 +1,4 @@ -package snapshot +package ociartifact import ( "bytes" @@ -84,7 +84,7 @@ func (r *ContentBackedBySnapshotAndComponent) open() (io.ReadCloser, error) { return nil, fmt.Errorf("failed to open repository: %w", err) } - data, err := repository.FetchSnapshot(ctx, r.Snapshot.GetDigest()) + data, err := repository.FetchArtifact(ctx, r.Snapshot.GetDigest()) if err != nil { return nil, fmt.Errorf("failed to fetch snapshot: %w", err) } diff --git a/pkg/ocm/snapshot.go b/pkg/ocm/snapshot.go index 09f68d8b..8ce61248 100644 --- a/pkg/ocm/snapshot.go +++ b/pkg/ocm/snapshot.go @@ -9,12 +9,12 @@ import ( "ocm.software/ocm/api/ocm/compdesc" "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" ) // GetComponentSetForSnapshot returns the component descriptor set for the given snapshot. -func GetComponentSetForSnapshot(ctx context.Context, repository snapshot.RepositoryType, snapshotResource *v1alpha1.Snapshot) (*compdesc.ComponentVersionSet, error) { - data, err := repository.FetchSnapshot(ctx, snapshotResource.GetDigest()) +func GetComponentSetForSnapshot(ctx context.Context, repository ociartifact.RepositoryType, snapshotResource *v1alpha1.Snapshot) (*compdesc.ComponentVersionSet, error) { + data, err := repository.FetchArtifact(ctx, snapshotResource.GetDigest()) if err != nil { return nil, err } diff --git a/pkg/snapshot/snapshot.go b/pkg/snapshot/snapshot.go deleted file mode 100644 index a9126b45..00000000 --- a/pkg/snapshot/snapshot.go +++ /dev/null @@ -1,84 +0,0 @@ -package snapshot - -import ( - "context" - "errors" - "fmt" - "os" - "strings" - - "github.com/fluxcd/pkg/runtime/conditions" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/validation" - "sigs.k8s.io/controller-runtime/pkg/client" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" -) - -// GenerateName generates a name for a snapshot CR. If the name exceeds the character limit, it will be cut off at 256. -func GenerateName(obj v1alpha1.SnapshotWriter) string { - name := strings.ToLower(fmt.Sprintf("%s-%s", obj.GetKind(), obj.GetName())) - - if len(name) > validation.DNS1123SubdomainMaxLength { - return name[:validation.DNS1123SubdomainMaxLength] - } - - return name -} - -func Create(owner v1alpha1.SnapshotWriter, ociRepository, manifestDigest string, blob *v1alpha1.BlobInfo) *v1alpha1.Snapshot { - return &v1alpha1.Snapshot{ - ObjectMeta: metav1.ObjectMeta{ - Name: GenerateName(owner), - Namespace: owner.GetNamespace(), - }, - Spec: v1alpha1.SnapshotSpec{ - Repository: ociRepository, - Digest: manifestDigest, - Blob: blob, - }, - Status: v1alpha1.SnapshotStatus{}, - } -} - -// ValidateSnapshotForOwner verifies if the snapshot for the given collectable is valid. -// This means that the snapshot must be present in the cluster the reader is connected to and -// the snapshot must be present in the OCI registry. -// Additionally, the passed digest must be different from the blob digest stored in the snapshot. -// -// This method can be used to determine if a snapshot needs an update or not because a snapshot that does not -// fulfill these conditions can be considered out of date (not in the cluster, not in the OCI registry, or mismatching -// digest). -func ValidateSnapshotForOwner( - ctx context.Context, - reader client.Reader, - owner v1alpha1.SnapshotWriter, - digest string, -) (bool, error) { - // If the owner cannot return a snapshot name, the snapshot is not created yet. - if owner.GetSnapshotName() == "" { - return false, nil - } - - snapshotResource := &v1alpha1.Snapshot{} - err := reader.Get(ctx, types.NamespacedName{Namespace: owner.GetNamespace(), Name: owner.GetSnapshotName()}, snapshotResource) - if errors.Is(err, os.ErrNotExist) { - return false, nil - } - if client.IgnoreNotFound(err) != nil { - return false, fmt.Errorf("failed to get snapshot: %w", err) - } - - if snapshotResource == nil { - return false, nil - } - - // Snapshot is only ready, if the repository exists in the OCI registry - if !conditions.IsReady(snapshotResource) { - return false, fmt.Errorf("snapshot %s is not ready", snapshotResource.GetName()) - } - - return snapshotResource.Spec.Blob.Digest != digest, nil -} diff --git a/pkg/test/component.go b/pkg/test/component.go index e28a4b87..c134f1d6 100644 --- a/pkg/test/component.go +++ b/pkg/test/component.go @@ -19,12 +19,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/status" ) type MockComponentOptions struct { - Registry snapshot.RegistryType + Registry ociartifact.RegistryType Client client.Client Recorder record.EventRecorder Info v1alpha1.ComponentInfo @@ -51,16 +51,16 @@ func SetupComponentWithDescriptorList( patchHelper := patch.NewSerialPatcher(component, options.Client) - repositoryName, err := snapshot.CreateRepositoryName(options.Repository, name) + repositoryName, err := ociartifact.CreateRepositoryName(options.Repository, name) Expect(err).ToNot(HaveOccurred()) repository, err := options.Registry.NewRepository(ctx, repositoryName) Expect(err).ToNot(HaveOccurred()) - manifestDigest, err := repository.PushSnapshot(ctx, options.Info.Version, descriptorListData) + manifestDigest, err := repository.PushArtifact(ctx, options.Info.Version, descriptorListData) Expect(err).ToNot(HaveOccurred()) - snapshotCR := snapshot.Create( + snapshotCR := ociartifact.Create( component, repositoryName, manifestDigest.String(), diff --git a/pkg/test/resource.go b/pkg/test/resource.go index fa830744..2c5ea9ba 100644 --- a/pkg/test/resource.go +++ b/pkg/test/resource.go @@ -22,7 +22,7 @@ import ( "github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1" "github.com/open-component-model/ocm-k8s-toolkit/pkg/compression" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" "github.com/open-component-model/ocm-k8s-toolkit/pkg/status" ) @@ -34,7 +34,7 @@ type MockResourceOptions struct { ComponentRef v1alpha1.ObjectKey - Registry snapshot.RegistryType + Registry ociartifact.RegistryType Clnt client.Client Recorder record.EventRecorder } @@ -78,14 +78,14 @@ func SetupMockResourceWithData( } version := "dummy" - repositoryName, err := snapshot.CreateRepositoryName(options.ComponentRef.Name, name) + repositoryName, err := ociartifact.CreateRepositoryName(options.ComponentRef.Name, name) Expect(err).ToNot(HaveOccurred()) repository, err := options.Registry.NewRepository(ctx, repositoryName) Expect(err).ToNot(HaveOccurred()) - manifestDigest, err := repository.PushSnapshot(ctx, version, data) + manifestDigest, err := repository.PushArtifact(ctx, version, data) Expect(err).ToNot(HaveOccurred()) - snapshotCR := snapshot.Create( + snapshotCR := ociartifact.Create( res, repositoryName, manifestDigest.String(), diff --git a/pkg/test/zot-registry.go b/pkg/test/zot-registry.go index ec4e8556..dedbfc72 100644 --- a/pkg/test/zot-registry.go +++ b/pkg/test/zot-registry.go @@ -13,14 +13,14 @@ import ( //nolint:revive,stylecheck // dot import necessary for Ginkgo DSL . "github.com/onsi/gomega" - "github.com/open-component-model/ocm-k8s-toolkit/pkg/snapshot" + "github.com/open-component-model/ocm-k8s-toolkit/pkg/ociartifact" ) const ( timeout = 30 * time.Second ) -func SetupRegistry(binPath, rootDir, address, port string) (*exec.Cmd, *snapshot.Registry) { +func SetupRegistry(binPath, rootDir, address, port string) (*exec.Cmd, *ociartifact.Registry) { config := []byte(fmt.Sprintf(`{"storage":{"rootDirectory":"%s"},"http":{"address":"%s","port": "%s"}}`, rootDir, address, port)) configFile := filepath.Join(rootDir, "config.json") err := os.WriteFile(configFile, config, 0o600) @@ -52,7 +52,7 @@ func SetupRegistry(binPath, rootDir, address, port string) (*exec.Cmd, *snapshot return nil }, timeout).Should(Succeed(), "Zot registry did not start in time") - registry, err := snapshot.NewRegistry(fmt.Sprintf("%s:%s", address, port)) + registry, err := ociartifact.NewRegistry(fmt.Sprintf("%s:%s", address, port)) Expect(err).NotTo(HaveOccurred()) registry.PlainHTTP = true