View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.fit.core;
20  
21  import static org.awaitility.Awaitility.await;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Set;
28  import java.util.concurrent.ExecutorService;
29  import java.util.concurrent.Executors;
30  import java.util.concurrent.Future;
31  import java.util.concurrent.TimeUnit;
32  import java.util.concurrent.atomic.AtomicReference;
33  import org.apache.syncope.client.lib.SyncopeClient;
34  import org.apache.syncope.common.lib.SyncopeConstants;
35  import org.apache.syncope.common.lib.request.ResourceDR;
36  import org.apache.syncope.common.lib.to.ExecTO;
37  import org.apache.syncope.common.lib.to.NotificationTaskTO;
38  import org.apache.syncope.common.lib.to.PagedResult;
39  import org.apache.syncope.common.lib.to.TaskTO;
40  import org.apache.syncope.common.lib.to.UserTO;
41  import org.apache.syncope.common.lib.types.ExecStatus;
42  import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
43  import org.apache.syncope.common.lib.types.TaskType;
44  import org.apache.syncope.common.rest.api.beans.AnyQuery;
45  import org.apache.syncope.common.rest.api.beans.ExecSpecs;
46  import org.apache.syncope.common.rest.api.beans.TaskQuery;
47  import org.apache.syncope.common.rest.api.service.TaskService;
48  import org.apache.syncope.core.provisioning.java.job.notification.NotificationJob;
49  import org.apache.syncope.fit.AbstractITCase;
50  
51  public abstract class AbstractTaskITCase extends AbstractITCase {
52  
53      protected static final String PULL_TASK_KEY = "c41b9b71-9bfa-4f90-89f2-84787def4c5c";
54  
55      protected static final String SCHED_TASK_KEY = "e95555d2-1b09-42c8-b25b-f4c4ec597979";
56  
57      /**
58       * Remove initial and synchronized users to make test re-runnable.
59       */
60      protected void removeTestUsers() {
61          for (int i = 0; i < 10; i++) {
62              String cUserName = "test" + i;
63              try {
64                  UserTO cUserTO = USER_SERVICE.read(cUserName);
65                  USER_SERVICE.delete(cUserTO.getKey());
66              } catch (Exception e) {
67                  // Ignore
68              }
69          }
70      }
71  
72      /**
73       * Clean Syncope and LDAP resource status.
74       */
75      protected void ldapCleanup() {
76          GROUP_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
77                  fiql(SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo("testLDAPGroup").query()).
78                  build()).getResult().forEach(group -> {
79                      GROUP_SERVICE.deassociate(new ResourceDR.Builder().key(group.getKey()).
80                              action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_LDAP).build());
81                      GROUP_SERVICE.delete(group.getKey());
82                  });
83          USER_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
84                  fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("pullFromLDAP").query()).
85                  build()).getResult().forEach(user -> {
86                      USER_SERVICE.deassociate(new ResourceDR.Builder().key(user.getKey()).
87                              action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_LDAP).build());
88                      USER_SERVICE.delete(user.getKey());
89                  });
90      }
91  
92      protected static ExecTO execTask(
93              final TaskService taskService,
94              final TaskType type,
95              final String taskKey,
96              final String initialStatus,
97              final int maxWaitSeconds,
98              final boolean dryRun) {
99  
100         AtomicReference<TaskTO> taskTO = new AtomicReference<>(taskService.read(type, taskKey, true));
101         int preSyncSize = taskTO.get().getExecutions().size();
102         ExecTO execution = taskService.execute(new ExecSpecs.Builder().key(taskKey).dryRun(dryRun).build());
103         assertEquals(initialStatus, execution.getStatus());
104         assertNotNull(execution.getExecutor());
105 
106         await().atMost(maxWaitSeconds, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> {
107             try {
108                 taskTO.set(taskService.read(type, taskKey, true));
109                 return preSyncSize < taskTO.get().getExecutions().size();
110             } catch (Exception e) {
111                 return false;
112             }
113         });
114 
115         return taskTO.get().getExecutions().get(taskTO.get().getExecutions().size() - 1);
116     }
117 
118     public static ExecTO execProvisioningTask(
119             final TaskService taskService, final TaskType type, final String taskKey,
120             final int maxWaitSeconds, final boolean dryRun) {
121 
122         return execTask(taskService, type, taskKey, "JOB_FIRED", maxWaitSeconds, dryRun);
123     }
124 
125     protected static ExecTO execNotificationTask(
126             final TaskService taskService, final String taskKey, final int maxWaitSeconds) {
127 
128         return execTask(taskService, TaskType.NOTIFICATION, taskKey,
129                 NotificationJob.Status.SENT.name(), maxWaitSeconds, false);
130     }
131 
132     protected void execProvisioningTasks(
133             final TaskService taskService,
134             final TaskType type,
135             final Set<String> taskKeys,
136             final int maxWaitSeconds,
137             final boolean dryRun) throws Exception {
138 
139         ExecutorService service = Executors.newFixedThreadPool(taskKeys.size());
140         List<Future<ExecTO>> futures = new ArrayList<>();
141 
142         taskKeys.forEach(taskKey -> {
143             futures.add(service.submit(() -> {
144                 try {
145                     return execProvisioningTask(taskService, type, taskKey, maxWaitSeconds, dryRun);
146                 } catch (Exception e) {
147                     ExecTO failure = new ExecTO();
148                     failure.setRefKey(taskKey);
149                     failure.setStatus(ExecStatus.FAILURE.name());
150                     failure.setMessage(e.getMessage());
151                     return failure;
152                 }
153             }));
154 
155             // avoid flooding the test server
156             try {
157                 Thread.sleep(2000);
158             } catch (InterruptedException e) {
159                 // ignore
160             }
161         });
162 
163         futures.forEach(future -> {
164             try {
165                 future.get(maxWaitSeconds, TimeUnit.SECONDS);
166             } catch (Exception e) {
167                 LOG.error("While getting futures", e);
168             }
169         });
170 
171         service.shutdownNow();
172     }
173 
174     protected NotificationTaskTO findNotificationTask(final String notification, final int maxWaitSeconds) {
175         AtomicReference<NotificationTaskTO> notificationTask = new AtomicReference<>();
176         await().atMost(maxWaitSeconds, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> {
177             try {
178                 PagedResult<NotificationTaskTO> tasks = TASK_SERVICE.search(
179                         new TaskQuery.Builder(TaskType.NOTIFICATION).notification(notification).build());
180                 if (!tasks.getResult().isEmpty()) {
181                     notificationTask.set(tasks.getResult().get(0));
182                 }
183             } catch (Exception e) {
184                 // ignore
185             }
186             return notificationTask.get() != null;
187         });
188 
189         return notificationTask.get();
190     }
191 }