diff --git a/pkg/cmd/infra/router/router.go b/pkg/cmd/infra/router/router.go index ce79bdb38..c758cd217 100644 --- a/pkg/cmd/infra/router/router.go +++ b/pkg/cmd/infra/router/router.go @@ -70,6 +70,9 @@ type RouterSelection struct { UpgradeValidation bool + UpgradeValidationForceAddCondition bool + UpgradeValidationForceRemoveCondition bool + ListenAddr string // WatchEndpoints when true will watch Endpoints instead of @@ -98,6 +101,8 @@ func (o *RouterSelection) Bind(flag *pflag.FlagSet) { flag.BoolVar(&o.DisableNamespaceOwnershipCheck, "disable-namespace-ownership-check", isTrue(env("ROUTER_DISABLE_NAMESPACE_OWNERSHIP_CHECK", "")), "Disables the namespace ownership checks for a route host with different paths or for overlapping host names in the case of wildcard routes. Please be aware that if namespace ownership checks are disabled, routes in a different namespace can use this mechanism to 'steal' sub-paths for existing domains. This is only safe if route creation privileges are restricted, or if all the users can be trusted.") flag.BoolVar(&o.ExtendedValidation, "extended-validation", isTrue(env("EXTENDED_VALIDATION", "true")), "If set, then an additional extended validation step is performed on all routes processed by this router. Defaults to true and enables the extended validation checks.") flag.BoolVar(&o.UpgradeValidation, "upgrade-validation", isTrue(env("UPGRADE_VALIDATION", "true")), "If set, then an additional upgrade validation step is performed on all routes processed by this router. Defaults to true and enables the upgrade validation checks.") + flag.BoolVar(&o.UpgradeValidationForceAddCondition, "debug-upgrade-validation-force-add-condition", isTrue(env("DEBUG_UPGRADE_VALIDATION_FORCE_ADD_CONDITION", "")), "If set, then the upgrade validation plugin will forcibly add the UnservableInFutureVersions condition. For testing purposes only.") + flag.BoolVar(&o.UpgradeValidationForceRemoveCondition, "debug-upgrade-validation-force-remove-condition", isTrue(env("DEBUG_UPGRADE_VALIDATION_FORCE_REMOVE_CONDITION", "")), "If set, then the upgrade validation plugin will forcibly remove the UnservableInFutureVersions condition. For testing purposes only.") flag.Bool("enable-ingress", false, "Enable configuration via ingress resources.") flag.MarkDeprecated("enable-ingress", "Ingress resources are now synchronized to routes automatically.") flag.StringVar(&o.ListenAddr, "listen-addr", env("ROUTER_LISTEN_ADDR", ""), "The name of an interface to listen on to expose metrics and health checking. If not specified, will not listen. Overrides stats port.") diff --git a/pkg/cmd/infra/router/template.go b/pkg/cmd/infra/router/template.go index 3b929709e..d92ae7060 100644 --- a/pkg/cmd/infra/router/template.go +++ b/pkg/cmd/infra/router/template.go @@ -799,7 +799,7 @@ func (o *TemplateRouterOptions) Run(stopCh <-chan struct{}) error { plugin = status } if o.UpgradeValidation { - plugin = controller.NewUpgradeValidation(plugin, recorder) + plugin = controller.NewUpgradeValidation(plugin, recorder, o.UpgradeValidationForceAddCondition, o.UpgradeValidationForceRemoveCondition) } if o.ExtendedValidation { plugin = controller.NewExtendedValidator(plugin, recorder) diff --git a/pkg/router/controller/upgrade_validation.go b/pkg/router/controller/upgrade_validation.go index dbed9d31a..3996c563a 100644 --- a/pkg/router/controller/upgrade_validation.go +++ b/pkg/router/controller/upgrade_validation.go @@ -2,7 +2,6 @@ package controller import ( kapi "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/watch" @@ -19,16 +18,24 @@ type UpgradeValidation struct { // recorder is an interface for indicating route status. recorder RouteStatusRecorder + + // forceAddCondition indicates the plugin should forcibly add the condition. + forceAddCondition bool + + // forceRemoveCondition indicates the plugin should forcibly remove the condition. + forceRemoveCondition bool } // NewUpgradeValidation creates a plugin wrapper that validates for upgrades // and adds an UnservableInFutureVersions status if needed. It does not stop // the plugin chain if the route is unservable in future versions. // Recorder is an interface for indicating routes status update. -func NewUpgradeValidation(plugin router.Plugin, recorder RouteStatusRecorder) *UpgradeValidation { +func NewUpgradeValidation(plugin router.Plugin, recorder RouteStatusRecorder, forceAddCondition, forceRemoveCondition bool) *UpgradeValidation { return &UpgradeValidation{ - plugin: plugin, - recorder: recorder, + plugin: plugin, + recorder: recorder, + forceAddCondition: forceAddCondition, + forceRemoveCondition: forceRemoveCondition, } } @@ -47,6 +54,18 @@ func (p *UpgradeValidation) HandleEndpoints(eventType watch.EventType, endpoints // and sets UnservableInFutureVersions condition if needed. func (p *UpgradeValidation) HandleRoute(eventType watch.EventType, route *routev1.Route) error { routeName := routeNameKey(route) + + // Force add and force removal logic for debugging and testing. + if p.forceAddCondition { + log.Info("force adding UnservableInFutureVersions condition in upgrade validation", "conditionType", p.forceRemoveCondition, "route", routeName) + p.recorder.RecordRouteUnservableInFutureVersions(route, "ForceUpgradeValidationCondition", "forced upgrade validation condition") + return p.plugin.HandleRoute(eventType, route) + } else if p.forceRemoveCondition { + log.Info("force removing UnservableInFutureVersions condition in upgrade validation", "conditionType", p.forceRemoveCondition, "route", routeName) + p.recorder.RecordRouteUnservableInFutureVersionsClear(route) + return p.plugin.HandleRoute(eventType, route) + } + if err := routeapihelpers.UpgradeRouteValidation(route).ToAggregate(); err != nil { log.Error(err, "route failed upgrade validation", "route", routeName) p.recorder.RecordRouteUnservableInFutureVersions(route, "UpgradeRouteValidationFailed", err.Error()) diff --git a/pkg/router/template/plugin_test.go b/pkg/router/template/plugin_test.go index e520ef8d0..f84477484 100644 --- a/pkg/router/template/plugin_test.go +++ b/pkg/router/template/plugin_test.go @@ -1099,7 +1099,7 @@ func TestHandleRouteExtendedValidation(t *testing.T) { func TestHandleRouteUpgradeValidation(t *testing.T) { rejections := &fakeStatusRecorder{} fake := &fakePlugin{} - plugin := controller.NewUpgradeValidation(fake, rejections) + plugin := controller.NewUpgradeValidation(fake, rejections, false, false) tests := []struct { name string