Skip to content

Commit

Permalink
POC for floating upgrades using channels
Browse files Browse the repository at this point in the history
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
  • Loading branch information
pierDipi committed Mar 29, 2024
1 parent 8fcfc17 commit fb22dc3
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 200 deletions.
80 changes: 12 additions & 68 deletions hack/lib/serverless.bash
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,26 @@ function ensure_serverless_installed {
# Otherwise, we cannot change log level by configmap.
enable_debug_log

local csv
local channel csv
if [[ "${INSTALL_OLDEST_COMPATIBLE}" == "true" ]]; then
channel="$(metadata.get "olm.channels.list[3]")"
csv="$(metadata.get "upgrade_sequence[0].csv")"
OLM_SOURCE=redhat-operators
elif [[ "${INSTALL_PREVIOUS_VERSION}" == "true" ]]; then
channel="$(metadata.get "olm.channels.list[2]")"
csv="$PREVIOUS_CSV"
else
channel="$(metadata.get "olm.channels.list[1]")"
csv="$CURRENT_CSV"
fi

# Remove installplan from previous installations, leaving this would make the operator
# upgrade to the latest version immediately
if [[ "$csv" != "$CURRENT_CSV" ]]; then
remove_installplan "$CURRENT_CSV"
fi

logger.info "Installing Serverless version $csv"
logger.info "Installing Serverless version $channel"

deploy_serverless_operator "$csv"
deploy_serverless_operator "$channel"

install_knative_resources "${csv#serverless-operator.v}"

logger.success "Serverless is installed: $csv"
logger.success "Serverless is installed: $channel"
}

function install_knative_resources {
Expand Down Expand Up @@ -68,26 +65,14 @@ function install_knative_resources {
fi
}

function remove_installplan {
local install_plan csv
csv="${1:?Pass a CSV as arg[1]}"
logger.info "Removing installplan for $csv"
install_plan=$(find_install_plan "$csv")
if [[ -n $install_plan ]]; then
oc delete "$install_plan" -n "${OPERATORS_NAMESPACE}"
else
logger.debug "No install plan for $csv"
fi
}

function deploy_serverless_operator_latest {
deploy_serverless_operator "$CURRENT_CSV"
deploy_serverless_operator "${OLM_UPGRADE_CHANNEL}"
}

function deploy_serverless_operator {
local csv tmpfile
csv="${1:?Pass as CSV as arg[1]}"
logger.info "Install the Serverless Operator: ${csv}"
local channel tmpfile
channel="${1:?Pass a channel as arg[1]}"
logger.info "Install the Serverless Operator: ${channel}"
tmpfile=$(mktemp /tmp/subscription.XXXXXX.yaml)
cat > "$tmpfile" <<EOF
apiVersion: operators.coreos.com/v1alpha1
Expand All @@ -96,54 +81,13 @@ metadata:
name: "${OPERATOR}"
namespace: "${OPERATORS_NAMESPACE}"
spec:
channel: "${OLM_CHANNEL}"
channel: "${channel}"
name: "${OPERATOR}"
source: "${OLM_SOURCE}"
sourceNamespace: "${OLM_NAMESPACE}"
installPlanApproval: Manual
startingCSV: "${csv}"
EOF
[ -n "$OPENSHIFT_CI" ] && cat "$tmpfile"
oc apply -f "$tmpfile"

# Approve the initial installplan automatically
approve_csv "$csv" "$OLM_CHANNEL"
}

function approve_csv {
local csv_version install_plan channel
csv_version=${1:?Pass a CSV as arg[1]}
channel=${2:?Pass channel as arg[2]}

logger.info 'Ensure channel and source is set properly'
oc patch subscriptions.operators.coreos.com "$OPERATOR" -n "${OPERATORS_NAMESPACE}" \
--type 'merge' \
--patch '{"spec": {"channel": "'"${channel}"'", "source": "'"${OLM_SOURCE}"'"}}'

logger.info 'Wait for the installplan to be available'
timeout 900 "[[ -z \$(find_install_plan ${csv_version}) ]]"

install_plan=$(find_install_plan "${csv_version}")
oc patch "$install_plan" -n "${OPERATORS_NAMESPACE}" \
--type merge --patch '{"spec":{"approved":true}}'

if ! timeout 300 "[[ \$(oc get ClusterServiceVersion $csv_version -n ${OPERATORS_NAMESPACE} -o jsonpath='{.status.phase}') != Succeeded ]]" ; then
oc get ClusterServiceVersion "$csv_version" -n "${OPERATORS_NAMESPACE}" -o yaml || true
return 105
fi
}

function find_install_plan {
local csv="${1:-Pass a CSV as arg[1]}"
for plan in $(oc get installplan -n "${OPERATORS_NAMESPACE}" --no-headers -o name); do
if [[ $(oc get "$plan" -n "${OPERATORS_NAMESPACE}" -o=jsonpath='{.spec.clusterServiceVersionNames}' | grep -c "$csv") -eq 1 && \
$(oc get "$plan" -n "${OPERATORS_NAMESPACE}" -o=jsonpath="{.status.bundleLookups[0].catalogSourceRef.name}" | grep -c "$OLM_SOURCE") -eq 1 ]]
then
echo "$plan"
return 0
fi
done
echo ""
}

function deploy_knativeserving_cr {
Expand Down
7 changes: 4 additions & 3 deletions hack/lib/vars.bash
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ export UPGRADE_OCP_IMAGE="${UPGRADE_OCP_IMAGE:-}"
export INSTALL_PREVIOUS_VERSION="${INSTALL_PREVIOUS_VERSION:-"false"}"
export INSTALL_OLDEST_COMPATIBLE="${INSTALL_OLDEST_COMPATIBLE:-"false"}"

OLM_CHANNEL="${OLM_CHANNEL:-$(metadata.get olm.channels.default)}"
export OLM_CHANNEL
OLM_PREVIOUS_CHANNEL="${OLM_PREVIOUS_CHANNEL:-$(metadata.get olm.channels.list[2])}"
export OLM_PREVIOUS_CHANNEL
# Change this when upgrades need switching to a different channel
export OLM_UPGRADE_CHANNEL="${OLM_UPGRADE_CHANNEL:-"$OLM_CHANNEL"}"
OLM_UPGRADE_CHANNEL="${OLM_UPGRADE_CHANNEL:-$(metadata.get olm.channels.list[1])}"
export OLM_UPGRADE_CHANNEL
export OLM_SOURCE="${OLM_SOURCE:-"$OPERATOR"}"
export TEST_KNATIVE_UPGRADE="${TEST_KNATIVE_UPGRADE:-true}"
export TEST_KNATIVE_E2E="${TEST_KNATIVE_E2E:-true}"
Expand Down
59 changes: 0 additions & 59 deletions test/installplan.go

This file was deleted.

10 changes: 4 additions & 6 deletions test/lib.bash
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function serverless_operator_e2e_tests {
fi

go_test_e2e -tags=e2e "${RUN_FLAGS[@]}" ./test/e2e \
--channel "$OLM_CHANNEL" \
--channel "$OLM_UPGRADE_CHANNEL" \
--kubeconfigs "${kubeconfigs_str}" \
--imagetemplate "${IMAGE_TEMPLATE}" \
"$@"
Expand All @@ -111,7 +111,7 @@ function serverless_operator_kafka_e2e_tests {
fi

go_test_e2e -tags=e2e "${RUN_FLAGS[@]}" ./test/e2ekafka \
--channel "$OLM_CHANNEL" \
--channel "$OLM_UPGRADE_CHANNEL" \
--kubeconfigs "${kubeconfigs_str}" \
--imagetemplate "${IMAGE_TEMPLATE}" \
"$@"
Expand Down Expand Up @@ -419,7 +419,7 @@ EOF
"--imagetemplate=${image_template}" \
"--images.producer.file=${images_file}" \
"--catalogsource=${OLM_SOURCE}" \
"--channel=${OLM_CHANNEL}" \
"--channel=${OLM_PREVIOUS_CHANNEL}" \
"--upgradechannel=${OLM_UPGRADE_CHANNEL}" \
"--csv=${CURRENT_CSV}" \
"--csvprevious=${PREVIOUS_CSV}" \
Expand Down Expand Up @@ -458,11 +458,9 @@ EOF
oc delete namespace serving-tests
fi
oc create namespace serving-tests
# Make sure the cluster upgrade is run with latest version of Serverless as
# the Serverless upgrade tests leave the product at the previous version (after downgrade).
approve_csv "$CURRENT_CSV" "$OLM_UPGRADE_CHANNEL"
go_test_e2e -run=TestClusterUpgrade -timeout=220m "${common_opts[@]}" \
--openshiftimage="${UPGRADE_OCP_IMAGE}" \
--upgradechannel="${OLM_UPGRADE_CHANNEL}" \
--upgradeopenshift
fi

Expand Down
18 changes: 12 additions & 6 deletions test/subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const (
)

func UpdateSubscriptionChannelSource(ctx *Context, name, channel, source string) (*operatorsv1alpha1.Subscription, error) {
ctx.T.Logf("Updating subscription %s to channel %s and source %s", name, channel, source)

patch := []byte(fmt.Sprintf(`{"spec":{"channel":"%s","source":"%s"}}`, channel, source))
return ctx.Clients.OLM.OperatorsV1alpha1().Subscriptions(OperatorsNamespace).
Patch(context.Background(), name, types.MergePatchType, patch, metav1.PatchOptions{})
Expand Down Expand Up @@ -55,11 +57,15 @@ func DeleteClusterServiceVersion(ctx *Context, name, namespace string) error {
return ctx.Clients.OLM.OperatorsV1alpha1().ClusterServiceVersions(namespace).Delete(context.Background(), name, metav1.DeleteOptions{})
}

func GetSubscription(ctx *Context, name, namespace string) (*operatorsv1alpha1.Subscription, error) {
return ctx.Clients.OLM.OperatorsV1alpha1().Subscriptions(namespace).Get(context.Background(), name, metav1.GetOptions{})
}

func DeleteSubscription(ctx *Context, name, namespace string) error {
return ctx.Clients.OLM.OperatorsV1alpha1().Subscriptions(namespace).Delete(context.Background(), name, metav1.DeleteOptions{})
}

func Subscription(subscriptionName, startingCSV string) *operatorsv1alpha1.Subscription {
func Subscription(subscriptionName, channel string) *operatorsv1alpha1.Subscription {
return &operatorsv1alpha1.Subscription{
TypeMeta: metav1.TypeMeta{
Kind: operatorsv1alpha1.SubscriptionKind,
Expand All @@ -73,15 +79,15 @@ func Subscription(subscriptionName, startingCSV string) *operatorsv1alpha1.Subsc
CatalogSource: Flags.CatalogSource,
CatalogSourceNamespace: OLMNamespace,
Package: ServerlessOperatorPackage,
Channel: Flags.Channel,
InstallPlanApproval: operatorsv1alpha1.ApprovalManual,
StartingCSV: startingCSV,
Channel: channel,
},
}
}

func CreateSubscription(ctx *Context, name, startingCSV string) (*operatorsv1alpha1.Subscription, error) {
subs, err := ctx.Clients.OLM.OperatorsV1alpha1().Subscriptions(OperatorsNamespace).Create(context.Background(), Subscription(name, startingCSV), metav1.CreateOptions{})
func CreateSubscription(ctx *Context, name, channel string) (*operatorsv1alpha1.Subscription, error) {
ctx.T.Logf("Creating subscription %s with channel %s", name, channel)

subs, err := ctx.Clients.OLM.OperatorsV1alpha1().Subscriptions(OperatorsNamespace).Create(context.Background(), Subscription(name, channel), metav1.CreateOptions{})
if err != nil {
return nil, err
}
Expand Down
62 changes: 13 additions & 49 deletions test/upgrade/installation/serverless.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,28 @@ package installation
import (
"context"
_ "embed"
"errors"
"fmt"
"os/exec"
"strings"
"time"

"github.com/openshift-knative/serverless-operator/openshift-knative-operator/pkg/common"
"github.com/openshift-knative/serverless-operator/test"
"github.com/openshift-knative/serverless-operator/test/v1alpha1"
"github.com/openshift-knative/serverless-operator/test/v1beta1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/retry"
)

const (
DefaultInstallPlanTimeout = 15 * time.Minute
"github.com/openshift-knative/serverless-operator/openshift-knative-operator/pkg/common"
"github.com/openshift-knative/serverless-operator/test"
"github.com/openshift-knative/serverless-operator/test/v1alpha1"
"github.com/openshift-knative/serverless-operator/test/v1beta1"
)

//go:embed downgrade.sh
var downgradeContractScript string

func UpgradeServerlessTo(ctx *test.Context, csv, source string, timeout time.Duration) error {
func UpgradeServerlessTo(ctx *test.Context, source string) error {
if _, err := test.UpdateSubscriptionChannelSource(ctx, test.Flags.Subscription, test.Flags.UpgradeChannel, source); err != nil {
return err
}

installPlan, err := test.WaitForInstallPlan(ctx, test.OperatorsNamespace, csv, source, timeout)
if err != nil {
if !errors.Is(err, wait.ErrWaitTimeout) {
return err
}
if source != test.ServerlessOperatorPackage {
// InstallPlan not found in the original catalog source, try the one that was just built.
if _, err := test.UpdateSubscriptionChannelSource(ctx,
test.Flags.Subscription, test.Flags.UpgradeChannel, test.ServerlessOperatorPackage); err != nil {
return err
}
installPlan, err = test.WaitForInstallPlan(ctx,
test.OperatorsNamespace, csv, test.ServerlessOperatorPackage, timeout)
}
if err != nil {
return err
}
}

if err := test.ApproveInstallPlan(ctx, installPlan.Name); err != nil {
return err
}
if _, err := test.WaitForClusterServiceVersionState(ctx, csv, test.OperatorsNamespace, test.IsCSVSucceeded); err != nil {
return err
}

servingInStateFunc := v1beta1.IsKnativeServingWithVersionReady(strings.TrimPrefix(test.Flags.ServingVersion, "v"))
if len(test.Flags.ServingVersion) == 0 {
servingInStateFunc = v1beta1.IsKnativeServingReady
Expand Down Expand Up @@ -99,18 +67,23 @@ func UpgradeServerlessTo(ctx *test.Context, csv, source string, timeout time.Dur
}

func UpgradeServerless(ctx *test.Context) error {
return UpgradeServerlessTo(ctx, test.Flags.CSV, test.Flags.CatalogSource, DefaultInstallPlanTimeout)
return UpgradeServerlessTo(ctx, test.Flags.CatalogSource)
}

func DowngradeServerless(ctx *test.Context) error {
const subscription = "serverless-operator"
crds := []string{"knativeservings.operator.knative.dev", "knativeeventings.operator.knative.dev"}

sub, err := test.GetSubscription(ctx, subscription, test.OperatorsNamespace)
if err != nil {
return err
}

if err := test.DeleteSubscription(ctx, subscription, test.OperatorsNamespace); err != nil {
return err
}

if err := test.DeleteClusterServiceVersion(ctx, test.Flags.CSV, test.OperatorsNamespace); err != nil {
if err := test.DeleteClusterServiceVersion(ctx, sub.Status.InstalledCSV, test.OperatorsNamespace); err != nil {
return err
}

Expand Down Expand Up @@ -158,16 +131,7 @@ func DowngradeServerless(ctx *test.Context) error {
return err
}

if _, err := test.CreateSubscription(ctx, subscription, test.Flags.CSVPrevious); err != nil {
return err
}

installPlan, err := test.WaitForInstallPlan(ctx, test.OperatorsNamespace, test.Flags.CSVPrevious, test.Flags.CatalogSource, DefaultInstallPlanTimeout)
if err != nil {
return err
}

if err := test.ApproveInstallPlan(ctx, installPlan.Name); err != nil {
if _, err := test.CreateSubscription(ctx, subscription, test.Flags.Channel); err != nil {
return err
}

Expand Down
Loading

0 comments on commit fb22dc3

Please sign in to comment.