Cleanup upgrade for 4.3.0

This commit is contained in:
VIacheslavKlimov 2025-09-02 14:28:03 +03:00
parent e79eec56cb
commit ba440ba7c1
4 changed files with 1 additions and 186 deletions

View File

@ -13,34 +13,3 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- UPDATE OTA PACKAGE EXTERNAL ID START
ALTER TABLE ota_package
ADD COLUMN IF NOT EXISTS external_id uuid;
DO
$$
BEGIN
IF NOT EXISTS(SELECT 1 FROM pg_constraint WHERE conname = 'ota_package_external_id_unq_key') THEN
ALTER TABLE ota_package ADD CONSTRAINT ota_package_external_id_unq_key UNIQUE (tenant_id, external_id);
END IF;
END;
$$;
-- UPDATE OTA PACKAGE EXTERNAL ID END
-- DROP INDEXES THAT DUPLICATE UNIQUE CONSTRAINT START
DROP INDEX IF EXISTS idx_device_external_id;
DROP INDEX IF EXISTS idx_device_profile_external_id;
DROP INDEX IF EXISTS idx_asset_external_id;
DROP INDEX IF EXISTS idx_entity_view_external_id;
DROP INDEX IF EXISTS idx_rule_chain_external_id;
DROP INDEX IF EXISTS idx_dashboard_external_id;
DROP INDEX IF EXISTS idx_customer_external_id;
DROP INDEX IF EXISTS idx_widgets_bundle_external_id;
-- DROP INDEXES THAT DUPLICATE UNIQUE CONSTRAINT END
ALTER TABLE mobile_app ADD COLUMN IF NOT EXISTS title varchar(255);

View File

@ -32,7 +32,7 @@ public class DefaultDatabaseSchemaSettingsService implements DatabaseSchemaSetti
// This list should include all versions which are compatible for the upgrade.
// The compatibility cycle usually breaks when we have some scripts written in Java that may not work after new release.
private static final List<String> SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("4.1.0");
private static final List<String> SUPPORTED_VERSIONS_FOR_UPGRADE = List.of("4.2.0");
private final ProjectInfo projectInfo;
private final JdbcTemplate jdbcTemplate;

View File

@ -15,8 +15,6 @@
*/
package org.thingsboard.server.service.install.update;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -24,12 +22,9 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.query.DynamicValue;
import org.thingsboard.server.common.data.query.FilterPredicateValue;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.component.RuleNodeClassInfo;
@ -129,60 +124,6 @@ public class DefaultDataUpdateService implements DataUpdateService {
return ruleNodeIds;
}
boolean convertDeviceProfileForVersion330(JsonNode profileData) {
boolean isUpdated = false;
if (profileData.has("alarms") && !profileData.get("alarms").isNull()) {
JsonNode alarms = profileData.get("alarms");
for (JsonNode alarm : alarms) {
if (alarm.has("createRules")) {
JsonNode createRules = alarm.get("createRules");
for (AlarmSeverity severity : AlarmSeverity.values()) {
if (createRules.has(severity.name())) {
JsonNode spec = createRules.get(severity.name()).get("condition").get("spec");
if (convertDeviceProfileAlarmRulesForVersion330(spec)) {
isUpdated = true;
}
}
}
}
if (alarm.has("clearRule") && !alarm.get("clearRule").isNull()) {
JsonNode spec = alarm.get("clearRule").get("condition").get("spec");
if (convertDeviceProfileAlarmRulesForVersion330(spec)) {
isUpdated = true;
}
}
}
}
return isUpdated;
}
boolean convertDeviceProfileAlarmRulesForVersion330(JsonNode spec) {
if (spec != null) {
if (spec.has("type") && spec.get("type").asText().equals("DURATION")) {
if (spec.has("value")) {
long value = spec.get("value").asLong();
var predicate = new FilterPredicateValue<>(
value, null, new DynamicValue<>(null, null, false)
);
((ObjectNode) spec).remove("value");
((ObjectNode) spec).putPOJO("predicate", predicate);
return true;
}
} else if (spec.has("type") && spec.get("type").asText().equals("REPEATING")) {
if (spec.has("count")) {
int count = spec.get("count").asInt();
var predicate = new FilterPredicateValue<>(
count, null, new DynamicValue<>(null, null, false)
);
((ObjectNode) spec).remove("count");
((ObjectNode) spec).putPOJO("predicate", predicate);
return true;
}
}
}
return false;
}
public static boolean getEnv(String name, boolean defaultValue) {
String env = System.getenv(name);
if (env == null) {

View File

@ -1,95 +0,0 @@
/**
* Copyright © 2016-2025 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.service.install.update;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.thingsboard.common.util.JacksonUtil;
import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.willCallRealMethod;
@ActiveProfiles("install")
@SpringBootTest(classes = DefaultDataUpdateService.class)
class DefaultDataUpdateServiceTest {
@MockBean
DefaultDataUpdateService service;
@BeforeEach
void setUp() {
willCallRealMethod().given(service).convertDeviceProfileAlarmRulesForVersion330(any());
willCallRealMethod().given(service).convertDeviceProfileForVersion330(any());
}
JsonNode readFromResource(String resourceName) throws IOException {
return JacksonUtil.OBJECT_MAPPER.readTree(this.getClass().getClassLoader().getResourceAsStream(resourceName));
}
@Test
void convertDeviceProfileAlarmRulesForVersion330FirstRun() throws IOException {
JsonNode spec = readFromResource("update/330/device_profile_001_in.json");
JsonNode expected = readFromResource("update/330/device_profile_001_out.json");
assertThat(service.convertDeviceProfileForVersion330(spec.get("profileData"))).isTrue();
assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString()); // use IDE feature <Click to see difference>
}
@Test
void convertDeviceProfileAlarmRulesForVersion330SecondRun() throws IOException {
JsonNode spec = readFromResource("update/330/device_profile_001_out.json");
JsonNode expected = readFromResource("update/330/device_profile_001_out.json");
assertThat(service.convertDeviceProfileForVersion330(spec.get("profileData"))).isFalse();
assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString()); // use IDE feature <Click to see difference>
}
@Test
void convertDeviceProfileAlarmRulesForVersion330EmptyJson() throws JsonProcessingException {
JsonNode spec = JacksonUtil.toJsonNode("{ }");
JsonNode expected = JacksonUtil.toJsonNode("{ }");
assertThat(service.convertDeviceProfileForVersion330(spec)).isFalse();
assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString());
}
@Test
void convertDeviceProfileAlarmRulesForVersion330AlarmNodeNull() throws JsonProcessingException {
JsonNode spec = JacksonUtil.toJsonNode("{ \"alarms\" : null }");
JsonNode expected = JacksonUtil.toJsonNode("{ \"alarms\" : null }");
assertThat(service.convertDeviceProfileForVersion330(spec)).isFalse();
assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString());
}
@Test
void convertDeviceProfileAlarmRulesForVersion330NoAlarmNode() throws JsonProcessingException {
JsonNode spec = JacksonUtil.toJsonNode("{ \"configuration\": { \"type\": \"DEFAULT\" } }");
JsonNode expected = JacksonUtil.toJsonNode("{ \"configuration\": { \"type\": \"DEFAULT\" } }");
assertThat(service.convertDeviceProfileForVersion330(spec)).isFalse();
assertThat(spec.toPrettyString()).isEqualTo(expected.toPrettyString());
}
}