This repository has been archived by the owner on Jul 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
reconcile.go
78 lines (67 loc) · 2.71 KB
/
reconcile.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package reconcile
import (
"context"
"fmt"
"time"
"github.com/go-logr/logr"
"github.com/google/wire"
"github.com/int128/scheduled-scaler/pkg/domain/errors"
"github.com/int128/scheduled-scaler/pkg/infrastructure/clock"
"github.com/int128/scheduled-scaler/pkg/repositories/deployment"
"github.com/int128/scheduled-scaler/pkg/repositories/scheduledpodscaler"
"golang.org/x/xerrors"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/pointer"
)
var Set = wire.NewSet(
wire.Bind(new(Interface), new(*Reconcile)),
wire.Struct(new(Reconcile), "*"),
)
type Interface interface {
Do(ctx context.Context, in Input) (*Output, error)
}
type Reconcile struct {
Log logr.Logger
Clock clock.Interface
ScheduledPodScalerRepository scheduledpodscaler.Interface
DeploymentRepository deployment.Interface
}
type Input struct {
Target types.NamespacedName
}
type Output struct {
NextReconcileAfter time.Duration
}
func (r *Reconcile) Do(ctx context.Context, in Input) (*Output, error) {
scheduledPodScaler, err := r.ScheduledPodScalerRepository.GetByName(ctx, in.Target)
if err != nil {
if errors.IsNotFound(err) {
r.Log.Info("the ScheduledPodScaler has already removed and ended up", "error", err)
return &Output{NextReconcileAfter: 0}, nil
}
return nil, xerrors.Errorf("could not get the ScheduledPodScaler: %w", err)
}
selectors := scheduledPodScaler.Spec.ScaleTarget.Selectors
deploymentList, err := r.DeploymentRepository.FindBySelectors(ctx, selectors)
if err != nil {
return nil, xerrors.Errorf("could not find the deployments: %w", err)
}
r.Log.Info(fmt.Sprintf("found %d deployments", len(deploymentList.Items)), "selectors", selectors)
now := r.Clock.Now()
desiredScaleSpec := scheduledPodScaler.Spec.ComputeDesiredScaleSpec(now)
for _, deploymentItem := range deploymentList.Items {
currentReplicas := pointer.Int32PtrDerefOr(deploymentItem.Spec.Replicas, 0)
r.Log.Info("comparing the replicas", "current", currentReplicas, "desired", desiredScaleSpec.Replicas)
if currentReplicas != desiredScaleSpec.Replicas {
r.Log.Info("applying the patch to the deployment", "replicas", currentReplicas)
if err := r.DeploymentRepository.Scale(ctx, &deploymentItem, desiredScaleSpec.Replicas); err != nil {
return nil, xerrors.Errorf("could not scale the deployment: %w", err)
}
}
}
scheduledPodScaler.Status.NextReconcileTime = scheduledPodScaler.Spec.FindNextReconcileTime(now)
if err := r.ScheduledPodScalerRepository.UpdateStatus(ctx, scheduledPodScaler); err != nil {
return nil, xerrors.Errorf("could not update the status of ScheduledPodScaler: %w", err)
}
return &Output{NextReconcileAfter: scheduledPodScaler.Status.NextReconcileTime.Sub(now)}, nil
}