Verified Commit defbd8a0 authored by Karel Koci's avatar Karel Koci 🤘

Steal configuration files from installed package too

Configuration files can be moved from package to package and we should
be able to handle that. Previous implementation had limitation that it
handled only configuration files from package that were removed. This
commit removes this restriction.

Also note that there should be no way that we could steal configuration
from package requiring it as that would be collision between packages
and as such we would already failed at this point.
parent 34a752b2
......@@ -60,7 +60,7 @@ local locks = require "locks"
module "backend"
-- Functions and variables used in other files
-- luacheck: globals pkg_temp_dir repo_parse status_dump pkg_unpack pkg_examine collision_check not_installed_confs steal_configs dir_ensure pkg_merge_files pkg_merge_control pkg_config_info pkg_cleanup_files control_cleanup version_cmp version_match flags_load flags_get script_run flags_get_ro flags_write flags_mark run_state
-- luacheck: globals pkg_temp_dir repo_parse status_dump pkg_unpack pkg_examine collision_check installed_confs steal_configs dir_ensure pkg_merge_files pkg_merge_control pkg_config_info pkg_cleanup_files control_cleanup version_cmp version_match flags_load flags_get script_run flags_get_ro flags_write flags_mark run_state
-- Variables that we want to access from outside (ex. for testing purposes)
-- luacheck: globals status_file info_dir root_dir pkg_temp_dir flags_storage cmd_timeout cmd_kill_timeout stored_flags dir_opkg_collided
-- Functions that we want to access from outside (ex. for testing purposes)
......@@ -707,45 +707,48 @@ end
--[[
Prepares table which is used for steal_config. Keys are all configuration files
of all not-installed packages. As values are tables with name of package (key pkg)
and hash (key hash).
in system. As values are tables with name of package (key pkg) and hash (key
hash).
--]]
function not_installed_confs(current_status)
local not_installed_confs = {}
function installed_confs(current_status)
local dt = {}
for pkg, status in pairs(current_status) do
if status.Status[3] == "not-installed" then
for conf, hash in pairs(status.Conffiles or {}) do
not_installed_confs[conf] = { pkg = pkg, hash = hash }
end
for conf, hash in pairs(status.Conffiles or {}) do
dt[conf] = { pkg = pkg, hash = hash }
end
end
return not_installed_confs
return dt
end
--[[
Checks if configs aren't part of some not installed package. If such configuration
is located, it is removed from not installed package and if it is last config,
not-installed package entry is removed.
Checks if configs aren't part of some other package. If such configuration is
located, it is removed from original package and package entry is removed if it is
last config in not-installed package.
Note that if we have come so far we are sure that every configuration file belongs
to exactly one package as otherwise we would fail with collision. So if there is
some installed package owning configuration file that should be in other package
we can freely remove it from that package as it no longer needs it anymore.
The current_status is what is returned from status_parse(). The not_installed_confs
is what not_installed_confs function returns. The configs is table of new
The current_status is what is returned from status_parse(). The installed_confs
is what installed_confs function returns. The configs is table of new
configuration files.
Returns table where key is configuration file name and value is hash.
--]]
function steal_configs(current_status, not_installed_confs, configs)
function steal_configs(current_status, installed_confs, configs)
local steal = {}
-- Go trough all configs and check if they are not in not_installed_confs
-- Go trough all configs and check if they are not in installed_confs
for conf, _ in pairs(configs) do
if not_installed_confs[conf] then
local pkg = not_installed_confs[conf].pkg
if installed_confs[conf] then
local pkg = installed_confs[conf].pkg
DBG("Stealing \"" .. conf .. "\" from package " .. pkg)
steal[conf] = not_installed_confs[conf].hash
not_installed_confs[conf] = nil
steal[conf] = installed_confs[conf].hash
installed_confs[conf] = nil
-- Remove config from not-installed package
current_status[pkg].Conffiles[conf] = nil
-- Remove package if it has no other coffiles.
if not next(current_status[pkg].Conffiles) then
-- Remove package if it's not installed and has no other coffiles.
if current_status[pkg].Status[3] == "not-installed" and not next(current_status[pkg].Conffiles) then
DBG("not-installed package " .. pkg .. " has no more conffiles, removing.")
current_status[pkg] = nil
end
......
......@@ -152,13 +152,13 @@ end
local function pkg_move(status, plan, early_remove, errors_collected)
-- Prepare table of not installed confs for config stealing
local not_installed_confs = backend.not_installed_confs(status)
local installed_confs = backend.installed_confs(status)
local all_configs = {}
-- Build list of all configs and steal from not-installed
for _, op in ipairs(plan) do
if op.op == "install" then
local steal = backend.steal_configs(status, not_installed_confs, op.configs)
local steal = backend.steal_configs(status, installed_confs, op.configs)
utils.table_merge(op.old_configs, steal)
utils.table_merge(all_configs, op.old_configs)
end
......
......@@ -609,47 +609,63 @@ function test_collisions()
assert_table_equal({}, rem)
end
-- Test config_steal and not_installed_confs function
-- Test config_steal and installed_confs function
function test_config_steal()
local status = B.status_parse()
-- Lets set dnsmasq-dhcpv6 as not installed
status["dnsmasq-dhcpv6"].Status[3] = "not-installed"
-- Prepare not_installed_confs table and check it
local not_installed_confs = B.not_installed_confs(status)
-- Prepare installed_confs table and check it
local installed_confs = B.installed_confs(status)
assert_table_equal({
["/etc/config/dhcp"] = { pkg = "dnsmasq-dhcpv6", hash = "f81fe9bd228dede2165be71e5c9dcf76cc" },
["/etc/dnsmasq.conf"] = { pkg = "dnsmasq-dhcpv6", hash = "1e6ab19c1ae5e70d609ac7b6246541d520" }
}, not_installed_confs)
}, installed_confs)
-- Now lets steal one of the configs
local stealed_confs = {
["/etc/config/dhcp"] = status["dnsmasq-dhcpv6"].Conffiles["/etc/config/dhcp"]
}
local steal = B.steal_configs(status, not_installed_confs, { ["/etc/config/dhcp"] = "hash" }) -- note that hash is not used
local steal = B.steal_configs(status, installed_confs, { ["/etc/config/dhcp"] = "hash" }) -- note that hash is not used
assert_table_equal(stealed_confs, steal)
assert_not_nil(status["dnsmasq-dhcpv6"]) -- package is one more configuration file so it should be still there
assert_nil(status["dnsmasq-dhcpv6"].Conffiles["/etc/config/dhcp"])
-- Now lets steal second one
stealed_confs = {
["/etc/dnsmasq.conf"] = status["dnsmasq-dhcpv6"].Conffiles["/etc/dnsmasq.conf"]
}
steal = B.steal_configs(status, not_installed_confs, { ["/etc/dnsmasq.conf"] = "pkg_test2" })
steal = B.steal_configs(status, installed_confs, { ["/etc/dnsmasq.conf"] = "pkg_test2" })
assert_table_equal(stealed_confs, steal)
assert_nil(status["dnsmasq-dhcpv6"]) -- Now whole package should disappear
status = B.status_parse()
status["dnsmasq-dhcpv6"].Status[3] = "not-installed"
local not_installed_confs = B.not_installed_confs(status)
local installed_confs = B.installed_confs(status)
-- Lets try again but now with package that steals both config files
stealed_confs = {
["/etc/config/dhcp"] = status["dnsmasq-dhcpv6"].Conffiles["/etc/config/dhcp"],
["/etc/dnsmasq.conf"] = status["dnsmasq-dhcpv6"].Conffiles["/etc/dnsmasq.conf"]
}
steal = B.steal_configs(status, not_installed_confs, {
steal = B.steal_configs(status, installed_confs, {
["/etc/config/dhcp"] = "hash",
["/etc/dnsmasq.conf"] = "hash",
["/etc/newone.conf"] = "hash"
})
assert_table_equal(stealed_confs, steal)
assert_nil(status["dnsmasq-dhcpv6"]) -- Whole package should disappear
status = B.status_parse()
local installed_confs = B.installed_confs(status)
-- Now let's steal from installed package
stealed_confs = {
["/etc/config/dhcp"] = status["dnsmasq-dhcpv6"].Conffiles["/etc/config/dhcp"],
["/etc/dnsmasq.conf"] = status["dnsmasq-dhcpv6"].Conffiles["/etc/dnsmasq.conf"]
}
steal = B.steal_configs(status, installed_confs, {
["/etc/config/dhcp"] = "hash",
["/etc/dnsmasq.conf"] = "hash"
})
assert_table_equal(stealed_confs, steal)
assert_not_nil(status["dnsmasq-dhcpv6"]) -- Package should be there
assert_nil(next(status["dnsmasq-dhcpv6"].Conffiles)) -- But there should be no configuration files in that package
end
function test_block_dump_ordered()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment