mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-10 13:21:53 +01:00
Initial contribution of an CLI upgrade-tool (#3268)
* Initial contribution of an upgrade-tool Signed-off-by: Jan N. Klug <github@klug.nrw>
This commit is contained in:
parent
cdab53b814
commit
c40dd73d77
@ -19,6 +19,7 @@
|
||||
<modules>
|
||||
<module>archetype</module>
|
||||
<module>i18n-plugin</module>
|
||||
<module>upgradetool</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
123
tools/upgradetool/pom.xml
Normal file
123
tools/upgradetool/pom.xml
Normal file
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.core.tools</groupId>
|
||||
<artifactId>org.openhab.core.reactor.tools</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>upgradetool</artifactId>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>openHAB Core :: Tools :: Upgrade tool</name>
|
||||
<description>A tool for upgrading openHAB from 3.4 to 4.0</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openhab.core.bundles</groupId>
|
||||
<artifactId>org.openhab.core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.core.bundles</groupId>
|
||||
<artifactId>org.openhab.core.thing</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.core.bundles</groupId>
|
||||
<artifactId>org.openhab.core.storage.json</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.5.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.measure</groupId>
|
||||
<artifactId>unit-api</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>si.uom</groupId>
|
||||
<artifactId>si-units</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.units</groupId>
|
||||
<artifactId>indriya</artifactId>
|
||||
<version>2.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jdt</groupId>
|
||||
<artifactId>org.eclipse.jdt.annotation</artifactId>
|
||||
<version>2.2.600</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack-eea</id>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.lastnpe.eea</groupId>
|
||||
<artifactId>eea-all</artifactId>
|
||||
<version>${eea.version}</version>
|
||||
<overWrite>true</overWrite>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.4.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>org.openhab.core.tools.UpgradeTool</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.core.tools;
|
||||
|
||||
import static org.openhab.core.tools.internal.Upgrader.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.tools.internal.Upgrader;
|
||||
|
||||
/**
|
||||
* The {@link UpgradeTool} is a tool for upgrading openHAB to mitigate breaking changes
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class UpgradeTool {
|
||||
private static final Set<String> LOG_LEVELS = Set.of("TRACE", "DEBUG", "INFO", "WARN", "ERROR");
|
||||
private static final String OPT_COMMAND = "command";
|
||||
private static final String OPT_DIR = "dir";
|
||||
private static final String OPT_LOG = "log";
|
||||
private static final String OPT_FORCE = "force";
|
||||
|
||||
private static Options getOptions() {
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption(
|
||||
Option.builder().longOpt(OPT_DIR).desc("directory to process").numberOfArgs(1).required().build());
|
||||
options.addOption(Option.builder().longOpt(OPT_COMMAND).numberOfArgs(1).desc("command to execute").build());
|
||||
options.addOption(Option.builder().longOpt(OPT_LOG).numberOfArgs(1).desc("log verbosity").build());
|
||||
options.addOption(Option.builder().longOpt(OPT_FORCE).desc("force execution (even if already done)").build());
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Options options = getOptions();
|
||||
try {
|
||||
CommandLine commandLine = new DefaultParser().parse(options, args);
|
||||
|
||||
String loglevel = commandLine.hasOption(OPT_LOG) ? commandLine.getOptionValue(OPT_LOG).toUpperCase()
|
||||
: "INFO";
|
||||
if (!LOG_LEVELS.contains(loglevel)) {
|
||||
System.out.println("Allowed log-levels are " + LOG_LEVELS);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, loglevel);
|
||||
|
||||
String baseDir = commandLine.hasOption(OPT_DIR) ? commandLine.getOptionValue(OPT_DIR) : "";
|
||||
boolean force = commandLine.hasOption(OPT_FORCE) ? true : false;
|
||||
|
||||
Upgrader upgrader = new Upgrader(baseDir, force);
|
||||
if (commandLine.hasOption(ITEM_COPY_UNIT_TO_METADATA)) {
|
||||
upgrader.itemCopyUnitToMetadata();
|
||||
} else if (commandLine.hasOption(LINK_UPGRADE_JS_PROFILE)) {
|
||||
upgrader.linkUpgradeJsProfile();
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
String commands = Set.of(ITEM_COPY_UNIT_TO_METADATA, LINK_UPGRADE_JS_PROFILE).toString();
|
||||
formatter.printHelp("upgradetool", "", options, "Available commands: " + commands, true);
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.core.tools.internal;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.items.ManagedItemProvider;
|
||||
import org.openhab.core.items.Metadata;
|
||||
import org.openhab.core.items.MetadataKey;
|
||||
import org.openhab.core.storage.json.internal.JsonStorage;
|
||||
import org.openhab.core.thing.internal.link.ItemChannelLinkConfigDescriptionProvider;
|
||||
import org.openhab.core.thing.link.ItemChannelLink;
|
||||
import org.openhab.core.types.util.UnitUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link Upgrader} contains the implementation of the upgrade methods
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Upgrader {
|
||||
public static final String ITEM_COPY_UNIT_TO_METADATA = "itemCopyUnitToMetadata";
|
||||
public static final String LINK_UPGRADE_JS_PROFILE = "linkUpgradeJsProfile";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(Upgrader.class);
|
||||
private final String baseDir;
|
||||
private final boolean force;
|
||||
private final JsonStorage<UpgradeRecord> upgradeRecords;
|
||||
|
||||
public Upgrader(String baseDir, boolean force) {
|
||||
this.baseDir = baseDir;
|
||||
this.force = force;
|
||||
|
||||
Path upgradeJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.tools.UpgradeTool");
|
||||
upgradeRecords = new JsonStorage<>(upgradeJsonDatabasePath.toFile(), null, 5, 0, 0, List.of());
|
||||
}
|
||||
|
||||
private boolean checkUpgradeRecord(String key) {
|
||||
UpgradeRecord upgradeRecord = upgradeRecords.get(key);
|
||||
if (upgradeRecord != null && !force) {
|
||||
logger.info("Already executed '{}' on {}. Use '--force' to execute it again.", key,
|
||||
upgradeRecord.executionDate);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void itemCopyUnitToMetadata() {
|
||||
if (checkUpgradeRecord(ITEM_COPY_UNIT_TO_METADATA)) {
|
||||
return;
|
||||
}
|
||||
Path itemJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.items.Item.json");
|
||||
Path metadataJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.items.Metadata.json");
|
||||
logger.info("Copying item unit from state description to metadata in database '{}'", itemJsonDatabasePath);
|
||||
|
||||
if (!Files.isReadable(itemJsonDatabasePath)) {
|
||||
logger.error("Cannot access item database '{}', check path and access rights.", itemJsonDatabasePath);
|
||||
return;
|
||||
}
|
||||
if (!Files.isWritable(metadataJsonDatabasePath)) {
|
||||
logger.error("Cannot access metadata database '{}', check path and access rights.",
|
||||
metadataJsonDatabasePath);
|
||||
return;
|
||||
}
|
||||
|
||||
JsonStorage<ManagedItemProvider.PersistedItem> itemStorage = new JsonStorage<>(itemJsonDatabasePath.toFile(),
|
||||
null, 5, 0, 0, List.of());
|
||||
JsonStorage<Metadata> metadataStorage = new JsonStorage<>(metadataJsonDatabasePath.toFile(), null, 5, 0, 0,
|
||||
List.of());
|
||||
|
||||
itemStorage.getKeys().forEach(itemName -> {
|
||||
ManagedItemProvider.PersistedItem item = itemStorage.get(itemName);
|
||||
if (item != null && item.itemType.startsWith("Number:")) {
|
||||
if (metadataStorage.containsKey("unit" + ":" + itemName)) {
|
||||
logger.debug("{}: already contains a 'unit' metadata, skipping it", itemName);
|
||||
} else {
|
||||
Metadata metadata = metadataStorage.get("stateDescription:" + itemName);
|
||||
if (metadata == null) {
|
||||
logger.debug("{}: Nothing to do, no state description found.", itemName);
|
||||
} else {
|
||||
String pattern = (String) metadata.getConfiguration().get("pattern");
|
||||
if (pattern.contains(UnitUtils.UNIT_PLACEHOLDER)) {
|
||||
logger.warn(
|
||||
"{}: State description contains unit place-holder '%unit%', check if 'unit' metadata is needed!",
|
||||
itemName);
|
||||
} else {
|
||||
Unit<?> stateDescriptionUnit = UnitUtils.parseUnit(pattern);
|
||||
if (stateDescriptionUnit != null) {
|
||||
String unit = stateDescriptionUnit.toString();
|
||||
MetadataKey defaultUnitMetadataKey = new MetadataKey("unit", itemName);
|
||||
Metadata defaultUnitMetadata = new Metadata(defaultUnitMetadataKey, unit, null);
|
||||
metadataStorage.put(defaultUnitMetadataKey.toString(), defaultUnitMetadata);
|
||||
logger.info("{}: Wrote 'unit={}' to metadata.", itemName, unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
metadataStorage.flush();
|
||||
upgradeRecords.put(ITEM_COPY_UNIT_TO_METADATA, new UpgradeRecord(ZonedDateTime.now()));
|
||||
}
|
||||
|
||||
public void linkUpgradeJsProfile() {
|
||||
if (checkUpgradeRecord(LINK_UPGRADE_JS_PROFILE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Path linkJsonDatabasePath = Path.of(baseDir, "jsondb", "org.openhab.core.thing.link.ItemChannelLink.json");
|
||||
logger.info("Upgrading JS profile configuration in database '{}'", linkJsonDatabasePath);
|
||||
|
||||
if (!Files.isWritable(linkJsonDatabasePath)) {
|
||||
logger.error("Cannot access link database '{}', check path and access rights.", linkJsonDatabasePath);
|
||||
return;
|
||||
}
|
||||
JsonStorage<ItemChannelLink> linkStorage = new JsonStorage<>(linkJsonDatabasePath.toFile(), null, 5, 0, 0,
|
||||
List.of());
|
||||
|
||||
List.copyOf(linkStorage.getKeys()).forEach(linkUid -> {
|
||||
ItemChannelLink link = Objects.requireNonNull(linkStorage.get(linkUid));
|
||||
Configuration configuration = link.getConfiguration();
|
||||
String profileName = (String) configuration.get(ItemChannelLinkConfigDescriptionProvider.PARAM_PROFILE);
|
||||
if ("transform:JS".equals(profileName)) {
|
||||
String function = (String) configuration.get("function");
|
||||
if (function != null) {
|
||||
configuration.put("toItemScript", function);
|
||||
configuration.put("toHandlerScript", "|input");
|
||||
configuration.remove("function");
|
||||
configuration.remove("sourceFormat");
|
||||
|
||||
linkStorage.put(linkUid, link);
|
||||
logger.info("{}: rewrote JS profile link to new format", linkUid);
|
||||
} else {
|
||||
logger.info("{}: link already has correct configuration", linkUid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
linkStorage.flush();
|
||||
upgradeRecords.put(LINK_UPGRADE_JS_PROFILE, new UpgradeRecord(ZonedDateTime.now()));
|
||||
}
|
||||
|
||||
private static class UpgradeRecord {
|
||||
public final ZonedDateTime executionDate;
|
||||
|
||||
public UpgradeRecord(ZonedDateTime executionDate) {
|
||||
this.executionDate = executionDate;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user