feat(runner): create new token for creating new runner

This commit is contained in:
fuxiaohei 2022-10-17 21:21:43 +08:00 committed by Jason Song
parent 243c1e5134
commit f633ec9704
7 changed files with 128 additions and 21 deletions

View File

@ -49,13 +49,6 @@ func init() {
db.RegisterModel(new(RunnerToken))
}
// NewRunnerToken creates new runner token.
func NewRunnerToken(t *RunnerToken) error {
t.Token = base.EncodeSha1(gouuid.New().String())
_, err := db.GetEngine(db.DefaultContext).Insert(t)
return err
}
// GetRunnerByToken returns a bot runner via token
func GetRunnerToken(token string) (*RunnerToken, error) {
var runnerToken RunnerToken
@ -81,3 +74,28 @@ func UpdateRunnerToken(ctx context.Context, r *RunnerToken, cols ...string) (err
}
return err
}
// NewRunnerToken creates a new runner token
func NewRunnerToken(ownerID, repoID int64) (*RunnerToken, error) {
runnerToken := &RunnerToken{
OwnerID: ownerID,
RepoID: repoID,
IsActive: false,
// FIXME: why token is 36 chars?
Token: base.EncodeSha1(gouuid.New().String())[:36],
}
_, err := db.GetEngine(db.DefaultContext).Insert(runnerToken)
return runnerToken, err
}
// GetUnactivatedRunnerToken returns a unactivated runner token
func GetUnactivatedRunnerToken(ownerID, repoID int64) (*RunnerToken, error) {
var runnerToken RunnerToken
has, err := db.GetEngine(db.DefaultContext).Where("owner_id=? AND repo_id=? AND is_active=0", ownerID, repoID).OrderBy("id DESC").Get(&runnerToken)
if err != nil {
return nil, err
} else if !has {
return nil, ErrRunnerTokenNotExist{}
}
return &runnerToken, nil
}

View File

@ -3005,6 +3005,32 @@ notices.desc = Description
notices.op = Op.
notices.delete_success = The system notices have been deleted.
runners = Runners
runners.runner_manage_panel = Runners Management
runners.new = Create new Runner
runners.new_notice = Show runner installation documentation
runners.status = Status
runners.id = ID
runners.owner_type = Type
runners.description = Description
runners.labels = Labels
runners.latest_online = Last Online Time
runners.agent_labels = Agent Labels
runners.custom_labels = Custom Labels
runners.custom_labels_helper = Custom labels are labels that are not automatically added by the agent. They are added by the administrator. Use comma separated.
runners.runner_title = Runner
runners.task_list = Recent jobs on this runner
runners.edit_runner = Edit Runner
runners.update_runner = Update Changes
runners.update_runner_success = Runner updated successfully
runners.update_runner_failed = Failed to update runner
runners.delete_runner = Delete this runner
runners.delete_runner_success = Runner deleted successfully
runners.delete_runner_failed = Failed to delete runner
runners.delete_runner_header = Confirm to delete this runner
runners.delete_runner_notice = If job is running on this runner, it will be terminated and mark as failed. It may break building workflow.
runners.delete_runner_confirm = Delete this runner
[action]
create_repo = created repository <a href="%s">%s</a>
rename_repo = renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>

View File

@ -63,9 +63,26 @@ func Runners(ctx *context.Context) {
return
}
// ownid=0,repo_id=0,means this token is used for global
var token *bots_model.RunnerToken
token, err = bots_model.GetUnactivatedRunnerToken(0, 0)
if _, ok := err.(bots_model.ErrRunnerTokenNotExist); ok {
token, err = bots_model.NewRunnerToken(0, 0)
if err != nil {
ctx.ServerError("CreateRunnerToken", err)
return
}
} else {
if err != nil {
ctx.ServerError("GetUnactivatedRunnerToken", err)
return
}
}
ctx.Data["Keyword"] = opts.Filter
ctx.Data["Runners"] = runners
ctx.Data["Total"] = count
ctx.Data["RegistrationToken"] = token.Token
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
ctx.Data["Page"] = pager
@ -75,7 +92,7 @@ func Runners(ctx *context.Context) {
// EditRunner show editing runner page
func EditRunner(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("admin.runners.edit")
ctx.Data["Title"] = ctx.Tr("admin.runners.edit_runner")
ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminRunners"] = true
@ -107,7 +124,7 @@ func EditRunnerPost(ctx *context.Context) {
err = bots_model.UpdateRunner(ctx, runner, "description", "custom_labels")
if err != nil {
log.Warn("EditRunnerPost.UpdateRunner failed: %v, url: %s", err, ctx.Req.URL)
ctx.Flash.Warning(ctx.Tr("admin.runners.edit_failed"))
ctx.Flash.Warning(ctx.Tr("admin.runners.update_runner_failed"))
ctx.Redirect(setting.AppSubURL + "/admin/runners/" + url.PathEscape(ctx.Params(":runnerid")))
return
}
@ -118,7 +135,7 @@ func EditRunnerPost(ctx *context.Context) {
log.Debug("EditRunnerPost success: %s", ctx.Req.URL)
ctx.Flash.Success(ctx.Tr("admin.runners.edit_success"))
ctx.Flash.Success(ctx.Tr("admin.runners.update_runner_success"))
ctx.Redirect(setting.AppSubURL + "/admin/runners/" + url.PathEscape(ctx.Params(":runnerid")))
}
@ -134,14 +151,25 @@ func DeleteRunnerPost(ctx *context.Context) {
err = bots_model.DeleteRunner(ctx, runner)
if err != nil {
log.Warn("DeleteRunnerPost.UpdateRunner failed: %v, url: %s", err, ctx.Req.URL)
ctx.Flash.Warning(ctx.Tr("admin.runners.delete_failed"))
ctx.Flash.Warning(ctx.Tr("admin.runners.delete_runner_failed"))
ctx.Redirect(setting.AppSubURL + "/admin/runners/" + url.PathEscape(ctx.Params(":runnerid")))
return
}
log.Info("DeleteRunnerPost success: %s", ctx.Req.URL)
ctx.Flash.Success(ctx.Tr("admin.runners.deletion_success"))
ctx.Flash.Success(ctx.Tr("admin.runners.delete_runner_success"))
ctx.Redirect(setting.AppSubURL + "/admin/runners/")
}
func ResetRunnerRegistrationToken(ctx *context.Context) {
_, err := bots_model.NewRunnerToken(0, 0)
if err != nil {
ctx.ServerError("ResetRunnerRegistrationToken", err)
return
}
ctx.Flash.Success(ctx.Tr("admin.runners.reset_registration_token_success"))
ctx.Redirect(setting.AppSubURL + "/admin/runners/")
}

View File

@ -627,6 +627,7 @@ func RegisterRoutes(m *web.Route) {
m.Group("/runners", func() {
m.Get("", admin.Runners)
m.Get("/reset_registration_token", admin.ResetRunnerRegistrationToken)
m.Combo("/{runnerid}").Get(admin.EditRunner).Post(bindIgnErr(forms.AdminEditRunnerForm{}), admin.EditRunnerPost)
m.Post("/{runnerid}/delete", admin.DeleteRunnerPost)
})

View File

@ -16,7 +16,7 @@
<span class="runner-status-{{.Runner.StatusType}}">{{.Runner.StatusType}}</span>
</div>
<div class="field dib">
<label>{{.locale.Tr "admin.runners.last_online"}}</label>
<label>{{.locale.Tr "admin.runners.latest_online"}}</label>
<span>{{TimeSinceUnix .Runner.LastOnline $.locale}}</span>
</div>
<div class="field dib">
@ -56,7 +56,7 @@
</div>
<h4 class="ui top attached header">
{{.locale.Tr "admin.runner.task_list"}}
{{.locale.Tr "admin.runners.task_list"}}
</h4>
<div class="ui attached segment">
Comming soon
@ -66,18 +66,18 @@
<div class="ui small modal" id="runner-delete-modal">
<div class="header">
{{.locale.Tr "admin.runners.delete_header"}}
{{.locale.Tr "admin.runners.delete_runner_header"}}
</div>
<div class="content">
<div class="ui warning message text left">
{{.locale.Tr "admin.runnners.delete_notice" | Safe}}
{{.locale.Tr "admin.runners.delete_runner_notice" | Safe}}
</div>
<form class="ui form" action="{{.Link}}/delete" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="delete">
<div class="text right actions">
<div class="ui cancel button">{{.locale.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.locale.Tr "admin.runners.delete_confirm"}}</button>
<button class="ui red button">{{.locale.Tr "admin.runners.delete_runner_confirm"}}</button>
</div>
</form>
</div>

View File

@ -6,7 +6,32 @@
<h4 class="ui top attached header">
{{.locale.Tr "admin.runners.runner_manage_panel"}} ({{.locale.Tr "admin.total" .Total}})
<div class="ui right">
<a class="ui primary tiny button" href="{{AppSubUrl}}/admin/runners/new">{{.locale.Tr "admin.runners.new"}}</a>
<!--<a class="ui primary tiny button" href="{{AppSubUrl}}/admin/runners/new">{{.locale.Tr "admin.runners.new"}}</a>-->
<div class="ui top right pointing dropdown button primary" id="runner-new">
<span class="text runner-new-text">{{.locale.Tr "admin.runners.new"}}</span>
<div class="menu runner-new-menu">
<div class="item">
<a href="#">{{.locale.Tr "admin.runners.new_notice"}}</a>
</div>
<div class="divider"></div>
<div class="header">
Registration Token
</div>
<div class="ui input">
<input type="text" value="{{.RegistrationToken}}">
<div class="ui basic label button" data-clipboard-text="{{.RegistrationToken}}">
{{svg "octicon-copy" 14}}
</div>
</div>
<div class="divider"></div>
<div class="item">
<a href="{{$.Link}}/reset_registration_token">Reset registration token</a>
</div>
</div>
</div>
</div>
</h4>
<div class="ui attached segment">
@ -26,9 +51,9 @@
<th data-sortt-asc="alphabetically">
{{.locale.Tr "admin.runners.id"}}
</th>
<th>{{.locale.Tr "admin.runners.own_type"}}</th>
<th>{{.locale.Tr "admin.runners.tags"}}</th>
<th>{{.locale.Tr "admin.runners.latest_contact"}}</th>
<th>{{.locale.Tr "admin.runners.owner_type"}}</th>
<th>{{.locale.Tr "admin.runners.labels"}}</th>
<th>{{.locale.Tr "admin.runners.latest_online"}}</th>
<th></th>
</tr>
</thead>

View File

@ -15,4 +15,13 @@
background-color: var(--color-green);
color: var(--color-white);
}
.runner-new-text{
color: var(--color-white)
}
#runner-new:hover .runner-new-text{
color: var(--color-white) !important;
}
.runner-new-menu{
width: 300px;
}
}