From b85cd7332f25181a3cdddae25fc1738ff0ae5eb6 Mon Sep 17 00:00:00 2001 From: Arnon Gilboa Date: Fri, 5 Aug 2022 20:22:19 +0300 Subject: [PATCH] Update DataSource LastTransitionTime when populated PVC is updated (#2381) * Update DataSource LastTransitionTime when populated source PVC is updated Signed-off-by: Arnon Gilboa * Add Source field to DataSourceStatus Signed-off-by: Arnon Gilboa --- api/openapi-spec/swagger.json | 8 +++++++ pkg/apis/core/v1beta1/openapi_generated.go | 10 +++++++- pkg/controller/datasource-controller.go | 4 ++++ pkg/operator/resources/crds_generated.go | 21 +++++++++++++++++ .../pkg/apis/core/v1beta1/types.go | 2 ++ .../core/v1beta1/types_swagger_generated.go | 3 ++- .../core/v1beta1/zz_generated.deepcopy.go | 1 + tests/datasource_test.go | 23 +++++++++++++++++++ 8 files changed, 70 insertions(+), 2 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 58fe2fbd86..471215bfdd 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -5439,6 +5439,9 @@ "v1beta1.DataSourceStatus": { "description": "DataSourceStatus provides the most recently observed status of the DataSource", "type": "object", + "required": [ + "source" + ], "properties": { "conditions": { "type": "array", @@ -5446,6 +5449,11 @@ "default": {}, "$ref": "#/definitions/v1beta1.DataSourceCondition" } + }, + "source": { + "description": "Source is the current source of the data referenced by the DataSource", + "default": {}, + "$ref": "#/definitions/v1beta1.DataSourceSource" } } }, diff --git a/pkg/apis/core/v1beta1/openapi_generated.go b/pkg/apis/core/v1beta1/openapi_generated.go index 2a67586f2d..dfd2d47b7e 100644 --- a/pkg/apis/core/v1beta1/openapi_generated.go +++ b/pkg/apis/core/v1beta1/openapi_generated.go @@ -23805,6 +23805,13 @@ func schema_pkg_apis_core_v1beta1_DataSourceStatus(ref common.ReferenceCallback) Description: "DataSourceStatus provides the most recently observed status of the DataSource", Type: []string{"object"}, Properties: map[string]spec.Schema{ + "source": { + SchemaProps: spec.SchemaProps{ + Description: "Source is the current source of the data referenced by the DataSource", + Default: map[string]interface{}{}, + Ref: ref("kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.DataSourceSource"), + }, + }, "conditions": { SchemaProps: spec.SchemaProps{ Type: []string{"array"}, @@ -23819,10 +23826,11 @@ func schema_pkg_apis_core_v1beta1_DataSourceStatus(ref common.ReferenceCallback) }, }, }, + Required: []string{"source"}, }, }, Dependencies: []string{ - "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.DataSourceCondition"}, + "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.DataSourceCondition", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.DataSourceSource"}, } } diff --git a/pkg/controller/datasource-controller.go b/pkg/controller/datasource-controller.go index 8b5d464b3a..f872d5d744 100644 --- a/pkg/controller/datasource-controller.go +++ b/pkg/controller/datasource-controller.go @@ -68,6 +68,10 @@ func (r *DataSourceReconciler) Reconcile(ctx context.Context, req reconcile.Requ } func (r *DataSourceReconciler) update(ctx context.Context, dataSource *cdiv1.DataSource) error { + if !reflect.DeepEqual(dataSource.Status.Source, dataSource.Spec.Source) { + dataSource.Spec.Source.DeepCopyInto(&dataSource.Status.Source) + dataSource.Status.Conditions = nil + } dataSourceCopy := dataSource.DeepCopy() sourcePVC := dataSource.Spec.Source.PVC if sourcePVC != nil { diff --git a/pkg/operator/resources/crds_generated.go b/pkg/operator/resources/crds_generated.go index 246d8d3702..e37ff48c9f 100644 --- a/pkg/operator/resources/crds_generated.go +++ b/pkg/operator/resources/crds_generated.go @@ -5754,6 +5754,27 @@ spec: - type type: object type: array + source: + description: Source is the current source of the data referenced by + the DataSource + properties: + pvc: + description: DataVolumeSourcePVC provides the parameters to create + a Data Volume from an existing PVC + properties: + name: + description: The name of the source PVC + type: string + namespace: + description: The namespace of the source PVC + type: string + required: + - name + - namespace + type: object + type: object + required: + - source type: object required: - spec diff --git a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go index 2b474aa47e..e9ac71ebf0 100644 --- a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go +++ b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go @@ -443,6 +443,8 @@ type DataSourceSource struct { // DataSourceStatus provides the most recently observed status of the DataSource type DataSourceStatus struct { + // Source is the current source of the data referenced by the DataSource + Source DataSourceSource `json:"source"` Conditions []DataSourceCondition `json:"conditions,omitempty" optional:"true"` } diff --git a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go index e28c95ccc5..33a6104946 100644 --- a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go +++ b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go @@ -215,7 +215,8 @@ func (DataSourceSource) SwaggerDoc() map[string]string { func (DataSourceStatus) SwaggerDoc() map[string]string { return map[string]string{ - "": "DataSourceStatus provides the most recently observed status of the DataSource", + "": "DataSourceStatus provides the most recently observed status of the DataSource", + "source": "Source is the current source of the data referenced by the DataSource", } } diff --git a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go index c9e3e6f3eb..7010e9c5f9 100644 --- a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go @@ -678,6 +678,7 @@ func (in *DataSourceSpec) DeepCopy() *DataSourceSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DataSourceStatus) DeepCopyInto(out *DataSourceStatus) { *out = *in + in.Source.DeepCopyInto(&out.Source) if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]DataSourceCondition, len(*in)) diff --git a/tests/datasource_test.go b/tests/datasource_test.go index dcc2c37142..b98d1d9bc3 100644 --- a/tests/datasource_test.go +++ b/tests/datasource_test.go @@ -130,4 +130,27 @@ var _ = Describe("DataSource", func() { ds1 = waitForReadyCondition(ds1, corev1.ConditionFalse, "NotFound") ds2 = waitForReadyCondition(ds2, corev1.ConditionFalse, "NotFound") }) + + It("status conditions timestamp should be updated when DataSource referred pvc is updated, although condition status does not change", func() { + createDv(pvc1Name, testUrl()) + ds := createDs(ds1Name, pvc1Name) + ds = waitForReadyCondition(ds, corev1.ConditionTrue, "Ready") + cond := controller.FindDataSourceConditionByType(ds, cdiv1.DataSourceReady) + Expect(cond).ToNot(BeNil()) + ts := cond.LastTransitionTime + + createDv(pvc2Name, testUrl()) + err := utils.WaitForDataVolumePhase(f, f.Namespace.Name, cdiv1.Succeeded, pvc2Name) + Expect(err).ToNot(HaveOccurred()) + updateDsPvc(ds, pvc2Name) + + Eventually(func() metav1.Time { + ds, err = f.CdiClient.CdiV1beta1().DataSources(ds.Namespace).Get(context.TODO(), ds.Name, metav1.GetOptions{}) + Expect(ds.Spec.Source.PVC.Name).To(Equal(pvc2Name)) + cond = controller.FindDataSourceConditionByType(ds, cdiv1.DataSourceReady) + Expect(cond).ToNot(BeNil()) + Expect(cond.Status).To(Equal(corev1.ConditionTrue)) + return cond.LastTransitionTime + }, 60*time.Second, pollingInterval).ShouldNot(Equal(ts)) + }) })