雲效跨賬號遷移

新鈦雲服已累計為您分享837篇技術乾貨
背 景  
由於業務調整或組織架構變更,原阿里雲賬號將不再繼續使用。為了確保業務連續性和資料完整性,需要將源賬號下的所有云產品及其相關資料完整、安全地遷移到目標賬號。由於雲效(DevOps平臺)無法直接透過例項劃撥至目標賬號,因此需要對雲效中的資料進行遷移。
建立企業
在目標賬號上點選
https://devops.console.aliyun.com/organizations/standard
此連結,進入雲效控制檯介面,點選“新建組織”按鈕。
選擇“雲效DevOps”點選“立即開啟”按鈕。
根據源賬號雲效,填寫“組織名稱”和“研發組織規模”,填寫完成後點選“立即建立”按鈕,完成雲效企業的建立。
新建專案
進入剛新建企業的控制檯後,點選“專案協作 Projects”旁的“進入工作”按鈕。
點選“新建”按鈕,建立專案。
根據源賬號專案型別,選擇對應的專案模板。
根據源賬號專案資訊進行填寫,填寫完成後點選“新建”按鈕。
新建完成後的專案如下圖所示:
遷移需求
源賬號匯出需求
在源賬號需求介面,點選“批次操作”,在下拉選單中單擊“匯出全部”。
全選所有要匯出的屬性,完成後點選“開始匯出”按鈕。
在跳轉後的“批次操作記錄”介面,等待“進展”的進度條顯示成功後,點選右邊的“下載”圖表按鈕,下載資料檔案。
需求資料表格開啟後如下圖所示:
目標賬號匯入需求
在目標賬號的任務介面右上角,點選“匯入資料”按鈕。
選中“包含子工作項”後,點選“下載模板”按鈕。
將源賬號匯出的資料,根據匯入模板的格式,寫入到該excel表格裡。
注意:負責人必須為當前企業已存在的使用者名稱稱,迭代為當前專案已建立的迭代,填寫不存在的資訊會導致匯入報錯

返回到匯入資料介面中,繼續點選“下一步”按鈕。

將剛填寫完資料的匯入模板上傳上去,完成後點選“開始匯入”按鈕。
直到“匯入工作項”顯示為成功,則表示需求資料匯入完成。
檢查需求資料是否跟源賬號上的資料一致。
遷移任務
源賬號匯出任務

在源賬號任務介面,點選“批次操作”,在下拉選單中單擊“匯出全部”。

全選所有要匯出的屬性,完成後點選“開始匯出”按鈕。
檢視匯出的任務資料,如下圖所示:
目標賬號匯入任務
在目標賬號的任務介面右上角,點選匯入資料按鈕。
選中包含子工作項後,點選下載模板按鈕。
將源賬號匯出的資料,根據匯入模板的格式,寫入到該excel表格裡。
和遷移需求一樣,點選下一步按鈕,將任務資料匯入到目標賬號中。
遷移程式碼組、程式碼倉庫、迭代
程式碼和迭代無法像需求和任務一樣批次匯出匯入,為了提高效率和準確性,我們採用程式碼化方式批次遷移程式碼組、程式碼倉庫和迭代,避免手動操作的費時費力及潛在錯誤。

獲取組織ID

程式碼裡需要用到“組織ID”,點選頭像下拉選單裡的“管理後臺”按鈕,在“基本資訊”頁面即可看到“組織ID”。

獲取企業空間ID

程式碼裡需要用到“企業空間ID”,點選
https://next.api.aliyun.com/api/devops/2021-06-25/GetCodeupOrganizatio
此連結,在“identity 企業標識”輸入框內輸入“組織ID”,完成後點選“發起呼叫”按鈕。在左側“呼叫結果”頁面可以看到“namespaceId”,即為企業空間ID。

獲取個人訪問令牌

點選頭像,在下拉選單中點選“個人設定”,進入個人設定介面,選擇“個人訪問令牌”,點選“建立訪問令牌”按鈕。
輸入“令牌名稱”,選擇到期時間,按需選擇許可權。程式碼管理許可權必選,後續要用它進行程式碼倉庫資料匯入操作。完成上述配置後,點選“新建”按鈕建立個人訪問令牌。

執行程式碼批次遷移

執行“源賬號匯出程式碼”,會print輸出程式碼組、程式碼倉庫和迭代的資訊,執行“目標賬號匯入程式碼”時按程式碼提示輸入程式碼組、程式碼倉庫和迭代的資訊,即可完成匯入。執行前請在測試環境執行測試!!!
源賬號匯出程式碼
# -*- coding: utf-8 -*-# This file is auto-generated, don't edit it. Thanks.import sys,timefrom typing importListfrom alibabacloud_devops20210625.client import Client as devops20210625Clientfrom alibabacloud_tea_openapi import models as open_api_modelsfrom alibabacloud_devops20210625 import models as devops_20210625_modelsfrom alibabacloud_tea_util import models as util_modelsfrom alibabacloud_tea_util.client import Client as UtilClientak="源賬號AK"sk="源賬號SK"organization_id='源賬號組織ID'parent_id= 源賬號企業空間IDclassSample:def__init__(self):pass    @staticmethoddefcreate_client(        access_key_id: str,        access_key_secret: str,    ) -> devops20210625Client:        config = open_api_models.Config(access_key_id=ak,access_key_secret=sk)        config.endpoint = f'devops.cn-hangzhou.aliyuncs.com'return devops20210625Client(config)#匯出程式碼組    @staticmethoddefListGroupMember(            args: List[str],    ) -> None:        organization_id = args[0]        groupId = args[1]        User_list=[]        client = Sample.create_client(ak, sk)        list_group_member_request = devops_20210625_models.ListGroupMemberRequest(organization_id=organization_id)        runtime = util_models.RuntimeOptions()        headers = {}        Users = client.list_group_member_with_options(groupId, list_group_member_request, headers,runtime).body.resultfor User in Users:            User_dic={}            User_dic["name"]=User.name            User_dic["access_level"] = User.access_level            User_list.append(User_dic)return User_list    @staticmethoddefListRepositoryGroups(        args: List[str],    ) -> None:        organization_id=args[0]        parent_id=args[1]        ListRepositoryGroups_list=[]        client = Sample.create_client(ak, sk)        list_repository_groups_request = devops_20210625_models.ListRepositoryGroupsRequest(organization_id=organization_id,parent_id=parent_id,page_size=100)        runtime = util_models.RuntimeOptions()        headers = {}        ListRepositoryGroups=client.list_repository_groups_with_options(list_repository_groups_request, headers, runtime).body.resultfor RepositoryGroups in ListRepositoryGroups:            ListRepositoryGroup_dic = {}            ListRepositoryGroup_dic["id"] = RepositoryGroups.id            ListRepositoryGroup_dic["name"] =RepositoryGroups.name            ListRepositoryGroup_dic["description"] =RepositoryGroups.description            ListRepositoryGroup_dic["path"] = RepositoryGroups.path            ListRepositoryGroup_dic["visibility_level"] = RepositoryGroups.visibility_level            User_list=Sample.ListGroupMember([organization_id, str(RepositoryGroups.id)])            ListRepositoryGroup_dic["user_list"] = User_list            ListRepositoryGroups_list.append(ListRepositoryGroup_dic)return ListRepositoryGroups_list#獲取程式碼倉庫資訊    @staticmethoddefGetRepositorymain(            args: List[str],    ) -> None:        organization_id = args[0]        identity = args[1]        client = Sample.create_client(ak, sk)        get_repository_request = devops_20210625_models.GetRepositoryRequest(organization_id=organization_id,identity=identity)        runtime = util_models.RuntimeOptions()        headers = {}        http_url_to_repository = client.get_repository_with_options(get_repository_request, headers,runtime).body.repository.http_url_to_repositoryreturn http_url_to_repository    @staticmethoddefListRepositoriesmain(            args: List[str],    ) -> None:        organization_id = args[0]        client = Sample.create_client(ak, sk)        list_repositories_request = devops_20210625_models.ListRepositoriesRequest(organization_id=organization_id,per_page=100)        runtime = util_models.RuntimeOptions()        headers = {}        ListRepositories = client.list_repositories_with_options(list_repositories_request, headers,runtime).body.result        repository_list = []for Repository in ListRepositories:            repository_dic = {}            repository_dic["name"] = Repository.name            repository_dic["path"] = Repository.path            repository_dic["namespace_id"] = Repository.namespace_id            repository_dic["description"] = Repository.description            repository_dic["visibility_level"] = Repository.visibility_level            http_url_to_repository = Sample.GetRepositorymain([organization_id, Repository.id])            repository_dic["import_url"] = http_url_to_repository            repository_list.append(repository_dic)return repository_list# 匯出迭代資訊    @staticmethoddefListProjectsmain(            args: List[str],    ) -> None:        organization_id = args[0]        client = Sample.create_client(ak, sk)        list_projects_request = devops_20210625_models.ListProjectsRequest(category='Project')        runtime = util_models.RuntimeOptions()        headers = {}        projects = client.list_projects_with_options(organization_id, list_projects_request, headers,runtime).body.projects        projects_info = {}for project in projects:            identifier = project.identifier            name = project.name            projects_info[name] = identifierreturn projects_info    @staticmethoddefListSprintsmain(            args: List[str],    ) -> None:        organization_id = args[0]        space_identifier = args[1]        client = Sample.create_client(ak, sk)        list_sprints_request = devops_20210625_models.ListSprintsRequest(space_identifier=space_identifier,space_type='Project',max_results=200)        runtime = util_models.RuntimeOptions()        headers = {}        sprints = client.list_sprints_with_options(organization_id, list_sprints_request, headers,runtime).body.sprints        sprint_list = []for sprint in sprints:            sprint_dic = {}            sprint_dic["name"] = sprint.name            sprint_dic["start_date"] = time.strftime('%Y-%m-%d', time.localtime(sprint.start_date / 1000))            sprint_dic["end_date"] = time.strftime('%Y-%m-%d', time.localtime(sprint.end_date / 1000))            sprint_list.append(sprint_dic)return sprint_listif __name__ == '__main__':#獲取程式碼組資訊    ListRepositoryGroups_list=Sample.ListRepositoryGroups([organization_id,parent_id])print("程式碼組資訊:"+str(ListRepositoryGroups_list))#獲取程式碼倉庫資訊    repository_list = Sample.ListRepositoriesmain([organization_id, ])print("程式碼倉庫資訊:"+str(repository_list))#獲取迭代資訊whileTrue:        projects_info = Sample.ListProjectsmain([organization_id, ])print("專案名稱和專案ID的對應關係"+str(projects_info))        identifier = input("請輸入要匯出的迭代是哪個專案的ID(不需要匯出請輸入no):")if identifier=="no":break        sprint_list = Sample.ListSprintsmain([organization_id, identifier])print("迭代的資訊:"+str(sprint_list))
目標賬號匯入程式碼
# -*- coding: utf-8 -*-# This file is auto-generated, don't edit it. Thanks.from typing importListfrom alibabacloud_devops20210625.client import Client as devops20210625Clientfrom alibabacloud_tea_openapi import models as open_api_modelsfrom alibabacloud_devops20210625 import models as devops_20210625_modelsfrom alibabacloud_tea_util import models as util_modelsfrom alibabacloud_tea_util.client import Client as UtilClientimport astak="目標賬號AK"sk="目標賬號SK"organization_id="目標賬號組織ID"namespaceId="目標賬號企業空間ID"import_account="目標賬號個人訪問令牌名稱"import_token="目標賬號個人訪問令牌token"classSample:def__init__(self):pass    @staticmethoddefcreate_client(        access_key_id: str,        access_key_secret: str,    ) -> devops20210625Client:        config = open_api_models.Config(access_key_id=ak,access_key_secret=sk)        config.endpoint = f'devops.cn-hangzhou.aliyuncs.com'return devops20210625Client(config)#匯入程式碼組    @staticmethoddefCreateRepositoryGroupmain(        args: List[str],    ) -> None:        organization_id = args[0]        name = args[1]        path = args[2]        visibility_level = args[3]        namespaceId = args[4]        description = args[5]        client = Sample.create_client(ak,sk)        create_repository_group_request = devops_20210625_models.CreateRepositoryGroupRequest(organization_id=organization_id,name=name,path=path,visibility_level=visibility_level,parent_id=namespaceId,description=description)        runtime = util_models.RuntimeOptions()        headers = {}print(client.create_repository_group_with_options(create_repository_group_request, headers, runtime))#獲取原始碼組ID與目的碼組ID的對應關係    @staticmethoddefListRepositoryGroups(            args: List[str],    ) -> None:        organization_id = args[0]        parent_id = args[1]        ListRepositoryGroups_list = []        client = Sample.create_client(ak,sk)        list_repository_groups_request = devops_20210625_models.ListRepositoryGroupsRequest(organization_id=organization_id,parent_id=parent_id,page_size=100)        runtime = util_models.RuntimeOptions()        headers = {}        ListRepositoryGroups = client.list_repository_groups_with_options(list_repository_groups_request, headers,runtime).body.resultfor RepositoryGroups in ListRepositoryGroups:            ListRepositoryGroup_dic = {}            ListRepositoryGroup_dic["id"] = RepositoryGroups.id            ListRepositoryGroup_dic["name"] = RepositoryGroups.name            ListRepositoryGroup_dic["description"] = RepositoryGroups.description            ListRepositoryGroup_dic["path"] = RepositoryGroups.path            ListRepositoryGroup_dic["visibility_level"] = RepositoryGroups.visibility_level            ListRepositoryGroups_list.append(ListRepositoryGroup_dic)return ListRepositoryGroups_list#匯入程式碼倉庫    @staticmethoddefCreateRepositorymain(            args: List[str],    ) -> None:        organization_id = args[0]        name = args[1]        path = args[2]        namespace_id = args[3]        description = args[4]        visibility_level = args[5]        import_url = args[6]        import_account = args[7]        import_token = args[8]        client = Sample.create_client(ak,sk)        create_repository_request = devops_20210625_models.CreateRepositoryRequest(organization_id=organization_id,name=name,path=path,namespace_id=namespace_id,description=description,visibility_level=visibility_level,import_url=import_url,import_account=import_account,import_token=import_token)        runtime = util_models.RuntimeOptions()        headers = {}print(client.create_repository_with_options(create_repository_request, headers, runtime))# 得到專案名稱和專案ID的對應關係    @staticmethoddefListProjectsmain(            args: List[str],    ) -> None:        organization_id = args[0]        client = Sample.create_client(ak,sk)        list_projects_request = devops_20210625_models.ListProjectsRequest(category='Project')        runtime = util_models.RuntimeOptions()        headers = {}        projects = client.list_projects_with_options(organization_id, list_projects_request, headers,runtime).body.projects        projects_info = {}for project in projects:            identifier = project.identifier            name = project.name            projects_info[name] = identifierreturn projects_info#建立迭代    @staticmethoddefCreateSprintmain(        args: List[str],    ) -> None:        organization_id=args[0]        identifier=args[1]        FROM_diedai=args[2]        staff_id=args[3]        client = Sample.create_client(ak,sk)        create_sprint_request = devops_20210625_models.CreateSprintRequest(            staff_ids=[staff_id],  #ram使用者uid            name=FROM_diedai["name"],  #迭代名稱            space_identifier=identifier,  #專案ID            start_date=FROM_diedai["start_date"],  #迭代開始時間            end_date=FROM_diedai["end_date"]     #迭代結束時間        )        runtime = util_models.RuntimeOptions()        headers = {}print(client.create_sprint_with_options(organization_id, create_sprint_request, headers, runtime))if __name__ == '__main__':# 匯入程式碼組    FROMListRepositoryGroups_list=ast.literal_eval(input("請輸入源賬號匯出的程式碼組列表:"))for RepositoryGroup in FROMListRepositoryGroups_list:        Sample.CreateRepositoryGroupmain([organization_id,RepositoryGroup["name"],RepositoryGroup["path"],RepositoryGroup["visibility_level"],namespaceId,RepositoryGroup["description"]])# 獲取原始碼組ID與目的碼組ID的對應關係    TOListRepositoryGroups_list = Sample.ListRepositoryGroups([organization_id, namespaceId])    FROM_TOListRepositoryGroupID_dic = {}for FROMListRepositoryGroup in FROMListRepositoryGroups_list:for TOListRepositoryGroup in TOListRepositoryGroups_list:if FROMListRepositoryGroup["name"] == TOListRepositoryGroup["name"]:                FROM_TOListRepositoryGroupID_dic[FROMListRepositoryGroup["id"]] = TOListRepositoryGroup["id"]    FROMparent_id=ast.literal_eval(input("請輸入源賬號的parent_id,也就是namespace_id:"))    FROM_TOListRepositoryGroupID_dic[FROMparent_id]=int(namespaceId)print("源賬號程式碼組ID與目標賬號程式碼組ID的對應關係:"+str(FROM_TOListRepositoryGroupID_dic))#匯入程式碼倉庫    FROMrepository_list=ast.literal_eval(input("請輸入源賬號匯出的程式碼倉庫列表:"))for FROMrepository in FROMrepository_list:        Sample.CreateRepositorymain([organization_id, FROMrepository["name"], FROMrepository["path"],FROM_TOListRepositoryGroupID_dic[FROMrepository["namespace_id"]], FROMrepository["description"],FROMrepository["visibility_level"], FROMrepository["import_url"], import_account, import_token])# 匯入迭代whileTrue:        projects_info = Sample.ListProjectsmain([organization_id, ])print("專案名稱和專案ID的對應關係:"+str(projects_info))        identifier = input("請輸入要匯入的迭代是哪個專案的ID(不需要匯出請輸入no):")if identifier=="no":breakprint("使用者ID:{使用者A:使用者A的RAM賬號UID,使用者B:使用者B的RAM賬號UID,使用者C:使用者C的RAM賬號UID}")print("專案與負責人的對應關係:{'專案A':'負責人A','專案B':'負責人B','專案C':'負責人C'}")        staff_id = input("請輸入要匯入迭代負責人的RAM賬號UID:")        FROM_diedai_list = ast.literal_eval(input("請輸入要匯入的迭代內容列表:"))for FROM_diedai in FROM_diedai_list:            Sample.CreateSprintmain([organization_id, identifier, FROM_diedai, staff_id])
總 結
為了確保業務連續性和資料完整性,針對源阿里雲賬號即將停用的情況,我們完成了雲效(DevOps平臺)的資料遷移工作。由於雲效無法直接透過例項遷移至目標賬號,我們採取了資料匯出與匯入的方式,確保所有專案、流水線配置及程式碼倉庫等資料完整無誤地遷移到目標賬號下。至此,平穩順利的完成此次遷移。

如有相關問題,請在文章後面給小編留言,小編安排作者第一時間和您聯絡,為您答疑解惑。

    推薦閱讀   

    推薦影片    

相關文章