# Обратная миграция омеги
## миграция 1 юзера
```lua
local moonwalker = require 'moonwalker'
local fiber = require 'fiber'
local ctx_t = require 'ctx'
local id = require 'breeze.local'.gen_id
local json = require 'json'
local function is_web_role(role)
return role.attr and role.attr.description and role.attr.description.web
end
local function get_global_domain(user)
local global
box.space.links.index.user:pairs{user.id, breeze.static.roles.mcs_owner.id}:grep(function(link)
local project = breeze.models.projects.select.id(link.project)
if project.is_domain and project.attr.mcs_global then
global = project
end
return false
end):totable()
return global
end
local function comeback_user_migrate(ctx, get_user)
local user = breeze.models.users.get(get_user)
local ctx = ctx_t(ctx.log.prefix .. "_" .. user.uid)
box.atomic(function()
ctx.log:warn('START user %s', user.email)
local global = get_global_domain(user)
if not global then
ctx.log:error('no global domain for user %s %s', user.id, user.email)
return
end
local projects = box.space.projects.index.name:pairs{global.id}:map(breeze.models.projects.select.tuple):totable()
local domain_users = box.space.users.index.domain:pairs{global.id}:map(breeze.models.users.select.tuple):totable()
local domain_groups = box.space.groups.index.name:pairs{global.id}:map(breeze.models.groups.select.tuple):totable()
for _, project in pairs(projects) do
local ctx = ctx_t(ctx.log.prefix .. "_" .. project.pid)
project:update({
domain = breeze.static.domains.root.id;
parent = project.id;
is_domain = true;
})
ctx.log:warn('project became domain %s', project.id)
if project.attr.services and project.attr.services.infra then
local old_infra_id = project.id
local delete_project = table.deepcopy(project)
project.id = id(box.space.projects)
ctx.log:warn('project_id (old infra_id) -> new id: %s -> %s', delete_project.id, project.id)
delete_project:delete(ctx)
project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))
local infra
if project.attr.migrate_infra_pid then
infra = breeze.models.projects.select.pid(project.attr.migrate_infra_pid)
end
if not infra then
infra = breeze.models.projects.select.pid(project.pid .. "_infra")
end
if not infra then
infra = breeze.models.projects.create(ctx, {
is_domain = false;
is_service = false;
name = user.email;
type = 'infra';
domain_id = project.id;
})
ctx.log:warn('create infra %s', infra.id)
end
local old_project_id = infra.id
local delete_infra = table.deepcopy(infra)
infra.id = old_infra_id
ctx.log:warn('infra_id (old project_id) -> old infra id: %s -> %s', delete_infra.id, infra.id)
delete_infra:delete(ctx)
infra = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(infra)))
delete_project = table.deepcopy(project)
project.id = old_project_id
project.parent = old_project_id
ctx.log:warn('project_id (new id) -> old project id: %s -> %s', delete_project.id, project.id)
delete_project:delete(ctx)
project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))
infra.name = string.match(infra.name, "(.+) (.+)") or infra.name
infra:update({
domain = project.id;
parent = project.id;
type = 'infra';
name = infra.name;
})
local exist, copy_link, copy_glink, role
box.space.links.index.project_role:pairs{infra.id}
:map(breeze.models.links.select.tuple):grep(function(link)
role = breeze.models.roles.get({ id = link.role }, { raise = true })
if is_web_role(role) then
exist = breeze.models.links.select.project_user_role_domain(project.id, link.user, link.role, link.is_domain)
if user and not exist then
local l = breeze.models.links.create(ctx, {
project = project.id;
user = link.user;
role = link.role;
is_domain = link.is_domain;
is_inherited = link.is_inherited;
no_user_check = true;
})
ctx.log:warn('copy link from infra to project, new_link: %s [%s]', l.id, link.id)
end
end
end):totable()
box.space.group_links.index.project_role:pairs{infra.id}
:map(breeze.models.group_links.select.tuple):grep(function(glink)
role = breeze.models.roles.get({ id = glink.role }, { raise = true })
if is_web_role(role) then
exist = breeze.models.group_links.select.project_group_role_domain(project.id, glink.user, glink.role, glink.is_domain)
if user and not exist then
local gl = breeze.models.group_links.create(ctx, {
project = project.id;
group = glink.group;
role = glink.role;
is_domain = glink.is_domain;
is_inherited = glink.is_inherited;
})
ctx.log:warn('copy group_link from infra to project, new_link: %s [%s]', gl.id, glink.id)
end
end
end):totable()
end
breeze.models.links.create(ctx, {
project = project.id;
user = user.id;
role = breeze.static.roles.mcs_owner.id;
is_domain = false;
is_inherited = true;
})
for _, user in pairs(domain_users) do
if user.attr.from_project == project.pid then
ctx.log:warn('user changed domain: %s -> %s', user.domain, project.id)
user:update({
domain = project.id;
})
end
end
for _, group in pairs(domain_groups) do
if group.attr.from_project == project.pid then
ctx.log:warn('group changed domain: %s -> %s', group.domain, project.id)
group:update({
domain = project.id;
})
end
end
end
local links = global:list_links()
for _, link in pairs(links.links) do
link:delete()
end
for _, link in pairs(links.group_links) do
link:delete()
end
global:delete()
ctx.log:warn('END success user %s', user.email)
end)
end
local email = "nastya-241197@mail.ru"
return comeback_user_migrate(ctx_t("MIGRATE_BACK"), {email = email})
```
## миграция всех юзеров
```lua
local moonwalker = require 'moonwalker'
local fiber = require 'fiber'
local ctx_t = require 'ctx'
local id = require 'breeze.local'.gen_id
local json = require 'json'
local function is_web_role(role)
return role.attr and role.attr.description and role.attr.description.web
end
local function get_global_domain(user)
local global
box.space.links.index.user:pairs{user.id, breeze.static.roles.mcs_owner.id}:grep(function(link)
local project = breeze.models.projects.select.id(link.project)
if project.is_domain and project.attr.mcs_global then
global = project
end
return false
end):totable()
return global
end
local function comeback_user_migrate(ctx, get_user)
local user = breeze.models.users.get(get_user)
local ctx = ctx_t(ctx.log.prefix .. "_" .. user.uid)
box.atomic(function()
ctx.log:warn('START user %s', user.email)
local global = get_global_domain(user)
if not global then
ctx.log:error('no global domain for user %s %s', user.id, user.email)
return
end
local projects = box.space.projects.index.name:pairs{global.id}:map(breeze.models.projects.select.tuple):totable()
local domain_users = box.space.users.index.domain:pairs{global.id}:map(breeze.models.users.select.tuple):totable()
local domain_groups = box.space.groups.index.name:pairs{global.id}:map(breeze.models.groups.select.tuple):totable()
for _, project in pairs(projects) do
local ctx = ctx_t(ctx.log.prefix .. "_" .. project.pid)
project:update({
domain = breeze.static.domains.root.id;
parent = project.id;
is_domain = true;
})
ctx.log:warn('project became domain %s', project.id)
if project.attr.services and project.attr.services.infra then
local old_infra_id = project.id
local delete_project = table.deepcopy(project)
project.id = id(box.space.projects)
ctx.log:warn('project_id (old infra_id) -> new id: %s -> %s', delete_project.id, project.id)
delete_project:delete(ctx)
project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))
local infra
if project.attr.migrate_infra_pid then
infra = breeze.models.projects.select.pid(project.attr.migrate_infra_pid)
end
if not infra then
infra = breeze.models.projects.select.pid(project.pid .. "_infra")
end
if not infra then
infra = breeze.models.projects.create(ctx, {
is_domain = false;
is_service = false;
name = user.email;
type = 'infra';
domain_id = project.id;
})
ctx.log:warn('create infra %s', infra.id)
end
local old_project_id = infra.id
local delete_infra = table.deepcopy(infra)
infra.id = old_infra_id
ctx.log:warn('infra_id (old project_id) -> old infra id: %s -> %s', delete_infra.id, infra.id)
delete_infra:delete(ctx)
infra = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(infra)))
delete_project = table.deepcopy(project)
project.id = old_project_id
project.parent = old_project_id
ctx.log:warn('project_id (new id) -> old project id: %s -> %s', delete_project.id, project.id)
delete_project:delete(ctx)
project = breeze.models.projects.select.tuple(box.space.projects:insert(T.projects.tuple(project)))
infra.name = string.match(infra.name, "(.+) (.+)") or infra.name
infra:update({
domain = project.id;
parent = project.id;
type = 'infra';
name = infra.name;
})
local exist, copy_link, copy_glink, role
box.space.links.index.project_role:pairs{infra.id}
:map(breeze.models.links.select.tuple):grep(function(link)
role = breeze.models.roles.get({ id = link.role }, { raise = true })
if is_web_role(role) then
exist = breeze.models.links.select.project_user_role_domain(project.id, link.user, link.role, link.is_domain)
if user and not exist then
local l = breeze.models.links.create(ctx, {
project = project.id;
user = link.user;
role = link.role;
is_domain = link.is_domain;
is_inherited = link.is_inherited;
no_user_check = true;
})
ctx.log:warn('copy link from infra to project, new_link: %s [%s]', l.id, link.id)
end
end
end):totable()
box.space.group_links.index.project_role:pairs{infra.id}
:map(breeze.models.group_links.select.tuple):grep(function(glink)
role = breeze.models.roles.get({ id = glink.role }, { raise = true })
if is_web_role(role) then
exist = breeze.models.group_links.select.project_group_role_domain(project.id, glink.user, glink.role, glink.is_domain)
if user and not exist then
local gl = breeze.models.group_links.create(ctx, {
project = project.id;
group = glink.group;
role = glink.role;
is_domain = glink.is_domain;
is_inherited = glink.is_inherited;
})
ctx.log:warn('copy group_link from infra to project, new_link: %s [%s]', gl.id, glink.id)
end
end
end):totable()
end
breeze.models.links.create(ctx, {
project = project.id;
user = user.id;
role = breeze.static.roles.mcs_owner.id;
is_domain = false;
is_inherited = true;
})
for _, user in pairs(domain_users) do
if user.attr.from_project == project.pid then
ctx.log:warn('user changed domain: %s -> %s', user.domain, project.id)
user:update({
domain = project.id;
})
end
end
for _, group in pairs(domain_groups) do
if group.attr.from_project == project.pid then
ctx.log:warn('group changed domain: %s -> %s', group.domain, project.id)
group:update({
domain = project.id;
})
end
end
end
local links = global:list_links()
for _, link in pairs(links.links) do
link:delete()
end
for _, link in pairs(links.group_links) do
link:delete()
end
global:delete()
ctx.log:warn('END success user %s', user.email)
end)
end
local function comeback_projects_migrate()
local name = 'COMEBACK_MIGRATE_PROJECTS'
local count = 0
local ctx = ctx_t(name)
moonwalker {
name = name;
progress = '1%';
space = box.space.users;
actor = function(u)
local ok, err = pcall(comeback_user_migrate, ctx, {id = u.id})
if not ok then
ctx.log:error('dont migrate user %s, error: %s', u.email, json.encode(err))
count = count + 1
end
end;
}
return ("dont migrate back %s users"):format(count)
end
return comeback_projects_migrate()
```