Skip to content

Commit

Permalink
Merge pull request #18 from nemomobile/staging
Browse files Browse the repository at this point in the history
Consider backup as failed if any unit is failed
  • Loading branch information
Denis Zalevskiy committed May 27, 2015
2 parents 42948f9 + ae46fe4 commit 194e92a
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 22 deletions.
1 change: 0 additions & 1 deletion .gitignore
Expand Up @@ -23,5 +23,4 @@ units/vault-*
*.moc
tests/tests.xml
tests/*_unit.cpp
tests/*_vault_test
src/config.hpp
1 change: 1 addition & 0 deletions include/vault/config.hpp
Expand Up @@ -47,6 +47,7 @@ class Unit
QString script() const;
inline QVariantMap data() const { return m_data; }

bool isLocal() const { return is(m_data.value("local", QVariant(false))); }
private:
QVariantMap m_data;
};
Expand Down
12 changes: 10 additions & 2 deletions qml/Vault/vault.cpp
Expand Up @@ -64,10 +64,18 @@ class Worker : public QObject
Q_INVOKABLE void backup(const QString &home, const QStringList &units, const QString &message)
{
debug::debug("Backup: home", home);
m_vault->backup(home, units, message, [this](const QString unit, const QString &status) {
auto res = m_vault->backup(home, units, message, [this](const QString unit, const QString &status) {
emit progress(Vault::Backup, {{"unit", unit}, {"status", status}});
});
emit done(Vault::Backup, QVariantMap());
if (res.failedUnits.size() == 0) {
emit done(Vault::Backup, QVariantMap());
} else {
QVariantMap info{{"msg", "Backup of some units is failed"}
, {"reason", "Backup"}
, {"succeeded", res.succededUnits}
, {"failed", res.failedUnits}};
emit error(Vault::Backup, info);
}
}

QStringList snapshots() const
Expand Down
28 changes: 20 additions & 8 deletions src/vault.cpp
Expand Up @@ -180,8 +180,12 @@ int Vault::execute(const QVariantMap &options)
if (!options.contains("data")) {
error::raise({{"action", action}, {"msg", "Needs data"}});
}
qDebug()<<parseKvPairs(options.value("data").toString());
vault.registerConfig(parseKvPairs(options.value("data").toString()));
auto data = parseKvPairs(str(options["data"]));
if (options.contains("unit"))
data["unit"] = options["unit"];
data["local"] = true;
debug::info("Register local unit:", data);
vault.registerConfig(data);
} else if (action == "unregister") {
if (!options.contains("unit")) {
error::raise({{"action", action}, {"msg", "Needs unit name"}});
Expand Down Expand Up @@ -337,8 +341,13 @@ void Vault::setup(const QVariantMap *config)
} else if (config) {
debug::info("Repository initialization is requested");

if (os::path::exists(m_path))
error::raise({{"msg", "Vault dir already exists, can't create"}, {"path", m_path}});
if (os::path::exists(m_path)) {
QDir d(m_path);
if (!d.entryList(QDir::NoDotAndDotDot).isEmpty())
error::raise({
{"msg", "Vault dir already exists and not empty"}
, {"path", m_path}});
}

try {
createRepo();
Expand Down Expand Up @@ -396,7 +405,6 @@ Vault::Result Vault::backup(const QString &home, const QStringList &units, const
debug::info("Backup units", units, ", home", home);
auto l = lock();
Result res;
res.failedUnits << units;

if (!os::path::isDir(home)) {
qWarning("Home is not a dir: %s", qPrintable(home));
Expand All @@ -408,6 +416,7 @@ Vault::Result Vault::backup(const QString &home, const QStringList &units, const
};

resetMaster();
Gittin::Commit head = Gittin::Branch(&m_vcs, "master").head();

QStringList usedUnits = units;
if (units.isEmpty()) {
Expand All @@ -419,12 +428,14 @@ Vault::Result Vault::backup(const QString &home, const QStringList &units, const
}
for (const QString &unit: usedUnits) {
if (backupUnit(home, unit, progress)) {
res.failedUnits.removeOne(unit);
res.succededUnits << unit;
} else {
res.failedUnits << unit;
break;
}
}

if (res.succededUnits.size()) {
if (res.succededUnits.size() == usedUnits.size()) {
QString timeTag = QDateTime::currentDateTimeUtc().toString("yyyy-MM-ddTHH-mm-ss.zzzZ");
qDebug()<<timeTag<<message;
QString msg = message.isEmpty() ? timeTag : message + '\n' + timeTag;
Expand All @@ -434,7 +445,8 @@ Vault::Result Vault::backup(const QString &home, const QStringList &units, const
commit.addNote(message);
tagSnapshot(timeTag);
} else {
debug::warning("There is no succeeded units, no tag");
debug::warning("Some unit backup is failed, no tag");
reset(head.sha());
}
return res;
}
Expand Down
21 changes: 13 additions & 8 deletions src/vault_config.cpp
Expand Up @@ -225,19 +225,24 @@ bool Vault::update(const QMap<QString, Unit> &src)
bool Vault::update(const QVariantMap &src)
{
bool updated = false;
QStringList units = m_config.units().keys();
auto before = m_config.units();
for (auto i = src.begin(); i != src.end(); ++i) {
if (set(i.value().toMap())) {
updated = true;
}
}
for (const QString &n: units) {
if (!src.contains(n)) {
if (!rm(n)) {
error::raise({{"msg", n + " is not removed??"}});
}
updated = true;
}
// remove local copy of the global unit if there is no global
// counterpart
for (auto it = before.cbegin(); it != before.cend(); ++it) {
auto name = it.key();
if (it.value().isLocal() || src.contains(name))
continue;

debug::info("Global unit", name, "is not registered, removing");
if (!rm(name))
error::raise({{"msg", name + " is not removed??"}});

updated = true;
}
return updated;
}
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Expand Up @@ -42,6 +42,7 @@ ENDMACRO(UNIT_IMPL)

UNIT_IMPL(unit1)
UNIT_IMPL(unit2)
install(PROGRAMS unit_fail_vault_test DESTINATION ${TESTS_DIR})

configure_file(tests.xml.in tests.xml @ONLY)
install(FILES tests.xml DESTINATION ${TESTS_DIR})
Expand Down
4 changes: 4 additions & 0 deletions tests/unit_fail_vault_test
@@ -0,0 +1,4 @@
#!/bin/sh
echo "SHOULD FAIL"
echo "FAIL UNIT is FAILED" >&2
exit 1
50 changes: 47 additions & 3 deletions tests/vault.cpp
Expand Up @@ -18,6 +18,7 @@
#include <unistd.h>

namespace os = qtaround::os;
namespace subprocess = qtaround::subprocess;
namespace error = qtaround::error;

namespace tut
Expand All @@ -41,7 +42,8 @@ enum test_ids {
tid_config_update,
tid_simple_blobs,
tid_clear,
tid_cli_backup_restore_several_units
tid_cli_backup_restore_several_units,
tid_backup_fail
};

namespace {
Expand Down Expand Up @@ -174,7 +176,7 @@ void object::test<tid_config_update>()

units = vlt->config().units();
ensure("no unit1 in vault config", units.contains("unit1"));
ensure("unit2 should be removed from vault config", !units.contains("unit2"));
ensure("local unit2 should not be removed", units.contains("unit2"));
on_exit();
}

Expand Down Expand Up @@ -298,10 +300,52 @@ void object::test<tid_cli_backup_restore_several_units>()
vault_init();
register_unit(vault_dir, "unit1", false);
register_unit(vault_dir, "unit2", false);
vault::Vault::execute({{"action", "export"}
auto rc = vault::Vault::execute({{"action", "export"}
, {"vault", vault_dir}
, {"home", home}
, {"unit", "unit1,unit2"}});
ensure_eq("Should succeed", rc, 0);
on_exit();
}

template<> template<>
void object::test<tid_backup_fail>()
{
using vault::Vault;
auto on_exit = setup(tid_backup_fail);
auto describe = []() {
subprocess::Process ps;
ps.setWorkingDirectory(vault_dir);
ps.start("git", {"describe", "--tags", "--exact-match"});
return std::move(ps);
};
auto last_snapshot = []() {
return vlt->snapshots().last().name();
};
os::rmtree(home);
os::mkdir(home);
vault_init();
register_unit(vault_dir, "unit1", false);
register_unit(vault_dir, "unit2", false);
auto rc = Vault::execute({{"action", "export"}
, {"vault", vault_dir}
, {"home", home}
, {"unit", "unit1,unit2"}});
ensure_eq("These units should proceed", rc, 0);

auto snap1 = last_snapshot();

register_unit(vault_dir, "unit_fail", false);
rc = Vault::execute({{"action", "export"}
, {"vault", vault_dir}
, {"home", home}
, {"unit", "unit1,unit2,unit_fail"}});
ensure_eq("With failed unit it should fail", rc, 1);

auto ps = describe();
ensure("Git is not found", ps.wait(10));
ensure_eq("There should be a previous tag on top", ps.rc(), 0);
ensure_eq("Should be the same snapshot as before", snap1, last_snapshot());
on_exit();
}

Expand Down

0 comments on commit 194e92a

Please sign in to comment.