Skip to content

Commit 32bf82c

Browse files
authored
Worker builds binary in case the binary doesn't match the worker arch (#200)
* Initial try to build binary by worker. * A little bit of refactoring. * Cleaning up the errorous binary. * A different approach. * Creating an api which the worker can call to get information about the pipeline repo. * Skeleton of the api * Added more logic. * Using the name instead * Moar info * Added correct error display. * RPC endpoint. * Changed impl to gRPC * Fixed wording and nil panic * Using the ID instead. * Cannot save pipeline run * GitPull the repo... * Handling error * It works! * Agent test build failure. * linter * Trying out createpipeline again. * Extracting rebuilding of binary. * Linting fix * mergin... * Fixed version of protoc-gen-go * Create the skeleton for the sha pair work * The skeleton is there. Daughter woke up I will have to continue this a bit later. * Small adjustments. * Added metadata uniqueid to shapair. * Using pipelinID as string. * Working on checking if there was a record or not. * Fixed condition. * Added re-try of the failed operation after the binary has been rebuilt. * Fixed the test. * Added test and nil check for private key. * Deleting it for now... And then I will try to fix that. * Removed gosdk. * Added a basic test case for the re-builder. * Added test for the pipeline rebuilder. * Some more coverage. * TODO: Fix whatever is adding an extra run to the update workflow. It is probably the exec error test. * Fixed the test which was causing problems. * Passed test. * Added moar coverage for the worker. * Added coverage to sha pair methods. * Shifted the sha storing process into bolt db. * Added tests and fixed bucket names. * Changed to PipelineID instead of UniqueID which was unique per run instead of per pipeline. * Fixed comments. * Renamed uniqueID field to pipelineid so it does not get accidentally mistaken for pipeline.UniqueID
1 parent 7c0f920 commit 32bf82c

File tree

11 files changed

+973
-123
lines changed

11 files changed

+973
-123
lines changed

gaia.go

+8
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,14 @@ type Worker struct {
273273
Tags []string `json:"tags"`
274274
}
275275

276+
// SHAPair struct contains the original sha of a pipeline executable and the
277+
// new sha which was created when the worker had to rebuild it.
278+
type SHAPair struct {
279+
Original []byte `json:"original"`
280+
Worker []byte `json:"worker"`
281+
PipelineID int `json:"pipelineid"`
282+
}
283+
276284
// Cfg represents the global config instance
277285
var Cfg = &Config{}
278286

store/sha_pair.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package store
2+
3+
import (
4+
"encoding/json"
5+
6+
bolt "github.com/coreos/bbolt"
7+
"github.com/gaia-pipeline/gaia"
8+
)
9+
10+
// UpsertSHAPair creates or updates a record for a SHA pair of the original SHA and the
11+
// rebuilt Worker SHA for a pipeline.
12+
func (s *BoltStore) UpsertSHAPair(pair gaia.SHAPair) error {
13+
return s.db.Update(func(tx *bolt.Tx) error {
14+
// Get bucket
15+
b := tx.Bucket(shaPairBucket)
16+
17+
// Marshal SHAPair struct
18+
m, err := json.Marshal(pair)
19+
if err != nil {
20+
return err
21+
}
22+
23+
// Put SHAPair
24+
return b.Put(itob(pair.PipelineID), m)
25+
})
26+
}
27+
28+
// GetSHAPair returns a pair of shas for this pipeline run.
29+
func (s *BoltStore) GetSHAPair(pipelineID int) (ok bool, pair gaia.SHAPair, err error) {
30+
return ok, pair, s.db.View(func(tx *bolt.Tx) error {
31+
// Get bucket
32+
b := tx.Bucket(shaPairBucket)
33+
34+
// Get SHAPair
35+
v := b.Get(itob(pipelineID))
36+
37+
// Check if we found the SHAPair
38+
if v == nil {
39+
ok = false
40+
return nil
41+
}
42+
43+
// Unmarshal SHAPair struct
44+
err := json.Unmarshal(v, &pair)
45+
if err != nil {
46+
return err
47+
}
48+
ok = true
49+
return nil
50+
})
51+
}

store/sha_pair_test.go

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package store
2+
3+
import (
4+
"bytes"
5+
"io/ioutil"
6+
"os"
7+
"testing"
8+
9+
"github.com/gaia-pipeline/gaia"
10+
)
11+
12+
func TestGetSHAPair(t *testing.T) {
13+
// Create tmp folder
14+
tmp, err := ioutil.TempDir("", "TestGetSHAPAir")
15+
if err != nil {
16+
t.Fatal(err)
17+
}
18+
defer os.RemoveAll(tmp)
19+
20+
store := NewBoltStore()
21+
gaia.Cfg.Bolt.Mode = 0600
22+
err = store.Init(tmp)
23+
if err != nil {
24+
t.Fatal(err)
25+
}
26+
defer store.Close()
27+
28+
pair := gaia.SHAPair{}
29+
pair.PipelineID = 1
30+
pair.Original = []byte("original")
31+
pair.Worker = []byte("worker")
32+
err = store.UpsertSHAPair(pair)
33+
if err != nil {
34+
t.Fatal(err)
35+
}
36+
37+
ok, p, err := store.GetSHAPair(1)
38+
if err != nil {
39+
t.Fatal(err)
40+
}
41+
if !ok {
42+
t.Fatalf("sha pair not found")
43+
}
44+
45+
if p.PipelineID != pair.PipelineID {
46+
t.Fatalf("pipeline id match error. want %d got %d", pair.PipelineID, p.PipelineID)
47+
}
48+
if !bytes.Equal(p.Worker, pair.Worker) {
49+
t.Fatalf("worker sha match error. want %s got %s", pair.Worker, p.Worker)
50+
}
51+
if !bytes.Equal(p.Original, pair.Original) {
52+
t.Fatalf("original sha match error. want %s got %s", pair.Original, p.Original)
53+
}
54+
}
55+
56+
func TestUpsertSHAPair(t *testing.T) {
57+
// Create tmp folder
58+
tmp, err := ioutil.TempDir("", "TestUpsertSHAPair")
59+
if err != nil {
60+
t.Fatal(err)
61+
}
62+
defer os.RemoveAll(tmp)
63+
64+
store := NewBoltStore()
65+
gaia.Cfg.Bolt.Mode = 0600
66+
err = store.Init(tmp)
67+
if err != nil {
68+
t.Fatal(err)
69+
}
70+
defer store.Close()
71+
72+
pair := gaia.SHAPair{}
73+
pair.PipelineID = 1
74+
pair.Original = []byte("original")
75+
pair.Worker = []byte("worker")
76+
err = store.UpsertSHAPair(pair)
77+
if err != nil {
78+
t.Fatal(err)
79+
}
80+
// Test is upsert overwrites existing records.
81+
pair.Original = []byte("original2")
82+
err = store.UpsertSHAPair(pair)
83+
if err != nil {
84+
t.Fatal(err)
85+
}
86+
87+
ok, p, err := store.GetSHAPair(1)
88+
if err != nil {
89+
t.Fatal(err)
90+
}
91+
if !ok {
92+
t.Fatalf("sha pair not found")
93+
}
94+
95+
if p.PipelineID != pair.PipelineID {
96+
t.Fatalf("pipeline id match error. want %d got %d", pair.PipelineID, p.PipelineID)
97+
}
98+
if !bytes.Equal(p.Worker, pair.Worker) {
99+
t.Fatalf("worker sha match error. want %s got %s", pair.Worker, p.Worker)
100+
}
101+
if !bytes.Equal(p.Original, pair.Original) {
102+
t.Fatalf("original sha match error. want %s got %s", pair.Original, p.Original)
103+
}
104+
}

store/store.go

+41-39
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ var (
3333

3434
// Name of the bucket where we store all worker.
3535
workerBucket = []byte("Worker")
36+
37+
// SHA pair bucket.
38+
shaPairBucket = []byte("SHAPair")
3639
)
3740

3841
const (
@@ -85,6 +88,8 @@ type GaiaStore interface {
8588
WorkerDelete(id string) error
8689
WorkerDeleteAll() error
8790
WorkerGet(id string) (*gaia.Worker, error)
91+
UpsertSHAPair(pair gaia.SHAPair) error
92+
GetSHAPair(pipelineID int) (bool, gaia.SHAPair, error)
8893
}
8994

9095
// Compile time interface compliance check for BoltStore. If BoltStore
@@ -120,54 +125,48 @@ func (s *BoltStore) Close() error {
120125
return s.db.Close()
121126
}
122127

123-
// setupDatabase create all buckets in the db.
124-
// Additionally, it makes sure that the admin user exists.
125-
func (s *BoltStore) setupDatabase() error {
126-
// Create bucket if not exists function
127-
var bucketName []byte
128+
type setup struct {
129+
bs *BoltStore
130+
err error
131+
}
132+
133+
// Create bucket if not exists function
134+
func (s *setup) update(bucketName []byte) {
135+
// update is a no-op in case there was already an error
136+
if s.err != nil {
137+
return
138+
}
128139
c := func(tx *bolt.Tx) error {
129140
_, err := tx.CreateBucketIfNotExists(bucketName)
130141
if err != nil {
131142
return fmt.Errorf("create bucket: %s", err)
132143
}
133144
return nil
134145
}
146+
s.err = s.bs.db.Update(c)
147+
}
135148

136-
// Make sure buckets exist
137-
bucketName = userBucket
138-
err := s.db.Update(c)
139-
if err != nil {
140-
return err
141-
}
142-
bucketName = userPermsBucket
143-
err = s.db.Update(c)
144-
if err != nil {
145-
return err
146-
}
147-
bucketName = pipelineBucket
148-
err = s.db.Update(c)
149-
if err != nil {
150-
return err
151-
}
152-
bucketName = createPipelineBucket
153-
err = s.db.Update(c)
154-
if err != nil {
155-
return err
156-
}
157-
bucketName = pipelineRunBucket
158-
err = s.db.Update(c)
159-
if err != nil {
160-
return err
161-
}
162-
bucketName = settingsBucket
163-
err = s.db.Update(c)
164-
if err != nil {
165-
return err
149+
// setupDatabase create all buckets in the db.
150+
// Additionally, it makes sure that the admin user exists.
151+
func (s *BoltStore) setupDatabase() error {
152+
// Create bucket if not exists function
153+
setP := &setup{
154+
bs: s,
155+
err: nil,
166156
}
167-
bucketName = workerBucket
168-
err = s.db.Update(c)
169-
if err != nil {
170-
return err
157+
158+
// Make sure buckets exist
159+
setP.update(userBucket)
160+
setP.update(userPermsBucket)
161+
setP.update(pipelineBucket)
162+
setP.update(createPipelineBucket)
163+
setP.update(pipelineRunBucket)
164+
setP.update(settingsBucket)
165+
setP.update(workerBucket)
166+
setP.update(shaPairBucket)
167+
168+
if setP.err != nil {
169+
return setP.err
171170
}
172171

173172
// Make sure that the user "admin" does exist
@@ -195,6 +194,9 @@ func (s *BoltStore) setupDatabase() error {
195194
}
196195

197196
u, err := s.UserGet(autoUsername)
197+
if err != nil {
198+
return err
199+
}
198200

199201
if u == nil {
200202
triggerToken := security.GenerateRandomUUIDV5()

0 commit comments

Comments
 (0)