Skip to content

Commit 40e2156

Browse files
committed
Implemented ticker which periodically checks the pipeline folder for new pipelines. New pipelines are added to a global slice
1 parent 37ec131 commit 40e2156

File tree

4 files changed

+166
-20
lines changed

4 files changed

+166
-20
lines changed

gaia.go

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import (
1111
type PipelineType string
1212

1313
const (
14+
// UNKNOWN plugin type
15+
UNKNOWN PipelineType = "unknown"
16+
1417
// GOLANG plugin type
1518
GOLANG PipelineType = "golang"
1619
)
@@ -76,3 +79,8 @@ type Config struct {
7679
Mode os.FileMode
7780
}
7881
}
82+
83+
// String returns a pipeline type string back
84+
func (p PipelineType) String() string {
85+
return string(p)
86+
}

pipeline/build_golang.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (b *BuildPipelineGolang) ExecuteBuild(p *gaia.CreatePipeline) error {
7171
args = []string{
7272
"build",
7373
"-o",
74-
p.Pipeline.Name,
74+
appendTypeToName(p.Pipeline.Name, p.Pipeline.Type),
7575
}
7676

7777
// Execute and wait until finish or timeout
@@ -104,8 +104,8 @@ func executeCmd(path string, args []string, env []string, dir string) ([]byte, e
104104
// destination folder.
105105
func (b *BuildPipelineGolang) CopyBinary(p *gaia.CreatePipeline) error {
106106
// Define src and destination
107-
src := p.Pipeline.Repo.LocalDest + string(os.PathSeparator) + p.Pipeline.Name
108-
dest := gaia.Cfg.PipelinePath + string(os.PathSeparator) + p.Pipeline.Name
107+
src := p.Pipeline.Repo.LocalDest + string(os.PathSeparator) + appendTypeToName(p.Pipeline.Name, p.Pipeline.Type)
108+
dest := gaia.Cfg.PipelinePath + string(os.PathSeparator) + appendTypeToName(p.Pipeline.Name, p.Pipeline.Type)
109109

110110
return copyFileContents(src, dest)
111111
}

pipeline/pipeline.go

+72
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package pipeline
22

33
import (
4+
"fmt"
5+
"sync"
6+
47
"github.com/gaia-pipeline/gaia"
58
)
69

@@ -20,12 +23,30 @@ type BuildPipeline interface {
2023
CopyBinary(*gaia.CreatePipeline) error
2124
}
2225

26+
// ActivePipelines holds all active pipelines.
27+
// ActivePipelines can be safely shared between goroutines.
28+
type ActivePipelines struct {
29+
sync.RWMutex
30+
31+
// All active pipelines
32+
Pipelines []gaia.Pipeline
33+
}
34+
2335
const (
2436
// Temp folder where we store our temp files during build pipeline.
2537
tmpFolder = "tmp"
2638

2739
// Max minutes until the build process will be interrupted and marked as failed
2840
maxTimeoutMinutes = 60
41+
42+
// typeDelimiter defines the delimiter in the file name to define
43+
// the pipeline type.
44+
typeDelimiter = "_"
45+
)
46+
47+
var (
48+
// GlobalActivePipelines holds globally all current active pipleines.
49+
GlobalActivePipelines *ActivePipelines
2950
)
3051

3152
// NewBuildPipeline creates a new build pipeline for the given
@@ -43,3 +64,54 @@ func NewBuildPipeline(t gaia.PipelineType) BuildPipeline {
4364

4465
return bP
4566
}
67+
68+
// NewActivePipelines creates a new instance of ActivePipelines
69+
func NewActivePipelines() *ActivePipelines {
70+
ap := &ActivePipelines{
71+
Pipelines: make([]gaia.Pipeline, 0),
72+
}
73+
74+
return ap
75+
}
76+
77+
// Append appends a new pipeline to ActivePipelines.
78+
func (ap *ActivePipelines) Append(p gaia.Pipeline) {
79+
ap.Lock()
80+
defer ap.Unlock()
81+
82+
ap.Pipelines = append(ap.Pipelines, p)
83+
}
84+
85+
// Iter iterates over the pipelines in the concurrent slice.
86+
func (ap *ActivePipelines) Iter() <-chan gaia.Pipeline {
87+
c := make(chan gaia.Pipeline)
88+
89+
go func() {
90+
ap.Lock()
91+
defer ap.Unlock()
92+
for _, pipeline := range ap.Pipelines {
93+
c <- pipeline
94+
}
95+
close(c)
96+
}()
97+
98+
return c
99+
}
100+
101+
// Contains checks if the given pipeline name has been already appended
102+
// to the given ActivePipelines instance.
103+
func (ap *ActivePipelines) Contains(n string) bool {
104+
for pipeline := range ap.Iter() {
105+
if pipeline.Name == n {
106+
return true
107+
}
108+
}
109+
110+
return false
111+
}
112+
113+
// appendTypeToName appends the type to the output binary name.
114+
// This allows us later to define the pipeline type by the name.
115+
func appendTypeToName(n string, pType gaia.PipelineType) string {
116+
return fmt.Sprintf("%s%s%s", n, typeDelimiter, pType.String())
117+
}

pipeline/ticker.go

+83-17
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,109 @@
11
package pipeline
22

33
import (
4+
"errors"
45
"io/ioutil"
6+
"strings"
57
"time"
68

79
"github.com/gaia-pipeline/gaia"
810
)
911

1012
const (
13+
// tickerIntervalSeconds defines how often the ticker will tick.
14+
// Definition in seconds.
1115
tickerIntervalSeconds = 5
1216
)
1317

18+
var (
19+
// errMissingType is the error thrown when a pipeline is missing the type
20+
// in the file name.
21+
errMissingType = errors.New("couldnt find pipeline type definition")
22+
)
23+
1424
// InitTicker inititates the pipeline ticker.
1525
// This periodic job will check for new pipelines.
1626
func InitTicker() {
27+
// Init global active pipelines slice
28+
GlobalActivePipelines = NewActivePipelines()
29+
30+
// Check immediately to make sure we fill the list as fast as possible.
31+
checkActivePipelines()
32+
1733
// Create ticker
1834
ticker := time.NewTicker(tickerIntervalSeconds * time.Second)
19-
quit := make(chan struct{})
20-
21-
// Actual ticker implementation
2235
go func() {
2336
for {
2437
select {
2538
case <-ticker.C:
26-
files, err := ioutil.ReadDir(gaia.Cfg.PipelinePath)
27-
if err != nil {
28-
gaia.Cfg.Logger.Error("cannot read pipelines folder", "error", err.Error(), "path", gaia.Cfg.PipelinePath)
29-
} else {
30-
// Iterate all found pipeline
31-
for _, file := range files {
32-
// TODO: Create for every file a pipeline object
33-
// and store it in a global pipeline array
34-
gaia.Cfg.Logger.Debug("pipeline found", "name", file.Name())
35-
}
36-
}
37-
case <-quit:
38-
ticker.Stop()
39-
return
39+
checkActivePipelines()
4040
}
4141
}
4242
}()
4343
}
44+
45+
// checkActivePipelines looks up all files in the pipeline folder.
46+
// Every file will be handled as an active pipeline and therefore
47+
// saved in the global active pipelines slice.
48+
func checkActivePipelines() {
49+
files, err := ioutil.ReadDir(gaia.Cfg.PipelinePath)
50+
if err != nil {
51+
gaia.Cfg.Logger.Error("cannot read pipelines folder", "error", err.Error(), "path", gaia.Cfg.PipelinePath)
52+
} else {
53+
// Iterate all found pipelines
54+
for _, file := range files {
55+
n := strings.TrimSpace(strings.ToLower(file.Name()))
56+
57+
// Get pipeline type
58+
pType, err := getPipelineType(n)
59+
if err != nil {
60+
gaia.Cfg.Logger.Debug("at least one pipeline in pipeline folder is missing the type definition")
61+
gaia.Cfg.Logger.Debug("Info", "name", n)
62+
gaia.Cfg.Logger.Error("error thrown", "error", err.Error())
63+
continue
64+
}
65+
66+
// Get real pipeline name and check if the global active pipelines slice
67+
// already contains it.
68+
pName := getRealPipelineName(n, pType)
69+
if GlobalActivePipelines.Contains(pName) {
70+
continue
71+
}
72+
73+
// Create pipeline object and fill it with information
74+
p := gaia.Pipeline{
75+
Name: pName,
76+
Type: pType,
77+
Created: time.Now(),
78+
}
79+
80+
// Append new pipeline
81+
GlobalActivePipelines.Append(p)
82+
}
83+
}
84+
}
85+
86+
// getPipelineType looks up for specific suffix on the given file name.
87+
// If found, returns the pipeline type.
88+
func getPipelineType(n string) (gaia.PipelineType, error) {
89+
s := strings.Split(n, typeDelimiter)
90+
91+
// Length must be higher than one
92+
if len(s) < 2 {
93+
return gaia.UNKNOWN, errMissingType
94+
}
95+
96+
// Get last element and look for type
97+
t := s[len(s)-1]
98+
switch t {
99+
case gaia.GOLANG.String():
100+
return gaia.GOLANG, nil
101+
}
102+
103+
return gaia.UNKNOWN, errMissingType
104+
}
105+
106+
// getRealPipelineName removes the suffix from the pipeline name.
107+
func getRealPipelineName(n string, pType gaia.PipelineType) string {
108+
return strings.TrimSuffix(n, typeDelimiter+pType.String())
109+
}

0 commit comments

Comments
 (0)