Skip to content
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

(c-r v0.2.0) *: bump controller-runtime to v0.2.0, update APIs #1839

Merged
Show file tree
Hide file tree
Changes from 13 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
13 changes: 9 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
- CSV config field `role-path` is now `role-paths` and takes a list of strings. Users can now specify multiple `Role` and `ClusterRole` manifests using `role-paths`. ([#1704](https://github.com/operator-framework/operator-sdk/pull/1704))
- Upgrade Kubernetes version from `kubernetes-1.13.4` to `kubernetes-1.14.1`
- Upgrade `github.com/operator-framework/operator-lifecycle-manager` version from `b8a4faf68e36feb6d99a6aec623b405e587b17b1` to `0.10.1`
- Upgrade [`controller-runtime`](https://github.com/kubernetes-sigs/controller-runtime) version from `v0.1.12` to `v0.2.0-beta.3`
- Upgrade [`controller-runtime`](https://github.com/kubernetes-sigs/controller-runtime) version from `v0.1.12` to `v0.2.0`
- The package `sigs.k8s.io/controller-runtime/pkg/runtime/scheme` is deprecated, and contains no code. Replace this import with `sigs.k8s.io/controller-runtime/pkg/scheme` where relevant.
- The package `sigs.k8s.io/controller-runtime/pkg/runtime/log` is deprecated. Replace this import with `sigs.k8s.io/controller-runtime/pkg/log` where relevant.
- The package `sigs.k8s.io/controller-runtime/pkg/runtime/signals` is deprecated. Replace this import with `sigs.k8s.io/controller-runtime/pkg/manager/signals` where relevant.
- [`sigs.k8s.io/controller-runtime/pkg/client.Client`](https://github.com/kubernetes-sigs/controller-runtime/blob/aaddbd9d9a89d8ff329a084aece23be0406e6467/pkg/client/interfaces.go#L101)'s `List()` method signature has been updated: `List(ctx context.Context, opts *client.ListOptions, list runtime.Object) error` is now [`List(ctx context.Context, list runtime.Object, opts ...client.ListOptionFunc) error`](https://github.com/kubernetes-sigs/controller-runtime/blob/aaddbd9d9a89d8ff329a084aece23be0406e6467/pkg/client/interfaces.go#L61). To migrate:
- All methods on [`sigs.k8s.io/controller-runtime/pkg/client.Client`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L104) (except for `Get()`) have been updated. Instead of each using a `struct`-typed or variadic functional option parameter, or having no option parameter, each now uses a variadic interface option parameter typed for each method. See `List()` below for an example.
- [`sigs.k8s.io/controller-runtime/pkg/client.Client`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L104)'s `List()` method signature has been updated: `List(ctx context.Context, opts *client.ListOptions, list runtime.Object) error` is now [`List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L61). To migrate:
estroz marked this conversation as resolved.
Show resolved Hide resolved
```go
import (
"context"
Expand All @@ -30,11 +31,15 @@

...

listOpts := &client.ListOptions{}
// Old
listOpts := &client.ListOptions{}
listOpts.InNamespace("namespace")
err = r.client.List(context.TODO(), listOps, podList)
// New
err = r.client.List(context.TODO(), podList, client.UseListOptions(listOps))
listOpts := []client.ListOption{
client.InNamespace("namespace"),
}
err = r.client.List(context.TODO(), podList, listOpts...)
```
- CRD file names were previously of the form `<group>_<version>_<kind>_crd.yaml`. Now that CRD manifest `spec.version` is deprecated in favor of `spec.versions`, i.e. multiple versions can be specified in one CRD, CRD file names have the form `<full group>_<resource>_crd.yaml`. `<full group>` is the full group name of your CRD while `<group>` is the last subdomain of `<full group>`, ex. `foo.bar.com` vs `foo`. `<resource>` is the plural lower-case CRD Kind found at `spec.names.plural`.

Expand Down
177 changes: 108 additions & 69 deletions doc/user/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,32 +134,10 @@ func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, e
```Go
// List retrieves a list of objects for a given namespace and list options
// and stores the list in obj.
func (c Client) List(ctx context.Context, list runtime.Object, opts ...client.ListOptionFunc) error
func (c Client) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error
```

A `client.ListOptionFunc` can be created either by using the provided [functional options](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#ListOptionFunc) or using `client.ListOptions`:

```Go
type ListOptions struct {
// LabelSelector filters results by label. Use SetLabelSelector to
// set from raw string form.
LabelSelector labels.Selector

// FieldSelector filters results by a particular field. In order
// to use this with cache-based implementations, restrict usage to
// a single field-value pair that's been added to the indexers.
FieldSelector fields.Selector

// Namespace represents the namespace to list for, or empty for
// non-namespaced objects, or to list across all namespaces.
Namespace string

// Raw represents raw ListOptions, as passed to the API server. Note
// that these may not be respected by all implementations of interface,
// and the LabelSelector and FieldSelector fields are ignored.
Raw *metav1.ListOptions
}
```
A `client.ListOption` is an interface that sets [`client.ListOptions`][list-options] fields. A `client.ListOption` is created by using one of the provided implementations: [`MatchingLabels`][matchinglabels], [`MatchingFields`][matchingfields], [`InNamespace`][innamespace].
estroz marked this conversation as resolved.
Show resolved Hide resolved

Example:

Expand All @@ -176,26 +154,37 @@ func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, e
...

// Return all pods in the request namespace with a label of `app=<name>`
opts := &client.ListOptions{}
opts.SetLabelSelector(fmt.Sprintf("app=%s", request.NamespacedName.Name))
opts.InNamespace(request.NamespacedName.Namespace)

// and phase `Running`.
podList := &v1.PodList{}
opts := []client.ListOption{
client.InNamespace(request.NamespacedName.Namespace),
client.MatchingLabels{"app", request.NamespacedName.Name},
client.MatchingFields{"status.phase": "Running"},
}
ctx := context.TODO()
err := r.client.List(ctx, podList, client.UseListOptions(listOps))
err := r.client.List(ctx, podList, opts...)

...
}
```

[list-options]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#ListOptions
[matchinglabels]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#MatchingLabels
[matchingfields]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#MatchingFields
[innamespace]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#InNamespace

#### Create

```Go
// Create saves the object obj in the Kubernetes cluster.
// Returns an error
func (c Client) Create(ctx context.Context, obj runtime.Object) error
func (c Client) Create(ctx context.Context, obj runtime.Object, opts ...client.CreateOption) error
```

A `client.CreateOption` is an interface that sets [`client.CreateOptions`][create-options] fields. A `client.CreateOption` is created by using one of the provided implementations: [`DryRunAll`][dryrunall], [`ForceOwnership`][forceownership]. Generally these options are not needed.
estroz marked this conversation as resolved.
Show resolved Hide resolved

Example:

```Go
import (
"context"
Expand All @@ -216,16 +205,22 @@ func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, e
}
```

[create-options]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#CreateOptions

#### Update

```Go
// Update updates the given obj in the Kubernetes cluster. obj must be a
// struct pointer so that obj can be updated with the content returned
// by the API server. Update does *not* update the resource's status
// subresource
func (c Client) Update(ctx context.Context, obj runtime.Object) error
func (c Client) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOption) error
```

A `client.UpdateOption` is an interface that sets [`client.UpdateOptions`][update-options] fields. A `client.UpdateOption` is created by using one of the provided implementations: [`DryRunAll`][dryrunall], [`ForceOwnership`][forceownership]. Generally these options are not needed.

Example:

```Go
import (
"context"
Expand All @@ -249,10 +244,54 @@ func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, e
}
```

[update-options]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#UpdateOptions

#### Patch

```Go
// Patch patches the given obj in the Kubernetes cluster. obj must be a
// struct pointer so that obj can be updated with the content returned by the Server.
func (c Client) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.UpdateOption) error
```

A `client.PatchOption` is an interface that sets [`client.PatchOptions`][patch-options] fields. A `client.PatchOption` is created by using one of the provided implementations: [`DryRunAll`][dryrunall], [`ForceOwnership`][forceownership]. Generally these options are not needed.

Example:

```Go
import (
"context"
"k8s.io/api/apps/v1"
estroz marked this conversation as resolved.
Show resolved Hide resolved
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, error) {
...

dep := &v1.Deployment{}
err := r.client.Get(context.TODO(), request.NamespacedName, dep)

...

ctx := context.TODO()
dep.Spec.Selector.MatchLabels["is_running"] = "true"
// A merge patch will preserve other fields modified at runtime.
patch := client.MergeFrom(dep)
err := r.client.Patch(ctx, dep, patch)

...
}
```

[patch-options]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#PatchOption
[dryrunall]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#DryRunAll
[forceownership]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#ForceOwnership

##### Updating Status Subresource

When updating the [status subresource][cr-status-subresource] from the client,
the StatusWriter must be used which can be gotten with `Status()`
When updating the [status subresource][cr-status-subresource] from the client, the [`StatusWriter`][statuswriter] must be used. The status subresource is retrieved with `Status()` and updated with `Update()` or patched with `Patch()`.

`Update()` takes variadic `client.UpdateOption`'s, and `Patch()` takes variadic `client.PatchOption`'s. See [`Client.Update()`](#update) and [`Client.Patch()`](#patch) for more details. Generally these options are not needed.

##### Status

Expand All @@ -273,57 +312,39 @@ import (
func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, error) {
...

ctx := context.TODO()
mem := &cachev1alpha1.Memcached{}
err := r.client.Get(context.TODO(), request.NamespacedName, mem)
err := r.client.Get(ctx, request.NamespacedName, mem)

...

ctx := context.TODO()
// Update
mem.Status.Nodes = []string{"pod1", "pod2"}
err := r.client.Status().Update(ctx, mem)

...

// Patch
patch := client.MergeFrom(mem)
err := r.client.Status().Patch(ctx, mem, patch)

...
}
```

[statuswriter]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#StatusWriter
estroz marked this conversation as resolved.
Show resolved Hide resolved

#### Delete

```Go
// Delete deletes the given obj from Kubernetes cluster.
func (c Client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error
```
A `client.DeleteOptionFunc` sets fields of `client.DeleteOptions` to configure a `Delete` call:
```Go
// DeleteOptionFunc is a function that mutates a DeleteOptions struct.
type DeleteOptionFunc func(*DeleteOptions)

type DeleteOptions struct {
// GracePeriodSeconds is the duration in seconds before the object should be
// deleted. Value must be non-negative integer. The value zero indicates
// delete immediately. If this value is nil, the default grace period for the
// specified type will be used.
GracePeriodSeconds *int64

// Preconditions must be fulfilled before a deletion is carried out. If not
// possible, a 409 Conflict status will be returned.
Preconditions *metav1.Preconditions

// PropagationPolicy determined whether and how garbage collection will be
// performed. Either this field or OrphanDependents may be set, but not both.
// The default policy is decided by the existing finalizer set in the
// metadata.finalizers and the resource-specific default policy.
// Acceptable values are: 'Orphan' - orphan the dependents; 'Background' -
// allow the garbage collector to delete the dependents in the background;
// 'Foreground' - a cascading policy that deletes all dependents in the
// foreground.
PropagationPolicy *metav1.DeletionPropagation

// Raw represents raw DeleteOptions, as passed to the API server.
Raw *metav1.DeleteOptions
}
func (c Client) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteOption) error
```

A `client.DeleteOption` is an interface that sets [`client.DeleteOptions`][delete-opts] fields. A `client.DeleteOption` is created by using one of the provided implementations: [`GracePeriodSeconds`][graceperiodseconds], [`Preconditions`][preconditions], [`PropagationPolicy`][propagationpolicy].

Example:

```Go
import (
"context"
Expand Down Expand Up @@ -351,6 +372,22 @@ func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, e
}
```

[delete-opts]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#DeleteOptions
[graceperiodseconds]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#GracePeriodSeconds
[preconditions]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#Preconditions
[propagationpolicy]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#PropagationPolicy

#### Delete
estroz marked this conversation as resolved.
Show resolved Hide resolved

```Go
// DeleteAllOf deletes all objects of the given type matching the given options.
func (c Client) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteAllOfOption) error
estroz marked this conversation as resolved.
Show resolved Hide resolved
```

A `client.DeleteAllOfOption` is an interface that sets [`client.DeleteAllOfOptions`][deleteallof-opts] fields. A `client.DeleteAllOfOption` wraps a [`client.ListOption`](#list) and [`client.DeleteOption`](#delete).

estroz marked this conversation as resolved.
Show resolved Hide resolved
[deleteallof-opts]:https://godoc.org/sigs.k8s.io/controller-runtime/pkg/client#DeleteAllOfOptions

### Example usage

```Go
Expand Down Expand Up @@ -418,9 +455,11 @@ func (r *ReconcileApp) Reconcile(request reconcile.Request) (reconcile.Result, e
// Update the App status with the pod names.
// List the pods for this app's deployment.
podList := &corev1.PodList{}
labelSelector := labels.SelectorFromSet(labelsForApp(app.Name))
listOps := &client.ListOptions{Namespace: app.Namespace, LabelSelector: labelSelector}
if err = r.client.List(context.TODO(), podList, client.UseListOptions(listOps)); err != nil {
listOpts := []client.ListOption{
client.InNamespace(app.Namespace),
client.MatchingLabels(labelsForApp(app.Name)),
}
if err = r.client.List(context.TODO(), podList, listOpts...); err != nil {
return reconcile.Result{}, err
}

Expand Down
10 changes: 5 additions & 5 deletions example/memcached-operator/memcached_controller.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -142,10 +141,11 @@ func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Res
// Update the Memcached status with the pod names
// List the pods for this memcached's deployment
podList := &corev1.PodList{}
labelSelector := labels.SelectorFromSet(labelsForMemcached(memcached.Name))
listOps := &client.ListOptions{Namespace: memcached.Namespace, LabelSelector: labelSelector}
err = r.client.List(context.TODO(), podList, client.UseListOptions(listOps))
if err != nil {
listOpts := []client.ListOption{
client.InNamespace(memcached.Namespace),
client.MatchingLabels(labelsForMemcached(memcached.Name)),
}
if err = r.client.List(context.TODO(), podList, listOpts...); err != nil {
reqLogger.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name)
return reconcile.Result{}, err
}
Expand Down
11 changes: 5 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.12

require (
cloud.google.com/go v0.37.2 // indirect
contrib.go.opencensus.io/exporter/ocagent v0.4.11 // indirect
contrib.go.opencensus.io/exporter/ocagent v0.4.12 // indirect
github.com/Azure/go-autorest v11.7.0+incompatible // indirect
github.com/DATA-DOG/go-sqlmock v1.3.3 // indirect
github.com/MakeNowJust/heredoc v0.0.0-20171113091838-e9091a26100e // indirect
Expand All @@ -27,6 +27,7 @@ require (
github.com/go-logr/logr v0.1.0
github.com/go-logr/zapr v0.1.1
github.com/go-openapi/swag v0.19.0 // indirect
github.com/go-sql-driver/mysql v1.4.1 // indirect
github.com/gobuffalo/packr v1.30.1 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/google/uuid v1.1.1 // indirect
Expand All @@ -50,9 +51,7 @@ require (
github.com/pelletier/go-toml v1.3.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect
github.com/prometheus/procfs v0.0.0-20190403104016-ea9eea638872 // indirect
github.com/prometheus/client_golang v0.9.3
github.com/rogpeppe/go-internal v1.3.0
github.com/rubenv/sql-migrate v0.0.0-20190618074426-f4d34eae5a5c // indirect
github.com/sergi/go-diff v1.0.0
Expand All @@ -72,6 +71,7 @@ require (
go.uber.org/zap v1.10.0
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a // indirect
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c
google.golang.org/api v0.3.2 // indirect
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 // indirect
gopkg.in/gorp.v1 v1.7.2 // indirect
gopkg.in/square/go-jose.v2 v2.3.0 // indirect
Expand All @@ -89,7 +89,7 @@ require (
k8s.io/kube-openapi v0.0.0-20190401085232-94e1e7b7574c
k8s.io/kube-state-metrics v1.6.0
k8s.io/kubernetes v1.14.2
sigs.k8s.io/controller-runtime v0.2.0-beta.3
sigs.k8s.io/controller-runtime v0.2.0
sigs.k8s.io/controller-tools v0.2.0
sigs.k8s.io/kustomize v2.0.3+incompatible // indirect
vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787 // indirect
Expand All @@ -114,5 +114,4 @@ replace (
github.com/operator-framework/operator-lifecycle-manager => github.com/operator-framework/operator-lifecycle-manager v0.0.0-20190605231540-b8a4faf68e36
k8s.io/helm => k8s.io/helm v2.14.1+incompatible
k8s.io/kube-state-metrics => k8s.io/kube-state-metrics v1.6.0
sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.2.0-beta.3
)
Loading