Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 39 additions & 28 deletions webhook/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (

"github.com/go-logr/logr"
opv1a1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/utils/ptr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -71,19 +70,27 @@ func (r *ClusterServiceVersionDeploymentScaler) Handle(ctx context.Context, req
return admission.Allowed("csv is not managed by ODF")
}

running, err := r.isPreviousCsvHasRunningDeployments(ctx, logger, csv)
if err != nil {
logger.Error(err, "failed getting replicas from csv")
return admission.Errored(http.StatusInternalServerError, fmt.Errorf("failed getting replicas from csv: %v", err))
var isPrevCsvHasRunningDeployments bool
if csv.Spec.Replaces != "" {
prevCsv := &opv1a1.ClusterServiceVersion{}
key := client.ObjectKey{Name: csv.Spec.Replaces, Namespace: csv.Namespace}
if err := r.Client.Get(ctx, key, prevCsv); err != nil {
if client.IgnoreNotFound(err) != nil {
logger.Error(err, "failed to get previous CSV", "csv", csv.Spec.Replaces)
return admission.Errored(http.StatusInternalServerError, fmt.Errorf("failed getting previous csv %q: %w", csv.Spec.Replaces, err))
}
} else {
logger.Info("previous CSV found", "csv", csv.Spec.Replaces)
isPrevCsvHasRunningDeployments = r.isCsvHasRunningDeployments(prevCsv)
r.syncNewCsvWithPrevCsv(prevCsv, csv)
}
}

if running {
logger.Info("ignoring csv as the previous csv deployments are running")
return admission.Allowed("previous csv deployments are running")
if !isPrevCsvHasRunningDeployments {
logger.Info("scaling down deployments")
r.scaleDownCsvDeployments(logger, csv)
}

r.scaleDownCsvDeployments(logger, csv)

marshaledCsv, err := json.Marshal(csv)
if err != nil {
logger.Error(err, "failed marshaling csv")
Expand Down Expand Up @@ -123,35 +130,39 @@ func (r *ClusterServiceVersionDeploymentScaler) loadOdfConfigMapData(ctx context
return nil
}

func (r *ClusterServiceVersionDeploymentScaler) isPreviousCsvHasRunningDeployments(ctx context.Context, logger logr.Logger, csv *opv1a1.ClusterServiceVersion) (bool, error) {
// syncNewCsvWithPrevCsv copies the required fields from the previous csv that are required after upgrade in the new csv
func (r *ClusterServiceVersionDeploymentScaler) syncNewCsvWithPrevCsv(prevCsv *opv1a1.ClusterServiceVersion, newCsv *opv1a1.ClusterServiceVersion) {

if csv.Spec.Replaces == "" {
logger.Info("csv.Spec.Replaces is not populated")
return false, nil
}
prevDeployments := prevCsv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs
newDeployments := newCsv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs

prevCsv := &opv1a1.ClusterServiceVersion{}
key := client.ObjectKey{Name: csv.Spec.Replaces, Namespace: csv.Namespace}
for i := range newDeployments {
newDeployment := &newDeployments[i]

if err := r.Client.Get(ctx, key, prevCsv); errors.IsNotFound(err) {
// new install where an previous csv does not exists
return false, nil
} else if err != nil {
logger.Error(err, "failed getting previous csv")
return false, err
for j := range prevDeployments {
prevDeployment := &prevDeployments[j]

if newDeployment.Name == prevDeployment.Name {
newDeployment.Spec.Template.Spec.HostNetwork = prevDeployment.Spec.Template.Spec.HostNetwork
newDeployment.Spec.Template.Spec.DNSPolicy = prevDeployment.Spec.Template.Spec.DNSPolicy
newDeployment.Spec.Replicas = prevDeployment.Spec.Replicas
break
}
}
}
}

func (r *ClusterServiceVersionDeploymentScaler) isCsvHasRunningDeployments(csv *opv1a1.ClusterServiceVersion) bool {

deployments := prevCsv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs
deployments := csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs
for i := range deployments {
deployment := &deployments[i]
if deployment.Spec.Replicas == nil || *deployment.Spec.Replicas > 0 {
// upgrade case where an older csv is found with replica 1
return true, nil
return true
}
}

// upgrade case where an older csv is found with replica 0
return false, nil
return false
}

func (r *ClusterServiceVersionDeploymentScaler) scaleDownCsvDeployments(logger logr.Logger, csv *opv1a1.ClusterServiceVersion) {
Expand Down
Loading