@@ -106,7 +106,7 @@ public class ComputeEngineContainerImplTest { | |||
assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize( | |||
COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION | |||
+ 25 // level 1 | |||
+ 46 // content of DaoModule | |||
+ 47 // content of DaoModule | |||
+ 2 // content of EsSearchModule | |||
+ 62 // content of CorePropertyDefinitions | |||
+ 1 // content of CePropertyDefinitions |
@@ -66,6 +66,7 @@ import org.sonar.db.user.RoleDao; | |||
import org.sonar.db.user.UserDao; | |||
import org.sonar.db.user.UserGroupDao; | |||
import org.sonar.db.user.UserTokenDao; | |||
import org.sonar.db.webhook.WebhookDeliveryDao; | |||
public class DaoModule extends Module { | |||
private static final List<Class<? extends Dao>> classes = ImmutableList.<Class<? extends Dao>>builder().add( | |||
@@ -112,7 +113,8 @@ public class DaoModule extends Module { | |||
UserDao.class, | |||
UserGroupDao.class, | |||
UserPermissionDao.class, | |||
UserTokenDao.class).build(); | |||
UserTokenDao.class, | |||
WebhookDeliveryDao.class).build(); | |||
@Override | |||
protected void configureModule() { |
@@ -66,6 +66,7 @@ import org.sonar.db.user.RoleDao; | |||
import org.sonar.db.user.UserDao; | |||
import org.sonar.db.user.UserGroupDao; | |||
import org.sonar.db.user.UserTokenDao; | |||
import org.sonar.db.webhook.WebhookDeliveryDao; | |||
public class DbClient { | |||
@@ -115,6 +116,7 @@ public class DbClient { | |||
private final ActiveRuleDao activeRuleDao; | |||
private final QProfileChangeDao qProfileChangeDao; | |||
private final UserPermissionDao userPermissionDao; | |||
private final WebhookDeliveryDao webhookDeliveryDao; | |||
public DbClient(Database database, MyBatis myBatis, Dao... daos) { | |||
this.database = database; | |||
@@ -168,6 +170,7 @@ public class DbClient { | |||
activeRuleDao = getDao(map, ActiveRuleDao.class); | |||
qProfileChangeDao = getDao(map, QProfileChangeDao.class); | |||
userPermissionDao = getDao(map, UserPermissionDao.class); | |||
webhookDeliveryDao = getDao(map, WebhookDeliveryDao.class); | |||
} | |||
public DbSession openSession(boolean batch) { | |||
@@ -358,6 +361,10 @@ public class DbClient { | |||
return userPermissionDao; | |||
} | |||
public WebhookDeliveryDao webhookDeliveryDao() { | |||
return webhookDeliveryDao; | |||
} | |||
protected <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) { | |||
return (K) map.get(clazz); | |||
} |
@@ -122,6 +122,7 @@ import org.sonar.db.version.SchemaMigrationMapper; | |||
import org.sonar.db.version.v45.Migration45Mapper; | |||
import org.sonar.db.version.v50.Migration50Mapper; | |||
import org.sonar.db.version.v53.Migration53Mapper; | |||
import org.sonar.db.webhook.WebhookDeliveryMapper; | |||
public class MyBatis { | |||
@@ -248,7 +249,8 @@ public class MyBatis { | |||
UserGroupMapper.class, | |||
UserMapper.class, | |||
UserPermissionMapper.class, | |||
UserTokenMapper.class | |||
UserTokenMapper.class, | |||
WebhookDeliveryMapper.class | |||
}; | |||
confBuilder.loadMappers(mappers); | |||
@@ -0,0 +1,42 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.db.webhook; | |||
import java.util.Optional; | |||
import org.sonar.db.Dao; | |||
import org.sonar.db.DbSession; | |||
public class WebhookDeliveryDao implements Dao { | |||
public Optional<WebhookDeliveryDto> selectByUuid(DbSession dbSession, String uuid) { | |||
return Optional.ofNullable(mapper(dbSession).selectByUuid(uuid)); | |||
} | |||
public void insert(DbSession dbSession, WebhookDeliveryDto dto) { | |||
mapper(dbSession).insert(dto); | |||
} | |||
public void deleteComponentBeforeDate(DbSession dbSession, String componentUuid, long beforeDate) { | |||
mapper(dbSession).deleteComponentBeforeDate(componentUuid, beforeDate); | |||
} | |||
private static WebhookDeliveryMapper mapper(DbSession dbSession) { | |||
return dbSession.getMapper(WebhookDeliveryMapper.class); | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.db.webhook; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.builder.ToStringBuilder; | |||
public class WebhookDeliveryDto extends WebhookDeliveryLiteDto<WebhookDeliveryDto> { | |||
/** Error message if HTTP request cannot be sent, else null */ | |||
private String errorStacktrace; | |||
/** The payload that has been sent, cannot be null */ | |||
private String payload; | |||
@CheckForNull | |||
public String getErrorStacktrace() { | |||
return errorStacktrace; | |||
} | |||
public WebhookDeliveryDto setErrorStacktrace(@Nullable String s) { | |||
this.errorStacktrace = s; | |||
return this; | |||
} | |||
@CheckForNull | |||
public String getPayload() { | |||
return payload; | |||
} | |||
public WebhookDeliveryDto setPayload(@Nullable String s) { | |||
this.payload = s; | |||
return this; | |||
} | |||
@Override | |||
public String toString() { | |||
return new ToStringBuilder(this) | |||
.append("uuid", uuid) | |||
.append("componentUuid", componentUuid) | |||
.append("name", name) | |||
.append("success", success) | |||
.append("httpStatus", httpStatus) | |||
.append("durationMs", durationMs) | |||
.append("url", url) | |||
.append("createdAt", createdAt) | |||
.append("errorStacktrace", errorStacktrace) | |||
.toString(); | |||
} | |||
} |
@@ -0,0 +1,142 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.db.webhook; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.builder.ToStringBuilder; | |||
public class WebhookDeliveryLiteDto<T extends WebhookDeliveryLiteDto> { | |||
/** Technical unique identifier, can't be null */ | |||
protected String uuid; | |||
/** Component UUID, can't be null */ | |||
protected String componentUuid; | |||
/** Compute Engine task UUID, can't be null */ | |||
protected String ceTaskUuid; | |||
/** Name, can't be null */ | |||
protected String name; | |||
protected boolean success; | |||
/** HTTP response status. Null if HTTP request cannot be sent */ | |||
protected Integer httpStatus; | |||
/** Duration in ms. Null if HTTP request cannot be sent */ | |||
protected Integer durationMs; | |||
/** URL, cannot be null */ | |||
protected String url; | |||
/** Time of delivery */ | |||
protected long createdAt; | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public T setUuid(String s) { | |||
this.uuid = s; | |||
return (T)this; | |||
} | |||
public String getComponentUuid() { | |||
return componentUuid; | |||
} | |||
public T setComponentUuid(String s) { | |||
this.componentUuid = s; | |||
return (T)this; | |||
} | |||
public String getCeTaskUuid() { | |||
return ceTaskUuid; | |||
} | |||
public T setCeTaskUuid(String s) { | |||
this.ceTaskUuid = s; | |||
return (T)this; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public T setName(String s) { | |||
this.name = s; | |||
return (T)this; | |||
} | |||
public boolean isSuccess() { | |||
return success; | |||
} | |||
public T setSuccess(boolean b) { | |||
this.success = b; | |||
return (T)this; | |||
} | |||
@CheckForNull | |||
public Integer getHttpStatus() { | |||
return httpStatus; | |||
} | |||
public T setHttpStatus(@Nullable Integer i) { | |||
this.httpStatus = i; | |||
return (T)this; | |||
} | |||
@CheckForNull | |||
public Integer getDurationMs() { | |||
return durationMs; | |||
} | |||
public T setDurationMs(@Nullable Integer i) { | |||
this.durationMs = i; | |||
return (T)this; | |||
} | |||
public String getUrl() { | |||
return url; | |||
} | |||
public T setUrl(String s) { | |||
this.url = s; | |||
return (T)this; | |||
} | |||
public long getCreatedAt() { | |||
return createdAt; | |||
} | |||
public T setCreatedAt(long l) { | |||
this.createdAt = l; | |||
return (T)this; | |||
} | |||
@Override | |||
public String toString() { | |||
return new ToStringBuilder(this) | |||
.append("uuid", uuid) | |||
.append("componentUuid", componentUuid) | |||
.append("ceTaskUuid", ceTaskUuid) | |||
.append("name", name) | |||
.append("success", success) | |||
.append("httpStatus", httpStatus) | |||
.append("durationMs", durationMs) | |||
.append("url", url) | |||
.append("createdAt", createdAt) | |||
.toString(); | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.db.webhook; | |||
import javax.annotation.CheckForNull; | |||
import org.apache.ibatis.annotations.Param; | |||
public interface WebhookDeliveryMapper { | |||
@CheckForNull | |||
WebhookDeliveryDto selectByUuid(@Param("uuid") String uuid); | |||
void insert(WebhookDeliveryDto dto); | |||
void deleteComponentBeforeDate(@Param("componentUuid") String componentUuid, @Param("beforeDate") long beforeDate); | |||
} |
@@ -0,0 +1,24 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@ParametersAreNonnullByDefault | |||
package org.sonar.db.webhook; | |||
import javax.annotation.ParametersAreNonnullByDefault; | |||
@@ -0,0 +1,58 @@ | |||
<?xml version="1.0" encoding="UTF-8" ?> | |||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
<mapper namespace="org.sonar.db.webhook.WebhookDeliveryMapper"> | |||
<select id="selectByUuid" parameterType="String" resultType="org.sonar.db.webhook.WebhookDeliveryDto"> | |||
select | |||
uuid, | |||
component_uuid as componentUuid, | |||
ce_task_uuid as ceTaskUuid, | |||
name, | |||
url, | |||
success, | |||
http_status as httpStatus, | |||
duration_ms as durationMs, | |||
payload, | |||
error_stacktrace as errorStacktrace, | |||
created_at as createdAt | |||
from webhook_deliveries | |||
where uuid = #{uuid,jdbcType=VARCHAR} | |||
</select> | |||
<insert id="insert" parameterType="org.sonar.db.webhook.WebhookDeliveryDto" useGeneratedKeys="false"> | |||
insert into webhook_deliveries ( | |||
uuid, | |||
component_uuid, | |||
ce_task_uuid, | |||
name, | |||
url, | |||
success, | |||
http_status, | |||
duration_ms, | |||
payload, | |||
error_stacktrace, | |||
created_at | |||
) values ( | |||
#{uuid,jdbcType=VARCHAR}, | |||
#{componentUuid,jdbcType=VARCHAR}, | |||
#{ceTaskUuid,jdbcType=VARCHAR}, | |||
#{name,jdbcType=VARCHAR}, | |||
#{url,jdbcType=VARCHAR}, | |||
#{success,jdbcType=BOOLEAN}, | |||
#{httpStatus,jdbcType=INTEGER}, | |||
#{durationMs,jdbcType=INTEGER}, | |||
#{payload,jdbcType=VARCHAR}, | |||
#{errorStacktrace,jdbcType=VARCHAR}, | |||
#{createdAt,jdbcType=TIMESTAMP} | |||
) | |||
</insert> | |||
<delete id="deleteComponentBeforeDate" parameterType="map"> | |||
delete from webhook_deliveries | |||
where | |||
component_uuid = #{componentUuid,jdbcType=VARCHAR} and | |||
created_at < #{beforeDate,jdbcType=BIGINT} | |||
</delete> | |||
</mapper> |
@@ -29,6 +29,6 @@ public class DaoModuleTest { | |||
public void verify_count_of_added_components() { | |||
ComponentContainer container = new ComponentContainer(); | |||
new DaoModule().configure(container); | |||
assertThat(container.size()).isEqualTo(2 + 44); | |||
assertThat(container.size()).isEqualTo(2 + 45); | |||
} | |||
} |
@@ -0,0 +1,131 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.db.webhook; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.stream.Collectors; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class WebhookDeliveryDaoTest { | |||
private static final long DATE_1 = 1_999_000L; | |||
@Rule | |||
public final DbTester dbTester = DbTester.create(System2.INSTANCE).setDisableDefaultOrganization(true); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private final DbClient dbClient = dbTester.getDbClient(); | |||
private final DbSession dbSession = dbTester.getSession(); | |||
private final WebhookDeliveryDao underTest = dbClient.webhookDeliveryDao(); | |||
@Test | |||
public void insert_row_with_only_mandatory_columns() { | |||
WebhookDeliveryDto dto = newDto("DELIVERY_1", "COMPONENT_1", "TASK_1"); | |||
underTest.insert(dbSession, dto); | |||
WebhookDeliveryDto stored = selectByUuid(dto.getUuid()); | |||
verifyMandatoryFields(dto, stored); | |||
// optional fields are null | |||
assertThat(stored.getHttpStatus()).isNull(); | |||
assertThat(stored.getDurationMs()).isNull(); | |||
assertThat(stored.getErrorStacktrace()).isNull(); | |||
} | |||
@Test | |||
public void insert_row_with_all_columns() { | |||
WebhookDeliveryDto dto = newDto("DELIVERY_1", "COMPONENT_1", "TASK_1") | |||
.setDurationMs(10000) | |||
.setHttpStatus(200) | |||
.setErrorStacktrace("timeout") | |||
.setPayload("{json}"); | |||
underTest.insert(dbSession, dto); | |||
WebhookDeliveryDto stored = selectByUuid(dto.getUuid()); | |||
verifyMandatoryFields(dto, stored); | |||
assertThat(stored.getHttpStatus()).isEqualTo(dto.getHttpStatus()); | |||
assertThat(stored.getDurationMs()).isEqualTo(dto.getDurationMs()); | |||
assertThat(stored.getErrorStacktrace()).isEqualTo(dto.getErrorStacktrace()); | |||
} | |||
@Test | |||
public void delete_rows_before_date() { | |||
underTest.insert(dbSession, newDto("DELIVERY_1", "COMPONENT_1", "TASK_1").setCreatedAt(1_000_000L)); | |||
underTest.insert(dbSession, newDto("DELIVERY_2", "COMPONENT_1", "TASK_2").setCreatedAt(2_000_000L)); | |||
underTest.insert(dbSession, newDto("DELIVERY_3", "COMPONENT_2", "TASK_3").setCreatedAt(1_000_000L)); | |||
// should delete the old delivery on COMPONENT_1 and keep the one of COMPONENT_2 | |||
underTest.deleteComponentBeforeDate(dbSession, "COMPONENT_1", 1_500_000L); | |||
List<Object> uuids = dbTester.select(dbSession, "select uuid as \"uuid\" from webhook_deliveries") | |||
.stream() | |||
.map(columns -> columns.get("uuid")) | |||
.collect(Collectors.toList()); | |||
assertThat(uuids).containsOnly("DELIVERY_2", "DELIVERY_3"); | |||
} | |||
private void verifyMandatoryFields(WebhookDeliveryDto expected, WebhookDeliveryDto actual) { | |||
assertThat(actual.getUuid()).isEqualTo(expected.getUuid()); | |||
assertThat(actual.getComponentUuid()).isEqualTo(expected.getComponentUuid()); | |||
assertThat(actual.getCeTaskUuid()).isEqualTo(expected.getCeTaskUuid()); | |||
assertThat(actual.getName()).isEqualTo(expected.getName()); | |||
assertThat(actual.getUrl()).isEqualTo(expected.getUrl()); | |||
assertThat(actual.isSuccess()).isEqualTo(expected.isSuccess()); | |||
assertThat(actual.getPayload()).isEqualTo(expected.getPayload()); | |||
assertThat(actual.getCreatedAt()).isEqualTo(expected.getCreatedAt()); | |||
} | |||
/** | |||
* Build a {@link WebhookDeliveryDto} with all mandatory fields. | |||
* Optional fields are kept null. | |||
*/ | |||
private static WebhookDeliveryDto newDto(String uuid, String componentUuid, String ceTaskUuid) { | |||
return new WebhookDeliveryDto() | |||
.setUuid(uuid) | |||
.setComponentUuid(componentUuid) | |||
.setCeTaskUuid(ceTaskUuid) | |||
.setName("Jenkins") | |||
.setUrl("http://jenkins") | |||
.setSuccess(true) | |||
.setPayload("{json}") | |||
.setCreatedAt(DATE_1); | |||
} | |||
private WebhookDeliveryDto selectByUuid(String uuid) { | |||
Optional<WebhookDeliveryDto> dto = underTest.selectByUuid(dbSession, uuid); | |||
assertThat(dto).isPresent(); | |||
return dto.get(); | |||
} | |||
} |