Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
aktualizr-lite: Fix logic for finding latest version
Browse files Browse the repository at this point in the history
You can't assume the targets will be ordered latest->oldest. This
creates a version comparison helper that tries its best to compare
things based on the glibc function:

 http://man7.org/linux/man-pages/man3/strverscmp.3.html

Signed-off-by: Andy Doan <andy@foundries.io>
  • Loading branch information
doanac committed Jul 1, 2019
1 parent 12f8558 commit 546c832
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 4 deletions.
7 changes: 5 additions & 2 deletions src/aktualizr_lite/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
if(BUILD_OSTREE)
add_executable(aktualizr-lite main.cc)
set(SOURCES main.cc version.h)
add_executable(aktualizr-lite ${SOURCES})
target_link_libraries(aktualizr-lite aktualizr_static_lib ${AKTUALIZR_EXTERNAL_LIBS})

install(TARGETS aktualizr-lite RUNTIME DESTINATION bin COMPONENT aktualizr-lite)
Expand All @@ -18,5 +19,7 @@ add_test(test_aktualizr-lite

endif(BUILD_OSTREE)

aktualizr_source_file_checks(main.cc)
add_aktualizr_test(NAME lite-version SOURCES version_test.cc)

aktualizr_source_file_checks(${SOURCES} version_test.cc)
# vim: set tabstop=4 shiftwidth=4 expandtab:
13 changes: 12 additions & 1 deletion src/aktualizr_lite/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "config/config.h"
#include "package_manager/ostreemanager.h"
#include "primary/sotauptaneclient.h"
#include "version.h"

namespace bpo = boost::program_options;

Expand Down Expand Up @@ -111,15 +112,25 @@ static std::unique_ptr<Uptane::Target> find_target(const std::shared_ptr<SotaUpt
throw std::runtime_error("Unable to find update");
}
}

bool find_latest = (version == "latest");
std::unique_ptr<Uptane::Target> latest = nullptr;
for (auto &t : client->allTargets()) {
for (auto const &it : t.hardwareIds()) {
if (it == hwid) {
if (version == "latest" || version == t.filename() || version == t.custom_version()) {
if (find_latest) {
if (latest == nullptr || Version(latest->custom_version()) < Version(t.custom_version())) {
latest = std_::make_unique<Uptane::Target>(t);
}
} else if (version == t.filename() || version == t.custom_version()) {
return std_::make_unique<Uptane::Target>(t);
}
}
}
}
if (find_latest) {
return latest;
}
throw std::runtime_error("Unable to find update");
}

Expand Down
5 changes: 4 additions & 1 deletion src/aktualizr_lite/test_lite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_target() {
fi
cat >$custom_json <<EOF
{
"version": "$1",
"hardwareIds": ["hwid-for-test"],
"targetFormat": "OSTREE"
}
Expand Down Expand Up @@ -95,10 +96,12 @@ fi

## Check that we can do the update command
update=$(ostree admin status | head -n 1)
name=$(echo $update | cut -d\ -f1)
name="zlast" # give a name that will cause the custom version to be the latest
sha=$(echo $update | cut -d\ -f2 | sed 's/\.0$//')
echo "Adding new target: $name / $sha"
add_target $name $sha

$valgrind $aklite --loglevel 1 -c $sota_dir/sota.toml update --update-name $name
ostree admin status

$valgrind $aklite --loglevel 1 -c $sota_dir/sota.toml update | grep "Updating to: Target(zlast"
10 changes: 10 additions & 0 deletions src/aktualizr_lite/version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <string>

#include <string.h>

struct Version {
std::string raw_ver;
Version(const std::string& version) : raw_ver(std::move(version)) {}

bool operator<(const Version& other) { return strverscmp(raw_ver.c_str(), other.raw_ver.c_str()) < 0; }
};
28 changes: 28 additions & 0 deletions src/aktualizr_lite/version_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <gtest/gtest.h>

#include "version.h"

TEST(version, bad_versions) {
ASSERT_TRUE(Version("bar") < Version("foo"));
ASSERT_TRUE(Version("1.bar") < Version("2foo"));
ASSERT_TRUE(Version("1..0") < Version("1.1"));
ASSERT_TRUE(Version("1.-1") < Version("1.1"));
ASSERT_TRUE(Version("1.*bad #text") < Version("1.1")); // ord('*') < ord('1')
}

TEST(version, good_versions) {
ASSERT_TRUE(Version("1.0.1") < Version("1.0.1.1"));
ASSERT_TRUE(Version("1.0.1") < Version("1.0.2"));
ASSERT_TRUE(Version("0.9") < Version("1.0.1"));
ASSERT_TRUE(Version("1.0.0.0") < Version("1.0.0.1"));
ASSERT_TRUE(Version("1") < Version("1.0.0.1"));
ASSERT_TRUE(Version("1.9.0") < Version("1.10"));
}

#ifndef __NO_MAIN__
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);

return RUN_ALL_TESTS();
}
#endif

0 comments on commit 546c832

Please sign in to comment.