@@ -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+
388450func (r * RuntimeReconciler ) CheckIfReferenceDatasetIsSupported (ctx cruntime.ReconcileRequestContext ) (bool , string ) {
389451 mounted := base .GetPhysicalDatasetFromMounts (ctx .Dataset .Spec .Mounts )
390452
0 commit comments