Skip to content

Commit

Permalink
Record exit code in run status
Browse files Browse the repository at this point in the history
  • Loading branch information
leg100 committed Jan 22, 2021
1 parent 18c444c commit 34f7a68
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 13 deletions.
3 changes: 3 additions & 0 deletions api/etok.dev/v1alpha1/run_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ type RunStatus struct {
Phase RunPhase `json:"phase,omitempty"`

Conditions []metav1.Condition `json:"conditions,omitempty"`

// Exit code of run pod's runner container
ExitCode *int `json:"exitCode,omitempty"`
}

func (r *Run) IsReconciled() bool {
Expand Down
9 changes: 8 additions & 1 deletion cmd/launcher/launcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,14 @@ func mockControllers(t *testutil.T, f *cmdutil.Factory, o *launcherOptions, phas
createPodAction := func(action testcore.Action) (bool, runtime.Object, error) {
run := action.(testcore.CreateAction).GetObject().(*v1alpha1.Run)

pod := testobj.RunPod(run.Namespace, run.Name, testobj.WithPhase(phase), testobj.WithRunnerExitCode(exitCode))
var pod *corev1.Pod
// Only set phase if non-empty
if phase != "" {
pod = testobj.RunPod(run.Namespace, run.Name, testobj.WithPhase(phase), testobj.WithRunnerExitCode(exitCode))
} else {
pod = testobj.RunPod(run.Namespace, run.Name, testobj.WithRunnerExitCode(exitCode))
}

_, err := o.PodsClient(run.Namespace).Create(context.Background(), pod, metav1.CreateOptions{})
require.NoError(t, err)

Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/etok.dev_runs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ spec:
- type
type: object
type: array
exitCode:
description: Exit code of run pod's runner container
type: integer
phase:
description: Current phase of the run's lifecycle.
type: string
Expand Down
45 changes: 39 additions & 6 deletions pkg/controllers/run_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package controllers

import (
"context"
"errors"
"time"

v1alpha1 "github.com/leg100/etok/api/etok.dev/v1alpha1"
"github.com/leg100/etok/cmd/launcher"
"github.com/leg100/etok/pkg/globals"
"github.com/leg100/etok/pkg/k8s"
"github.com/leg100/etok/pkg/scheme"
"github.com/leg100/etok/pkg/util/slice"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -258,18 +261,48 @@ func (r *RunReconciler) managePod(ctx context.Context, run *v1alpha1.Run, ws v1a
return nil, err
}

switch pod.Status.Phase {
var isCompleted = metav1.ConditionFalse

if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodFailed {
// Record exit code in run status
code, err := getExitCode(&pod)
if err != nil {
return nil, errors.New("unable to retrieve container status")
}
run.RunStatus.ExitCode = &code

isCompleted = metav1.ConditionTrue
}

return &metav1.Condition{
Type: v1alpha1.RunCompleteCondition,
Status: isCompleted,
Reason: getReasonFromPodPhase(pod.Status.Phase),
}, nil
}

// Translate pod phase to a reason string for the run completed condition
func getReasonFromPodPhase(phase corev1.PodPhase) string {
switch phase {
case corev1.PodSucceeded:
return runComplete(v1alpha1.PodSucceededReason, ""), nil
return v1alpha1.PodSucceededReason
case corev1.PodFailed:
return runComplete(v1alpha1.PodFailedReason, ""), nil
return v1alpha1.PodFailedReason
case corev1.PodRunning:
return runIncomplete(v1alpha1.PodRunningReason, ""), nil
return v1alpha1.PodRunningReason
case corev1.PodPending:
return runIncomplete(v1alpha1.PodPendingReason, ""), nil
return v1alpha1.PodPendingReason
default:
return runIncomplete(v1alpha1.PodUnknownReason, ""), nil
return v1alpha1.PodUnknownReason
}
}

func getExitCode(pod *corev1.Pod) (int, error) {
status := k8s.ContainerStatusByName(pod, globals.RunnerContainerName)
if status == nil {
return 0, errors.New("unable to retrieve container status")
}
return int(status.State.Terminated.ExitCode), nil
}

func (r *RunReconciler) setOwnerOfArchive(ctx context.Context, run *v1alpha1.Run) error {
Expand Down
11 changes: 11 additions & 0 deletions pkg/controllers/run_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ func TestRunReconciler(t *testing.T) {
assert.Equal(t, "plan-1", archive.OwnerReferences[0].Name)
},
},
{
name: "Exit code recorded in status",
run: testobj.Run("operator-test", "plan-1", "plan", testobj.WithWorkspace("workspace-1")),
objs: []runtime.Object{
testobj.Workspace("operator-test", "workspace-1", testobj.WithSecret("secret-1")),
testobj.RunPod("operator-test", "plan-1", testobj.WithPhase(corev1.PodSucceeded), testobj.WithRunnerExitCode(5)),
},
runAssertions: func(t *testutil.T, run *v1alpha1.Run) {
assert.Equal(t, 5, *run.RunStatus.ExitCode)
},
},
}
for _, tt := range tests {
testutil.Run(t, tt.name, func(t *testutil.T) {
Expand Down
5 changes: 3 additions & 2 deletions pkg/controllers/workspace_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,9 @@ func (r *WorkspaceReconciler) restore(ctx context.Context, ws *v1alpha1.Workspac
return nil, err
}

// Blank out resource version to avoid error upon create
// Blank out certain fields to avoid errors upon create
secret.ResourceVersion = ""
secret.OwnerReferences = nil

if err := r.Create(ctx, &secret); err != nil {
r.recorder.Eventf(ws, "Warning", "RestoreError", "Error received when trying to restore state: %w", err)
Expand Down Expand Up @@ -673,7 +674,7 @@ func (r *WorkspaceReconciler) SetupWithManager(mgr ctrl.Manager) error {
blder = blder.Owns(&corev1.ConfigMap{})

// Watch terraform state files
blder = blder.Watches(&source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(func(o client.Object) []ctrl.Request {
blder = blder.Watches(&source.Kind{Type: &corev1.Secret{}}, handler.EnqueueRequestsFromMapFunc(func(o client.Object) []ctrl.Request {
var isStateFile bool
for k, v := range o.GetLabels() {
if k == "tfstate" && v == "true" {
Expand Down
5 changes: 1 addition & 4 deletions pkg/testobj/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,7 @@ func WorkspacePod(namespace, name string, opts ...func(*corev1.Pod)) *corev1.Pod

func WithPhase(phase corev1.PodPhase) func(*corev1.Pod) {
return func(pod *corev1.Pod) {
// Only set a phase if non-empty
if phase != "" {
pod.Status.Phase = phase
}
pod.Status.Phase = phase
}
}

Expand Down

0 comments on commit 34f7a68

Please sign in to comment.