Skip to content

Commit 13d8ff5

Browse files
authored
Merge pull request #137 from mcanoy/migrate-artifacts
migration functionality for artifacts. now with API
2 parents 5f835f5 + c2fb0be commit 13d8ff5

File tree

6 files changed

+139
-50
lines changed

6 files changed

+139
-50
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.redhat.labs.lodestar.resource;
2+
3+
import javax.inject.Inject;
4+
import javax.ws.rs.PUT;
5+
import javax.ws.rs.Path;
6+
import javax.ws.rs.QueryParam;
7+
import javax.ws.rs.core.Response;
8+
9+
import org.eclipse.microprofile.metrics.MetricUnits;
10+
import org.eclipse.microprofile.metrics.annotation.Counted;
11+
import org.eclipse.microprofile.metrics.annotation.Timed;
12+
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
13+
14+
import com.redhat.labs.lodestar.service.MigrationService;
15+
16+
@Path("/api/migrate")
17+
@Tag(name = "Migration", description = "Migratiion services")
18+
public class MigrationResource {
19+
20+
@Inject
21+
MigrationService migrationService;
22+
23+
@PUT
24+
@Counted(name = "migration", description = "How many migation requests have been invoked")
25+
@Timed(name = "performedMigration", description = "How much time it takes to migrate", unit = MetricUnits.MILLISECONDS)
26+
public Response migrate(@QueryParam(value = "participants") boolean migrateParticipants,
27+
@QueryParam(value = "artifacts") boolean migrateArtifacts,
28+
@QueryParam(value = "uuids") boolean migrateUuids) {
29+
30+
migrationService.migrate(migrateUuids, migrateParticipants, migrateArtifacts);
31+
32+
return Response.ok().build();
33+
34+
}
35+
}

src/main/java/com/redhat/labs/lodestar/rest/client/GitLabService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
import javax.ws.rs.Path;
1313
import javax.ws.rs.Produces;
1414
import javax.ws.rs.QueryParam;
15+
import javax.ws.rs.WebApplicationException;
1516
import javax.ws.rs.core.Response;
1617

18+
import org.apache.http.NoHttpResponseException;
1719
import org.eclipse.microprofile.faulttolerance.Retry;
1820
import org.eclipse.microprofile.rest.client.annotation.ClientHeaderParam;
1921
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
@@ -30,7 +32,7 @@
3032
import com.redhat.labs.lodestar.models.gitlab.ProjectTransfer;
3133
import com.redhat.labs.lodestar.resources.filter.Logged;
3234

33-
@Retry(maxRetries = 5, delay = 2000)
35+
@Retry(maxRetries = 5, delay = 1200, retryOn = NoHttpResponseException.class, abortOn = WebApplicationException.class)
3436
@Path("/api/v4")
3537
@RegisterRestClient(configKey = "gitlab.api")
3638
@RegisterProvider(value = GitLabServiceResponseMapper.class, priority = 50)

src/main/java/com/redhat/labs/lodestar/service/MigrationService.java

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.slf4j.LoggerFactory;
1616

1717
import com.redhat.labs.lodestar.config.JsonMarshaller;
18+
import com.redhat.labs.lodestar.models.Artifact;
1819
import com.redhat.labs.lodestar.models.Engagement;
1920
import com.redhat.labs.lodestar.models.EngagementUser;
2021
import com.redhat.labs.lodestar.models.gitlab.File;
@@ -26,7 +27,8 @@
2627
public class MigrationService {
2728
private static final Logger LOGGER = LoggerFactory.getLogger(MigrationService.class);
2829

29-
private static final String userJson = "users.json";
30+
private static final String PARTICIPANT_JSON = "participants.json";
31+
private static final String ARTIFACT_JSON = "artifacts.json";
3032

3133
@Inject
3234
EngagementService engagementService;
@@ -43,42 +45,48 @@ public class MigrationService {
4345
@ConfigProperty(name = "engagements.repository.id")
4446
int engagementRepositoryId;
4547

46-
@ConfigProperty(name = "migrate.users")
47-
boolean migrateUsers;
48+
@ConfigProperty(name = "commit.default.email")
49+
String commitEmail;
4850

49-
@ConfigProperty(name = "migrate.uuid")
50-
boolean migrateUuids;
51+
@ConfigProperty(name = "commit.default.author")
52+
String commitAuthor;
53+
54+
@ConfigProperty(name = "commit.default.branch")
55+
String commitBranch;
5156

5257
private Map<Integer, Engagement> allEngagements = new HashMap<>();
5358

5459
/**
55-
* Currently the migration will only occur if config properties are true.
5660
* The migration is idempotent so no harm in rerunning. It will only update
57-
* engagements that haven't been migrated. As we get closer to migration time
58-
* we should evaluate whether this is the right approach.
59-
* Once the start up is complete this service can not be called.
60-
* @param ev
61+
* engagements that haven't been migrated.
6162
*/
62-
void onStart(@Observes StartupEvent ev) {
63-
64-
if(migrateUsers) {
65-
LOGGER.info("Migrate users: {}", migrateUsers);
66-
migrateUsers();
67-
LOGGER.info("End Migrate users");
68-
}
69-
63+
public void migrate(boolean migrateUuids, boolean migrateParticipants, boolean migrateArtifacts) {
7064
if(migrateUuids) {
71-
LOGGER.info("Migrate uuids: {}", migrateUuids);
65+
LOGGER.info("Start Migrate uuids: {}", migrateUuids);
7266
migrateUuids();
7367
LOGGER.info("End Migrate uuids");
74-
}
68+
}
69+
70+
if(migrateParticipants) {
71+
LOGGER.info("Start Migrate participants: {}", migrateParticipants);
72+
migrateParticipants();
73+
LOGGER.info("End Migrate participants");
74+
}
7575

76+
if(migrateArtifacts) {
77+
LOGGER.info("Start Migrate artifacts");
78+
migrateArtifacts();
79+
LOGGER.info("End Migrate artifacts");
80+
}
7681
}
82+
7783
/**
78-
* Get all projects and split for individual update
84+
* Get all projects and split for individual update. This will add a description to any
85+
* project that doesn't have one. The description will included the uuid of the engagement
7986
*/
8087
private void migrateUuids() {
8188
List<Project> allProjects = projectService.getProjectsByGroup(engagementRepositoryId, true);
89+
getAllEngagements(); //hydrate before stream
8290
allProjects.parallelStream().forEach(this::updateProjectWithUuid);
8391
}
8492

@@ -94,21 +102,35 @@ private void updateProjectWithUuid(Project project) {
94102
projectService.updateProject(project);
95103

96104
LOGGER.info("Added uuid {} to project {} {}", uuid, project.getId(), project);
105+
} else {
106+
LOGGER.info("Skipped uuid update because description is already set or the project {} is not in the engagement map", project.getId());
97107
}
98108
}
99109

100110
/**
101111
* Get all engagements (engagement.json) and split for individual update
102112
*/
103-
private void migrateUsers() {
104-
getAllEngagements().values().parallelStream().forEach(this::migrateUsersToGitlab);
113+
private void migrateParticipants() {
114+
getAllEngagements().values().parallelStream().forEach(this::migrateParticipantsToGitlab);
115+
}
116+
117+
private void migrateArtifacts() {
118+
getAllEngagements().values().parallelStream().forEach(this::migrateArtifactsToGitlab);
119+
}
120+
121+
private void migrateArtifactsToGitlab(Engagement engagement) {
122+
List<Artifact> artifacts = engagement.getArtifacts() == null ? Collections.emptyList() : engagement.getArtifacts();
123+
String content = json.toJson(artifacts);
124+
migrateToGitlab(engagement, content, ARTIFACT_JSON, artifacts.size());
125+
105126
}
106127

107128
/**
108129
* Get All engagements. This is run by migrate users and uuids so only run once if both are active
109130
* @return
110131
*/
111132
private Map<Integer, Engagement> getAllEngagements() {
133+
LOGGER.debug("Engagement count (pre-fetch) {}", allEngagements.size());
112134
if (allEngagements.isEmpty()) {
113135
List<Engagement> engagements = engagementService.getAllEngagements(Optional.of(false), Optional.of(false));
114136
engagements.parallelStream().forEach(this::addToMap);
@@ -131,20 +153,24 @@ private void addToMap(Engagement engagement) {
131153
* fileService.deleteFile(engagement.getProjectId(), userJson);
132154
* @param engagement
133155
*/
134-
private void migrateUsersToGitlab(Engagement engagement) {
135-
136-
List<EngagementUser> users = engagement.getEngagementUsers();
156+
private void migrateParticipantsToGitlab(Engagement engagement) {
137157

138-
if(users == null) {
139-
users = Collections.emptyList();
140-
}
158+
List<EngagementUser> participants = engagement.getEngagementUsers() == null ? Collections.emptyList() : engagement.getEngagementUsers();
159+
String content = json.toJson(participants);
160+
migrateToGitlab(engagement, content, PARTICIPANT_JSON, participants.size());
161+
}
162+
163+
/**
164+
* This will write the user json to gitlab. Should you wish to rollback or redo you could add this code
165+
* fileService.deleteFile(engagement.getProjectId(), userJson);
166+
* @param engagement
167+
*/
168+
private void migrateToGitlab(Engagement engagement, String content, String fileName, int size) {
141169

142-
if(fileService.getFile(engagement.getProjectId(), userJson).isEmpty()) {
143-
String content = json.toJson(users);
144-
File file = File.builder().content(content).authorEmail("[email protected]").authorName("Jim Bot").branch("master").commitMessage("migrating users").build();
145-
146-
fileService.createFile(engagement.getProjectId(), userJson, file);
147-
LOGGER.info("Migrated {} users for engagement {}", users.size(), engagement.getUuid());
170+
if(fileService.getFile(engagement.getProjectId(), fileName).isEmpty()) {
171+
File file = File.builder().content(content).authorEmail(commitEmail).authorName(commitAuthor).branch(commitBranch).commitMessage(String.format("migrating %s", fileName)).build();
172+
fileService.createFile(engagement.getProjectId(), fileName, file);
173+
LOGGER.info("Migrated {} {} for engagement {}", size, fileName, engagement.getUuid());
148174
}
149175
}
150176
}

src/main/resources/application.properties

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ config.gitlab.ref=${CONFIG_GITLAB_REF:master}
3232
commit.page.size=100
3333
commit.msg.filter.list=${COMMIT_FILTERED_MESSAGE_LIST:manual_refresh}
3434
commit.filter.list=${COMMIT_FILTERED_EMAIL_LIST:[email protected]}
35+
commit.default.email=[email protected]
36+
commit.default.author=Otto Mayshin
37+
commit.default.branch=master
3538
config.reload=${CONFIG_RELOAD:false}
3639

40+
3741
# engagements
3842
engagements.repository.id=${ENGAGEMENTS_REPOSITORY_ID:2}
3943
engagements.do.not.delete=${ENGAGEMENTS_PRESERVE:false}
@@ -44,10 +48,4 @@ git.tag=${GIT_API_GIT_TAG:not.set}
4448

4549
environment.id=${ENV_ID:local}
4650

47-
migrate.users=${MIGRATE_USERS:false}
48-
migrate.uuid=${MIGRATE_UUID:false}
49-
50-
%test.migrate.users=true
51-
%test.migrate.uuid=true
52-
53-
seed.file.list=users.json,artifacts.json
51+
seed.file.list=participants.json,artifacts.json
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.redhat.labs.lodestar.resource;
2+
3+
import static io.restassured.RestAssured.given;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
import io.quarkus.test.junit.QuarkusTest;
8+
9+
@QuarkusTest
10+
public class MigrationResourceTest {
11+
@Test
12+
void testGetHookFileSuccess() {
13+
14+
given().when().put("/api/migrate").then().statusCode(200);
15+
given().queryParam("participants", true).queryParam("uuid", true).queryParam("artifacts", true).when()
16+
.put("/api/migrate").then().statusCode(200);
17+
}
18+
}

src/test/java/com/redhat/labs/lodestar/service/MigrationServiceTest.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.junit.jupiter.api.Test;
1111
import org.mockito.Mockito;
1212

13+
import com.redhat.labs.lodestar.models.Artifact;
1314
import com.redhat.labs.lodestar.models.Engagement;
1415
import com.redhat.labs.lodestar.models.EngagementUser;
1516
import com.redhat.labs.lodestar.models.gitlab.File;
@@ -45,6 +46,9 @@ public static void setup() {
4546

4647
List<EngagementUser> engagementUsers = new ArrayList<>();
4748
engagementUsers.add(EngagementUser.builder().uuid("b2").build());
49+
50+
List<Artifact> artifacts = new ArrayList<>();
51+
artifacts.add(Artifact.builder().uuid("1").build());
4852

4953
List<Engagement> allEngagements = new ArrayList<>();
5054

@@ -54,29 +58,35 @@ public static void setup() {
5458
e = Engagement.builder().uuid("c3").projectId(3).engagementUsers(engagementUsers).build();
5559
allEngagements.add(e);
5660

57-
e = Engagement.builder().uuid("d4").projectId(4).engagementUsers(engagementUsers).build();
61+
e = Engagement.builder().uuid("d4").projectId(4).engagementUsers(engagementUsers).artifacts(artifacts).build();
5862
allEngagements.add(e);
5963

6064
mockPS = Mockito.mock(ProjectService.class);
6165
Mockito.when(mockPS.getProjectsByGroup(2, true)).thenReturn(projects);
6266
QuarkusMock.installMockForType(mockPS, ProjectService.class);
6367

6468
fileServiceMock = Mockito.mock(FileService.class);
65-
Mockito.when(fileServiceMock.getFile(4, "users.json")).thenReturn(Optional.of(File.builder().build()));
69+
Mockito.when(fileServiceMock.getFile(4, "participants.json")).thenReturn(Optional.of(File.builder().build()));
6670
QuarkusMock.installMockForType(fileServiceMock, FileService.class);
6771

6872
EngagementService mockES = Mockito.mock(EngagementService.class);
6973
Mockito.when(mockES.getAllEngagements(Optional.of(false), Optional.of(false))).thenReturn(allEngagements);
7074
QuarkusMock.installMockForType(mockES, EngagementService.class);
7175
}
76+
77+
@Test
78+
void migrate() {
79+
migrationService.migrate(false, false, false);
80+
81+
Mockito.verify(mockPS, Mockito.never()).updateProject(Mockito.any());
82+
Mockito.verify(fileServiceMock, Mockito.never()).createFile(Mockito.anyInt(), Mockito.eq("participants.json"), Mockito.any(File.class));
7283

73-
@Test
74-
void startOk() {
75-
76-
migrationService.onStart(new StartupEvent());
84+
migrationService.migrate(true, true, true);
7785

7886
Mockito.verify(mockPS, Mockito.times(2)).updateProject(Mockito.any());
79-
Mockito.verify(fileServiceMock, Mockito.times(2)).createFile(Mockito.anyInt(), Mockito.eq("users.json"), Mockito.any(File.class));
87+
Mockito.verify(fileServiceMock, Mockito.times(2)).createFile(Mockito.anyInt(), Mockito.eq("participants.json"), Mockito.any(File.class));
8088
}
89+
90+
8191

8292
}

0 commit comments

Comments
 (0)