Skip to content

Commit

Permalink
Add DataImportCron status conditions (#2045)
Browse files Browse the repository at this point in the history
* Add DataImportCron status conditions

The `DataImportCron` controller updates the status conditions in a
controlled `DataImportCron` and its managed `DataSource`.

DataImportCron:
- UpToDate - indicates if the the most recent import is successful and
    `DataSource` is up-to-date. Updated to False whenever the source
     digest (latest sha256) is updated.
- Progressing - indicates whether the cron is currently in the process
    of importing. Updated to True if there is a current import and its
    `DataVolume` is `ImportInProgress`, otherwise False.

DataSource:
- Ready - indicates that the corresponding pvc exists and is populated.
    Update according to `DataImportCron.Status.LastImportedPVC`
    `DataVolume`'s `DataVolumeReady` condition, if the `DataVolume`
    exists. Otherwise False. Unlike `DataImportCron` `UpToDate`
    condition, this one does not care about newer source digest.

Signed-off-by: Arnon Gilboa <[email protected]>

* CR fixes

Signed-off-by: Arnon Gilboa <[email protected]>

* Add DataImportCron RetentionPolicy and remove OwnerReferences

Signed-off-by: Arnon Gilboa <[email protected]>

* More CR fixes

Signed-off-by: Arnon Gilboa <[email protected]>

* Add tests for retention policies and datasource/datavolume recreation if deleted

Signed-off-by: Arnon Gilboa <[email protected]>

* Add status condition tests

Signed-off-by: Arnon Gilboa <[email protected]>

* SetRecommendedLabels for all created CRs

Signed-off-by: Arnon Gilboa <[email protected]>
  • Loading branch information
arnongilboa authored Dec 16, 2021
1 parent cea6680 commit fe018f1
Show file tree
Hide file tree
Showing 13 changed files with 527 additions and 208 deletions.
2 changes: 1 addition & 1 deletion cmd/cdi-controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func start(ctx context.Context, cfg *rest.Config) {
os.Exit(1)
}

if _, err := controller.NewDataImportCronController(mgr, log, importerImage, pullPolicy); err != nil {
if _, err := controller.NewDataImportCronController(mgr, log, importerImage, pullPolicy, installerLabels); err != nil {
klog.Errorf("Unable to setup dataimportcron controller: %v", err)
os.Exit(1)
}
Expand Down
55 changes: 55 additions & 0 deletions pkg/apis/core/v1beta1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const (

// CDIComponentLabel can be added to all CDI resources
CDIComponentLabel = "cdi.kubevirt.io"
// CDIControllerName is the CDI controller name
CDIControllerName = "cdi-controller"

// AppKubernetesPartOfLabel is the Kubernetes recommended part-of label
AppKubernetesPartOfLabel = "app.kubernetes.io/part-of"
Expand Down
1 change: 1 addition & 0 deletions pkg/controller/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go_library(
srcs = [
"clone-controller.go",
"config-controller.go",
"dataimportcron-conditions.go",
"dataimportcron-controller.go",
"datavolume-conditions.go",
"datavolume-controller.go",
Expand Down
89 changes: 89 additions & 0 deletions pkg/controller/dataimportcron-conditions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Copyright 2021 The CDI Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
limitations under the License.
See the License for the specific language governing permissions and
*/

package controller

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
)

const (
noDigest = "NoDigest"
noImport = "NoImport"
outdated = "Outdated"
scheduled = "ImportScheduled"
inProgress = "ImportProgressing"
failed = "ImportFailed"
upToDate = "UpToDate"
ready = "Ready"
)

func updateDataImportCronCondition(cron *cdiv1.DataImportCron, conditionType cdiv1.DataImportCronConditionType, status corev1.ConditionStatus, message, reason string) {
if condition := FindDataImportCronConditionByType(cron, conditionType); condition != nil {
updateConditionState(&condition.ConditionState, status, message, reason)
} else {
condition = &cdiv1.DataImportCronCondition{Type: conditionType}
updateConditionState(&condition.ConditionState, status, message, reason)
cron.Status.Conditions = append(cron.Status.Conditions, *condition)
}
}

// FindDataImportCronConditionByType finds DataImportCronCondition by condition type
func FindDataImportCronConditionByType(cron *cdiv1.DataImportCron, conditionType cdiv1.DataImportCronConditionType) *cdiv1.DataImportCronCondition {
for i, condition := range cron.Status.Conditions {
if condition.Type == conditionType {
return &cron.Status.Conditions[i]
}
}
return nil
}

func updateDataSourceCondition(ds *cdiv1.DataSource, conditionType cdiv1.DataSourceConditionType, status corev1.ConditionStatus, message, reason string) {
if condition := FindDataSourceConditionByType(ds, conditionType); condition != nil {
updateConditionState(&condition.ConditionState, status, message, reason)
} else {
condition = &cdiv1.DataSourceCondition{Type: conditionType}
updateConditionState(&condition.ConditionState, status, message, reason)
ds.Status.Conditions = append(ds.Status.Conditions, *condition)
}
}

// FindDataSourceConditionByType finds DataSourceCondition by condition type
func FindDataSourceConditionByType(ds *cdiv1.DataSource, conditionType cdiv1.DataSourceConditionType) *cdiv1.DataSourceCondition {
for i, condition := range ds.Status.Conditions {
if condition.Type == conditionType {
return &ds.Status.Conditions[i]
}
}
return nil
}

func updateConditionState(condition *cdiv1.ConditionState, status corev1.ConditionStatus, message, reason string) {
conditionStatusUpdated := condition.Status != status
conditionUpdated := conditionStatusUpdated || condition.Message != message || condition.Reason != reason
if conditionUpdated {
now := metav1.Now()
if conditionStatusUpdated {
condition.Status = status
condition.LastTransitionTime = now
}
condition.LastHeartbeatTime = now
condition.Reason = reason
condition.Message = message
}
}
Loading

0 comments on commit fe018f1

Please sign in to comment.