# Обратная миграция омеги ## миграция 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() ```