Skip to content
This repository has been archived by the owner on Feb 27, 2023. It is now read-only.

Initial Contour Controller Implementation #10

Merged
merged 1 commit into from
Sep 2, 2020

Conversation

danehans
Copy link
Contributor

@danehans danehans commented Sep 1, 2020

  • Moves main() to cmd/operator pkg. cmd/operator/start.go : Exposes a flag to set the Contour image used by the operator.
  • Singularizes the controller pkg.
  • controller/contour/controller.go: Initial controller implementation that watches the contour CRD and a) finalizes the resource and b) creates the contour namespace if it does not exist.
  • util/retryableerror/retryableerror.go: Utility function for retrying reconciliation errors.
  • util/slice/slice.go: Utility function to check if a given slice of strings contains the provided string.

Signed-off-by: Daneyon Hansen [email protected]

@danehans
Copy link
Contributor Author

danehans commented Sep 1, 2020

/assign @jpeach
/cc @youngnick @Miciah

// so we can clean up later.
if !slice.ContainsString(contour.Finalizers, contourFinalizer) {
updated := contour.DeepCopy()
updated.Finalizers = append(updated.Finalizers, contourFinalizer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The kubebuilder finalizer example suggests checking ObjectMeta.DeletionTimestamp.IsZero() before adding the finalizer; is there a reason to omit that here?


// The contour is safe to process, so ensure current state matches desired state.
desired := true
if err := r.ensureContour(desired, contour); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, and the ensureNamespace below almost suggest a table-driven approach to me, e.f.:

steps:= []func(context.Context, *Reconciler) error {
    EnsureContourFinalizer,
    EnsureContourNamespace,
    ....
}

Not sure if this is a common pattern for this sort of thing though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensureContour is the func that will encapsulate all the lower-level funcs required to ensure dependent resources exist. A mirrored workflow will be created for removing contour and dependent resources. I've been working through the changes and will submit a new commit shortly. The pattern I'm trying to establish is similar to other operators and upstream k8s controllers. I'm open to feedback, so let me know your thoughts after I reviewing my upcoming commit.

"github.com/projectcontour/contour-operator/util/slice"
"k8s.io/apimachinery/pkg/api/errors"

operatorv1alpha1 "github.com/projectcontour/contour-operator/api/v1alpha1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I prefer import in 3 blocks - stdlib, local, vendor. I think that 2 blocks (stdlib, everything else) is the most common approach though, so let's do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm for stdlib, local, vendor. I'll clean up the imports with my upcoming commit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I believe that goimports has a -local flag that may help with this; maybe we can add that to the lint config :)

controller/contour/controller.go Show resolved Hide resolved
}

// ensureContour ensures all necessary resources exist for the given contour.
func (r *Reconciler) ensureContour(desired bool, contour *operatorv1alpha1.Contour) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass the caller context down?

controller/contour/namespace.go Show resolved Hide resolved
util/retryableerror/retryableerror_test.go Show resolved Hide resolved
expectAfter: time.Second * 15,
},
}
for _, test := range tests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use subtests here:

cases := map[string]struct{ ... } { ... }
for name, case := range cases {
   t.Run(name, func(t *testing.T) {
      err := NewMaybeRetryableAggregate(case.errors)
      ...
   }
}

}

// The contour is safe to process, so ensure current state matches desired state.
desired := true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's ok for now, but

  1. passing a bool is harder to read and understand than an enum
  2. teardown probably needs to be done in the reverse order

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I refactored based on #10 (comment).

ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}}
if err := r.Get(context.TODO(), types.NamespacedName{Name: ns.Name}, ns); err != nil {
if !errors.IsNotFound(err) {
return nil, fmt.Errorf("failed to get namespace %s: %v", ns.Name, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't an error if we are tearing down the namespace, though we wold want to update status in that case (maybe just add a TODO here?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack, fixed.

@danehans danehans force-pushed the init_impl branch 2 times, most recently from 15d8223 to 1d13240 Compare September 2, 2020 04:53
@danehans
Copy link
Contributor Author

danehans commented Sep 2, 2020

@jpeach I believe commit e83f7b1 addresses all your feedback except #10 (comment). I've never implemented subtests like you mention. Do you have a Contour example to share or would you mind implementing after this merges so I can learn?

Copy link
Contributor

@jpeach jpeach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jpeach jpeach merged commit aca8831 into projectcontour:main Sep 2, 2020
@danehans danehans deleted the init_impl branch September 2, 2020 18:35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants