Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Conditionally rerun executions
Browse files Browse the repository at this point in the history
Sometimes we want to ensure real world matches desired state, if state
annotated with "terraformcontroller.cattle.io/run-every" timestamp will
be used to generate new runHash and state update will be scheduled

Signed-off-by: Dinar Valeev <[email protected]>
  • Loading branch information
k0da committed Dec 3, 2020
1 parent 7fd29d1 commit 91a1c37
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
10 changes: 6 additions & 4 deletions pkg/apis/terraformcontroller.cattle.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var (
ModuleConditionGitUpdated = condition.Cond("GitUpdated")

StateConditionJobDeployed = condition.Cond("JobDeployed")
StateConfitionScheduled = condition.Cond("RefreshScheduled")
ExecutionConditionMissingInfo = condition.Cond("MissingInfo")
ExecutionConditionWatchRunning = condition.Cond("WatchRunning")
StateConditionDestroyed = condition.Cond("Destroyed")
Expand Down Expand Up @@ -87,10 +88,11 @@ type StateSpec struct {
}

type StateStatus struct {
Conditions []genericcondition.GenericCondition `json:"conditions,omitempty"`
LastRunHash string `json:"lastRunHash,omitempty"`
ExecutionName string `json:"executionName,omitempty"`
StatePlanName string `json:"executionPlanName,omitempty"`
Conditions []genericcondition.GenericCondition `json:"conditions,omitempty"`
RefreshSchedule metav1.Time `json:"schedule,omitempty"`
LastRunHash string `json:"lastRunHash,omitempty"`
ExecutionName string `json:"executionName,omitempty"`
StatePlanName string `json:"executionPlanName,omitempty"`
}

// +genclient
Expand Down
5 changes: 5 additions & 0 deletions pkg/terraform/state/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,11 @@ func generateRunHash(state *v1.State, vars map[string]string, h string, a string
fmt.Println("binary.Write failed:", err)
}

err = binary.Write(buf, binary.LittleEndian, state.Status.RefreshSchedule.Time.Unix())
if err != nil {
fmt.Println("binary.Write failed:", err)
}

hash := sha256.New()
if _, err := hash.Write([]byte(varHash)); err != nil {
logrus.Error("Failed to write to digest")
Expand Down
37 changes: 36 additions & 1 deletion pkg/terraform/state/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package state
import (
"context"
"fmt"
"github.com/rancher/terraform-controller/pkg/apis/terraformcontroller.cattle.io/v1"
"time"

v1 "github.com/rancher/terraform-controller/pkg/apis/terraformcontroller.cattle.io/v1"
tfv1 "github.com/rancher/terraform-controller/pkg/generated/controllers/terraformcontroller.cattle.io/v1"
batchv1 "github.com/rancher/wrangler/pkg/generated/controllers/batch/v1"
corev1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
Expand All @@ -19,6 +21,7 @@ const (
ActionDestroy = "destroy"
//Default Image
DefaultExecutorImage = "rancher/terraform-controller-executor"
RefreshAnnotationKey = "terraformcontroller.cattle.io/run-every"
)

func NewHandler(
Expand Down Expand Up @@ -62,6 +65,7 @@ type handler struct {

func (h *handler) OnChange(key string, obj *v1.State) (*v1.State, error) {
logrus.Debugf("State On Change Handler %s", key)
logrus.Infof("got update for %s", key)
if obj == nil {
return nil, nil
}
Expand All @@ -82,6 +86,21 @@ func (h *handler) OnChange(key string, obj *v1.State) (*v1.State, error) {
return h.states.Update(obj)
}

now := metaV1.Now()

if scheduleRefresh(obj, &now) && v1.StateConfitionScheduled.IsFalse(obj) {
duration, err := time.ParseDuration(obj.Annotations[RefreshAnnotationKey])
if err != nil {
logrus.Errorf("Failed to parse duration annotation: %s", err.Error())
return obj, err
}
schedule := metaV1.NewTime(now.Add(duration))

obj.Status.RefreshSchedule = schedule
v1.StateConfitionScheduled.True(obj)
return h.states.Update(obj)
}

if v1.StateConditionJobDeployed.IsTrue(obj) && obj.Status.LastRunHash != "" {
logrus.Debugf("job already running %s, checking execution", obj.Status.LastRunHash)
execution, err := h.executions.Get(obj.Namespace, obj.Status.ExecutionName, metaV1.GetOptions{})
Expand Down Expand Up @@ -140,9 +159,25 @@ func (h *handler) OnChange(key string, obj *v1.State) (*v1.State, error) {
obj.Status.ExecutionName = exec.Name
obj.Status.LastRunHash = runHash

if obj.Annotations[RefreshAnnotationKey] != "" {
duration, err := time.ParseDuration(obj.Annotations[RefreshAnnotationKey])
if err != nil {
logrus.Errorf("Failed to parse duration annotation: %s", err.Error())
return obj, err
}
h.states.EnqueueAfter(obj.Namespace, obj.Name, duration)
}
return h.states.Update(obj)
}

func scheduleRefresh(obj *v1.State, now *metaV1.Time) bool {
expired := obj.Status.RefreshSchedule.Before(now)
if expired {
v1.StateConfitionScheduled.False(obj)
}
return expired && obj.Annotations[RefreshAnnotationKey] != ""
}

func (h *handler) OnRemove(key string, obj *v1.State) (*v1.State, error) {
logrus.Debugf("State On Remove Handler %s", key)
input, ok, err := h.gatherInput(obj)
Expand Down

0 comments on commit 91a1c37

Please sign in to comment.