Skip to content

Commit

Permalink
[WIP] Remote triggering a pipeline (#158)
Browse files Browse the repository at this point in the history
* WIP for trigger.

* Started working on remote triggering a pipeline.

* Need to find a better way to inject a handler.. but maybe this is okay.

* Put the user generation into the right place.

* Auto user authentication.

* Updated auth.

* Update server.go

* Remote triggering works now.

* Do not use a pointer.

* This now works with parameters.

* Okay this works now.

* Added endpoints to reset the token... no front-end work yet.

* Updated echo.

* Displaying the tokens for users and pipelines.

* Fixed failing tests.

* Working user token re-generation.

* Extra warding..

* Only allow token reset for auto user.

* Only allow token reset for auto user.

* No need to autogenerate the password. No real login will be performed with auto

* Disallow deleting the auto user.

* First test.

* First pipeline test.

* Resetting mock.

* Moar coverage.

* Added test for pipeline token reset.

* Moar coverage.

* Addressed comments.

* Moved trigger token generation to the right place.

* Using a random namespace.

* Extracted the secret uuid generation into a separate package.

* Added test coverage.
  • Loading branch information
Skarlso authored Feb 5, 2019
1 parent ddf8c49 commit 6987967
Show file tree
Hide file tree
Showing 17 changed files with 692 additions and 21 deletions.
22 changes: 16 additions & 6 deletions frontend/client/views/overview/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,35 @@
<hr class="pipeline-hr">
<div>
<i class="fa fa-hourglass"></i>
<span style="color: #b1adad;">
Duration:
<span style="color: #b1adad;">
Duration:
</span>
<span v-if="pipeline.r.status === 'success' || pipeline.r.status === 'failed'">
<span v-if="pipeline.r.status === 'success' || pipeline.r.status === 'failed'">
{{ calculateDuration(pipeline.r.startdate, pipeline.r.finishdate) }}
</span>
<span v-else>
unknown
</span><br />
<i class="fa fa-calendar"></i>
<span style="color: #b1adad;">
Started:
<span style="color: #b1adad;">
Started:
</span>
<span v-if="pipeline.r.status === 'success' || pipeline.r.status === 'failed'">
<span v-if="pipeline.r.status === 'success' || pipeline.r.status === 'failed'">
{{ humanizedDate(pipeline.r.finishdate) }}
</span>
<span v-else>
unknown
</span><br />
<i class="fa fa-exchange"></i>
<span style="color: #b1adad;">
Trigger Token:
</span>
<span v-if="pipeline.p.trigger_token !== ''">
{{ pipeline.p.trigger_token }}
</span>
<span v-else>
unknown
</span><br />
<div class="pipelinegrid-footer">
<a class="button is-primary" @click="checkPipelineArgs(pipeline.p)" style="width: 100%;">
<span class="icon">
Expand Down
109 changes: 108 additions & 1 deletion frontend/client/views/settings/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@
<td :title="props.row.lastlogin" v-tippy="{ arrow : true, animation : 'shift-away'}">
<span>{{ convertTime(props.row.lastlogin) }}</span>
</td>
<td :title="props.row.trigger_token" v-tippy="{ arrow : true, animation : 'shift-away'}">
<span>{{ props.row.trigger_token }}</span>
</td>
<td>
<a v-on:click="editUserModal(props.row)"><i class="fa fa-edit"
style="color: whitesmoke;"></i></a>
<a v-on:click="deleteUserModal(props.row)" v-if="props.row.username !== session.username"><i
<a v-on:click="resetTriggerTokenModal(props.row)" v-if="props.row.username === 'auto'">
<i class="fa fa-sliders" style="color: whitesmoke;"></i></a>
<a v-on:click="deleteUserModal(props.row)" v-if="props.row.username !== session.username && props.row.username !== 'auto'"><i
class="fa fa-trash" style="color: whitesmoke;"></i></a>
</td>
</template>
Expand Down Expand Up @@ -83,6 +88,8 @@
<td>
<a v-on:click="editPipelineModal(props.row)"><i class="fa fa-edit"
style="color: whitesmoke;"></i></a>
<a v-on:click="resetPipelineTriggerTokenModal(props.row)"><i class="fa fa-sliders"
style="color: whitesmoke;"></i></a>
<a v-on:click="deletePipelineModal(props.row)"><i class="fa fa-trash"
style="color: whitesmoke;"></i></a>
</td>
Expand Down Expand Up @@ -144,6 +151,30 @@
</div>
</modal>

<!-- reset trigger token modal -->
<modal :visible="showResetTriggerTokenModal" class="modal-z-index" @close="close">
<div class="box user-modal">
<div class="block user-modal-content">
<collapse accordion is-fullwidth>
<collapse-item title="Reset Trigger Token" selected>
<div class="user-modal-content">
<label class="label" style="text-align: left;">Reset Trigger Token for user {{ selectUser.display_name
}}?</label>
</div>
</collapse-item>
</collapse>
<div class="modal-footer">
<div style="float: left;">
<button class="button is-primary" v-on:click="resetUserTriggerToken">Reset Token</button>
</div>
<div style="float: right;">
<button class="button is-danger" v-on:click="close">Cancel</button>
</div>
</div>
</div>
</div>
</modal>

<!-- delete user modal -->
<modal :visible="showDeleteUserModal" class="modal-z-index" @close="close">
<div class="box user-modal">
Expand Down Expand Up @@ -260,6 +291,32 @@
</div>
</modal>

<!-- reset trigger token modal -->
<modal :visible="showResetPipelineTriggerTokenModal" class="modal-z-index" @close="close">
<div class="box pipeline-modal">
<div class="block pipeline-modal-content">
<collapse accordion is-fullwidth>
<collapse-item title="Reset Pipeline Trigger Token" selected>
<div class="pipeline-modal-content">
<p class="control has-icons-left" style="padding-bottom: 5px;">
<label class="label" style="text-align: left;">Reset Token for pipeline {{ selectPipeline.name
}}?</label>
</p>
</div>
</collapse-item>
</collapse>
<div class="modal-footer">
<div style="float: left;">
<button class="button is-primary" v-on:click="resetPipelineTriggerToken">Reset Token</button>
</div>
<div style="float: right;">
<button class="button is-danger" v-on:click="close">Cancel</button>
</div>
</div>
</div>
</div>
</modal>

<!-- delete pipeline modal -->
<modal :visible="showDeletePipelineModal" class="modal-z-index" @close="close">
<div class="box pipeline-modal">
Expand Down Expand Up @@ -339,6 +396,10 @@
label: 'Last Login',
field: 'lastlogin'
},
{
label: 'Trigger Token',
field: 'trigger_token'
},
{
label: ''
}
Expand Down Expand Up @@ -366,8 +427,10 @@
selectPipeline: {},
showEditUserModal: false,
showDeleteUserModal: false,
showResetTriggerTokenModal: false,
showAddUserModal: false,
showEditPipelineModal: false,
showResetPipelineTriggerTokenModal: false,
showDeletePipelineModal: false,
pipelinePeriodicSchedules: ''
}
Expand Down Expand Up @@ -419,6 +482,11 @@
this.showEditUserModal = true
},
resetTriggerTokenModal (user) {
this.selectUser = user
this.showResetTriggerTokenModal = true
},
deleteUserModal (user) {
this.selectUser = user
this.showDeleteUserModal = true
Expand All @@ -439,6 +507,11 @@
this.showEditPipelineModal = true
},
resetPipelineTriggerTokenModal (pipeline) {
this.selectPipeline = pipeline
this.showResetPipelineTriggerTokenModal = true
},
deletePipelineModal (pipeline) {
this.selectPipeline = pipeline
this.showDeletePipelineModal = true
Expand All @@ -447,9 +520,11 @@
close () {
this.showEditUserModal = false
this.showDeleteUserModal = false
this.showResetTriggerTokenModal = false
this.showAddUserModal = false
this.selectUser = {}
this.showEditPipelineModal = false
this.showResetPipelineTriggerTokenModal = false
this.showDeletePipelineModal = false
this.selectPipeline = {}
this.pipelinePeriodicSchedules = ''
Expand Down Expand Up @@ -483,6 +558,22 @@
this.close()
},
resetUserTriggerToken () {
this.$http
.put('/api/v1/user/' + this.selectUser.username + '/reset-trigger-token')
.then(response => {
openNotification({
title: 'Token changed!',
message: 'New trigger token has been generated!',
type: 'success'
})
})
.catch((error) => {
this.$onError(error)
})
this.close()
},
addUser () {
// pre-validate
if (!this.selectUser.password || !this.selectUser.passwordconf) {
Expand Down Expand Up @@ -582,6 +673,22 @@
this.close()
},
resetPipelineTriggerToken () {
this.$http
.put('/api/v1/pipeline/' + this.selectPipeline.id + '/reset-trigger-token')
.then(response => {
openNotification({
title: 'Token changed!',
message: 'New trigger token has been generated!',
type: 'success'
})
})
.catch((error) => {
this.$onError(error)
})
this.close()
},
deletePipeline () {
this.$http
.delete('/api/v1/pipeline/' + this.selectPipeline.id)
Expand Down
14 changes: 8 additions & 6 deletions gaia.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,13 @@ const (

// User is the user object
type User struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
DisplayName string `json:"display_name,omitempty"`
Tokenstring string `json:"tokenstring,omitempty"`
JwtExpiry int64 `json:"jwtexpiry,omitempty"`
LastLogin time.Time `json:"lastlogin,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
DisplayName string `json:"display_name,omitempty"`
Tokenstring string `json:"tokenstring,omitempty"`
JwtExpiry int64 `json:"jwtexpiry,omitempty"`
LastLogin time.Time `json:"lastlogin,omitempty"`
TriggerToken string `json:"trigger_token,omitempty"`
}

// UserPermission is stored in its own data structure away from the core user. It represents all permission data
Expand Down Expand Up @@ -156,6 +157,7 @@ type Pipeline struct {
UUID string `json:"uuid,omitempty"`
IsNotValid bool `json:"notvalid,omitempty"`
PeriodicSchedules []string `json:"periodicschedules,omitempty"`
TriggerToken string `json:"trigger_token,omitempty"`
CronInst *cron.Cron `json:"-"`
}

Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ require (
github.com/emirpasic/gods v1.9.0 // indirect
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
github.com/gaia-pipeline/flag v1.7.4-pre
github.com/gaia-pipeline/gosdk v0.0.0-20180909192508-cc9f89055777
github.com/gaia-pipeline/protobuf v0.0.0-20180812091451-7be8a901b55a
github.com/gliderlabs/ssh v0.1.1 // indirect
github.com/golang/protobuf v1.2.0
github.com/google/go-cmp v0.2.0 // indirect
github.com/google/go-github v15.0.0+incompatible
github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 // indirect
Expand All @@ -21,7 +23,7 @@ require (
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v0.0.0-20180317175531-9fc7bb800b55 // indirect
github.com/labstack/echo v3.3.5+incompatible
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.0.0-20180613044413-d6898124de91 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.3 // indirect
Expand All @@ -39,9 +41,11 @@ require (
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect
github.com/xanzy/ssh-agent v0.2.0 // indirect
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 // indirect
golang.org/x/text v0.3.0
google.golang.org/grpc v1.18.0
gopkg.in/src-d/go-billy.v4 v4.3.0 // indirect
gopkg.in/src-d/go-git-fixtures.v3 v3.3.0 // indirect
Expand Down
6 changes: 5 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/gaia-pipeline/flag v1.7.4-pre h1:/TAmHVYVQGE4Mw9xl0Qs0D5UruVDMF95thexyEFbTAY=
github.com/gaia-pipeline/flag v1.7.4-pre/go.mod h1:rLpsWzqOEPa2K0Yl4aC34nmblLpIYjGqjP/srZbYvEk=
github.com/gaia-pipeline/gosdk v0.0.0-20180909192508-cc9f89055777 h1:Gn3nmETr4IE44pIFLeTDNNBBRhNXXh53PqFV23CsVok=
github.com/gaia-pipeline/gosdk v0.0.0-20180909192508-cc9f89055777/go.mod h1:e3TkvPdcdSdHZTgwiS89fs8lJrveYHsGLlz/Q0oXlN8=
github.com/gaia-pipeline/protobuf v0.0.0-20180812091451-7be8a901b55a h1:/5XAmdAyGl4yL9BugdPdBLaXquif1zw6Hih6go8E7Xs=
github.com/gaia-pipeline/protobuf v0.0.0-20180812091451-7be8a901b55a/go.mod h1:H0w7MofSuW53Nz7kesnBdVkvr437flf5B7D9Lcsb+lQ=
github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw=
Expand Down Expand Up @@ -53,8 +55,10 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo v3.3.5+incompatible h1:9PfxPUmasKzeJor9uQTaXLT6WUG/r+vSTmvXxvv3JO4=
github.com/labstack/echo v3.3.5+incompatible h1:Y3vG4kINVWNQN8Y6Jdur8uLat7fSLV5n5yLE8n+JbF4=
github.com/labstack/echo v3.3.5+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.0.0-20180613044413-d6898124de91 h1:6R2WAx0PYNGtK2ZED9xKlTGEha51GsCFZijom+NMGEk=
github.com/labstack/gommon v0.0.0-20180613044413-d6898124de91/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
Expand Down
3 changes: 2 additions & 1 deletion handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ func AuthMiddleware(roleAuth *AuthConfig) echo.MiddlewareFunc {
c.Path() == "/" ||
strings.Contains(c.Path(), "/assets/") ||
c.Path() == "/favicon.ico" ||
strings.Contains(c.Path(), "pipeline/githook") {
strings.Contains(c.Path(), "pipeline/githook") ||
strings.Contains(c.Path(), "/trigger") {
return next(c)
}

Expand Down
3 changes: 3 additions & 0 deletions handlers/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func InitHandlers(e *echo.Echo) error {
e.GET(p+"user/:username/permissions", UserGetPermissions)
e.PUT(p+"user/:username/permissions", UserPutPermissions)
e.POST(p+"user", UserAdd)
e.PUT(p+"user/:username/reset-trigger-token", UserResetTriggerToken)

perms := e.Group(p + "permission")
perms.GET("", PermissionGetAll)
Expand All @@ -58,6 +59,8 @@ func InitHandlers(e *echo.Echo) error {
e.PUT(p+"pipeline/:pipelineid", PipelineUpdate)
e.DELETE(p+"pipeline/:pipelineid", PipelineDelete)
e.POST(p+"pipeline/:pipelineid/start", PipelineStart)
e.POST(p+"pipeline/:pipelineid/:pipelinetoken/trigger", PipelineTrigger)
e.PUT(p+"pipeline/:pipelineid/reset-trigger-token", PipelineResetToken)
e.GET(p+"pipeline/latest", PipelineGetAllWithLatestRun)
e.POST(p+"pipeline/periodicschedules", PipelineCheckPeriodicSchedules)

Expand Down
Loading

0 comments on commit 6987967

Please sign in to comment.