Skip to content

Commit 2c57eea

Browse files
authored
Pipeline parameters (#71)
* Implemented pipeline parameters * Fixed auto redirect to startPipeline. Fixed reset of already set arguments
1 parent 22073ca commit 2c57eea

File tree

12 files changed

+305
-66
lines changed

12 files changed

+305
-66
lines changed

cmd/gaia/main.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,18 @@ func main() {
146146
os.Exit(1)
147147
}
148148

149+
// Initiating Vault
150+
// Check Vault path
151+
if gaia.Cfg.VaultPath == "" {
152+
// Set default to data folder
153+
gaia.Cfg.VaultPath = gaia.Cfg.DataPath
154+
}
155+
_, err = services.VaultService(nil)
156+
if err != nil {
157+
gaia.Cfg.Logger.Error("error initiating vault")
158+
os.Exit(1)
159+
}
160+
149161
// Initialize scheduler
150162
_, err = services.SchedulerService()
151163
if err != nil {
@@ -159,18 +171,6 @@ func main() {
159171
os.Exit(1)
160172
}
161173

162-
// Initiating Vault
163-
// Check Vault path
164-
if gaia.Cfg.VaultPath == "" {
165-
// Set default to data folder
166-
gaia.Cfg.VaultPath = gaia.Cfg.DataPath
167-
}
168-
_, err = services.VaultService(nil)
169-
if err != nil {
170-
gaia.Cfg.Logger.Error("error initiating vault")
171-
os.Exit(1)
172-
}
173-
174174
// Start ticker. Periodic job to check for new plugins.
175175
pipeline.InitTicker()
176176

frontend/client/router/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ export default new Router({
2323
name: 'Pipeline Logs',
2424
path: '/pipeline/log',
2525
component: lazyLoading('pipeline/log')
26+
},
27+
{
28+
name: 'Pipeline Parameters',
29+
path: '/pipeline/params',
30+
component: lazyLoading('pipeline/params')
2631
}
2732
]
2833
})

frontend/client/views/overview/index.vue

+23-6
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
unknown
3939
</span><br />
4040
<div class="pipelinegrid-footer">
41-
<a class="button is-primary" @click="startPipeline(pipeline.p.id)" style="width: 250px;">
41+
<a class="button is-primary" @click="checkPipelineArgs(pipeline.p)" style="width: 250px;">
4242
<span class="icon">
4343
<i class="fa fa-play-circle"></i>
4444
</span>
@@ -52,7 +52,7 @@
5252
</template>
5353
<div v-if="pipelines.length == 0" class="no-pipelines-div">
5454
<span class="no-pipelines-text">No pipelines are available. Please create a pipeline first.</span>
55-
</div>
55+
</div>
5656
</div>
5757
</template>
5858

@@ -62,7 +62,8 @@ import moment from 'moment'
6262
export default {
6363
data () {
6464
return {
65-
pipelines: []
65+
pipelines: [],
66+
pipeline: null
6667
}
6768
},
6869
@@ -102,13 +103,29 @@ export default {
102103
})
103104
},
104105
105-
startPipeline (pipelineid) {
106+
checkPipelineArgs (pipeline) {
107+
this.pipeline = pipeline
108+
109+
// check if this pipeline has args
110+
for (let x = 0, y = pipeline.jobs.length; x < y; x++) {
111+
if (pipeline.jobs[x].args && pipeline.jobs[x].args.type !== 'vault') {
112+
// we found args. Redirect user to params view.
113+
this.$router.push({path: '/pipeline/params', query: { pipelineid: pipeline.id }})
114+
return
115+
}
116+
}
117+
118+
// No args. Just start pipeline.
119+
this.startPipeline()
120+
},
121+
122+
startPipeline () {
106123
// Send start request
107124
this.$http
108-
.post('/api/v1/pipeline/' + pipelineid + '/start')
125+
.post('/api/v1/pipeline/' + this.pipeline.id + '/start')
109126
.then(response => {
110127
if (response.data) {
111-
this.$router.push({path: '/pipeline/detail', query: { pipelineid: pipelineid, runid: response.data.id }})
128+
this.$router.push({path: '/pipeline/detail', query: { pipelineid: this.pipeline.id, runid: response.data.id }})
112129
}
113130
})
114131
.catch((error) => {

frontend/client/views/pipeline/detail.vue

+22-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="tile is-ancestor">
33
<div class="tile is-vertical">
44
<div class="tile is-parent">
5-
<a class="button is-primary" @click="startPipeline(pipelineID)" style="margin-right: 10px;">
5+
<a class="button is-primary" @click="checkPipelineArgs" style="margin-right: 10px;">
66
<span class="icon">
77
<i class="fa fa-play-circle"></i>
88
</span>
@@ -120,7 +120,8 @@ export default {
120120
},
121121
arrows: {to: true}
122122
}
123-
}
123+
},
124+
pipeline: null
124125
}
125126
},
126127
@@ -183,6 +184,7 @@ export default {
183184
this.drawPipelineDetail(pipeline.data, pipelineRun.data)
184185
}
185186
this.runsRows = pipelineRuns.data
187+
this.pipeline = pipeline.data
186188
}.bind(this)))
187189
.catch((error) => {
188190
this.$store.commit('clearIntervals')
@@ -201,6 +203,7 @@ export default {
201203
if (pipelineRuns.data) {
202204
this.runsRows = pipelineRuns.data
203205
}
206+
this.pipeline = pipeline.data
204207
}.bind(this)))
205208
.catch((error) => {
206209
this.$store.commit('clearIntervals')
@@ -355,13 +358,27 @@ export default {
355358
this.$router.push({path: '/pipeline/log', query: { pipelineid: this.pipelineID, runid: this.runID }})
356359
},
357360
358-
startPipeline (pipelineid) {
361+
checkPipelineArgs () {
362+
// check if this pipeline has args
363+
for (let x = 0, y = this.pipeline.jobs.length; x < y; x++) {
364+
if (this.pipeline.jobs[x].args && this.pipeline.jobs[x].args.type !== 'vault') {
365+
// we found args. Redirect user to params view.
366+
this.$router.push({path: '/pipeline/params', query: { pipelineid: this.pipeline.id }})
367+
return
368+
}
369+
}
370+
371+
// No args. Just start pipeline.
372+
this.startPipeline()
373+
},
374+
375+
startPipeline () {
359376
// Send start request
360377
this.$http
361-
.post('/api/v1/pipeline/' + pipelineid + '/start')
378+
.post('/api/v1/pipeline/' + this.pipeline.id + '/start')
362379
.then(response => {
363380
if (response.data) {
364-
this.$router.push({path: '/pipeline/detail', query: { pipelineid: pipelineid, runid: response.data.id }})
381+
this.$router.push({path: '/pipeline/detail', query: { pipelineid: this.pipeline.id, runid: response.data.id }})
365382
}
366383
})
367384
.catch((error) => {
@@ -370,7 +387,6 @@ export default {
370387
})
371388
}
372389
}
373-
374390
}
375391
</script>
376392

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<template>
2+
<div>
3+
<div class="columns is-multiline">
4+
<template v-for="(arg, index) in args">
5+
<div class="column is-one-third" :key="index">
6+
<div class="content-article params-div">
7+
<h2 v-if="arg.type !== 'boolean'">{{ arg.desc }}</h2>
8+
<p class="control" style="padding-bottom: 5px;" v-if="arg.type === 'textfield'">
9+
<input class="input is-medium input-bar" v-focus v-model="arg.value" :placeholder="arg.key">
10+
</p>
11+
<p class="control" v-else-if="arg.type === 'textarea'">
12+
<textarea class="textarea input-bar" v-model="arg.value" :placeholder="arg.key"></textarea>
13+
</p>
14+
<p class="control" v-else-if="arg.type === 'boolean'">
15+
<label class="checkbox">
16+
<input type="checkbox">
17+
{{ arg.desc }}
18+
</label>
19+
</p>
20+
</div>
21+
</div>
22+
</template>
23+
</div>
24+
<a class="button is-primary" v-on:click="startPipeline" style="margin-top: 5px;">
25+
<span class="icon">
26+
<i class="fa fa-play-circle"></i>
27+
</span>
28+
<span>Start Pipeline</span>
29+
</a>
30+
</div>
31+
</template>
32+
33+
<script>
34+
export default {
35+
data () {
36+
return {
37+
args: [],
38+
pipelineID: null
39+
}
40+
},
41+
42+
mounted () {
43+
// Fetch data from backend
44+
this.fetchData()
45+
},
46+
47+
watch: {
48+
'$route': 'fetchData'
49+
},
50+
51+
methods: {
52+
fetchData () {
53+
// look up url parameters
54+
var pipelineID = this.$route.query.pipelineid
55+
if (!pipelineID) {
56+
return
57+
}
58+
this.pipelineID = pipelineID
59+
60+
// reset args
61+
this.args = []
62+
63+
this.$http
64+
.get('/api/v1/pipeline/' + pipelineID, { showProgressBar: false })
65+
.then(response => {
66+
if (response.data) {
67+
let pipeline = response.data
68+
69+
// Get all arguments
70+
for (let x = 0, y = pipeline.jobs.length; x < y; x++) {
71+
let args = pipeline.jobs[x].args
72+
// we skip vault cause this is automatically filled by the vault.
73+
if (args) {
74+
// iterate all arguments
75+
for (let argID = 0, argTotal = args.length; argID < argTotal; argID++) {
76+
// we skip vault arguments cause they are autofilled in the backend.
77+
if (args[argID].type !== 'vault') {
78+
this.args.push(args[argID])
79+
}
80+
}
81+
}
82+
}
83+
}
84+
})
85+
.catch((error) => {
86+
this.$onError(error)
87+
})
88+
},
89+
90+
startPipeline () {
91+
// Send start request
92+
this.$http
93+
.post('/api/v1/pipeline/' + this.pipelineID + '/start', this.args)
94+
.then(response => {
95+
if (response.data) {
96+
this.$router.push({path: '/pipeline/detail', query: { pipelineid: this.pipelineID, runid: response.data.id }})
97+
}
98+
})
99+
.catch((error) => {
100+
this.$onError(error)
101+
})
102+
}
103+
}
104+
}
105+
</script>
106+
107+
<style lang="scss">
108+
109+
.params-div {
110+
padding: 15px;
111+
width: 100%;
112+
}
113+
114+
.checkbox:hover {
115+
color: #4da2fc;
116+
}
117+
118+
</style>

gaia.go

+14-5
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,20 @@ type GitRepo struct {
110110

111111
// Job represents a single job of a pipeline
112112
type Job struct {
113-
ID uint32 `json:"id,omitempty"`
114-
Title string `json:"title,omitempty"`
115-
Description string `json:"desc,omitempty"`
116-
DependsOn []*Job `json:"dependson,omitempty"`
117-
Status JobStatus `json:"status,omitempty"`
113+
ID uint32 `json:"id,omitempty"`
114+
Title string `json:"title,omitempty"`
115+
Description string `json:"desc,omitempty"`
116+
DependsOn []*Job `json:"dependson,omitempty"`
117+
Status JobStatus `json:"status,omitempty"`
118+
Args []Argument `json:"args,omitempty"`
119+
}
120+
121+
// Argument represents a single argument of a job
122+
type Argument struct {
123+
Description string `json:"desc,omitempty"`
124+
Type string `json:"type,omitempty"`
125+
Key string `json:"key,omitempty"`
126+
Value string `json:"value,omitempty"`
118127
}
119128

120129
// CreatePipeline represents a pipeline which is not yet

handlers/pipeline.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,17 @@ func PipelineDelete(c echo.Context) error {
235235
}
236236

237237
// PipelineStart starts a pipeline by the given id.
238+
// It accepts arguments for the given pipeline.
238239
// Afterwards it returns the created/scheduled pipeline run.
239240
func PipelineStart(c echo.Context) error {
240241
schedulerService, _ := services.SchedulerService()
241242
pipelineIDStr := c.Param("pipelineid")
242243

244+
// Look for arguments.
245+
// We do not check for errors here cause arguments are optional.
246+
args := []gaia.Argument{}
247+
c.Bind(&args)
248+
243249
// Convert string to int because id is int
244250
pipelineID, err := strconv.Atoi(pipelineIDStr)
245251
if err != nil {
@@ -255,7 +261,7 @@ func PipelineStart(c echo.Context) error {
255261
}
256262

257263
if foundPipeline.Name != "" {
258-
pipelineRun, err := schedulerService.SchedulePipeline(&foundPipeline)
264+
pipelineRun, err := schedulerService.SchedulePipeline(&foundPipeline, args)
259265
if err != nil {
260266
return c.String(http.StatusBadRequest, err.Error())
261267
} else if pipelineRun != nil {

handlers/pipeline_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type mockScheduleService struct {
2727
err error
2828
}
2929

30-
func (ms *mockScheduleService) SchedulePipeline(p *gaia.Pipeline) (*gaia.PipelineRun, error) {
30+
func (ms *mockScheduleService) SchedulePipeline(p *gaia.Pipeline, args []gaia.Argument) (*gaia.PipelineRun, error) {
3131
return ms.pipelineRun, ms.err
3232
}
3333

0 commit comments

Comments
 (0)