Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
BBesrour committed Nov 27, 2024
1 parent 4eaba4e commit daa17ad
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public ResponseEntity<BuildJobsStatisticsDTO> getBuildJobStatistics(@RequestPara
}

/**
* {@code PUT /api/admin/agent/{agentName}/pause} : Pause the specified build agent.
* {@code PUT /api/admin/agents/{agentName}/pause} : Pause the specified build agent.
* This endpoint allows administrators to pause a specific build agent by its name.
* Pausing a build agent will prevent it from picking up any new build jobs until it is resumed.
*
Expand All @@ -207,15 +207,34 @@ public ResponseEntity<BuildJobsStatisticsDTO> getBuildJobStatistics(@RequestPara
* @return {@link ResponseEntity} with status code 204 (No Content) if the agent was successfully paused
* or an appropriate error response if something went wrong
*/
@PutMapping("agent/{agentName}/pause")
@PutMapping("agents/{agentName}/pause")
public ResponseEntity<Void> pauseBuildAgent(@PathVariable String agentName) {
log.debug("REST request to pause agent {}", agentName);
localCIBuildJobQueueService.pauseBuildAgent(agentName);
return ResponseEntity.noContent().build();
}

/**
* {@code PUT /api/admin/agent/{agentName}/resume} : Resume the specified build agent.
* {@code PUT /api/admin/agents/pause-all} : Pause all build agents.
* This endpoint allows administrators to pause all build agents.
* Pausing all build agents will prevent them from picking up any new build jobs until they are resumed.
*
* <p>
* <strong>Authorization:</strong> This operation requires admin privileges, enforced by {@code @EnforceAdmin}.
* </p>
*
* @return {@link ResponseEntity} with status code 204 (No Content) if all agents were successfully paused
* or an appropriate error response if something went wrong
*/
@PutMapping("agents/pause-all")
public ResponseEntity<Void> pauseAllBuildAgents() {
log.debug("REST request to pause all agents");
localCIBuildJobQueueService.pauseAllBuildAgents();
return ResponseEntity.noContent().build();
}

/**
* {@code PUT /api/admin/agents/{agentName}/resume} : Resume the specified build agent.
* This endpoint allows administrators to resume a specific build agent by its name.
* Resuming a build agent will allow it to pick up new build jobs again.
*
Expand All @@ -227,10 +246,29 @@ public ResponseEntity<Void> pauseBuildAgent(@PathVariable String agentName) {
* @return {@link ResponseEntity} with status code 204 (No Content) if the agent was successfully resumed
* or an appropriate error response if something went wrong
*/
@PutMapping("agent/{agentName}/resume")
@PutMapping("agents/{agentName}/resume")
public ResponseEntity<Void> resumeBuildAgent(@PathVariable String agentName) {
log.debug("REST request to resume agent {}", agentName);
localCIBuildJobQueueService.resumeBuildAgent(agentName);
return ResponseEntity.noContent().build();
}

/**
* {@code PUT /api/admin/agents/resume-all} : Resume all build agents.
* This endpoint allows administrators to resume all build agents.
* Resuming all build agents will allow them to pick up new build jobs again.
*
* <p>
* <strong>Authorization:</strong> This operation requires admin privileges, enforced by {@code @EnforceAdmin}.
* </p>
*
* @return {@link ResponseEntity} with status code 204 (No Content) if all agents were successfully resumed
* or an appropriate error response if something went wrong
*/
@PutMapping("agents/resume-all")
public ResponseEntity<Void> resumeAllBuildAgents() {
log.debug("REST request to resume all agents");
localCIBuildJobQueueService.resumeAllBuildAgents();
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,18 @@ public void pauseBuildAgent(String agent) {
pauseBuildAgentTopic.publish(agent);
}

public void pauseAllBuildAgents() {
getBuildAgentInformation().forEach(agent -> pauseBuildAgent(agent.buildAgent().name()));
}

public void resumeBuildAgent(String agent) {
resumeBuildAgentTopic.publish(agent);
}

public void resumeAllBuildAgents() {
getBuildAgentInformation().forEach(agent -> resumeBuildAgent(agent.buildAgent().name()));
}

/**
* Cancel a build job by removing it from the queue or stopping the build process.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
<div style="padding-bottom: 60px">
<h3 id="build-agents-heading" jhiTranslate="artemisApp.buildAgents.summary"></h3>
@if (buildAgents) {
<p>
{{ buildAgents.length }} <span jhiTranslate="artemisApp.buildAgents.onlineAgents"></span>: {{ currentBuilds }} <span jhiTranslate="artemisApp.buildAgents.of"></span>
{{ buildCapacity }} <span jhiTranslate="artemisApp.buildAgents.buildJobsRunning"></span>
</p>
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-3"></div>
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-3">
<div>
<h3 id="build-agents-heading" jhiTranslate="artemisApp.buildAgents.summary"></h3>
<p>
{{ buildAgents.length }} <span jhiTranslate="artemisApp.buildAgents.onlineAgents"></span>: {{ currentBuilds }}
<span jhiTranslate="artemisApp.buildAgents.of"></span> {{ buildCapacity }} <span jhiTranslate="artemisApp.buildAgents.buildJobsRunning"></span>
</p>
</div>
<div>
<button class="btn btn-success" (click)="resumeAllBuildAgents()">
<fa-icon [icon]="faPlay" />
<span jhiTranslate="artemisApp.buildAgents.resumeAll"></span>
</button>
<button class="btn btn-danger" (click)="displayPauseBuildAgentModal(content)">
<fa-icon [icon]="faPause" />
<span jhiTranslate="artemisApp.buildAgents.pauseAll"></span>
</button>
</div>
</div>
<jhi-data-table [showPageSizeDropdown]="false" [showSearchField]="false" entityType="buildAgent" [allEntities]="buildAgents!">
<ng-template let-settings="settings" let-controls="controls">
<ngx-datatable
Expand Down Expand Up @@ -115,3 +128,28 @@ <h3 id="build-agents-heading" jhiTranslate="artemisApp.buildAgents.summary"></h3
</jhi-data-table>
}
</div>

<!-- Modal -->
<ng-template #content let-modal>
<div class="modal-header">
<h5 class="modal-title">
<span jhiTranslate="artemisApp.buildAgents.pauseAll"></span>
</h5>
<button type="button" class="btn-close" aria-label="Close" (click)="modal.close()"></button>
</div>
<div class="modal-body">
<div>
<span jhiTranslate="artemisApp.buildAgents.pauseAllWarning"></span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="modal.close()">
<fa-icon [icon]="faTimes" />
<span jhiTranslate="artemisApp.buildQueue.filter.close"></span>
</button>
<button type="button" class="btn btn-danger" (click)="pauseAllBuildAgents(modal)">
<fa-icon [icon]="faPause" />
<span jhiTranslate="artemisApp.buildAgents.pauseAll"></span>
</button>
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { BuildAgentInformation } from 'app/entities/programming/build-agent-information.model';
import { BuildAgentInformation, BuildAgentStatus } from 'app/entities/programming/build-agent-information.model';
import { JhiWebsocketService } from 'app/core/websocket/websocket.service';
import { BuildAgentsService } from 'app/localci/build-agents/build-agents.service';
import { Subscription } from 'rxjs';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
import { faPause, faPlay, faTimes } from '@fortawesome/free-solid-svg-icons';
import { BuildQueueService } from 'app/localci/build-queue/build-queue.service';
import { Router } from '@angular/router';
import { BuildAgent } from 'app/entities/programming/build-agent.model';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { AlertService, AlertType } from 'app/core/util/alert.service';

@Component({
selector: 'jhi-build-agents',
Expand All @@ -23,13 +25,17 @@ export class BuildAgentSummaryComponent implements OnInit, OnDestroy {
routerLink: string;

//icons
faTimes = faTimes;
protected readonly faTimes = faTimes;
protected readonly faPause = faPause;
protected readonly faPlay = faPlay;

constructor(
private websocketService: JhiWebsocketService,
private buildAgentsService: BuildAgentsService,
private buildQueueService: BuildQueueService,
private router: Router,
private modalService: NgbModal,
private alertService: AlertService,
) {}

ngOnInit() {
Expand Down Expand Up @@ -59,7 +65,9 @@ export class BuildAgentSummaryComponent implements OnInit, OnDestroy {

private updateBuildAgents(buildAgents: BuildAgentInformation[]) {
this.buildAgents = buildAgents;
this.buildCapacity = this.buildAgents.reduce((sum, agent) => sum + (agent.maxNumberOfConcurrentBuildJobs || 0), 0);
this.buildCapacity = this.buildAgents
.filter((agent) => agent.status !== BuildAgentStatus.PAUSED)
.reduce((sum, agent) => sum + (agent.maxNumberOfConcurrentBuildJobs || 0), 0);
this.currentBuilds = this.buildAgents.reduce((sum, agent) => sum + (agent.numberOfCurrentBuildJobs || 0), 0);
}

Expand All @@ -86,4 +94,47 @@ export class BuildAgentSummaryComponent implements OnInit, OnDestroy {
this.buildQueueService.cancelAllRunningBuildJobsForAgent(buildAgentToCancel.buildAgent?.name).subscribe();
}
}

displayPauseBuildAgentModal(modal: any) {
this.modalService.open(modal);
}

pauseAllBuildAgents(modal?: any) {
this.buildAgentsService.pauseAllBuildAgents().subscribe({
next: () => {
this.load();
this.alertService.addAlert({
type: AlertType.SUCCESS,
message: 'artemisApp.buildAgents.alerts.buildAgentsPaused',
});
},
error: () => {
this.alertService.addAlert({
type: AlertType.DANGER,
message: 'artemisApp.buildAgents.alerts.buildAgentPauseFailed',
});
},
});
if (modal) {
modal.close();
}
}

resumeAllBuildAgents() {
this.buildAgentsService.resumeAllBuildAgents().subscribe({
next: () => {
this.load();
this.alertService.addAlert({
type: AlertType.SUCCESS,
message: 'artemisApp.buildAgents.alerts.buildAgentsResumed',
});
},
error: () => {
this.alertService.addAlert({
type: AlertType.DANGER,
message: 'artemisApp.buildAgents.alerts.buildAgentResumeFailed',
});
},
});
}
}
26 changes: 24 additions & 2 deletions src/main/webapp/app/localci/build-agents/build-agents.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,44 @@ export class BuildAgentsService {
*/
pauseBuildAgent(agentName: string): Observable<void> {
const encodedAgentName = encodeURIComponent(agentName);
return this.http.put<void>(`${this.adminResourceUrl}/agent/${encodedAgentName}/pause`, null).pipe(
return this.http.put<void>(`${this.adminResourceUrl}/agents/${encodedAgentName}/pause`, null).pipe(
catchError((err) => {
return throwError(() => new Error(`Failed to pause build agent ${agentName}\n${err.message}`));
}),
);
}

/**
* Pause All Build Agents
*/
pauseAllBuildAgents(): Observable<void> {
return this.http.put<void>(`${this.adminResourceUrl}/agents/pause-all`, null).pipe(
catchError((err) => {
return throwError(() => new Error(`Failed to pause build agents\n${err.message}`));
}),
);
}

/**
* Resume Build Agent
*/
resumeBuildAgent(agentName: string): Observable<void> {
const encodedAgentName = encodeURIComponent(agentName);
return this.http.put<void>(`${this.adminResourceUrl}/agent/${encodedAgentName}/resume`, null).pipe(
return this.http.put<void>(`${this.adminResourceUrl}/agents/${encodedAgentName}/resume`, null).pipe(
catchError((err) => {
return throwError(() => new Error(`Failed to resume build agent ${agentName}\n${err.message}`));
}),
);
}

/**
* Resume all Build Agents
*/
resumeAllBuildAgents(): Observable<void> {
return this.http.put<void>(`${this.adminResourceUrl}/agents/resume-all`, null).pipe(
catchError((err) => {
return throwError(() => new Error(`Failed to resume build agents\n${err.message}`));
}),
);
}
}
9 changes: 7 additions & 2 deletions src/main/webapp/i18n/de/buildAgents.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@
"buildAgentResumed": "Anfrage zum Fortsetzen des BuildJobs erfolgreich gesendet. Der Agent wird wieder neue BuildJobs annehmen.",
"buildAgentPauseFailed": "Anhalten des Build-Agenten fehlgeschlagen.",
"buildAgentResumeFailed": "Fortsetzen des Build-Agenten fehlgeschlagen.",
"buildAgentWithoutName": "Der Name des Build-Agenten ist erforderlich."
"buildAgentWithoutName": "Der Name des Build-Agenten ist erforderlich.",
"buildAgentsPaused": "Anfrage zum Anhalten aller Build-Agenten erfolgreich gesendet. Die Agenten akzeptieren keine neuen Build-Jobs und werden die aktuellen Build-Jobs entweder ordnungsgemäß beenden oder nach einer konfigurierbaren Anzahl von Sekunden abbrechen.",
"buildAgentsResumed": "Anfrage zum Fortsetzen aller Build-Agenten erfolgreich gesendet. Die Agenten werden wieder neue Build-Jobs annehmen."
},
"pause": "Anhalten",
"resume": "Fortsetzen"
"resume": "Fortsetzen",
"pauseAll": "Alle Agenten Anhalten",
"resumeAll": "Alle Agenten fortsetzen",
"pauseAllWarning": "Du bist dabei, alle Build-Agenten anzuhalten. Dies wird verhindern, dass sie neue Build-Jobs verarbeiten.\nBist du sicher, dass du fortfahren möchtest?"
}
}
}
13 changes: 9 additions & 4 deletions src/main/webapp/i18n/en/buildAgents.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@
"alerts": {
"buildAgentPaused": "Build agent pause request sent successfully. The agent will not accept new build jobs and will gracefully finish the current build jobs or will cancel them after a configurable seconds.",
"buildAgentResumed": "Build agent resume request sent successfully. The agent will start accepting new build jobs.",
"buildAgentPauseFailed": "Failed to pause the build agent.",
"buildAgentResumeFailed": "Failed to resume the build agent.",
"buildAgentWithoutName": "Build agent name is required."
"buildAgentPauseFailed": "Failed to pause build agent.",
"buildAgentResumeFailed": "Failed to resume build agent.",
"buildAgentWithoutName": "Build agent name is required.",
"buildAgentsPaused": "Pause request sent to all build agents. The agents will not accept new build jobs and will gracefully finish the current build jobs or will cancel them after a configurable seconds.",
"buildAgentsResumed": "Resume request sent to all build agents. The agents will start accepting new build jobs."
},
"pause": "Pause",
"resume": "Resume"
"resume": "Resume",
"pauseAll": "Pause All Agents",
"resumeAll": "Resume All Agents",
"pauseAllWarning": "You are about to pause all build agents. This will prevent them from processing any new build jobs.\nAre you sure you want to proceed?"
}
}
}
Loading

0 comments on commit daa17ad

Please sign in to comment.