Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 36 additions & 33 deletions keeper/src/keeper/gov/service/upload.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,18 @@ type RegistryEntry = {
}

type SourceAuthority = {
host: boolean,
modules: {[string]: boolean},
roots: {string},
owners: {[string]: boolean},
ordered_owners: {string},
}

function M.retain_authoritative_entries(entries: {RegistryEntry}, authority: SourceAuthority)
local retained: {RegistryEntry} = {}
local skipped = {}
for _, entry in ipairs(entries or {}) do
local module = entry.meta and entry.meta.module
local authoritative = authority.host and (module == nil or module == "")
if type(module) == "string" and module ~= "" then
authoritative = authority.modules[module] == true
end
local owner = "application"
if type(module) == "string" and module ~= "" then owner = module end
local authoritative = authority.owners[owner] == true
if authoritative then
table.insert(retained, entry)
else
Expand Down Expand Up @@ -140,15 +138,15 @@ local function add_skip_stats(stats, filesystem_skipped, registry_skipped, manag
return stats
end

local function build_details(managed_namespaces, filesystem_skipped, registry_skipped, unmounted_registry, source_roots)
local function build_details(managed_namespaces, filesystem_skipped, registry_skipped, unmounted_registry, source_owners)
return {
managed_namespaces = managed_namespaces or {},
skipped_unmanaged = {
filesystem = M.skipped_summary(filesystem_skipped),
registry = M.skipped_summary(registry_skipped),
unmounted_registry = M.skipped_summary(unmounted_registry),
},
source_roots = source_roots or {},
source_owners = source_owners or {},
}
end

Expand Down Expand Up @@ -210,34 +208,39 @@ end
local function get_filesystem_entries(options)
log:debug("Getting filesystem entries", options)

local source_modules = rawget(system, "source_modules")
local load_sources = rawget(loader, "load_sources")
if (source_modules == nil) ~= (load_sources == nil) then
return nil, nil, nil, nil, "runtime module-source capabilities are incomplete"
end

local authority: SourceAuthority = { host = true, modules = {}, roots = { "application" } }
local source = rawget(system, "source")
local authority: SourceAuthority = {
owners = { application = true },
ordered_owners = { "application" },
}
local all_entries: {RegistryEntry} = {}

if source_modules ~= nil and load_sources ~= nil then
if type(source_modules) ~= "function" or type(load_sources) ~= "function" then
return nil, nil, nil, nil, "runtime module-source capabilities have invalid types"
if source ~= nil then
if type(source) ~= "table" then
return nil, nil, nil, nil, "runtime source capability has an invalid type"
end
local modules, modules_err = source_modules()
if not modules then return nil, nil, nil, nil, tostring(modules_err) end
for _, module in ipairs(modules) do
if type(module) ~= "string" then
return nil, nil, nil, nil, "runtime returned an invalid module-source identifier"
end
local module_name: string = module
authority.modules[module_name] = true
table.insert(authority.roots, module_name)
local load = rawget(source, "load")
if type(load) ~= "function" then
return nil, nil, nil, nil, "runtime source load capability is unavailable"
end
local loaded, load_err = load_sources()
local loaded, load_err = load()
if not loaded then
return nil, nil, nil, nil, "Failed to load deployment sources: " .. tostring(load_err)
end
all_entries = M.retain_authoritative_entries(loaded :: {RegistryEntry}, authority)
if type(loaded.owners) ~= "table" or type(loaded.entries) ~= "table" then
return nil, nil, nil, nil, "runtime returned an invalid deployment source snapshot"
end
authority = { owners = {}, ordered_owners = {} }
for _, owner in ipairs(loaded.owners) do
if type(owner) ~= "string" or owner == "" then
return nil, nil, nil, nil, "runtime returned an invalid source owner"
end
if not authority.owners[owner] then
authority.owners[owner] = true
table.insert(authority.ordered_owners, owner)
end
end
all_entries = M.retain_authoritative_entries(loaded.entries :: {RegistryEntry}, authority)
else
-- Older runtimes expose only the application filesystem. Module-owned
-- snapshots stay outside this sync operation.
Expand Down Expand Up @@ -347,7 +350,7 @@ local function has_changes(options)
has_changes = comparison.has_changes,
count = comparison.count,
details = build_details(managed_namespaces, filesystem_skipped, registry_skipped,
unmounted_registry, authority.roots),
unmounted_registry, authority.ordered_owners),
}
end

Expand Down Expand Up @@ -399,7 +402,7 @@ local function upload(options)
delete = 0
}, filesystem_skipped, registry_skipped, managed_namespaces, unmounted_registry),
details = build_details(managed_namespaces, filesystem_skipped, registry_skipped,
unmounted_registry, authority.roots),
unmounted_registry, authority.ordered_owners),
}
end

Expand All @@ -424,7 +427,7 @@ local function upload(options)
count = comparison.count,
stats = stats,
details = build_details(managed_namespaces, filesystem_skipped, registry_skipped,
unmounted_registry, authority.roots),
unmounted_registry, authority.ordered_owners),
}
end

Expand Down
5 changes: 2 additions & 3 deletions keeper/src/keeper/gov/service/upload_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,8 @@ local function define_tests()
{ id = "example.packed:item", kind = "registry.entry",
meta = { module = "example/packed" } },
}, {
host = true,
modules = { ["example/local"] = true },
roots = { "application", "example/local" },
owners = { application = true, ["example/local"] = true },
ordered_owners = { "application", "example/local" },
})
test.eq(#retained, 2)
test.eq(retained[1].id, "app:host")
Expand Down