Skip to content

Commit f73e164

Browse files
feat(runtime): support dataset auto-create policy
Add a new DatasetAutoCreatePolicy feature that allows runtimes to automatically create a Dataset when one does not already exist. Use controllerutil.SetControllerReference to set proper owner reference on the auto-created Dataset so it is garbage-collected with the runtime. Signed-off-by: Monika Jakhar <jakharmonika364@gmail.com>
1 parent b666fa2 commit f73e164

3 files changed

Lines changed: 78 additions & 7 deletions

File tree

pkg/common/constants.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,8 @@ const (
225225
SkipPrecheckAnnotationKey = "sidecar.fluid.io/skip-precheck"
226226
HostMountPathModeOnDefaultPlatformKey = "default.fuse-sidecar.fluid.io/host-mount-path-mode"
227227
)
228+
229+
const (
230+
// DatasetPolicyAutoCreate indicates that a Dataset should be auto-created for the Runtime.
231+
DatasetPolicyAutoCreate = "auto-create"
232+
)

pkg/common/label.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ const (
8282
// i.e. fluid.io/check-mount-script-sha256
8383
AnnotationCheckMountScriptSHA256 = LabelAnnotationPrefix + "check-mount-script-sha256"
8484

85+
// AnnotationDatasetPolicy is a runtime annotation that controls how Dataset is handled.
86+
// i.e. fluid.io/dataset-policy
87+
AnnotationDatasetPolicy = LabelAnnotationPrefix + "dataset-policy"
88+
8589
// AnnotationDisableRuntimeHelmValueConfig is a runtime label indicates the configmap contains helm value will not be created in setup.
8690
AnnotationDisableRuntimeHelmValueConfig = "runtime." + LabelAnnotationPrefix + "disable-helm-value-config"
8791

pkg/controllers/runtime_controller.go

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"strings"
2424
"time"
2525

26+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2627
"k8s.io/apimachinery/pkg/types"
2728
"k8s.io/apimachinery/pkg/util/validation"
2829
"k8s.io/apimachinery/pkg/util/validation/field"
@@ -34,8 +35,7 @@ import (
3435
"k8s.io/client-go/util/retry"
3536
ctrl "sigs.k8s.io/controller-runtime"
3637
"sigs.k8s.io/controller-runtime/pkg/client"
37-
38-
// "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
38+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3939

4040
"github.com/fluid-cloudnative/fluid/pkg/dump"
4141
fluiderrs "github.com/fluid-cloudnative/fluid/pkg/errors"
@@ -110,14 +110,27 @@ func (r *RuntimeReconciler) ReconcileInternal(ctx cruntime.ReconcileRequestConte
110110
return utils.RequeueIfError(err)
111111
}
112112

113+
var datasetPolicy string
114+
if annotations := objectMeta.GetAnnotations(); annotations != nil {
115+
datasetPolicy = annotations[common.AnnotationDatasetPolicy]
116+
}
117+
113118
// 5.Get the dataset
114119
dataset, err := r.GetDataset(ctx)
115120
if err != nil {
116-
// r.Recorder.Eventf(ctx.Dataset, corev1.EventTypeWarning, common.ErrorProcessRuntimeReason, "Process Runtime error %v", err)
117121
if utils.IgnoreNotFound(err) == nil {
118-
ctx.Log.Info("The dataset is not found", "dataset", ctx.NamespacedName)
119-
dataset = nil
120-
// return ctrl.Result{}, nil
122+
if datasetPolicy == common.DatasetPolicyAutoCreate {
123+
ctx.Log.Info("The dataset is not found, auto-creating according to policy", "dataset", ctx.NamespacedName)
124+
dataset, err = r.ensureDatasetForRuntime(ctx, objectMeta)
125+
if err != nil {
126+
ctx.Log.Error(err, "Failed to auto-create the dataset")
127+
r.Recorder.Eventf(runtime, corev1.EventTypeWarning, common.ErrorCreateDataset, "Failed to auto-create dataset: %v", err)
128+
return utils.RequeueAfterInterval(5 * time.Second)
129+
}
130+
} else {
131+
ctx.Log.Info("The dataset is not found", "dataset", ctx.NamespacedName)
132+
dataset = nil
133+
}
121134
} else {
122135
ctx.Log.Error(err, "Failed to get the ddc dataset")
123136
return utils.RequeueIfError(errors.Wrap(err, "Unable to get dataset"))
@@ -172,7 +185,11 @@ func (r *RuntimeReconciler) ReconcileInternal(ctx cruntime.ReconcileRequestConte
172185
}
173186
} else {
174187
// If dataset is nil, need to wait because the user may have not created dataset
175-
ctx.Log.Info("No dataset can be bound to the runtime, waiting.")
188+
if datasetPolicy == common.DatasetPolicyAutoCreate {
189+
ctx.Log.Info("No dataset is available for the runtime after auto-create, waiting.", "dataset", ctx.NamespacedName)
190+
} else {
191+
ctx.Log.Info("No dataset can be bound to the runtime, waiting.")
192+
}
176193
r.Recorder.Event(runtime, corev1.EventTypeWarning, common.ErrorProcessRuntimeReason, "No dataset can be bound to the runtime, waiting.")
177194
return utils.RequeueAfterInterval(time.Duration(5 * time.Second))
178195
}
@@ -385,6 +402,51 @@ func (r *RuntimeReconciler) GetDataset(ctx cruntime.ReconcileRequestContext) (*d
385402
return &dataset, nil
386403
}
387404

405+
func (r *RuntimeReconciler) ensureDatasetForRuntime(ctx cruntime.ReconcileRequestContext, objectMeta metav1.Object) (*datav1alpha1.Dataset, error) {
406+
runtime := ctx.Runtime
407+
if runtime == nil {
408+
return nil, fmt.Errorf("runtime is nil")
409+
}
410+
411+
annotations := make(map[string]string)
412+
for k, v := range objectMeta.GetAnnotations() {
413+
annotations[k] = v
414+
}
415+
annotations[common.AnnotationDatasetPolicy] = common.DatasetPolicyAutoCreate
416+
417+
dataset := &datav1alpha1.Dataset{
418+
TypeMeta: metav1.TypeMeta{
419+
Kind: datav1alpha1.Datasetkind,
420+
APIVersion: datav1alpha1.GroupVersion.Group + "/" + datav1alpha1.GroupVersion.Version,
421+
},
422+
ObjectMeta: metav1.ObjectMeta{
423+
Name: objectMeta.GetName(),
424+
Namespace: objectMeta.GetNamespace(),
425+
Annotations: annotations,
426+
},
427+
}
428+
429+
// SetControllerReference looks up the GVK from the scheme, avoiding the
430+
// empty-TypeMeta problem that arises when runtime.GetObjectKind() is used
431+
// on objects retrieved via controller-runtime's client.Get().
432+
if err := controllerutil.SetControllerReference(runtime, dataset, r.Client.Scheme()); err != nil {
433+
return nil, fmt.Errorf("failed to set controller reference on auto-created dataset: %w", err)
434+
}
435+
436+
err := r.Create(ctx, dataset)
437+
if err != nil && !apierrors.IsAlreadyExists(err) {
438+
return nil, err
439+
}
440+
441+
if err := r.Get(ctx, ctx.NamespacedName, dataset); err != nil {
442+
return nil, err
443+
}
444+
445+
r.Recorder.Eventf(runtime, corev1.EventTypeNormal, common.Succeed, "Auto-created Dataset %s for Runtime", dataset.Name)
446+
447+
return dataset, nil
448+
}
449+
388450
func (r *RuntimeReconciler) CheckIfReferenceDatasetIsSupported(ctx cruntime.ReconcileRequestContext) (bool, string) {
389451
mounted := base.GetPhysicalDatasetFromMounts(ctx.Dataset.Spec.Mounts)
390452

0 commit comments

Comments
 (0)