Skip to content

Commit 6ac0457

Browse files
committed
add private API to patch robot executor
1 parent 6a184d8 commit 6ac0457

File tree

10 files changed

+695
-2
lines changed

10 files changed

+695
-2
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Cerberus Copyright (C) 2013 - 2025 cerberustesting
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This file is part of Cerberus.
6+
*
7+
* Cerberus is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* Cerberus is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with Cerberus. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.cerberus.core.api.controllers;
21+
22+
import com.fasterxml.jackson.annotation.JsonView;
23+
import io.swagger.v3.oas.annotations.Operation;
24+
import io.swagger.v3.oas.annotations.Parameter;
25+
import io.swagger.v3.oas.annotations.media.Content;
26+
import io.swagger.v3.oas.annotations.media.Schema;
27+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
28+
import io.swagger.v3.oas.annotations.tags.Tag;
29+
import lombok.AllArgsConstructor;
30+
import org.apache.logging.log4j.LogManager;
31+
import org.apache.logging.log4j.Logger;
32+
import org.cerberus.core.api.controllers.wrappers.ResponseWrapper;
33+
import org.cerberus.core.api.dto.application.CountryEnvironmentParametersDTOV001;
34+
import org.cerberus.core.api.dto.robot.RobotDTOV001;
35+
import org.cerberus.core.api.dto.robot.RobotExecutorDTOV001;
36+
import org.cerberus.core.api.dto.robot.RobotExecutorMapperV001;
37+
import org.cerberus.core.api.dto.robot.RobotMapperV001;
38+
import org.cerberus.core.api.dto.views.View;
39+
import org.cerberus.core.api.exceptions.EntityNotFoundException;
40+
import org.cerberus.core.api.services.PublicApiAuthenticationService;
41+
import org.cerberus.core.crud.entity.Application;
42+
import org.cerberus.core.crud.entity.LogEvent;
43+
import org.cerberus.core.crud.entity.RobotExecutor;
44+
import org.cerberus.core.crud.service.ILogEventService;
45+
import org.cerberus.core.crud.service.impl.RobotExecutorService;
46+
import org.cerberus.core.crud.service.impl.RobotService;
47+
import org.cerberus.core.exception.CerberusException;
48+
import org.springframework.http.HttpStatus;
49+
import org.springframework.http.MediaType;
50+
import org.springframework.web.bind.annotation.*;
51+
52+
import javax.servlet.http.HttpServletRequest;
53+
import javax.validation.Valid;
54+
import java.security.Principal;
55+
56+
/**
57+
* @author bcivel
58+
*/
59+
@AllArgsConstructor
60+
@Tag(name = "Robot", description = "Endpoints related to Robots")
61+
@RestController
62+
@RequestMapping(path = "/public/robots")
63+
public class RobotController {
64+
65+
private static final String API_VERSION_1 = "X-API-VERSION=1";
66+
private static final String API_KEY = "X-API-KEY";
67+
68+
private final RobotService robotService;
69+
private final RobotExecutorService robotExecutorService;
70+
private final RobotMapperV001 robotMapper;
71+
private final RobotExecutorMapperV001 robotExecutorMapper;
72+
private final ILogEventService logEventService;
73+
private final PublicApiAuthenticationService apiAuthenticationService;
74+
75+
private static final Logger LOG = LogManager.getLogger(RobotController.class);
76+
77+
//FIND ROBOT BY NAME
78+
@GetMapping(path = "/{robot}", headers = API_VERSION_1, produces = MediaType.APPLICATION_JSON_VALUE)
79+
@Operation(
80+
summary = "Get Robot",
81+
description = "Get a robot by its name",
82+
responses = {
83+
@ApiResponse(responseCode = "200", description = "Found the robot", content = { @Content(mediaType = "application/json",schema = @Schema(implementation = RobotDTOV001.class))}),
84+
}
85+
)
86+
@JsonView(View.Public.GET.class)
87+
@ResponseStatus(HttpStatus.OK)
88+
public ResponseWrapper<RobotDTOV001> findRobotByIdName(
89+
@Parameter(description = "Robot name") @PathVariable("robot") String robot,
90+
@Parameter(description = "X-API-KEY for authentication") @RequestHeader(name = API_KEY, required = false) String apiKey,
91+
@Parameter(hidden = true) HttpServletRequest request,
92+
@Parameter(hidden = true) Principal principal) throws CerberusException {
93+
94+
String login = this.apiAuthenticationService.authenticateLogin(principal, apiKey);
95+
logEventService.createForPublicCalls("/public/robots", "CALL-GET", LogEvent.STATUS_INFO, String.format("API /applications called with URL: %s", request.getRequestURL()), request, login);
96+
97+
return ResponseWrapper.wrap(
98+
this.robotMapper.toDTO(
99+
this.robotService.readByKey(robot)
100+
)
101+
);
102+
}
103+
104+
105+
//PATCH ROBOT EXECUTOR
106+
@PatchMapping(path = "/{robot}/{executor}", headers = {API_VERSION_1}, produces = MediaType.APPLICATION_JSON_VALUE)
107+
@Operation(
108+
summary = "Patch Robot Executor",
109+
description = "Patch an robot executor",
110+
responses = {
111+
@ApiResponse(responseCode = "200", description = "Patch the robot executor", content = { @Content(mediaType = "application/json",schema = @Schema(implementation = ResponseWrapper.class))}),
112+
}
113+
)
114+
@JsonView(View.Public.GET.class)
115+
@ResponseStatus(HttpStatus.OK)
116+
public ResponseWrapper<RobotExecutorDTOV001> patchExecutor(
117+
@Parameter(description = "Robot name") @PathVariable("robot") String robot,
118+
@Parameter(description = "Executor name") @PathVariable("executor") String executor,
119+
@Parameter(description = "X-API-KEY for authentication") @RequestHeader(name = API_KEY, required = false) String apiKey,
120+
@Valid @JsonView(View.Public.PATCH.class) @RequestBody RobotExecutorDTOV001 robotExecutorToUpdate,
121+
@Parameter(hidden = true) HttpServletRequest request,
122+
@Parameter(hidden = true) Principal principal) throws CerberusException {
123+
124+
String login = this.apiAuthenticationService.authenticateLogin(principal, apiKey);
125+
logEventService.createForPublicCalls("/public/robots/", "CALL-PATCH", LogEvent.STATUS_INFO, String.format("API /robots called with URL: %s", request.getRequestURL()), request, login);
126+
127+
// We first get the application in order to retreive the system.
128+
RobotExecutor robotExecutor = this.robotExecutorService.readByKey(robot, executor).getItem();
129+
if (robotExecutor == null) {
130+
throw new EntityNotFoundException(RobotExecutor.class, "robotExecutor", robot + "|" + executor);
131+
}
132+
133+
LOG.warn(robotExecutorToUpdate.toString());
134+
135+
return ResponseWrapper.wrap(
136+
this.robotExecutorMapper.toDTO(
137+
this.robotExecutorService.updateRobotExecutorPATCH(
138+
robot,
139+
executor,
140+
robotExecutorToUpdate,
141+
principal,
142+
login
143+
))
144+
);
145+
}
146+
147+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.cerberus.core.api.dto.robot;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
5+
import com.fasterxml.jackson.annotation.JsonView;
6+
import io.swagger.v3.oas.annotations.media.Schema;
7+
import lombok.Builder;
8+
import lombok.Data;
9+
import lombok.extern.jackson.Jacksonized;
10+
import org.cerberus.core.api.dto.views.View;
11+
12+
import javax.validation.constraints.NotBlank;
13+
14+
@Data
15+
@Builder
16+
@Jacksonized
17+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
18+
@JsonPropertyOrder({
19+
"id",
20+
"robot",
21+
"capability",
22+
"value"
23+
})
24+
@Schema(name = "RobotCapability")
25+
public class RobotCapabilityDTOV001 {
26+
27+
@JsonView(View.Public.GET.class)
28+
@Schema(description = "Technical identifier", example = "42")
29+
private Integer id;
30+
31+
@JsonView(View.Public.GET.class)
32+
@Schema(description = "Robot name", example = "CHROME_LINUX")
33+
private String robot;
34+
35+
@NotBlank
36+
@JsonView({View.Public.GET.class, View.Public.POST.class})
37+
@Schema(description = "Capability key", example = "browserName", required = true)
38+
private String capability;
39+
40+
@NotBlank
41+
@JsonView({View.Public.GET.class, View.Public.POST.class})
42+
@Schema(description = "Capability value", example = "chrome", required = true)
43+
private String value;
44+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Cerberus Copyright (C) 2013 - 2025 cerberustesting
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This file is part of Cerberus.
6+
*
7+
* Cerberus is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* Cerberus is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with Cerberus. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.cerberus.core.api.dto.robot;
21+
22+
import org.cerberus.core.crud.entity.RobotCapability;
23+
import org.mapstruct.InheritInverseConfiguration;
24+
import org.mapstruct.Mapper;
25+
26+
/**
27+
* @author bcivel
28+
*/
29+
@Mapper(componentModel = "spring")
30+
public interface RobotCapabilityMapperV001 {
31+
32+
RobotCapabilityDTOV001 toDTO(RobotCapability capability);
33+
34+
@InheritInverseConfiguration
35+
RobotCapability toEntity(RobotCapabilityDTOV001 capabilityDTO);
36+
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/**
2+
* Cerberus Copyright (C) 2013 - 2025 cerberustesting
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This file is part of Cerberus.
6+
*
7+
* Cerberus is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* Cerberus is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with Cerberus. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.cerberus.core.api.dto.robot;
21+
22+
import com.fasterxml.jackson.annotation.JsonInclude;
23+
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
24+
import com.fasterxml.jackson.annotation.JsonView;
25+
import io.swagger.v3.oas.annotations.media.Schema;
26+
import lombok.Builder;
27+
import lombok.Data;
28+
import lombok.extern.jackson.Jacksonized;
29+
import org.cerberus.core.api.dto.views.View;
30+
31+
import javax.validation.constraints.NotBlank;
32+
import javax.validation.constraints.NotNull;
33+
import java.sql.Timestamp;
34+
import java.util.List;
35+
36+
/**
37+
* @author bcivel
38+
*/
39+
@Data
40+
@Builder
41+
@Jacksonized
42+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
43+
@JsonPropertyOrder({
44+
"robotID",
45+
"robot",
46+
"type",
47+
"platform",
48+
"browser",
49+
"version",
50+
"isActive",
51+
"userAgent",
52+
"screenSize",
53+
"profileFolder",
54+
"extraParam",
55+
"acceptNotifications",
56+
"isAcceptInsecureCerts",
57+
"robotDecli",
58+
"lbexemethod",
59+
"description",
60+
"usrCreated",
61+
"dateCreated",
62+
"usrModif",
63+
"dateModif",
64+
"capabilities",
65+
"executors"
66+
})
67+
@Schema(name = "Robot")
68+
public class RobotDTOV001 {
69+
70+
@JsonView(View.Public.GET.class)
71+
@Schema(description = "Robot unique identifier", example = "12")
72+
private Integer robotID;
73+
74+
@NotNull
75+
@JsonView({View.Public.GET.class, View.Public.POST.class})
76+
@Schema(description = "Robot name", example = "CHROME_LINUX")
77+
private String robot;
78+
79+
@JsonView({View.Public.GET.class, View.Public.POST.class})
80+
@Schema(description = "Robot type", example = "GUI")
81+
private String type;
82+
83+
@JsonView({View.Public.GET.class, View.Public.POST.class})
84+
@Schema(description = "Platform", example = "LINUX")
85+
private String platform;
86+
87+
@JsonView({View.Public.GET.class, View.Public.POST.class})
88+
@Schema(description = "Browser", example = "chrome")
89+
private String browser;
90+
91+
@JsonView({View.Public.GET.class, View.Public.POST.class})
92+
@Schema(description = "Browser version", example = "120.0")
93+
private String version;
94+
95+
@JsonView({View.Public.GET.class, View.Public.POST.class})
96+
@Schema(description = "Robot activation status", example = "true")
97+
private Boolean isActive;
98+
99+
@JsonView({View.Public.GET.class, View.Public.POST.class})
100+
@Schema(description = "User agent", example = "Mozilla/5.0 ...")
101+
private String userAgent;
102+
103+
@JsonView({View.Public.GET.class, View.Public.POST.class})
104+
@Schema(description = "Screen resolution", example = "1920x1080")
105+
private String screenSize;
106+
107+
@JsonView({View.Public.GET.class, View.Public.POST.class})
108+
@Schema(description = "Profile folder", example = "/opt/cerberus/profiles/chrome")
109+
private String profileFolder;
110+
111+
@JsonView({View.Public.GET.class, View.Public.POST.class})
112+
@Schema(description = "Extra parameters (JSON or text)", example = "{\"headless\":true}")
113+
private String extraParam;
114+
115+
@JsonView({View.Public.GET.class, View.Public.POST.class})
116+
@Schema(description = "Accept notifications", example = "1")
117+
private Integer acceptNotifications;
118+
119+
@JsonView({View.Public.GET.class, View.Public.POST.class})
120+
@Schema(description = "Accept insecure certificates", example = "false")
121+
private Boolean isAcceptInsecureCerts;
122+
123+
@JsonView({View.Public.GET.class, View.Public.POST.class})
124+
@Schema(description = "Robot declination", example = "CHROME_LINUX_01")
125+
private String robotDecli;
126+
127+
@JsonView({View.Public.GET.class, View.Public.POST.class})
128+
@Schema(
129+
description = "Load balancing executor method",
130+
example = "ROUNDROBIN",
131+
allowableValues = {"ROUNDROBIN", "BYRANKING"}
132+
)
133+
private String lbexemethod;
134+
135+
@JsonView({View.Public.GET.class, View.Public.POST.class})
136+
@Schema(description = "Robot description", example = "Chrome robot for Linux execution")
137+
private String description;
138+
139+
@JsonView(View.Public.GET.class)
140+
@Schema(description = "User who created the robot", example = "admin")
141+
private String usrCreated;
142+
143+
@JsonView(View.Public.GET.class)
144+
@Schema(description = "Creation date")
145+
private Timestamp dateCreated;
146+
147+
@JsonView(View.Public.GET.class)
148+
@Schema(description = "User who last modified the robot", example = "qa_user")
149+
private String usrModif;
150+
151+
@JsonView(View.Public.GET.class)
152+
@Schema(description = "Last modification date")
153+
private Timestamp dateModif;
154+
155+
@JsonView(View.Public.GET.class)
156+
@Schema(description = "Robot capabilities")
157+
private List<RobotCapabilityDTOV001> capabilities;
158+
159+
@JsonView(View.Public.GET.class)
160+
@Schema(description = "Robot executors")
161+
private List<RobotExecutorDTOV001> executors;
162+
}

0 commit comments

Comments
 (0)