Skip to content

Commit

Permalink
omit snapshot 3
Browse files Browse the repository at this point in the history
  • Loading branch information
ikhandamirov committed Mar 6, 2025
1 parent c094a6b commit cf17eda
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 58 deletions.
22 changes: 22 additions & 0 deletions api/v1alpha1/configuredresource_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,28 @@ func (in *ConfiguredResource) SetTarget(v *ConfigurationReference) {
v.DeepCopyInto(&in.Spec.Target)
}

func (in *ConfiguredResource) GetOCIArtifact() *OCIArtifactInfo {
return in.Status.OCIArtifact
}

// GetOCIRepository returns the name of the OCI repository of the OCI artifact in which the component
// descriptors are stored.
func (in *ConfiguredResource) 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 *ConfiguredResource) 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 *ConfiguredResource) GetBlobDigest() string {
return in.Status.OCIArtifact.Blob.Digest
}

// ConfiguredResourceStatus defines the observed state of ConfiguredResource.
type ConfiguredResourceStatus struct {
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
Expand Down
68 changes: 28 additions & 40 deletions internal/controller/configuration/configuration_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ import (
"github.com/fluxcd/pkg/runtime/patch"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"

corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"

"github.com/open-component-model/ocm-k8s-toolkit/api/v1alpha1"
Expand All @@ -50,8 +48,6 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {

return ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.ConfiguredResource{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
// Update when the owned artifact containing the configured data changes
Owns(&v1alpha1.Snapshot{}).
// Update when a resource specified as target changes
Watches(&v1alpha1.Resource{}, onTargetChange).
Watches(&v1alpha1.LocalizedResource{}, onTargetChange).
Expand Down Expand Up @@ -159,21 +155,32 @@ func (r *Reconciler) reconcileExists(ctx context.Context, configuration *v1alpha
// Check if a snapshot of the configuration resource already exists and if it holds the same calculated combinedDigest
// from above
logger.V(1).Info("verifying configuration", "combinedDigest", combinedDigest, "revision", revision)
// TODO: Replace ValidateSnapshotForOwner
hasValidSnapshot, err := ociartifact.ValidateSnapshotForOwner(
ctx,
r.Client,
configuration,
combinedDigest,
)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to check if snapshot is valid: %w", err)

hasValidArtifact := false

if configuration.GetOCIArtifact() != nil {
ociRepository, err := r.Registry.NewRepository(ctx, configuration.GetOCIRepository())
if err != nil {
status.MarkNotReady(r.EventRecorder, configuration, v1alpha1.CreateOCIRepositoryFailedReason, err.Error())

return ctrl.Result{}, err
}

exists, err := ociRepository.ExistsArtifact(ctx, configuration.GetManifestDigest())
if err != nil {
status.MarkNotReady(r.EventRecorder, configuration, v1alpha1.OCIRepositoryExistsFailedReason, err.Error())

return ctrl.Result{}, err
}
if exists {
hasValidArtifact = combinedDigest == configuration.GetBlobDigest()
}
}

// If no valid snapshot is present (because it never existed or is just not valid), we will configure the target,
// create a snapshot and return.
// If no valid OCI artifact is present (because it never existed or is just not valid), we will configure the target,
// create an OCI artifact and return.
//nolint:nestif // Ignore as it is not that complex.
if !hasValidSnapshot {
if !hasValidArtifact {
logger.V(1).Info("configuring", "combinedDigest", combinedDigest, "revision", revision)
basePath, err := os.MkdirTemp("", "configured-")
if err != nil {
Expand Down Expand Up @@ -227,37 +234,18 @@ func (r *Reconciler) reconcileExists(ctx context.Context, configuration *v1alpha
}

// We use the combinedDigest calculated above for the blob-info combinedDigest, so we can compare for any changes
snapshotCR := ociartifact.Create(
configuration,
repositoryName,
manifestDigest.String(),
&v1alpha1.BlobInfo{
configuration.Status.OCIArtifact = &v1alpha1.OCIArtifactInfo{
Repository: repositoryName,
Digest: manifestDigest.String(),
Blob: &v1alpha1.BlobInfo{
Digest: combinedDigest,
Tag: tag,
Size: int64(len(dataTGZ)),
},
)

if _, err = controllerutil.CreateOrUpdate(ctx, r.GetClient(), snapshotCR, func() error {
if snapshotCR.ObjectMeta.CreationTimestamp.IsZero() {
if err := controllerutil.SetControllerReference(configuration, snapshotCR, r.GetScheme()); err != nil {
return fmt.Errorf("failed to set controller reference: %w", err)
}
}

configuration.Status.SnapshotRef = corev1.LocalObjectReference{
Name: snapshotCR.GetName(),
}

return nil
}); err != nil {
status.MarkNotReady(r.EventRecorder, configuration, v1alpha1.CreateSnapshotFailedReason, err.Error())

return ctrl.Result{}, err
}
}

logger.Info("configuration successful", "snapshot", configuration.Status.SnapshotRef)
logger.Info("configuration successful", "OCIArtifact", configuration.GetOCIArtifact())
status.MarkReady(r.EventRecorder, configuration, "configured successfully")

return ctrl.Result{RequeueAfter: configuration.Spec.Interval.Duration}, nil
Expand Down
32 changes: 14 additions & 18 deletions internal/controller/configuration/configuration_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package configuration

import (
"context"
"fmt"
"os"
"path/filepath"
"time"
Expand All @@ -15,7 +16,6 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"

corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -146,28 +146,30 @@ var _ = Describe("ConfiguredResource Controller", func() {
}
Expect(k8sClient.Create(ctx, configuredResource)).To(Succeed())

Eventually(func(ctx context.Context) bool {
Eventually(func(ctx context.Context) error {
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(configuredResource), configuredResource)
if err != nil {
return false
return err
}
return conditions.IsReady(configuredResource) && configuredResource.GetSnapshotName() != ""
}, "15s").WithContext(ctx).Should(BeTrue())

snapshotResource := &v1alpha1.Snapshot{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: configuredResource.GetNamespace(), Name: configuredResource.GetSnapshotName()}, snapshotResource)).To(Succeed())
if !conditions.IsReady(configuredResource) {
return fmt.Errorf("resource not ready")
}
if configuredResource.GetOCIArtifact() == nil {
return fmt.Errorf("OCI artifact not present")
}
return nil
}, "15s").WithContext(ctx).Should(Succeed())

snapshotRepository, err := registry.NewRepository(ctx, snapshotResource.Spec.Repository)
ociRepository, err := registry.NewRepository(ctx, configuredResource.GetOCIRepository())
Expect(err).NotTo(HaveOccurred())
snapshotResourceContent, err := snapshotRepository.FetchArtifact(ctx, snapshotResource.GetDigest())
resourceContent, err := ociRepository.FetchArtifact(ctx, configuredResource.GetManifestDigest())
Expect(err).NotTo(HaveOccurred())
dataExtracted, err := compression.ExtractDataFromTGZ(snapshotResourceContent)
dataExtracted, err := compression.ExtractDataFromTGZ(resourceContent)
Expect(err).NotTo(HaveOccurred())
Expect(dataExtracted).To(MatchYAML(fileContentAfterConfiguration))

By("delete resources manually")
Expect(k8sClient.Delete(ctx, configuredResource)).To(Succeed())
Expect(k8sClient.Delete(ctx, snapshotResource)).To(Succeed())
Eventually(func(ctx context.Context) bool {
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(configuredResource), configuredResource)
return errors.IsNotFound(err)
Expand All @@ -180,14 +182,8 @@ var _ = Describe("ConfiguredResource Controller", func() {
}, "15s").WithContext(ctx).Should(BeTrue())

Expect(k8sClient.Delete(ctx, targetResource)).To(Succeed())
snapshotTargetResource := &v1alpha1.Snapshot{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: targetResource.GetNamespace(), Name: targetResource.GetSnapshotName()}, snapshotTargetResource)).To(Succeed())
Expect(k8sClient.Delete(ctx, snapshotTargetResource)).To(Succeed())

Expect(k8sClient.Delete(ctx, component)).To(Succeed())
snapshotComponent := &v1alpha1.Snapshot{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: component.GetNamespace(), Name: component.GetSnapshotName()}, snapshotComponent)).To(Succeed())
Expect(k8sClient.Delete(ctx, snapshotComponent)).To(Succeed())
})
})

Expand Down

0 comments on commit cf17eda

Please sign in to comment.