Skip to content

Rename application package to builder #66

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

Merged
merged 1 commit into from
Jun 29, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
32 changes: 15 additions & 17 deletions pkg/patterns/application/application.go → pkg/builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package application
package builder

import (
"fmt"
Expand Down Expand Up @@ -52,13 +52,18 @@ type Builder struct {
predicates []predicate.Predicate
managedObjects []runtime.Object
config *rest.Config
reconcile reconcile.Reconciler
ctrl controller.Controller
}

// BuilderFor returns a new Builder for and BuilderFor
func BuilderFor(apiType runtime.Object) *Builder {
return &Builder{apiType: apiType}
// SimpleController returns a new Builder
func SimpleController() *Builder {
return &Builder{}
}

// ForType sets the ForType that generates other types
func (b *Builder) ForType(apiType runtime.Object) *Builder {
b.apiType = apiType
return b
}

// Owns configures the Application Controller to respond to create / delete / update events for objects it managedObjects
Expand Down Expand Up @@ -88,16 +93,9 @@ func (b *Builder) WithEventFilter(p predicate.Predicate) *Builder {
return b
}

// WithReconciler sets the Reconcile called in response to create / update / delete events for the
// BuilderFor type or Created object types.
func (b *Builder) WithReconciler(r reconcile.Reconciler) *Builder {
b.reconcile = r
return b
}

// Build builds the Application Controller and returns the Manager used to start it.
func (b *Builder) Build() (manager.Manager, error) {
if b.reconcile == nil {
func (b *Builder) Build(r reconcile.Reconciler) (manager.Manager, error) {
if r == nil {
return nil, fmt.Errorf("must call WithReconciler to set Reconciler")
}

Expand All @@ -112,7 +110,7 @@ func (b *Builder) Build() (manager.Manager, error) {
}

// Set the Controller
if err := b.doController(); err != nil {
if err := b.doController(r); err != nil {
return nil, err
}

Expand Down Expand Up @@ -168,11 +166,11 @@ func (b *Builder) getControllerName() (string, error) {
return name, nil
}

func (b *Builder) doController() error {
func (b *Builder) doController(r reconcile.Reconciler) error {
name, err := b.getControllerName()
if err != nil {
return err
}
b.ctrl, err = newController(name, b.mgr, controller.Options{Reconciler: b.reconcile})
b.ctrl, err = newController(name, b.mgr, controller.Options{Reconciler: r})
return err
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package application
package builder

import (
"context"
Expand Down Expand Up @@ -38,36 +38,51 @@ var _ = Describe("application", func() {

Describe("New", func() {
It("should return success if given valid objects", func() {
instance, err := BuilderFor(&appsv1.ReplicaSet{}).Owns(&appsv1.ReplicaSet{}).WithReconciler(noop).Build()
instance, err := SimpleController().
ForType(&appsv1.ReplicaSet{}).
Owns(&appsv1.ReplicaSet{}).
Build(noop)
Expect(err).NotTo(HaveOccurred())
Expect(instance).NotTo(BeNil())
})

It("should return an error if the Config is invalid", func() {
getConfig = func() (*rest.Config, error) { return cfg, fmt.Errorf("expected error") }
instance, err := BuilderFor(&appsv1.ReplicaSet{}).Owns(&appsv1.ReplicaSet{}).WithReconciler(noop).Build()
instance, err := SimpleController().
ForType(&appsv1.ReplicaSet{}).
Owns(&appsv1.ReplicaSet{}).
Build(noop)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("expected error"))
Expect(instance).To(BeNil())
})

It("should return an error if there is no GVK for an object", func() {
instance, err := BuilderFor(fakeType("")).Owns(&appsv1.ReplicaSet{}).WithReconciler(noop).Build()
instance, err := SimpleController().
ForType(&fakeType{}).
Owns(&appsv1.ReplicaSet{}).
Build(noop)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("expected pointer, but got application.fakeType"))
Expect(err.Error()).To(ContainSubstring("no kind is registered for the type builder.fakeType"))
Expect(instance).To(BeNil())

instance, err = BuilderFor(&appsv1.ReplicaSet{}).Owns(fakeType("")).WithReconciler(noop).Build()
instance, err = SimpleController().
ForType(&appsv1.ReplicaSet{}).
Owns(&fakeType{}).
Build(noop)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("expected pointer, but got application.fakeType"))
Expect(err.Error()).To(ContainSubstring("no kind is registered for the type builder.fakeType"))
Expect(instance).To(BeNil())
})

It("should return an error if it cannot create the manager", func() {
newManager = func(config *rest.Config, options manager.Options) (manager.Manager, error) {
return nil, fmt.Errorf("expected error")
}
instance, err := BuilderFor(&appsv1.ReplicaSet{}).Owns(&appsv1.ReplicaSet{}).WithReconciler(noop).Build()
instance, err := SimpleController().
ForType(&appsv1.ReplicaSet{}).
Owns(&appsv1.ReplicaSet{}).
Build(noop)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("expected error"))
Expect(instance).To(BeNil())
Expand All @@ -78,34 +93,14 @@ var _ = Describe("application", func() {
controller.Controller, error) {
return nil, fmt.Errorf("expected error")
}
instance, err := BuilderFor(&appsv1.ReplicaSet{}).Owns(&appsv1.ReplicaSet{}).WithReconciler(noop).Build()
instance, err := SimpleController().
ForType(&appsv1.ReplicaSet{}).
Owns(&appsv1.ReplicaSet{}).
Build(noop)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("expected error"))
Expect(instance).To(BeNil())
})

It("should return an error if there is no Reconciler", func() {
// Prevent getGVK from failing so watch fails
getGvk = func(obj runtime.Object, scheme *runtime.Scheme) (schema.GroupVersionKind, error) {
return schema.GroupVersionKind{Kind: "foo"}, nil
}
instance, err := BuilderFor(&appsv1.ReplicaSet{}).Owns(&appsv1.ReplicaSet{}).Build()
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("must call WithReconciler to set Reconciler"))
Expect(instance).To(BeNil())
})

It("should use the provide config", func() {

})

It("should use the provide manager", func() {

})

It("should use the provide filters", func() {

})
})

Describe("Start", func() {
Expand All @@ -118,11 +113,10 @@ var _ = Describe("application", func() {
return reconcile.Result{}, nil
})

instance, err := BuilderFor(&appsv1.Deployment{}).
instance, err := SimpleController().ForType(&appsv1.Deployment{}).
WithConfig(cfg).
Owns(&appsv1.ReplicaSet{}).
WithReconciler(fn).
Build()
Build(fn)
Expect(err).NotTo(HaveOccurred())

By("Starting the application")
Expand Down Expand Up @@ -198,9 +192,9 @@ var _ = Describe("application", func() {
})
})

var _ runtime.Object = fakeType("")
var _ runtime.Object = &fakeType{}

type fakeType string
type fakeType struct{}

func (fakeType) GetObjectKind() schema.ObjectKind { return nil }
func (fakeType) DeepCopyObject() runtime.Object { return nil }
func (*fakeType) GetObjectKind() schema.ObjectKind { return nil }
func (*fakeType) DeepCopyObject() runtime.Object { return nil }
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package application
package builder

import (
"testing"
Expand Down
22 changes: 22 additions & 0 deletions pkg/builder/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
Copyright 2018 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package builder provides wraps other controller-runtime libraries and exposes simple
Copy link
Contributor

Choose a reason for hiding this comment

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

remove 'provides'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

// patterns for building common Controllers.
//
// Projects built with the builder package can trivially be rebased on top of the underlying
// packages if the project requires more customized behavior in the future.
package builder
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package application_test
package builder_test

import (
"context"
Expand All @@ -23,33 +23,32 @@ import (

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/patterns/application"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
)

// This example creates a simple application Controller that is configured for ReplicaSets and Pods.
//
// * Create a new application for ReplicaSets that manages Pods owned by the ReplicaSet and calls into
// ReplicaSetController.
// ReplicaSetReconciler.
//
// * Start the application.
func ExampleBuilder() {
a, err := application.
BuilderFor(&appsv1.ReplicaSet{}). // ReplicaSet is the Application API
Owns(&corev1.Pod{}). // ReplicaSet owns Pods created by it
WithReconciler(&ReplicaSetController{}). // ReplicaSet and Pod events (create/update/del) trigger the handler
Build() // Build
rs, err := builder.SimpleController().
ForType(&appsv1.ReplicaSet{}). // ReplicaSet is the Application API
Owns(&corev1.Pod{}). // ReplicaSet owns Pods created by it
Build(&ReplicaSetReconciler{}) // Build
if err != nil {
log.Fatal(err)
}

log.Fatal(a.Start(signals.SetupSignalHandler()))
log.Fatal(rs.Start(signals.SetupSignalHandler()))
}

// ReplicaSetController is a simple Controller example implementation.
type ReplicaSetController struct {
// ReplicaSetReconciler is a simple Controller example implementation.
type ReplicaSetReconciler struct {
client.Client
}

Expand All @@ -60,7 +59,7 @@ type ReplicaSetController struct {
// * Read the ReplicaSet
// * Read the Pods
// * Set a Label on the ReplicaSet with the Pod count
func (a *ReplicaSetController) Reconcile(req reconcile.Request) (reconcile.Result, error) {
func (a *ReplicaSetReconciler) Reconcile(req reconcile.Request) (reconcile.Result, error) {
// Read the ReplicaSet
rs := &appsv1.ReplicaSet{}
err := a.Get(context.TODO(), req.NamespacedName, rs)
Expand All @@ -85,7 +84,7 @@ func (a *ReplicaSetController) Reconcile(req reconcile.Request) (reconcile.Resul
return reconcile.Result{}, nil
}

func (a *ReplicaSetController) InjectClient(c client.Client) error {
func (a *ReplicaSetReconciler) InjectClient(c client.Client) error {
a.Client = c
return nil
}
15 changes: 7 additions & 8 deletions pkg/patterns/application/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// Package application provides high-level porcelain wrapping the controller and manager libraries for
// building Kubernetes APIs for simple applications (operators).
// Package application documents patterns for building Controllers to manage specific applications.
//
// Note: Application is an alpha library and make have backwards compatibility breaking changes.
//
// Projects built with an application can trivially be rebased on top of the underlying Controller and Manager
// packages if the project requires more customized behavior in the future.
// An application is a Controller and Resource that together implement the operational logic for an application.
// They are often used to take off-the-shelf OSS applications, and make them Kubernetes native.
//
// Application
// A typical application Controller may use a new builder.SimpleController() to create a Controller
// for a single API type that manages other objects it creates.
//
// An application is a Controller that implements the operational logic for an application. It is often used
// to take off-the-shelf OSS applications, and make them Kubernetes native.
// Application Controllers are most useful for stateful applications such as Cassandra, Etcd and MySQL
// which contain operation logic for sharding, backup and restore, upgrade / downgrade, etc.
package application
Copy link
Contributor

Choose a reason for hiding this comment

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

We are keeping this around ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just for documentation