Skip to content

Commit e8d294d

Browse files
authored
Get All Engagement Paging and Status Performance (#124)
* initial paging for get all engagements * remove unused call * cleanup * fixes for get status perf, rest exception handling, tests * added pagination test for get all * cleanup commented code * fix for query param name and updated readme * moved pagedresults to pagination package * rm accidental commit of route template
1 parent 87be725 commit e8d294d

File tree

17 files changed

+771
-393
lines changed

17 files changed

+771
-393
lines changed

README.md

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,84 @@ The JSON REST APIs consist of the following resources:
1616

1717
### Config Resource
1818

19-
The config resource exposes an API that allows clients to retrieve a configured `Config` file from GitLab.
19+
The config resource exposes an API that allows clients to retrieve a configuration files from GitLab.
20+
21+
#### LodeStar Runtime Configuration File
2022

2123
```
2224
GET /api/v1/config
25+
GET /api/v2/config
2326
```
2427

28+
Version 1 of the API returns the file in YAML and version 2 of the API returns the file in JSON.
29+
30+
#### Webhooks Configuration File
31+
32+
```
33+
GET /api/v2/config/webhooks
34+
```
35+
36+
Returns a JSON representation of the configured webhooks.
37+
2538
### Engagement Resource
2639

2740
The engagement resource exposes an API that allows clients to create or update and engagement resource in GitLab.
2841

2942
```
30-
POST /api/v1/engagements
43+
POST ​ /api​/v1​/engagements
44+
```
45+
Used to create or update an engagement. This endpoint will create the expected group/project structure in GitLab. Then, will update the `engagement.json` file if it already exists or create it if it does not.
46+
```
47+
POST ​/api​/v1​/engagements​/customer​/{customer}​/{engagement}​/hooks
3148
```
49+
Used to create a webhook in GitLab for the project associated to the customer and engagement name combination.
50+
```
51+
GET ​ /api​/v1​/engagements
52+
```
53+
Optional query parameters:
54+
55+
- `includeCommits` - adds commit data to engagement if set to `true`
56+
- `includeStatus` - adds status data to engagement if set to `true`
57+
- `pagination` - returns a single page of engagements if true. all if false
58+
- `page` - page number to retrieve from GitLab
59+
- `per_page` - number of engagements to return per page
60+
61+
Pagination Headers Returned:
62+
- `Link` - contains links for rel `first`, `last`, and `next`. `next` omitted if last page is requested
63+
- `x-first-page` number of first page
64+
- `x-next-page` number of next page (omitted if last page)
65+
- `x-last-page` number of last page
3266

33-
This endpoint will create the expected group/project structure in GitLab. Then, will update the `engagement.json` file if it already exists or create it if it does not.
67+
```
68+
```
69+
GET ​ /api​/v1​/engagements​/customer​/{customer}​/{engagement}
70+
```
71+
Returns the engagement associated with the customer and engagement name combination.
72+
```
73+
```
74+
GET ​/api​/v1​/engagements​/customer​/{customer}​/{engagement}​/commits
75+
```
76+
Returns a list of commits associated with the customer and engagement name combination.
77+
```
78+
GET ​/api​/v1​/engagements​/customer​/{customer}​/{engagement}​/hooks
79+
```
80+
Returns the webhooks for the engagement associated with the customer and engagement name combination.
81+
```
82+
GET ​/api​/v1​/engagements​/customer​/{customer}​/{engagement}​/status
83+
```
84+
Returns the status data for the engagement associated with the customer and engagement name combination.
85+
```
86+
GET ​/api​/v1​/engagements​/namespace​/{namespace}
87+
```
88+
Returns the engagement associated with the provided namespace.
89+
```
90+
DELETE ​/api​/v1​/engagements​/customer​/{customer}​/{engagement}
91+
```
92+
Deletes the engagement associated with the customer and engagement name combination. Will only delete if engagement has not been lost.
93+
```
94+
DELETE ​/api​/v1​/engagements​/hooks
95+
```
96+
Deletes all webhooks in all configured engagement projects.
3497

3598
### Version Resource
3699

@@ -75,13 +138,15 @@ Deployment template will read from the above secret and inject following env var
75138
| CONFIG_FILE | my-config.yml | True |
76139
| CONFIG_GITLAB_REF | master | False |
77140
| WEBHOOK_FILE | webhooks.yml | False |
141+
| CONFIG_RELOAD | true | False |
78142

79143
### Engagements Resource
80144

81145
| Name | Example Value | Required |
82146
|------|---------------|----------|
83147
| ENGAGEMENTS_REPOSITORY_ID | 2 | True |
84148
| WEBHOOK_DEFAULT_TOKEN | tolkien | False |
149+
| ENGAGEMENTS_PRESERVE | true | False |
85150

86151
### Version Resource
87152

@@ -90,6 +155,13 @@ Deployment template will read from the above secret and inject following env var
90155
| GIT_API_GIT_COMMIT | a2adfk | False |
91156
| GIT_API_GIT_TAG | v1.2 | False |
92157

158+
### Other
159+
160+
| Name | Example Value | Required |
161+
|------|---------------|----------|
162+
| ENV_ID | TEST | False |
163+
164+
93165
## Development
94166

95167
See [the deployment README](deployment/README.md) for details on how to spin up a deployment for developing on OpenShift.

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
<maven.compiler.target>11</maven.compiler.target>
1515
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1616
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
17-
<quarkus-plugin.version>1.6.1.Final</quarkus-plugin.version>
17+
<quarkus-plugin.version>1.11.3.Final</quarkus-plugin.version>
1818
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
1919
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
20-
<quarkus.platform.version>1.6.1.Final</quarkus.platform.version>
21-
<surefire-plugin.version>2.22.1</surefire-plugin.version>
20+
<quarkus.platform.version>1.11.3.Final</quarkus.platform.version>
21+
<surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
2222
<lombok.version>1.18.12</lombok.version>
2323
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
2424
<sonar.project.key>rht-labs_lodestar-git-api</sonar.project.key>

src/main/java/com/redhat/labs/lodestar/exception/mapper/ApiExceptionMapper.java

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/main/java/com/redhat/labs/lodestar/exception/mapper/GitLabServiceResponseMapper.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,30 @@
99
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
1010

1111
@Priority(4000)
12-
public class GitLabServiceResponseMapper implements
13-
ResponseExceptionMapper<RuntimeException> {
14-
@Override
15-
public RuntimeException toThrowable(Response response) {
16-
int status = response.getStatus();
12+
public class GitLabServiceResponseMapper implements ResponseExceptionMapper<RuntimeException> {
13+
@Override
14+
public RuntimeException toThrowable(Response response) {
15+
int status = response.getStatus();
1716

18-
String msg = getBody(response);
17+
String msg = getBody(response);
1918

20-
return new WebApplicationException(msg, status);
19+
return new WebApplicationException(msg, status);
2120

22-
}
21+
}
22+
23+
private String getBody(Response response) {
24+
25+
if (response.hasEntity()) {
26+
27+
ByteArrayInputStream is = (ByteArrayInputStream) response.getEntity();
28+
byte[] bytes = new byte[is.available()];
29+
is.read(bytes, 0, is.available());
30+
return new String(bytes);
31+
32+
}
33+
34+
return null;
2335

24-
private String getBody(Response response) {
25-
ByteArrayInputStream is = (ByteArrayInputStream) response.getEntity();
26-
byte[] bytes = new byte[is.available()];
27-
is.read(bytes,0,is.available());
28-
return new String(bytes);
2936
}
3037

3138
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.redhat.labs.lodestar.models.gitlab;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
@Data
9+
@Builder
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
public class ProjectTreeNode {
13+
14+
private String id;
15+
private String name;
16+
private String type;
17+
private String path;
18+
private String mode;
19+
20+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.redhat.labs.lodestar.models.pagination;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.stream.Collectors;
8+
9+
import javax.ws.rs.core.Link;
10+
import javax.ws.rs.core.UriBuilder;
11+
12+
import com.redhat.labs.lodestar.models.Engagement;
13+
import com.redhat.labs.lodestar.models.gitlab.Project;
14+
15+
import lombok.AllArgsConstructor;
16+
import lombok.Builder;
17+
import lombok.Data;
18+
import lombok.NoArgsConstructor;
19+
20+
@Data
21+
@Builder
22+
@NoArgsConstructor
23+
@AllArgsConstructor
24+
public class Page {
25+
26+
private static final String CURRENT_PAGE = "page";
27+
private static final String PER_PAGE = "per_page";
28+
private static final String PAGE_HEADER_FORMAT = "x-%s-page";
29+
private static final String PER_PAGE_HEADER = "x-per-page";
30+
31+
private static final String FIRST = "first";
32+
private static final String FIRST_PAGE_HEADER = String.format(PAGE_HEADER_FORMAT, FIRST);
33+
34+
private static final String NEXT = "next";
35+
private static final String NEXT_PAGE_HEADER = String.format(PAGE_HEADER_FORMAT, NEXT);
36+
37+
private static final String LAST = "last";
38+
private static final String LAST_PAGE_HEADER = String.format(PAGE_HEADER_FORMAT, LAST);
39+
40+
private static final String REGEX = ".*&page=(\\d+)&.*";
41+
42+
@Builder.Default
43+
Integer perPage = 20;
44+
String gitLabLinkHeader;
45+
46+
@Builder.Default
47+
Map<String, Map<String, Integer>> linkHeaders = new HashMap<>();
48+
49+
@Builder.Default
50+
Map<String, Object> headers = new HashMap<>();
51+
52+
@Builder.Default
53+
List<Project> results = new ArrayList<>();
54+
55+
@Builder.Default
56+
List<Engagement> engagements = new ArrayList<>();
57+
58+
public void setHeadersFromGitLabHeader() {
59+
60+
if (null == this.gitLabLinkHeader) {
61+
return;
62+
}
63+
64+
// clear before reloading
65+
linkHeaders.clear();
66+
67+
setHeadersForRelations();
68+
69+
}
70+
71+
private void setHeadersForRelations() {
72+
73+
// split links
74+
String[] links = gitLabLinkHeader.split(",");
75+
76+
headers.put(PER_PAGE_HEADER, perPage);
77+
78+
for (String link : links) {
79+
80+
String rel;
81+
String pageHeader;
82+
Integer pageValue = Integer.valueOf(link.replaceAll(REGEX, "$1"));
83+
84+
if (link.contains(FIRST)) {
85+
86+
rel = FIRST;
87+
linkHeaders.put(FIRST, new HashMap<>());
88+
pageHeader = FIRST_PAGE_HEADER;
89+
90+
} else if (link.contains(NEXT)) {
91+
92+
rel = NEXT;
93+
linkHeaders.put(NEXT, new HashMap<>());
94+
pageHeader = NEXT_PAGE_HEADER;
95+
96+
} else if (link.contains(LAST)) {
97+
98+
rel = LAST;
99+
linkHeaders.put(LAST, new HashMap<>());
100+
pageHeader = LAST_PAGE_HEADER;
101+
102+
} else {
103+
continue;
104+
}
105+
106+
headers.put(pageHeader, pageValue);
107+
linkHeaders.get(rel).put(CURRENT_PAGE, pageValue);
108+
linkHeaders.get(rel).put(PER_PAGE, perPage);
109+
110+
}
111+
112+
}
113+
114+
public Link[] getLinks(UriBuilder uriBuilder) {
115+
116+
List<Link> links = linkHeaders.entrySet().stream().map(e1 -> {
117+
118+
String rel = e1.getKey();
119+
Map<String, Integer> headerMap = e1.getValue();
120+
121+
javax.ws.rs.core.Link.Builder builder = Link.fromUriBuilder(uriBuilder).rel(rel);
122+
headerMap.entrySet().forEach(e2 -> builder.param(e2.getKey(), String.valueOf(e2.getValue())));
123+
124+
return builder.build();
125+
126+
}).collect(Collectors.toList());
127+
128+
return links.toArray(new Link[links.size()]);
129+
130+
}
131+
132+
}

src/main/java/com/redhat/labs/lodestar/models/PagedResults.java renamed to src/main/java/com/redhat/labs/lodestar/models/pagination/PagedResults.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.redhat.labs.lodestar.models;
1+
package com.redhat.labs.lodestar.models.pagination;
22

33
import java.util.ArrayList;
44
import java.util.List;
@@ -51,7 +51,7 @@ public void update(Response response, GenericType<List<T>> type) {
5151

5252
if(totalPageString == null) {
5353
total = UNDEFINED_PAGE_COUNT; //Should not be able to get this high
54-
LOGGER.debug("X-Total-Pages header is missing");
54+
LOGGER.trace("X-Total-Pages header is missing");
5555
} else {
5656
total = Integer.valueOf(totalPageString);
5757
}

0 commit comments

Comments
 (0)