Skip to content

Commit d75d101

Browse files
committed
migrate-engagements
1 parent ce15a84 commit d75d101

File tree

5 files changed

+182
-98
lines changed

5 files changed

+182
-98
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
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.11.3.Final</quarkus-plugin.version>
17+
<quarkus-plugin.version>1.13.7.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.11.3.Final</quarkus.platform.version>
20+
<quarkus.platform.version>1.13.7.Final</quarkus.platform.version>
2121
<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>

src/main/java/com/redhat/labs/lodestar/resource/MigrationResource.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,30 @@
77
import javax.ws.rs.core.Response;
88

99
import org.eclipse.microprofile.metrics.MetricUnits;
10-
import org.eclipse.microprofile.metrics.annotation.Counted;
1110
import org.eclipse.microprofile.metrics.annotation.Timed;
1211
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
1312

1413
import com.redhat.labs.lodestar.service.MigrationService;
1514

1615
@Path("/api/migrate")
17-
@Tag(name = "Migration", description = "Migratiion services")
16+
@Tag(name = "Migration", description = "Migration services")
1817
public class MigrationResource {
1918

2019
@Inject
2120
MigrationService migrationService;
2221

2322
@PUT
24-
@Counted(name = "migration", description = "How many migation requests have been invoked")
2523
@Timed(name = "performedMigration", description = "How much time it takes to migrate", unit = MetricUnits.MILLISECONDS)
2624
public Response migrate(@QueryParam(value = "participants") boolean migrateParticipants,
27-
@QueryParam(value = "artifacts") boolean migrateArtifacts,
28-
@QueryParam(value = "uuids") boolean migrateUuids, @QueryParam(value = "hosting") boolean migrateHosting) {
25+
@QueryParam("artifacts") boolean migrateArtifacts,
26+
@QueryParam("uuids") boolean migrateUuids,
27+
@QueryParam("hosting") boolean migrateHosting,
28+
@QueryParam("engagements") boolean migrateEngagements,
29+
@QueryParam("overwrite") boolean overwrite,
30+
@QueryParam("uuid") String uuid) {
2931

30-
migrationService.migrate(migrateUuids, migrateParticipants, migrateArtifacts, migrateHosting);
32+
migrationService.migrate(migrateUuids, migrateParticipants, migrateArtifacts, migrateHosting, migrateEngagements,
33+
overwrite, uuid);
3134

3235
return Response.ok().build();
3336

Lines changed: 149 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,31 @@
11
package com.redhat.labs.lodestar.service;
22

3-
import java.util.Collections;
4-
import java.util.HashMap;
5-
import java.util.List;
6-
import java.util.Map;
7-
import java.util.Optional;
3+
import java.time.Instant;
4+
import java.time.LocalDateTime;
5+
import java.time.ZoneOffset;
6+
import java.time.format.DateTimeFormatter;
7+
import java.util.*;
88

99
import javax.enterprise.context.ApplicationScoped;
1010
import javax.inject.Inject;
1111

12+
import com.redhat.labs.lodestar.models.*;
13+
import com.redhat.labs.lodestar.models.gitlab.*;
1214
import org.eclipse.microprofile.config.inject.ConfigProperty;
1315
import org.slf4j.Logger;
1416
import org.slf4j.LoggerFactory;
1517

1618
import com.redhat.labs.lodestar.config.JsonMarshaller;
17-
import com.redhat.labs.lodestar.models.Artifact;
18-
import com.redhat.labs.lodestar.models.Engagement;
19-
import com.redhat.labs.lodestar.models.EngagementUser;
20-
import com.redhat.labs.lodestar.models.HostingEnvironment;
21-
import com.redhat.labs.lodestar.models.gitlab.File;
22-
import com.redhat.labs.lodestar.models.gitlab.Project;
2319

2420
@ApplicationScoped
2521
public class MigrationService {
2622
private static final Logger LOGGER = LoggerFactory.getLogger(MigrationService.class);
27-
23+
2824
private static final String ENGAGEMENT_DIR = "engagement/";
2925
private static final String PARTICIPANT_JSON = ENGAGEMENT_DIR + "participants.json";
3026
private static final String ARTIFACT_JSON = ENGAGEMENT_DIR + "artifacts.json";
3127
private static final String HOSTING_JSON = ENGAGEMENT_DIR + "hosting.json";
28+
private static final String ENGAGEMENT_JSON = ENGAGEMENT_DIR + "engagement.json";
3229

3330
@Inject
3431
EngagementService engagementService;
@@ -54,51 +51,145 @@ public class MigrationService {
5451
@ConfigProperty(name = "commit.default.branch")
5552
String commitBranch;
5653

57-
private Map<Integer, Engagement> allEngagements = new HashMap<>();
54+
private final Map<Integer, Engagement> allEngagements = new HashMap<>();
5855

5956
/**
6057
* The migration is idempotent so no harm in rerunning. It will only update
6158
* engagements that haven't been migrated.
6259
*/
63-
public void migrate(boolean migrateUuids, boolean migrateParticipants, boolean migrateArtifacts, boolean migrateHosting) {
60+
public void migrate(boolean migrateUuids, boolean migrateParticipants, boolean migrateArtifacts, boolean migrateHosting,
61+
boolean migrateEngagements, boolean overwrite, String uuid) {
62+
LOGGER.debug("uuids {} participants {} artifacts {} hosting {} engagements {} overwrite {} uuid {}", migrateUuids,
63+
migrateParticipants, migrateArtifacts, migrateHosting, migrateEngagements, overwrite, uuid);
64+
65+
getAllEngagements(); //hydrate before stream
66+
6467
if(migrateUuids) {
65-
LOGGER.info("Start Migrate uuids: {}", migrateUuids);
68+
LOGGER.info("Start Migrate uuids");
6669
migrateUuids();
6770
LOGGER.info("End Migrate uuids");
68-
}
69-
70-
if(migrateParticipants) {
71-
LOGGER.info("Start Migrate participants: {}", migrateParticipants);
72-
migrateParticipants();
73-
LOGGER.info("End Migrate participants");
74-
}
75-
76-
if(migrateArtifacts) {
77-
LOGGER.info("Start Migrate artifacts");
78-
migrateArtifacts();
79-
LOGGER.info("End Migrate artifacts");
8071
}
81-
82-
if(migrateHosting) {
83-
LOGGER.info("Start Migrate hosting");
84-
migrateHosting();
85-
LOGGER.info("End Migrate hosting");
72+
73+
LOGGER.info("Start Migrate content");
74+
migrateAll(migrateParticipants, migrateArtifacts, migrateHosting, migrateEngagements, overwrite, uuid);
75+
LOGGER.info("End Migrate content");
76+
77+
}
78+
79+
private void migrateAll(boolean migrateParticipants, boolean migrateArtifacts, boolean migrateHosting,
80+
boolean migrateEngagements, boolean overwrite, String uuid ) {
81+
getAllEngagements().values().forEach(e -> {
82+
LOGGER.debug("Migrating {}", e.getUuid());
83+
if(uuid == null || e.getUuid().equals(uuid)) {
84+
List<Action> actions = new ArrayList<>();
85+
String content;
86+
if(migrateEngagements) {
87+
content = migrateEngagement(e);
88+
actions.add(createAction(content, ENGAGEMENT_JSON, overwrite, e.getProjectId()));
89+
}
90+
91+
if(migrateParticipants) {
92+
content = migrateParticipantsToGitlab(e);
93+
actions.add(createAction(content, PARTICIPANT_JSON, overwrite, e.getProjectId()));
94+
}
95+
96+
if(migrateHosting) {
97+
content = migrateHostingToGitlab(e);
98+
actions.add(createAction(content, HOSTING_JSON, overwrite, e.getProjectId()));
99+
}
100+
101+
if(migrateArtifacts) {
102+
content = migrateArtifactsToGitlab(e);
103+
actions.add(createAction(content, ARTIFACT_JSON, overwrite, e.getProjectId()));
104+
}
105+
106+
if(!actions.isEmpty()) {
107+
String commitMessage = "Migrating to v2";
108+
109+
CommitMultiple commit = CommitMultiple.builder().id(e.getProjectId()).branch(commitBranch).commitMessage(commitMessage).actions(actions)
110+
.authorName(commitAuthor).authorEmail(commitEmail).build();
111+
112+
fileService.createFiles(e.getProjectId(), commit);
113+
}
114+
}
115+
});
116+
}
117+
118+
/**
119+
*
120+
* @param content the new content to write
121+
* @param filePath the file path to write to
122+
* @param overwrite if true - will check for existence of file and overwrite if it exists
123+
* @return the file to write to on commit
124+
*/
125+
private Action createAction(String content, String filePath, boolean overwrite, int projectId) {
126+
FileAction action = FileAction.create;
127+
if(overwrite && fileService.getFile(projectId, filePath).isPresent()) {
128+
action = FileAction.update;
129+
86130
}
131+
return Action.builder().action(action).filePath(filePath).content(content).encoding("base64").build();
87132
}
88133

89134
/**
90135
* Get all projects and split for individual update. This will add a description to any
91-
* project that doesn't have one. The description will included the uuid of the engagement
136+
* project that doesn't have one. The description will include the uuid of the engagement
92137
*/
93138
private void migrateUuids() {
94139
List<Project> allProjects = projectService.getProjectsByGroup(engagementRepositoryId, true);
95-
getAllEngagements(); //hydrate before stream
140+
96141
allProjects.parallelStream().forEach(this::updateProjectWithUuid);
97142
}
143+
144+
private String migrateEngagement(Engagement engagement) {
145+
Engagement copy = clone(engagement, Engagement.class);
146+
147+
if(copy.getCategories() != null) {
148+
copy.getCategories().forEach(cat -> {
149+
try {
150+
cat.setCreated(convertDateTime(cat.getCreated()));
151+
cat.setUpdated(convertDateTime(cat.getUpdated()));
152+
} catch(Exception ex) {
153+
LOGGER.error ("dtf exception {}", cat.getCreated(), ex);
154+
}
155+
});
156+
}
157+
158+
if(copy.getUseCases() != null) {
159+
copy.getUseCases().forEach((use -> {
160+
try {
161+
use.setCreated(convertDateTime(use.getCreated()));
162+
use.setUpdated(convertDateTime(use.getUpdated()));
163+
} catch(Exception ex) {
164+
LOGGER.error ("dtf exception {}", use.getCreated(), ex);
165+
}
166+
}));
167+
}
168+
169+
copy.setHostingEnvironments(null);
170+
copy.setEngagementUsers(null);
171+
copy.setCommits(null);
172+
copy.setArtifacts(null);
173+
174+
return json.toJson(copy);
175+
}
176+
177+
private <T> T clone(T toClone, Class<T> clazz) {
178+
return json.fromJson(json.toJson(toClone), clazz);
179+
}
180+
181+
private String convertDateTime(String oldDateTime) {
182+
LOGGER.trace("Date In {}", oldDateTime);
183+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS");
184+
LocalDateTime expected = LocalDateTime.parse(oldDateTime, formatter);
185+
Instant instant = expected.toInstant(ZoneOffset.UTC);
186+
LOGGER.trace("Date Out {}", instant);
187+
return instant.toString();
188+
}
98189

99190
/**
100191
* Update a single project if the description is not already set and an engagement has been found
101-
* @param project
192+
* @param project the project to update
102193
*/
103194
private void updateProjectWithUuid(Project project) {
104195

@@ -112,34 +203,28 @@ private void updateProjectWithUuid(Project project) {
112203
LOGGER.info("Skipped uuid update because description is already set or the project {} is not in the engagement map", project.getId());
113204
}
114205
}
115-
116-
/**
117-
* Get all engagements (engagement.json) and split for individual update
118-
*/
119-
private void migrateParticipants() {
120-
getAllEngagements().values().parallelStream().forEach(this::migrateParticipantsToGitlab);
121-
}
122-
123-
private void migrateArtifacts() {
124-
getAllEngagements().values().parallelStream().forEach(this::migrateArtifactsToGitlab);
125-
}
126206

127-
private void migrateArtifactsToGitlab(Engagement engagement) {
207+
private String migrateArtifactsToGitlab(Engagement engagement) {
128208
List<Artifact> artifacts = engagement.getArtifacts() == null ? Collections.emptyList() : engagement.getArtifacts();
129-
artifacts.forEach(a -> a.setRegion(engagement.getRegion()));
130-
String content = json.toJson(artifacts);
131-
LOGGER.debug(content);
132-
migrateToGitlab(engagement, content, ARTIFACT_JSON, artifacts.size());
133-
134-
}
135-
136-
private void migrateHosting() {
137-
getAllEngagements().values().parallelStream().forEach(this::migrateHostingToGitlab);
209+
List<Artifact> copies = new ArrayList<>(artifacts.size());
210+
artifacts.forEach(a -> {
211+
Artifact copy = clone(a, Artifact.class);
212+
copy.setRegion(copy.getRegion());
213+
if(copy.getCreated() == null) {
214+
copy.setCreated(engagement.getEndDate());
215+
}
216+
217+
if(copy.getUpdated() == null) {
218+
copy.setUpdated(engagement.getEndDate());
219+
}
220+
copies.add(copy);
221+
});
222+
return json.toJson(copies);
138223
}
139224

140225
/**
141226
* Get All engagements. This is run by migrate users and uuids so only run once if both are active
142-
* @return
227+
* @return a map of engagements keyed by project id
143228
*/
144229
private Map<Integer, Engagement> getAllEngagements() {
145230
LOGGER.debug("Engagement count (pre-fetch) {}", allEngagements.size());
@@ -154,7 +239,7 @@ private Map<Integer, Engagement> getAllEngagements() {
154239

155240
/**
156241
* Do a quick project id to engagement mapping to easily find the engagement by project id
157-
* @param engagement
242+
* @param engagement map this
158243
*/
159244
private void addToMap(Engagement engagement) {
160245
allEngagements.put(engagement.getProjectId(), engagement);
@@ -163,34 +248,19 @@ private void addToMap(Engagement engagement) {
163248
/**
164249
* This will write the user json to gitlab. Should you wish to rollback or redo you could add this code
165250
* fileService.deleteFile(engagement.getProjectId(), userJson);
166-
* @param engagement
251+
* @param engagement participants of this engagement
167252
*/
168-
private void migrateParticipantsToGitlab(Engagement engagement) {
253+
private String migrateParticipantsToGitlab(Engagement engagement) {
169254

170255
List<EngagementUser> participants = engagement.getEngagementUsers() == null ? Collections.emptyList() : engagement.getEngagementUsers();
171256
participants.forEach(p -> p.setRegion(engagement.getRegion()));
172-
String content = json.toJson(participants);
173-
migrateToGitlab(engagement, content, PARTICIPANT_JSON, participants.size());
257+
return json.toJson(participants);
174258
}
175259

176-
private void migrateHostingToGitlab(Engagement engagement) {
260+
private String migrateHostingToGitlab(Engagement engagement) {
177261
List<HostingEnvironment> hosting = engagement.getHostingEnvironments() == null ? Collections.emptyList() : engagement.getHostingEnvironments();
178262
hosting.forEach(h -> h.setRegion(engagement.getRegion()));
179-
String content = json.toJson(hosting);
180-
migrateToGitlab(engagement, content, HOSTING_JSON, hosting.size());
181-
}
182-
183-
/**
184-
* This will write the user json to gitlab. Should you wish to rollback or redo you could add this code
185-
* fileService.deleteFile(engagement.getProjectId(), userJson);
186-
* @param engagement
187-
*/
188-
private void migrateToGitlab(Engagement engagement, String content, String fileName, int size) {
189-
190-
if(fileService.getFile(engagement.getProjectId(), fileName).isEmpty()) {
191-
File file = File.builder().content(content).authorEmail(commitEmail).authorName(commitAuthor).branch(commitBranch).commitMessage(String.format("migrating %s", fileName)).build();
192-
fileService.createFile(engagement.getProjectId(), fileName, file);
193-
LOGGER.info("Migrated {} {} for engagement {}", size, fileName, engagement.getUuid());
194-
}
263+
return json.toJson(hosting);
195264
}
265+
196266
}

src/main/resources/META-INF/resources/index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8">
55
<link rel="icon" href="/favicon.ico"/>
6-
<title>Lodestar Participants - 1.0.0-SNAPSHOT</title>
6+
<title>Lodestar Git API- 1.0.0-SNAPSHOT</title>
77
<style>
88
h1, h2, h3, h4, h5, h6 {
99
margin-bottom: 0.5rem;
@@ -110,7 +110,7 @@
110110
<body>
111111

112112
<div class="banner lead">
113-
LodeStar Participants API
113+
LodeStar Git API
114114
</div>
115115

116116
<div class="container">
@@ -128,7 +128,7 @@
128128
<h3>Application</h3>
129129
<ul>
130130
<li>GroupId: <code>com.redhat.labs.lodestar</code></li>
131-
<li>ArtifactId: <code>lodestar-participants</code></li>
131+
<li>ArtifactId: <code>lodestar-git-api</code></li>
132132
<li>Version: <code>1.0.0-SNAPSHOT</code></li>
133133
<li>Quarkus Version: <code>1.13.7.Final</code></li>
134134
</ul>

0 commit comments

Comments
 (0)