Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui,api): display spawn info on waiting job #3667

Merged
merged 17 commits into from
Dec 3, 2018
3 changes: 1 addition & 2 deletions engine/api/workflow/dao_node_job_run_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"time"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/api/database/gorpmapping"
"github.com/ovh/cds/sdk"
"github.com/ovh/cds/sdk/log"
Expand Down Expand Up @@ -52,6 +51,6 @@ func insertNodeRunJobInfo(db gorp.SqlExecutor, info *sdk.WorkflowNodeJobRunInfo)
return fmt.Errorf("insertNodeRunJobInfo> Unable to insert into workflow_node_run_job_info id = %d", info.WorkflowNodeJobRunID)
}

log.Debug("insertNodeRunJobInfo> on node run: %d (%d)", info.ID, info.WorkflowNodeJobRunID)
log.Debug("insertNodeRunJobInfo> on node run: %v (%d)", info.SpawnInfos, info.WorkflowNodeJobRunID)
return nil
}
17 changes: 11 additions & 6 deletions engine/api/workflow/dao_node_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func LoadNodeRun(db gorp.SqlExecutor, projectkey, workflowname string, number, i
return nil, sdk.WrapError(err, "Unable to load workflow_node_run proj=%s, workflow=%s, num=%d, node=%d", projectkey, workflowname, number, id)
}

r, err := fromDBNodeRun(rr, loadOpts)
r, err := fromDBNodeRun(db, rr, loadOpts)
if err != nil {
return nil, sdk.WithStack(err)
}
Expand Down Expand Up @@ -140,7 +140,7 @@ func LoadNodeRunByNodeJobID(db gorp.SqlExecutor, nodeJobRunID int64, loadOpts Lo
return nil, sdk.WrapError(err, "Unable to load workflow_node_run node_job_id=%d", nodeJobRunID)
}

r, err := fromDBNodeRun(rr, loadOpts)
r, err := fromDBNodeRun(db, rr, loadOpts)
if err != nil {
return nil, sdk.WithStack(err)
}
Expand Down Expand Up @@ -185,7 +185,7 @@ func LoadAndLockNodeRunByID(ctx context.Context, db gorp.SqlExecutor, id int64,
}
return nil, sdk.WrapError(err, "Unable to load workflow_node_run node=%d", id)
}
return fromDBNodeRun(rr, LoadRunOptions{})
return fromDBNodeRun(db, rr, LoadRunOptions{})
}

//LoadNodeRunByID load a specific node run on a workflow
Expand All @@ -205,7 +205,7 @@ func LoadNodeRunByID(db gorp.SqlExecutor, id int64, loadOpts LoadRunOptions) (*s
return nil, sdk.WrapError(err, "Unable to load workflow_node_run node=%d", id)
}

r, err := fromDBNodeRun(rr, loadOpts)
r, err := fromDBNodeRun(db, rr, loadOpts)
if err != nil {
return nil, sdk.WithStack(err)
}
Expand Down Expand Up @@ -248,7 +248,7 @@ func nodeRunExist(db gorp.SqlExecutor, nodeID, num int64, subnumber int) (bool,
return nb > 0, err
}

func fromDBNodeRun(rr NodeRun, opts LoadRunOptions) (*sdk.WorkflowNodeRun, error) {
func fromDBNodeRun(db gorp.SqlExecutor, rr NodeRun, opts LoadRunOptions) (*sdk.WorkflowNodeRun, error) {
r := new(sdk.WorkflowNodeRun)
if rr.WorkflowID.Valid {
r.WorkflowID = rr.WorkflowID.Int64
Expand Down Expand Up @@ -300,6 +300,11 @@ func fromDBNodeRun(rr NodeRun, opts LoadRunOptions) (*sdk.WorkflowNodeRun, error
if rj.Status == sdk.StatusWaiting.String() {
rj.QueuedSeconds = time.Now().Unix() - rj.Queued.Unix()
}
spawnInfos, err := loadNodeRunJobInfo(db, rj.ID)
if err != nil {
return nil, sdk.WrapError(err, "unable to load spawn infos for runJob: %d", rj.ID)
}
rj.SpawnInfos = spawnInfos
}
}

Expand Down Expand Up @@ -716,7 +721,7 @@ func PreviousNodeRun(db gorp.SqlExecutor, nr sdk.WorkflowNodeRun, n sdk.Workflow
if err := db.SelectOne(&rr, query, workflowID, n.Name, nr.VCSBranch, nr.VCSTag, nr.Number, nr.ID); err != nil {
return nodeRun, sdk.WrapError(err, "Cannot load previous run on workflow %d node %s nr.VCSBranch:%s nr.VCSTag:%s nr.Number:%d nr.ID:%d ", workflowID, n.Name, nr.VCSBranch, nr.VCSTag, nr.Number, nr.ID)
}
pNodeRun, errF := fromDBNodeRun(rr, LoadRunOptions{})
pNodeRun, errF := fromDBNodeRun(db, rr, LoadRunOptions{})
if errF != nil {
return nodeRun, sdk.WrapError(errF, "PreviousNodeRun> Cannot read node run")
}
Expand Down
3 changes: 1 addition & 2 deletions engine/api/workflow/dao_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"time"

"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/api/database/gorpmapping"
"github.com/ovh/cds/engine/api/observability"
"github.com/ovh/cds/sdk"
Expand Down Expand Up @@ -724,7 +723,7 @@ func syncNodeRuns(db gorp.SqlExecutor, wr *sdk.WorkflowRun, loadOpts LoadRunOpti
}

for _, n := range dbNodeRuns {
wnr, err := fromDBNodeRun(n, loadOpts)
wnr, err := fromDBNodeRun(db, n, loadOpts)
if err != nil {
return err
}
Expand Down
3 changes: 1 addition & 2 deletions engine/api/workflow/execute_node_job_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/go-gorp/gorp"
"github.com/lib/pq"

"github.com/ovh/cds/engine/api/application"
"github.com/ovh/cds/engine/api/cache"
"github.com/ovh/cds/engine/api/environment"
Expand Down Expand Up @@ -745,7 +744,7 @@ func RestartWorkflowNodeJob(ctx context.Context, db gorp.SqlExecutor, wNodeJob s
return sdk.WrapError(errNR, "RestartWorkflowNodeJob> Cannot load node run")
}

//Synchronise struct but not in db
//Synchronize struct but not in db
sync, errS := SyncNodeRunRunJob(ctx, db, nodeRun, wNodeJob)
if errS != nil {
return sdk.WrapError(errS, "RestartWorkflowNodeJob> error on sync nodeJobRun")
Expand Down
11 changes: 10 additions & 1 deletion engine/api/workflow/execute_node_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"github.com/fsamin/go-dump"
"github.com/go-gorp/gorp"

"github.com/ovh/cds/engine/api/cache"
"github.com/ovh/cds/engine/api/group"
"github.com/ovh/cds/engine/api/observability"
Expand Down Expand Up @@ -426,6 +425,12 @@ func addJobsToQueue(ctx context.Context, db gorp.SqlExecutor, stage *sdk.Stage,
Message: spawnInfos,
RemoteTime: time.Now(),
}}
} else {
wjob.SpawnInfos = []sdk.SpawnInfo{sdk.SpawnInfo{
APITime: time.Now(),
Message: sdk.SpawnMsg{ID: sdk.MsgSpawnInfoJobInQueue.ID, Args: []interface{}{}},
RemoteTime: time.Now(),
}}
}

//Insert in database
Expand All @@ -436,6 +441,10 @@ func addJobsToQueue(ctx context.Context, db gorp.SqlExecutor, stage *sdk.Stage,
}
next()

if err := AddSpawnInfosNodeJobRun(db, wjob.ID, PrepareSpawnInfos(wjob.SpawnInfos)); err != nil {
return nil, sdk.WrapError(err, "Cannot save spawn info job %d", wjob.ID)
}

//Put the job run in database
stage.RunJobs = append(stage.RunJobs, wjob)

Expand Down
2 changes: 2 additions & 0 deletions sdk/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ var (
MsgSpawnInfoHatcheryErrorSpawn = &Message{"MsgSpawnInfoHatcheryErrorSpawn", trad{FR: "Une erreur est survenue lorsque la Hatchery %s (%s) a démarré un worker avec le modèle %s après %s, err:%s", EN: "Error while Hatchery %s (%s) spawn worker with model %s after %s, err:%s"}, nil}
MsgSpawnInfoHatcheryStartsSuccessfully = &Message{"MsgSpawnInfoHatcheryStartsSuccessfully", trad{FR: "La Hatchery %s (%s) a démarré le worker %s avec succès en %s", EN: "Hatchery %s (%s) spawn worker %s successfully in %s"}, nil}
MsgSpawnInfoWorkerEnd = &Message{"MsgSpawnInfoWorkerEnd", trad{FR: "Le worker %s a terminé et a passé %s à travailler sur les étapes", EN: "Worker %s finished working on this job and took %s to work on the steps"}, nil}
MsgSpawnInfoJobInQueue = &Message{"MsgSpawnInfoJobInQueue", trad{FR: "Le job a été pris mis en file d'attente", EN: "Job was queued"}, nil}
MsgSpawnInfoJobTaken = &Message{"MsgSpawnInfoJobTaken", trad{FR: "Le job %s a été pris par le worker %s", EN: "Job %s was taken by worker %s"}, nil}
MsgSpawnInfoJobTakenWorkerVersion = &Message{"MsgSpawnInfoJobTakenWorkerVersion", trad{FR: "Worker %s version:%s os:%s arch:%s", EN: "Worker %s version:%s os:%s arch:%s"}, nil}
MsgSpawnInfoWorkerForJob = &Message{"MsgSpawnInfoWorkerForJob", trad{FR: "Ce worker %s a été créé pour lancer ce job", EN: "This worker %s was created to take this action"}, nil}
Expand Down Expand Up @@ -125,6 +126,7 @@ var Messages = map[string]*Message{
MsgSpawnInfoHatcheryErrorSpawn.ID: MsgSpawnInfoHatcheryErrorSpawn,
MsgSpawnInfoHatcheryStartsSuccessfully.ID: MsgSpawnInfoHatcheryStartsSuccessfully,
MsgSpawnInfoWorkerEnd.ID: MsgSpawnInfoWorkerEnd,
MsgSpawnInfoJobInQueue.ID: MsgSpawnInfoJobInQueue,
MsgSpawnInfoJobTaken.ID: MsgSpawnInfoJobTaken,
MsgSpawnInfoJobTakenWorkerVersion.ID: MsgSpawnInfoJobTakenWorkerVersion,
MsgSpawnInfoWorkerForJob.ID: MsgSpawnInfoWorkerForJob,
Expand Down
4 changes: 2 additions & 2 deletions ui/src/app/views/workflow/run/node/pipeline/pipeline.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@
<div class="log animated fadeIn" *ngIf="selectedRunJob && mapStepStatus">
<ul>
<li>
<app-workflow-rin-job-spawn-info
<app-workflow-run-job-spawn-info
[spawnInfos]="selectedRunJob.spawninfos"
[variables]="selectedRunJob.parameters"
[job]="selectedRunJob.job"
[(displayServicesLogs)]="displayServiceLogs">
</app-workflow-rin-job-spawn-info>
</app-workflow-run-job-spawn-info>
</li>
<ng-container *ngIf="!displayServiceLogs">
<li *ngFor="let step of selectedRunJob.job.action.actions; let i = index">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {Component, EventEmitter, Input, Output, ViewChild} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import * as AU from 'ansi_up';
import {Job} from '../../../../../../model/job.model';
import {Parameter} from '../../../../../../model/parameter.model';
import {SpawnInfo} from '../../../../../../model/pipeline.model';
import {JobVariableComponent} from '../../../../../run/workflow/variables/job.variables.component';

@Component({
selector: 'app-workflow-rin-job-spawn-info',
selector: 'app-workflow-run-job-spawn-info',
templateUrl: './spawninfo.html',
styleUrls: ['./spawninfo.scss']
})
Expand Down Expand Up @@ -42,7 +43,7 @@ export class WorkflowRunJobSpawnInfoComponent {
_displayServiceLogs: boolean;
ansi_up = new AU.default;

constructor() { }
constructor(private _translate: TranslateService) {}

refreshDisplayServiceLogsLink() {
if (this.job && this.job.action && Array.isArray(this.job.action.requirements)) {
Expand All @@ -64,7 +65,7 @@ export class WorkflowRunJobSpawnInfoComponent {
if (msg !== '') {
return this.ansi_up.ansi_to_html(msg);
}
return '';
return this._translate.instant('job_spawn_no_information');
}

openVariableModal(event: Event): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="spawn" *ngIf="spawnInfos">
<div class="spawn">
<div class="header pointing" (click)="toggle()">
<div class="status">
<i class="icon heartbeat"></i>
Expand All @@ -20,7 +20,7 @@
</a>
</div>
</div>
<div class="spawnInfos" *ngIf="spawnInfos" [hidden]="!show">
<div class="spawnInfos" [hidden]="!show">
<pre [innerHTML]="getSpawnInfos()">
</pre>
</div>
Expand Down
1 change: 1 addition & 0 deletions ui/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@
"job_delete": "Delete job",
"job_save": "Save job",
"job_spawn_title": "Information",
"job_spawn_no_information": "No information for now...",

"monitoring": "Monitoring",

Expand Down
1 change: 1 addition & 0 deletions ui/src/assets/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@
"job_delete": "Supprimer le job",
"job_save": "Sauvegarder le job",
"job_spawn_title": "Informations",
"job_spawn_no_information": "Pas d'information pour l'instant...",

"monitoring": "Monitoring",

Expand Down