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

Break down methods in instance controller #563

Merged
merged 5 commits into from
Jul 12, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
188 changes: 95 additions & 93 deletions pkg/controller/instance/instance_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,95 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
return err
}

inPredicate := predicate.Funcs{
// Watch for changes to Instance
if err = c.Watch(&source.Kind{Type: &kudov1alpha1.Instance{}}, &handler.EnqueueRequestForObject{}, instanceEventPredicateFunc(mgr)); err != nil {
return err
}

// Watch for changes to OperatorVersion. Since changes to OperatorVersion and Instance are often happening
// concurrently there is an inherent race between both update events so that we might see a new Instance first
// without the corresponding OperatorVersion. We additionally watch OperatorVersions and trigger
// reconciliation for the corresponding instances.
//
// Define a mapping from the object in the event (OperatorVersion) to one or more objects to
// reconcile (Instances). Specifically this calls for a reconciliation of any owned objects.
ovMapFn := handler.ToRequestsFunc(
func(a handler.MapObject) []reconcile.Request {
requests := make([]reconcile.Request, 0)
// We want to query and queue up operators Instances
instances := &kudov1alpha1.InstanceList{}
err := mgr.GetClient().List(
context.TODO(),
instances,
client.MatchingLabels(map[string]string{"operator": a.Meta.GetName()}),
)

if err != nil {
log.Printf("InstanceController: Error fetching instances list for operator %v: %v", a.Meta.GetName(), err)
return nil
}

for _, instance := range instances.Items {
// Sanity check - lets make sure that this instance references the operatorVersion
if instance.Spec.OperatorVersion.Name == a.Meta.GetName() &&
instance.GetOperatorVersionNamespace() == a.Meta.GetNamespace() &&
instance.Status.ActivePlan.Name == "" {

log.Printf("InstanceController: Creating a deploy execution plan for the instance %v", instance.Name)
err = createPlan(mgr, "deploy", &instance)
if err != nil {
log.Printf("InstanceController: Error creating \"%v\" object for \"deploy\": %v", instance.Name, err)
}

log.Printf("InstanceController: Queing instance %v for reconciliation", instance.Name)
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Name: instance.Name,
Namespace: instance.Namespace,
},
})
}
}
log.Printf("Found %v instances to reconcile", len(requests))
return requests
})

// This map function makes sure that we *ONLY* handle created operatorVersion
ovPredicate := predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return true
},
UpdateFunc: func(e event.UpdateEvent) bool {
return false
},
DeleteFunc: func(e event.DeleteEvent) bool {
return false
},
}

if err = c.Watch(&source.Kind{Type: &kudov1alpha1.OperatorVersion{}}, &handler.EnqueueRequestsFromMapFunc{ToRequests: ovMapFn}, ovPredicate); err != nil {
return err
}

return nil
}

func instanceEventPredicateFunc(mgr manager.Manager) predicate.Funcs {
return predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
old := e.ObjectOld.(*kudov1alpha1.Instance)
new := e.ObjectNew.(*kudov1alpha1.Instance)

// Get the OperatorVersion that corresponds to the new instance.
ov := &kudov1alpha1.OperatorVersion{}
err = mgr.GetClient().Get(context.TODO(),
err := mgr.GetClient().Get(context.TODO(),
types.NamespacedName{
Name: new.Spec.OperatorVersion.Name,
Namespace: new.GetOperatorVersionNamespace(),
},
ov)
if err != nil {
log.Printf("InstanceController: Error getting operatorversion \"%v\" for instance \"%v\": %v",
log.Printf("InstanceEventPredicate: Error getting operatorversion \"%v\" for instance \"%v\": %v",
kensipe marked this conversation as resolved.
Show resolved Hide resolved
new.Spec.OperatorVersion.Name,
new.Name,
err)
Expand All @@ -103,7 +177,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
}

if !planFound {
log.Printf("InstanceController: Could not find any plan to use to upgrade instance %v", new.Name)
log.Printf("InstanceEventPredicate: Could not find any plan to use to upgrade instance %v", new.Name)
return false
}
} else if !reflect.DeepEqual(old.Spec, new.Spec) {
Expand Down Expand Up @@ -136,15 +210,15 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
}

if planFound {
log.Printf("InstanceController: Instance %v updated parameter %v, but it is not associated to a trigger. Using default plan %v\n", new.Name, k, planName)
log.Printf("InstanceEventPredicate: Instance %v updated parameter %v, but it is not associated to a trigger. Using default plan %v\n", new.Name, k, planName)
}
}

if !planFound {
log.Printf("InstanceController: Could not find any plan to use to update instance %v", new.Name)
log.Printf("InstanceEventPredicate: Could not find any plan to use to update instance %v", new.Name)
}
} else {
log.Printf("InstanceController: Instance %v updated parameter %v, but parameter not found in operatorversion %v\n", new.Name, k, ov.Name)
log.Printf("InstanceEventPredicate: Instance %v updated parameter %v, but parameter not found in operatorversion %v\n", new.Name, k, ov.Name)
}
}
} else {
Expand All @@ -154,24 +228,24 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
// `PlanExecution`.
// See https://github.com/kudobuilder/kudo/issues/422
if new.Status.ActivePlan.Name == "" {
log.Printf("InstanceController: Old and new spec matched...\n %+v ?= %+v\n", old.Spec, new.Spec)
log.Printf("InstanceEventPredicate: Old and new spec matched...\n %+v ?= %+v\n", old.Spec, new.Spec)
planName = "deploy"
planFound = true
}
}

if planFound {
log.Printf("InstanceController: Going to run plan \"%v\" for instance %v", planName, new.Name)
log.Printf("InstanceEventPredicate: Going to run plan \"%v\" for instance %v", planName, new.Name)
// Suspend the the current plan.
current := &kudov1alpha1.PlanExecution{}
err = mgr.GetClient().Get(context.TODO(), client.ObjectKey{Name: new.Status.ActivePlan.Name, Namespace: new.Status.ActivePlan.Namespace}, current)
if err != nil {
log.Printf("InstanceController: Ignoring error when getting plan for new instance: %v", err)
log.Printf("InstanceEventPredicate: Ignoring error when getting plan for new instance: %v", err)
} else {
if current.Status.State == kudov1alpha1.PhaseStateComplete {
log.Printf("InstanceController: Current plan for instance %v is already done, won't change the Suspend flag.", new.Name)
log.Printf("InstanceEventPredicate: Current plan for instance %v is already done, won't change the Suspend flag.", new.Name)
} else {
log.Printf("InstanceController: Suspending the PlanExecution for instance %v", new.Name)
log.Printf("InstanceEventPredicate: Suspending the PlanExecution for instance %v", new.Name)
t := true
current.Spec.Suspend = &t
did, err := controllerutil.CreateOrUpdate(context.TODO(), mgr.GetClient(), current, func() error {
Expand All @@ -180,15 +254,15 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
return nil
})
if err != nil {
log.Printf("InstanceController: Error suspending PlanExecution for instance %v: %v", new.Name, err)
log.Printf("InstanceEventPredicate: Error suspending PlanExecution for instance %v: %v", new.Name, err)
} else {
log.Printf("InstanceController: Successfully suspended PlanExecution for instance %v. Returned: %v", new.Name, did)
log.Printf("InstanceEventPredicate: Successfully suspended PlanExecution for instance %v. Returned: %v", new.Name, did)
}
}
}

if err = createPlan(mgr, planName, new); err != nil {
log.Printf("InstanceController: Error creating PlanExecution \"%v\" for instance \"%v\": %v", planName, new.Name, err)
log.Printf("InstanceEventPredicate: Error creating PlanExecution \"%v\" for instance \"%v\": %v", planName, new.Name, err)
}
}

Expand All @@ -197,19 +271,19 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
},
// New Instances should have Deploy called
CreateFunc: func(e event.CreateEvent) bool {
log.Printf("InstanceController: Received create event for instance \"%v\"", e.Meta.GetName())
log.Printf("InstanceEventPredicate: Received create event for instance \"%v\"", e.Meta.GetName())
instance := e.Object.(*kudov1alpha1.Instance)

// Get the instance OperatorVersion object
ov := &kudov1alpha1.OperatorVersion{}
err = mgr.GetClient().Get(context.TODO(),
err := mgr.GetClient().Get(context.TODO(),
types.NamespacedName{
Name: instance.Spec.OperatorVersion.Name,
Namespace: instance.GetOperatorVersionNamespace(),
},
ov)
if err != nil {
log.Printf("InstanceController: Error getting operatorversion \"%v\" for instance \"%v\": %v",
log.Printf("InstanceEventPredicate: Error getting operatorversion \"%v\" for instance \"%v\": %v",
instance.Spec.OperatorVersion.Name,
instance.Name,
err)
Expand All @@ -221,93 +295,21 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
planName := "deploy"

if _, ok := ov.Spec.Plans[planName]; !ok {
log.Printf("InstanceController: Could not find deploy plan \"%v\" for instance \"%v\"", planName, instance.Name)
log.Printf("InstanceEventPredicate: Could not find deploy plan \"%v\" for instance \"%v\"", planName, instance.Name)
return false
}

err = createPlan(mgr, planName, instance)
if err != nil {
log.Printf("InstanceController: Error creating PlanExecution \"%v\" for instance \"%v\": %v", planName, instance.Name, err)
log.Printf("InstanceEventPredicate: Error creating PlanExecution \"%v\" for instance \"%v\": %v", planName, instance.Name, err)
}
return err == nil
},
DeleteFunc: func(e event.DeleteEvent) bool {
log.Printf("InstanceController: Received delete event for instance \"%v\"", e.Meta.GetName())
log.Printf("InstanceEventPredicate: Received delete event for instance \"%v\"", e.Meta.GetName())
return true
},
}

// Watch for changes to Instance
if err = c.Watch(&source.Kind{Type: &kudov1alpha1.Instance{}}, &handler.EnqueueRequestForObject{}, inPredicate); err != nil {
return err
}

// Watch for changes to OperatorVersion. Since changes to OperatorVersion and Instance are often happening
// concurrently there is an inherent race between both update events so that we might see a new Instance first
// without the corresponding OperatorVersion. We additionally watch OperatorVersions and trigger
// reconciliation for the corresponding instances.
//
// Define a mapping from the object in the event (OperatorVersion) to one or more objects to
// reconcile (Instances). Specifically this calls for a reconciliation of any owned objects.
ovMapFn := handler.ToRequestsFunc(
func(a handler.MapObject) []reconcile.Request {
requests := make([]reconcile.Request, 0)
// We want to query and queue up operators Instances
instances := &kudov1alpha1.InstanceList{}
err := mgr.GetClient().List(
context.TODO(),
instances,
client.MatchingLabels(map[string]string{"operator": a.Meta.GetName()}),
)

if err != nil {
log.Printf("InstanceController: Error fetching instances list for operator %v: %v", a.Meta.GetName(), err)
return nil
}

for _, instance := range instances.Items {
// Sanity check - lets make sure that this instance references the operatorVersion
if instance.Spec.OperatorVersion.Name == a.Meta.GetName() &&
instance.GetOperatorVersionNamespace() == a.Meta.GetNamespace() &&
instance.Status.ActivePlan.Name == "" {

log.Printf("InstanceController: Creating a deploy execution plan for the instance %v", instance.Name)
err = createPlan(mgr, "deploy", &instance)
if err != nil {
log.Printf("InstanceController: Error creating \"%v\" object for \"deploy\": %v", instance.Name, err)
}

log.Printf("InstanceController: Queing instance %v for reconciliation", instance.Name)
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Name: instance.Name,
Namespace: instance.Namespace,
},
})
}
}
log.Printf("Found %v instances to reconcile", len(requests))
return requests
})

// This map function makes sure that we *ONLY* handle created operatorVersion
ovPredicate := predicate.Funcs{
CreateFunc: func(e event.CreateEvent) bool {
return true
},
UpdateFunc: func(e event.UpdateEvent) bool {
return false
},
DeleteFunc: func(e event.DeleteEvent) bool {
return false
},
}

if err = c.Watch(&source.Kind{Type: &kudov1alpha1.OperatorVersion{}}, &handler.EnqueueRequestsFromMapFunc{ToRequests: ovMapFn}, ovPredicate); err != nil {
return err
}

return nil
}

func createPlan(mgr manager.Manager, planName string, instance *kudov1alpha1.Instance) error {
Expand Down
10 changes: 3 additions & 7 deletions pkg/controller/operator/operator_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,13 @@ import (
// and Start it when the Manager is Started.
func Add(mgr manager.Manager) error {
log.Printf("OperatorController: Registering operator controller.")
reconciler, err := newReconciler(mgr)
if err != nil {
return err
}
return add(mgr, reconciler)
return add(mgr, newReconciler(mgr))
}

// newReconciler returns a new reconcile.Reconciler
func newReconciler(mgr manager.Manager) (reconcile.Reconciler, error) {
func newReconciler(mgr manager.Manager) reconcile.Reconciler {

return &ReconcileOperator{Client: mgr.GetClient(), scheme: mgr.GetScheme(), recorder: mgr.GetEventRecorderFor("operator-controller")}, nil
return &ReconcileOperator{Client: mgr.GetClient(), scheme: mgr.GetScheme(), recorder: mgr.GetEventRecorderFor("operator-controller")}
}

// add adds a new Controller to mgr with r as the reconcile.Reconciler
Expand Down