-
Notifications
You must be signed in to change notification settings - Fork 32
OTA-423: Validate route host before creating app #135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import ( | |
| "context" | ||
| "fmt" | ||
| "reflect" | ||
| "regexp" | ||
|
|
||
| "github.com/go-logr/logr" | ||
| conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" | ||
|
|
@@ -28,6 +29,13 @@ import ( | |
| "github.com/openshift/library-go/pkg/route/routeapihelpers" | ||
| ) | ||
|
|
||
| const dns1123LabelFmt string = "^[a-z]([-a-z0-9]*[a-z0-9])?$" | ||
|
|
||
| // DNS1123LabelMaxLength is a label's max length in DNS (RFC 1123) | ||
| const DNS1123LabelMaxLength int = 63 | ||
|
|
||
| var dns1123LabelRegexp = regexp.MustCompile(dns1123LabelFmt) | ||
|
|
||
| var log = logf.Log.WithName("controller_updateservice") | ||
|
|
||
| // blank assignment to verify that ReconcileUpdateService implements reconcile.Reconciler | ||
|
|
@@ -78,6 +86,20 @@ func (r *UpdateServiceReconciler) Reconcile(ctx context.Context, req ctrl.Reques | |
| instanceCopy := instance.DeepCopy() | ||
| instanceCopy.Status = cv1.UpdateServiceStatus{} | ||
|
|
||
| if err := validateRouteName(instanceCopy, req.Name, req.Namespace); err != nil { | ||
| conditionsv1.SetStatusCondition(&instanceCopy.Status.Conditions, conditionsv1.Condition{ | ||
| Type: cv1.ConditionReconcileError, | ||
| Status: corev1.ConditionTrue, | ||
| Reason: "Unable to create UpdateService route", | ||
| Message: err.Error(), | ||
| }) | ||
| if err := r.Client.Status().Update(ctx, instanceCopy); err != nil { | ||
| reqLogger.Error(err, "Failed to update Status") | ||
| } | ||
| reqLogger.Error(err, "Unable to create UpdateService route") | ||
| return ctrl.Result{}, nil | ||
| } | ||
|
|
||
| // 1. Gather conditions | ||
| // Look at the existing cluster resources and communicate to kubeResources | ||
| // how it should create resources. | ||
|
|
@@ -464,6 +486,28 @@ func (r *UpdateServiceReconciler) ensurePolicyEngineService(ctx context.Context, | |
| return nil | ||
| } | ||
|
|
||
| func validateRouteName(instance *cv1.UpdateService, name string, namespace string) error { | ||
| var errReasons []string | ||
| routeName := namePolicyEngineRoute(instance) + "-" + namespace | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some kind of It's going to be a pain to match our operator-side validation with a potentially evolving default route plugin. If we are going to grow opinions like this, perhaps we should set
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't feel strongly that we need to have this precheck so if you and/or Lala are okay with dropping it so am I. With the shortened route name change in here I wouldn't think we'll encounter the >63 issue very often if at all. So it's the cost of maintenance vs. catching the error before the operand is created and thereby eliminating the need for the user to have to delete the operand after route creation failure.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Hmm... Do they even need to delete the operand? I'd expect them to have to delete the UpdateService and create a replacement with a shorter name (unless you're allowed to patch resource names?). And when the old UpdateService goes away, I'd expect our operator to notice and remove the operand and other associated resources we'd been using to fulfill the outgoing UpdateService's request.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this check fails nothing is created so if they could try again with a shorter operand name.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jottofar AFAIU this check will consider the name given to the route and then validate if the name falls within the 63 character length. To do that it needs to take the namespace length in to account because that's how the route name length is calculated. Is that right?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. Namespace is part of the route name and is out of our control and something that could change. For example, if we created the operand named
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Confirming via a 4.9.0 OpenShift Update Service operator in a So the repair for "the name you picked is too long" will be "notice, delete the UpdateService, and create a replacement with a shorter name". I don't think it's worth jumping through hoops to guess at Route validity, because the upside would be shaving a minute or so off that notice cycle. And the downside is that we need this inlined copy making assumptions about how the cluster will be generating domain names for Routes.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine with dropping the validation piece. It's not how I originally envisioned it anyway. I'll just change this to only include the name shortening change which should reduce/eliminate issue occurrence. |
||
|
|
||
| if len(routeName) > DNS1123LabelMaxLength { | ||
| errReasons = append(errReasons, | ||
| fmt.Sprintf("cannot exceed RFC 1123 maximum length of %d. Shorten the application name and/or namespace.", | ||
| DNS1123LabelMaxLength)) | ||
| } | ||
| if !dns1123LabelRegexp.MatchString(routeName) { | ||
| errReasons = append(errReasons, | ||
| fmt.Sprintf("has invalid format; must comply with %q.", dns1123LabelFmt)) | ||
| } | ||
| numErrors := len(errReasons) | ||
| if numErrors == 0 { | ||
| return nil | ||
| } else if numErrors == 1 { | ||
| return fmt.Errorf(fmt.Sprintf("UpdateService route name %q %s", routeName, errReasons[0])) | ||
| } | ||
| return fmt.Errorf(fmt.Sprintf("UpdateService route name %q %s Route name %s", routeName, errReasons[0], errReasons[1])) | ||
| } | ||
|
|
||
| func (r *UpdateServiceReconciler) ensurePolicyEngineRoute(ctx context.Context, reqLogger logr.Logger, instance *cv1.UpdateService, resources *kubeResources) error { | ||
| route := resources.policyEngineRoute | ||
| // Set UpdateService instance as the owner and controller | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.