-
Notifications
You must be signed in to change notification settings - Fork 0
/
job.go
132 lines (103 loc) · 3.08 KB
/
job.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package models
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"github.com/Noah-Huppert/kube-git-deploy/api/libetcd"
etcd "go.etcd.io/etcd/client"
)
// Job holds information about a job.
type Job struct {
// ID identifies the job.
ID JobID `json:"id"`
// Target identifies the Git event which triggered the job.
Target JobTarget `json:"target"`
// WorkingDir is the directory that the repository source is located.
WorkingDir string `json:"working_dir"`
// State holds the job state.
State JobState `json:"state"`
// Config holds the job configuration. Nil if it hasn't been
// loaded yet.
Config *JobConfig `json:"config"`
}
// NewJob creates a new Job. Intializes all JobState.Stage fields to Queued.
func NewJob(repoID RepositoryID, target JobTarget) *Job {
j := Job{
ID: JobID{
RepositoryID: repoID,
},
Target: target,
}
// Initialize PrepareState
j.State.PrepareState = NewActionState()
// Initialize CleanupState
j.State.CleanupState = NewActionState()
return &j
}
// JobTarget identifies the Git event which triggered the job.
type JobTarget struct {
// Branch is the Git branch.
Branch string `json:"branch"`
// Commit is the Git Sha.
Commit string `json:"commit"`
}
// JobID identifies a job.
type JobID struct {
// RepositoryID is the GitHub repository.
RepositoryID RepositoryID `json:"repository_id"`
// ID is the unique identifying number of the job.
ID int64 `json:"id"`
}
// key indicates the Etcd in which job data will be stored.
func (i JobID) key() string {
return fmt.Sprintf("%s/jobs/%d", i.RepositoryID.key(), i.ID)
}
// Create stores a new job. Finds the next job ID and saves it in the Job.ID
// field. Does not work if the job has already been stored
func (j *Job) Create(ctx context.Context, etcdKV etcd.KeysAPI) error {
// Find next ID
jobsDir := fmt.Sprintf("%s/jobs", j.ID.RepositoryID.key())
resp, err := etcdKV.Get(ctx, jobsDir, &etcd.GetOptions{
Recursive: true,
Sort: true,
Quorum: true,
})
if err != nil {
return fmt.Errorf("error querying job IDs: %s", err.Error())
}
if resp.Node == nil {
return errors.New("while finding next Job ID, result node " +
"was nil")
}
var highestJobID int64 = -1
for _, node := range resp.Node.Nodes {
keyParts := strings.Split(node.Key, "/")
jobIDStr := keyParts[len(keyParts)-1]
jobID, err := strconv.ParseInt(jobIDStr, 10, 64)
if err != nil {
return fmt.Errorf("error parsing Job ID to int, "+
"job ID: %s, error: %s", jobIDStr, err.Error())
}
if jobID > highestJobID {
highestJobID = jobID
}
}
j.ID.ID = highestJobID + 1
// Save
err = j.Set(ctx, etcdKV)
if err != nil {
return fmt.Errorf("error setting job: %s", err.Error())
}
return nil
}
// Set stores a job in Etcd
func (j Job) Set(ctx context.Context, etcdKV etcd.KeysAPI) error {
return libetcd.SetJSON(ctx, etcdKV, j.ID.key(), j)
}
// Get retrieves a job from Etcd. The ID, Metadata.Owner, and
// Metadata.Name fields must be set for method to work properly.
func (j Job) Get(ctx context.Context, etcdKV etcd.KeysAPI) error {
return libetcd.GetJSON(ctx, etcdKV, j.ID.key(), j)
}