Newer
Older
package reconciler
import (
"context"
"sort"
"github.com/hashicorp/go-version"
"k8s.libre.sh/application"
interfaces "k8s.libre.sh/interfaces"
"k8s.libre.sh/status"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
type InstanceReconciler struct {
*ReconcilerBase
Instance application.Instance
SyncOrder map[int]string
}
func NewInstanceReconciler(r *ReconcilerBase, i application.Instance, order map[int]string) *InstanceReconciler {
return &InstanceReconciler{
ReconcilerBase: r,
Instance: i,
SyncOrder: order,
}
}
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/* func (er *InstanceReconciler) ManageSuccess(instance apis.Resource) (reconcile.Result, error) {
if enforcingReconcileStatusAware, updateStatus := (instance).(apis.EnforcingReconcileStatusAware); updateStatus {
condition := status.Condition{
Type: "ReconcileSuccess",
LastTransitionTime: metav1.Now(),
Message: astatus.SuccessfulMessage,
Reason: astatus.SuccessfulReason,
Status: corev1.ConditionTrue,
}
status := apis.EnforcingReconcileStatus{
Conditions: status.NewConditions(condition),
LockedResourceStatuses: er.GetLockedResourceStatuses(instance),
LockedPatchStatuses: er.GetLockedPatchStatuses(instance),
}
enforcingReconcileStatusAware.SetEnforcingReconcileStatus(status)
log.V(1).Info("about to modify state for", "instance version", instance.GetResourceVersion())
err := er.GetClient().Status().Update(context.Background(), instance)
if err != nil {
if errors.IsResourceExpired(err) {
log.Info("unable to update status for", "object version", instance.GetResourceVersion(), "resource version expired, will trigger another reconcile cycle", "")
} else {
log.Error(err, "unable to update status for", "object", instance)
}
return reconcile.Result{}, err
}
} else {
log.V(1).Info("object is not RecocileStatusAware, not setting status")
}
return reconcile.Result{}, nil
}
*/
func (r *InstanceReconciler) ManageError(owner status.ObjectWithStatus) (reconcile.Result, error) {
return reconcile.Result{}, nil
}
func (r *InstanceReconciler) Reconcile(request reconcile.Request) (reconcile.Result, error) {
appStatus := r.Instance.GetApplicationStatus()
oldStatus := appStatus.DeepCopy()
err := application.Init(r.Instance, r.ReconcilerBase)
if err != nil {
return reconcile.Result{}, err
}
for name, s := range r.Instance.GetSettings() {
res, err := SyncComponent(context.TODO(), r.ReconcilerBase, s, r.Instance.GetOwner())
cptStatus := status.ComponentStatus{
Resources: res,
}
if len(appStatus.Settings) == 0 {
appStatus.Settings = make(map[string]status.ComponentStatus)
}
appStatus.Settings[name] = cptStatus
appStatus.Settings[name] = cptStatus
}
jobs := r.Instance.GetJobs()
current, err := version.NewVersion(r.Instance.GetApplicationStatus().Version)
// get nextcloud desired version in spec
desired, err := version.NewVersion(r.Instance.GetVersion())
if len(r.Instance.GetApplicationStatus().Version) == 0 {
// Sync INSTALL
res, err := SyncComponent(context.TODO(), r.ReconcilerBase, jobs["install"], r.Instance.GetOwner())
cptStatus := status.ComponentStatus{
Resources: res,
}
if len(appStatus.Components) == 0 {
appStatus.Components = make(map[string]status.ComponentStatus)
}
if err != nil {
cptStatus.ComponentsReady = "NotReady"
appStatus.Components["jobs"] = cptStatus
return ctrl.Result{}, err
}
cptStatus.ComponentsReady = "Ready"
appStatus.Components["jobs"] = cptStatus
// ADD manage success
// return ctrl.Result{}, nil
delete(jobs, "upgrade")
} else {
switch current.Compare(desired) {
case 1:
// current version is greater than desired, no downgrade
// TODO Format error
return ctrl.Result{}, err
case -1:
// current version lower than desired, upgrade job
// current version and desired are the same, normal start
delete(jobs, "install")
delete(jobs, "upgrade")
}
}
cpts := make(map[string]application.ComponentMutate)
for name, j := range jobs {
cpts[name] = j
}
for name, c := range r.Instance.GetComponents() {
cpts[name] = c
}
sts, err := SyncComponents(context.TODO(), r.ReconcilerBase, cpts, r.Instance.GetOwner(), r.SyncOrder)
appStatus.Components = sts.Components
appStatus.SetConditions(sts.Conditions...)
appStatus.Version = desired.String()
owner := r.Instance.GetOwner()
owner.SetApplicationStatus(*appStatus)
if err := r.ReconcilerBase.GetClient().Status().Update(context.TODO(), owner); err != nil {
return ctrl.Result{}, err
}
if err := r.ReconcilerBase.GetClient().Status().Update(context.TODO(), owner); err != nil {
// Clean up resources and update status
err = CleanUpResources(oldStatus.GetResources(), appStatus.GetResources(), r.ReconcilerBase.GetClient(), r.Instance.GetNamespace())
if err != nil {
}
return ctrl.Result{}, nil
}
func SyncComponents(ctx context.Context, r interfaces.Reconcile, cpts map[string]application.ComponentMutate, owner interfaces.Object, order map[int]string) (appStatus status.ApplicationStatus, err error) {
keys := []int{}
appStatus.Components = make(map[string]status.ComponentStatus)
for k := range order {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
if cpts[order[k]] != nil {
resources, err := SyncComponent(ctx, r, cpts[order[k]], owner)
cptStatus := status.ComponentStatus{
cptStatus.ComponentsReady = "NotReady"
appStatus.Components[order[k]] = cptStatus
appStatus.SetConditions(status.ReconcileError(err))
cptStatus.ComponentsReady = "Ready"
appStatus.Components[order[k]] = cptStatus
appStatus.SetConditions(status.ReconcileSuccess())