Непрерывные интеграция и поставка в Фабрике данных AzureContinuous integration and delivery (CI/CD) in Azure Data Factory

Непрерывная интеграция — это способ автоматического тестирования каждого изменения, внесенного в базу кода.Continuous Integration is the practice of testing each change done to your codebase automatically and as early as possible. Непрерывная поставка следует за проверкой, которая выполняется во время непрерывной интеграции. Она передает изменения в промежуточную или рабочую систему. Continuous Delivery follows the testing that happens during Continuous Integration and pushes changes to a staging or production system.

В Фабрике данных Azure под непрерывными интеграцией и поставкой подразумевается перемещение конвейеров Фабрики данных из одной среды (разработки, тестирования, рабочей) в другую.For Azure Data Factory, continuous integration & delivery means moving Data Factory pipelines from one environment (development, test, production) to another. Чтобы выполнить непрерывные интеграцию и поставку, можно использовать интеграцию через пользовательский интерфейс Фабрики данных с шаблонами Azure Resource Manager.To do continuous integration & delivery, you can use Data Factory UI integration with Azure Resource Manager templates. Если выбрать вариант Шаблон ARM, пользовательский интерфейс фабрики данных создаст шаблон Resource Manager.The Data Factory UI can generate a Resource Manager template when you select the ARM template options. При выборе варианта Export ARM template (Экспорт шаблона ARM) портал создает шаблон Resource Manager для фабрики данных и файл конфигурации, включающий все строки подключения, а также другие параметры.When you select Export ARM template, the portal generates the Resource Manager template for the data factory and a configuration file that includes all your connections strings and other parameters. Затем необходимо создать один файл конфигурации для каждой среды (разработки, тестирования, рабочей).Then you have to create one configuration file for each environment (development, test, production). Главный файл шаблона Resource Manager одинаков для всех сред.The main Resource Manager template file remains the same for all the environments.

Уделите 9 минут вашего времени, чтобы просмотреть следующее видео с кратким обзором и демонстрацией этой функции:For a nine-minute introduction and demonstration of this feature, watch the following video:

Примечание

Эта статья была изменена и теперь содержит сведения о новом модуле Az для Azure PowerShell.This article has been updated to use the new Azure PowerShell Az module. Вы по-прежнему можете использовать модуль AzureRM, исправления ошибок для которого будут продолжать выпускаться как минимум до декабря 2020 г.You can still use the AzureRM module, which will continue to receive bug fixes until at least December 2020. Дополнительные сведения о совместимости модуля Az с AzureRM см. в статье Introducing the new Azure PowerShell Az module (Знакомство с новым модулем Az для Azure PowerShell).To learn more about the new Az module and AzureRM compatibility, see Introducing the new Azure PowerShell Az module. Инструкции по установке модуля Az см. в статье об установке Azure PowerShell.For Az module installation instructions, see Install Azure PowerShell.

Создание шаблона Resource Manager для каждой средыCreate a Resource Manager template for each environment

Выберите Export ARM template (Экспорт шаблона ARM), чтобы экспортировать шаблон Resource Manager в фабрику данных в среде разработки.Select Export ARM template to export the Resource Manager template for your data factory in the development environment.

Затем перейдите к фабрикам данных в тестовой и рабочей средах и выберите Import ARM template (Импорт шаблона ARM).Then go to your test data factory and production data factory and select Import ARM template.

После этого вы перейдете на портал Azure, где сможете импортировать экспортированный шаблон.This action takes you to the Azure portal, where you can import the exported template. Выберите Build your own template in the editor (Создать собственный шаблон в редакторе), а затем — Загрузить файл и выберите созданный шаблон Resource Manager.Select Build your own template in the editor and then Load file and select the generated Resource Manager template. Укажите параметры, и фабрика данных и весь конвейер импортируются в вашу рабочую среду.Provide the settings, and the data factory and the entire pipeline is imported in your production environment.

Нажмите кнопку Загрузить файл, выберите экспортированный шаблон Resource Manager и укажите все значения конфигурации (например, связанные службы).Select Load file to select the exported Resource Manager template and provide all the configuration values (for example, linked services).

Строки подключения.Connection strings. Можно найти сведения, необходимые для создания строки подключения, в статьях об отдельных соединителях.You can find the info required to create connection strings in the articles about the individual connectors. Дополнительные сведения о базе данных SQL Azure см. в статье Копирование данных в базу данных Azure SQL и из нее с помощью фабрики данных Azure.For example, for Azure SQL Database, see Copy data to or from Azure SQL Database by using Azure Data Factory. Чтобы проверить правильную строку (например, для связанной службы), можно также открыть представление кода для ресурса в пользовательском интерфейсе Фабрики данных.To verify the correct connection string - for a linked service, for example - you can also open code view for the resource in the Data Factory UI. Однако в представлении кода пароль или часть ключа учетной записи строки подключения удаляется.In code view, however, the password or account key portion of the connection string is removed. Чтобы открыть представление кода, щелкните значок, который выделен на следующем снимке экрана.To open code view, select the icon highlighted in the following screenshot.

Откройте представление кода, чтобы просмотреть строку подключения

Жизненный цикл непрерывной интеграцииContinuous integration lifecycle

Ниже приведен полный жизненный цикл для непрерывных интеграции и поставки, который можно использовать после включения интеграции Git Azure Repos в пользовательском интерфейсе Фабрики данных:Here is the entire lifecycle for continuous integration & delivery that you can use after you enable Azure Repos Git integration in the Data Factory UI:

  1. Настройте фабрику данных в среде разработки с Azure Repos, в которой все разработчики могут создавать ресурсы Фабрики данных, такие как конвейеры, наборы данных и т. д.Set up a development data factory with Azure Repos in which all developers can author Data Factory resources like pipelines, datasets, and so forth.

  2. Затем разработчики могут изменить ресурсы (например, конвейеры).Then developers can modify resources such as pipelines. Во время этого процесса можно выбрать команду Отладить, чтобы увидеть, как работает конвейер с последними изменениями.As they make their modifications, they can select Debug to see how the pipeline runs with the most recent changes.

  3. После того как разработчики внесут изменения, они могут создать запрос Pull из своей ветви в главную ветвь (или ветвь совместной работы), чтобы их коллеги могли просмотреть изменения.After developers are satisfied with their changes, they can create a pull request from their branch to the master branch (or the collaboration branch) to get their changes reviewed by peers.

  4. Внесенные в главную ветвь изменения можно опубликовать в фабрике в среде разработки, выбрав Опубликовать.After changes are in the master branch, they can publish to the development factory by selecting Publish.

  5. Если команда готова применить изменения к фабрикам в тестовой и рабочей средах, можно экспортировать шаблон Resource Manager из главной ветви или любой другой, если главная поддерживает активную фабрику данных в среде разработки.When the team is ready to promote changes to the test factory and the production factory, they can export the Resource Manager template from the master branch, or from any other branch in case their master branch backs the live development Data Factory.

  6. Экспортированный шаблон Resource Manager можно развернуть с файлами различных параметров в фабрики в тестовой и рабочей средах.The exported Resource Manager template can be deployed with different parameter files to the test factory and the production factory.

Автоматизация непрерывной интеграции с помощью выпусков Azure PipelinesAutomate continuous integration with Azure Pipelines releases

Ниже приведены шаги настройки выпуска Azure Pipelines для автоматизации развертывания фабрики данных в различные среды.Here are the steps to set up an Azure Pipelines release so you can automate the deployment of a data factory to multiple environments.

Схема непрерывной интеграции с помощью Azure Pipelines

ТребованияRequirements

Настройка выпуска Azure PipelinesSet up an Azure Pipelines release

  1. Перейдите на страницу Azure Repos в настроенный проект с Фабрикой данных.Go to your Azure Repos page in the same project as the one configured with the Data Factory.

  2. В верхнем меню щелкните Azure Pipelines > Выпуски > Создать определение выпуска.Click on the top menu Azure Pipelines > Releases > Create release definition.

  3. Выберите шаблон Пустой процесс.Select the Empty process template.

  4. Введите имя своей среды.Enter the name of your environment.

  5. Добавьте артефакт Git и выберите настроенный репозиторий с фабрикой данных.Add a Git artifact and select the same repo configured with the Data Factory. Выберите adf_publish в качестве стандартной ветви с последней версией по умолчанию.Choose adf_publish as the default branch with latest default version.

  6. Добавьте задачу развертывания Azure Resource Manager.Add an Azure Resource Manager Deployment task:

    a.a. Создайте новую задачу, найдите и добавьте Развертывание группы ресурсов Azure.Create new task, search for Azure Resource Group Deployment, and add it.

    2.b. В задаче "Развертывание" выберите подписку, группу ресурсов и расположение для целевой фабрики данных и при необходимости предоставьте учетные данные.In the Deployment task, choose the subscription, resource group, and location for the target Data Factory, and provide credentials if necessary.

    c.c. Выберите действие Create or Update Resource Group (Создание или изменение группы ресурсов).Select the Create or update resource group action.

    d.d. Выберите Select в поле Шаблон.in the Template field. Найдите шаблон Resource Manager (ARMTemplateForFactory.json), созданный с помощью действия публикации на портале.Browse for the Resource Manager template (ARMTemplateForFactory.json) that was created by the publish action in the portal. Найдите этот файл в папке <FactoryName> в ветви adf_publish.Look for this file in the folder <FactoryName> of the adf_publish branch.

    д.e. Выполните те же действия для файла параметров.Do the same thing for the parameters file. Выберите правильный файл. Выбор зависит от того, была ли создана копия или используется файл по умолчанию ARMTemplateParametersForFactory.json.Choose the correct file depending on whether you created a copy or you’re using the default file ARMTemplateParametersForFactory.json.

    Е.f. Выберите Select рядом с полем Переопределить параметры шаблона и заполните сведения для целевой фабрики данных.next to the Override template parameters field and fill in the information for the target Data Factory. Для учетных данных, полученных из хранилища ключей, используйте одно и то же имя секрета в следующем формате: если имя секрета — cred1, введите "$(cred1)" (между кавычками).For the credentials that come from key vault, use the same name for the secret in the following format: assuming the secret’s name is cred1, enter "$(cred1)" (between quotes).

    ж.g. Выберите добавочный режим развертывания.Select the Incremental Deployment Mode.

    Предупреждение

    При выборе полного режима развертывания существующие ресурсы могут быть удалены, в том числе ресурсы в целевой группе ресурсов, которые не определены в шаблоне Resource Manager.If you select Complete deployment mode, existing resources may be deleted, including all the resources in the target resource group that are not defined in the Resource Manager template.

  7. Сохраните конвейер выпуска.Save the release pipeline.

  8. Создайте выпуск из этого конвейера выпуска.Create a new release from this release pipeline.

Получение секретов из Azure Key Vault (необязательно)Optional - Get the secrets from Azure Key Vault

Если вам нужно передать секреты в шаблоне Azure Resource Manager, рекомендуем использовать Azure Key Vault с выпуском Azure Pipelines.If you have secrets to pass in an Azure Resource Manager template, we recommend using Azure Key Vault with the Azure Pipelines release.

Обработать секреты можно двумя способами.There are two ways to handle the secrets:

  1. Добавьте секреты в файл параметров.Add the secrets to parameters file. Дополнительные сведения см. в статье Использование Azure Key Vault для передачи защищенного значения параметра во время развертывания.For more info, see Use Azure Key Vault to pass secure parameter value during deployment.

    • Создайте копию файла параметров, отправленного в ветвь публикации, и задайте значения параметров, которые необходимо получить из хранилища ключей в следующем формате:Create a copy of the parameters file that is uploaded to the publish branch and set the values of the parameters you want to get from key vault with the following format:
    {
        "parameters": {
            "azureSqlReportingDbPassword": {
                "reference": {
                    "keyVault": {
                        "id": "/subscriptions/<subId>/resourceGroups/<resourcegroupId> /providers/Microsoft.KeyVault/vaults/<vault-name> "
                    },
                    "secretName": " < secret - name > "
                }
            }
        }
    }
    
    • При использовании этого метода секрет автоматически извлекается из хранилища ключей.When you use this method, the secret is pulled from the key vault automatically.

    • Файл параметров также должен находиться в ветви публикации.The parameters file needs to be in the publish branch as well.

  2. Перед развертыванием Azure Resource Manager, описанным в предыдущем разделе, добавьте задачу Azure Key Vault:Add an Azure Key Vault task before the Azure Resource Manager Deployment described in the previous section:

    • Выберите вкладку Задачи, создайте новую задачу, найдите и добавьте Azure Key Vault.Select the Tasks tab, create a new task, search for Azure Key Vault and add it.

    • В задаче Key Vault выберите подписку, в которой было создано хранилище ключей, при необходимости введите учетные данные, а затем выберите хранилище ключей.In the Key Vault task, choose the subscription in which you created the key vault, provide credentials if necessary, and then choose the key vault.

Предоставление разрешений для агента Azure PipelinesGrant permissions to the Azure Pipelines agent

Задача Azure Key Vault может завершиться ошибкой времени выполнения fIntegration с отказано в доступе.The Azure Key Vault task may fail the fIntegration Runtime time with an Access Denied error. Загрузите журналы для выпуска и найдите файл .ps1 с помощью команды для предоставления разрешений агенту Azure Pipelines.Download the logs for the release, and locate the .ps1 file with the command to give permissions to the Azure Pipelines agent. Вы можете выполнить команду напрямую или же скопировать идентификатор участника из файла и вручную добавить политику доступа на портале Azure.You can run the command directly, or you can copy the principal ID from the file and add the access policy manually in the Azure portal. (Get и List — минимальные требуемые разрешения.)(Get and List are the minimum permissions required).

Обновление активных триггеровUpdate active triggers

При попытке обновления активных триггеров развертывание может завершиться сбоем.Deployment can fail if you try to update active triggers. Чтобы обновить активные триггеры, необходимо вручную остановить и запустить их после развертывания.To update active triggers, you need to manually stop them and start them after the deployment. Для этого можно добавить задачу Azure PowerShell, как показано в следующем примере.You can add an Azure Powershell task for this purpose, as shown in the following example:

  1. На вкладке задач выпуска найдите и добавьте Azure PowerShell.In the Tasks tab of the release, search for Azure Powershell and add it.

  2. Выберите Azure Resource Manager в качестве типа подключения, а затем — свою подписку.Choose Azure Resource Manager as the connection type and select your subscription.

  3. Выберите Встроенный скрипт в качестве типа скрипта, а затем укажите код.Choose Inline Script as the script type and then provide your code. Следующий пример останавливает триггеры.The following example stops the triggers:

    $triggersADF = Get-AzDataFactoryV2Trigger -DataFactoryName $DataFactoryName -ResourceGroupName $ResourceGroupName
    
    $triggersADF | ForEach-Object { Stop-AzDataFactoryV2Trigger -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Name $_.name -Force }
    

Вы можете выполнить те же шаги и использовать аналогичный код (с функцией Start-AzDataFactoryV2Trigger), чтобы перезапустить триггеры после развертывания.You can follow similar steps and use similar code (with the Start-AzDataFactoryV2Trigger function) to restart the triggers after deployment.

Важно!

В сценариях непрерывных интеграции и развертывания тип среды выполнения интеграции в разных средах должен совпадать.In continuous integration and deployment scenarios, the Integration Runtime type across different environments must be the same. Например, если у вас есть локальная среда выполнения интеграции в среде разработки, ей необходим тип Локальная в других средах, таких как рабочая и тестовая.For example, if you have a Self-Hosted Integration Runtime (IR) in the development environment, the same IR must be of type Self-Hosted in other environments such as test and production also. Аналогично, если вы совместно используете среды выполнения интеграции в нескольких средах, необходимо настроить их в качестве связанных локальных сред во всех средах (разработки, тестирования и рабочей).Similarly, if you're sharing integration runtimes across multiple stages, you have to configure the Integration Runtimes as Linked Self-Hosted in all environments, such as development, test, and production.

Пример шаблона развертыванияSample deployment template

Ниже приведен пример шаблона развертывания, который можно импортировать в Azure Pipelines.Here is a sample deployment template that you can import in Azure Pipelines.

{
    "source": 2,
    "id": 1,
    "revision": 51,
    "name": "Data Factory Prod Deployment",
    "description": null,
    "createdBy": {
        "displayName": "Sample User",
        "url": "https://pde14b1dc-d2c9-49e5-88cb-45ccd58d0335.codex.ms/vssps/_apis/Identities/c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
        "id": "c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
        "uniqueName": "sampleuser@microsoft.com",
        "imageUrl": "https://sampleuser.visualstudio.com/_api/_common/identityImage?id=c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
        "descriptor": "aad.M2Y2N2JlZGUtMDViZC03ZWI3LTgxYWMtMDcwM2UyODMxNTBk"
    },
    "createdOn": "2018-03-01T22:57:25.660Z",
    "modifiedBy": {
        "displayName": "Sample User",
        "url": "https://pde14b1dc-d2c9-49e5-88cb-45ccd58d0335.codex.ms/vssps/_apis/Identities/c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
        "id": "c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
        "uniqueName": "sampleuser@microsoft.com",
        "imageUrl": "https://sampleuser.visualstudio.com/_api/_common/identityImage?id=c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
        "descriptor": "aad.M2Y2N2JlZGUtMDViZC03ZWI3LTgxYWMtMDcwM2UyODMxNTBk"
    },
    "modifiedOn": "2018-03-14T17:58:11.643Z",
    "isDeleted": false,
    "path": "\\",
    "variables": {},
    "variableGroups": [],
    "environments": [{
        "id": 1,
        "name": "Prod",
        "rank": 1,
        "owner": {
            "displayName": "Sample User",
            "url": "https://pde14b1dc-d2c9-49e5-88cb-45ccd58d0335.codex.ms/vssps/_apis/Identities/c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
            "id": "c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
            "uniqueName": "sampleuser@microsoft.com",
            "imageUrl": "https://sampleuser.visualstudio.com/_api/_common/identityImage?id=c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
            "descriptor": "aad.M2Y2N2JlZGUtMDViZC03ZWI3LTgxYWMtMDcwM2UyODMxNTBk"
        },
        "variables": {
            "factoryName": {
                "value": "sampleuserprod"
            }
        },
        "variableGroups": [],
        "preDeployApprovals": {
            "approvals": [{
                "rank": 1,
                "isAutomated": true,
                "isNotificationOn": false,
                "id": 1
            }],
            "approvalOptions": {
                "requiredApproverCount": null,
                "releaseCreatorCanBeApprover": false,
                "autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped": false,
                "enforceIdentityRevalidation": false,
                "timeoutInMinutes": 0,
                "executionOrder": 1
            }
        },
        "deployStep": {
            "id": 2
        },
        "postDeployApprovals": {
            "approvals": [{
                "rank": 1,
                "isAutomated": true,
                "isNotificationOn": false,
                "id": 3
            }],
            "approvalOptions": {
                "requiredApproverCount": null,
                "releaseCreatorCanBeApprover": false,
                "autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped": false,
                "enforceIdentityRevalidation": false,
                "timeoutInMinutes": 0,
                "executionOrder": 2
            }
        },
        "deployPhases": [{
            "deploymentInput": {
                "parallelExecution": {
                    "parallelExecutionType": "none"
                },
                "skipArtifactsDownload": false,
                "artifactsDownloadInput": {
                    "downloadInputs": []
                },
                "queueId": 19,
                "demands": [],
                "enableAccessToken": false,
                "timeoutInMinutes": 0,
                "jobCancelTimeoutInMinutes": 1,
                "condition": "succeeded()",
                "overrideInputs": {}
            },
            "rank": 1,
            "phaseType": 1,
            "name": "Run on agent",
            "workflowTasks": [{
                "taskId": "72a1931b-effb-4d2e-8fd8-f8472a07cb62",
                "version": "2.*",
                "name": "Azure PowerShell script: FilePath",
                "refName": "",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceNameSelector": "ConnectedServiceNameARM",
                    "ConnectedServiceName": "",
                    "ConnectedServiceNameARM": "e4e2ef4b-8289-41a6-ba7c-92ca469700aa",
                    "ScriptType": "FilePath",
                    "ScriptPath": "$(System.DefaultWorkingDirectory)/Dev/deployment.ps1",
                    "Inline": "param\n(\n    [parameter(Mandatory = $false)] [String] $rootFolder=\"C:\\Users\\sampleuser\\Downloads\\arm_template\",\n    [parameter(Mandatory = $false)] [String] $armTemplate=\"$rootFolder\\arm_template.json\",\n    [parameter(Mandatory = $false)] [String] $armTemplateParameters=\"$rootFolder\\arm_template_parameters.json\",\n    [parameter(Mandatory = $false)] [String] $domain=\"microsoft.onmicrosoft.com\",\n    [parameter(Mandatory = $false)] [String] $TenantId=\"72f988bf-86f1-41af-91ab-2d7cd011db47\",\n    [parame",
                    "ScriptArguments": "-rootFolder \"$(System.DefaultWorkingDirectory)/Dev/\" -DataFactoryName $(factoryname) -predeployment $true",
                    "TargetAzurePs": "LatestVersion",
                    "CustomTargetAzurePs": "5.*"
                }
            }, {
                "taskId": "1e244d32-2dd4-4165-96fb-b7441ca9331e",
                "version": "1.*",
                "name": "Azure Key Vault: sampleuservault",
                "refName": "secret1",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceName": "e4e2ef4b-8289-41a6-ba7c-92ca469700aa",
                    "KeyVaultName": "sampleuservault",
                    "SecretsFilter": "*"
                }
            }, {
                "taskId": "94a74903-f93f-4075-884f-dc11f34058b4",
                "version": "2.*",
                "name": "Azure Deployment:Create Or Update Resource Group action on sampleuser-datafactory",
                "refName": "",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceName": "e4e2ef4b-8289-41a6-ba7c-92ca469700aa",
                    "action": "Create Or Update Resource Group",
                    "resourceGroupName": "sampleuser-datafactory",
                    "location": "East US",
                    "templateLocation": "Linked artifact",
                    "csmFileLink": "",
                    "csmParametersFileLink": "",
                    "csmFile": "$(System.DefaultWorkingDirectory)/Dev/ARMTemplateForFactory.json",
                    "csmParametersFile": "$(System.DefaultWorkingDirectory)/Dev/ARMTemplateParametersForFactory.json",
                    "overrideParameters": "-factoryName \"$(factoryName)\" -linkedService1_connectionString \"$(linkedService1-connectionString)\" -linkedService2_connectionString \"$(linkedService2-connectionString)\"",
                    "deploymentMode": "Incremental",
                    "enableDeploymentPrerequisites": "None",
                    "deploymentGroupEndpoint": "",
                    "project": "",
                    "deploymentGroupName": "",
                    "copyAzureVMTags": "true",
                    "outputVariable": "",
                    "deploymentOutputs": ""
                }
            }, {
                "taskId": "72a1931b-effb-4d2e-8fd8-f8472a07cb62",
                "version": "2.*",
                "name": "Azure PowerShell script: FilePath",
                "refName": "",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceNameSelector": "ConnectedServiceNameARM",
                    "ConnectedServiceName": "",
                    "ConnectedServiceNameARM": "e4e2ef4b-8289-41a6-ba7c-92ca469700aa",
                    "ScriptType": "FilePath",
                    "ScriptPath": "$(System.DefaultWorkingDirectory)/Dev/deployment.ps1",
                    "Inline": "# You can write your azure powershell scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments",
                    "ScriptArguments": "-rootFolder \"$(System.DefaultWorkingDirectory)/Dev/\" -DataFactoryName $(factoryname) -predeployment $false",
                    "TargetAzurePs": "LatestVersion",
                    "CustomTargetAzurePs": ""
                }
            }]
        }],
        "environmentOptions": {
            "emailNotificationType": "OnlyOnFailure",
            "emailRecipients": "release.environment.owner;release.creator",
            "skipArtifactsDownload": false,
            "timeoutInMinutes": 0,
            "enableAccessToken": false,
            "publishDeploymentStatus": true,
            "badgeEnabled": false,
            "autoLinkWorkItems": false
        },
        "demands": [],
        "conditions": [{
            "name": "ReleaseStarted",
            "conditionType": 1,
            "value": ""
        }],
        "executionPolicy": {
            "concurrencyCount": 1,
            "queueDepthCount": 0
        },
        "schedules": [],
        "retentionPolicy": {
            "daysToKeep": 30,
            "releasesToKeep": 3,
            "retainBuild": true
        },
        "processParameters": {
            "dataSourceBindings": [{
                "dataSourceName": "AzureRMWebAppNamesByType",
                "parameters": {
                    "WebAppKind": "$(WebAppKind)"
                },
                "endpointId": "$(ConnectedServiceName)",
                "target": "WebAppName"
            }]
        },
        "properties": {},
        "preDeploymentGates": {
            "id": 0,
            "gatesOptions": null,
            "gates": []
        },
        "postDeploymentGates": {
            "id": 0,
            "gatesOptions": null,
            "gates": []
        },
        "badgeUrl": "https://sampleuser.vsrm.visualstudio.com/_apis/public/Release/badge/19749ef3-2f42-49b5-9696-f28b49faebcb/1/1"
    }, {
        "id": 2,
        "name": "Staging",
        "rank": 2,
        "owner": {
            "displayName": "Sample User",
            "url": "https://pde14b1dc-d2c9-49e5-88cb-45ccd58d0335.codex.ms/vssps/_apis/Identities/c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
            "id": "c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
            "uniqueName": "sampleuser@microsoft.com",
            "imageUrl": "https://sampleuser.visualstudio.com/_api/_common/identityImage?id=c9f828d1-2dbb-4e39-b096-f1c53d82bc2c",
            "descriptor": "aad.M2Y2N2JlZGUtMDViZC03ZWI3LTgxYWMtMDcwM2UyODMxNTBk"
        },
        "variables": {
            "factoryName": {
                "value": "sampleuserstaging"
            }
        },
        "variableGroups": [],
        "preDeployApprovals": {
            "approvals": [{
                "rank": 1,
                "isAutomated": true,
                "isNotificationOn": false,
                "id": 4
            }],
            "approvalOptions": {
                "requiredApproverCount": null,
                "releaseCreatorCanBeApprover": false,
                "autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped": false,
                "enforceIdentityRevalidation": false,
                "timeoutInMinutes": 0,
                "executionOrder": 1
            }
        },
        "deployStep": {
            "id": 5
        },
        "postDeployApprovals": {
            "approvals": [{
                "rank": 1,
                "isAutomated": true,
                "isNotificationOn": false,
                "id": 6
            }],
            "approvalOptions": {
                "requiredApproverCount": null,
                "releaseCreatorCanBeApprover": false,
                "autoTriggeredAndPreviousEnvironmentApprovedCanBeSkipped": false,
                "enforceIdentityRevalidation": false,
                "timeoutInMinutes": 0,
                "executionOrder": 2
            }
        },
        "deployPhases": [{
            "deploymentInput": {
                "parallelExecution": {
                    "parallelExecutionType": "none"
                },
                "skipArtifactsDownload": false,
                "artifactsDownloadInput": {
                    "downloadInputs": []
                },
                "queueId": 19,
                "demands": [],
                "enableAccessToken": false,
                "timeoutInMinutes": 0,
                "jobCancelTimeoutInMinutes": 1,
                "condition": "succeeded()",
                "overrideInputs": {}
            },
            "rank": 1,
            "phaseType": 1,
            "name": "Run on agent",
            "workflowTasks": [{
                "taskId": "72a1931b-effb-4d2e-8fd8-f8472a07cb62",
                "version": "2.*",
                "name": "Azure PowerShell script: FilePath",
                "refName": "",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceNameSelector": "ConnectedServiceNameARM",
                    "ConnectedServiceName": "",
                    "ConnectedServiceNameARM": "e4e2ef4b-8289-41a6-ba7c-92ca469700aa",
                    "ScriptType": "FilePath",
                    "ScriptPath": "$(System.DefaultWorkingDirectory)/Dev/deployment.ps1",
                    "Inline": "# You can write your azure powershell scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments",
                    "ScriptArguments": "-rootFolder \"$(System.DefaultWorkingDirectory)/Dev/\" -DataFactoryName $(factoryname) -predeployment $true",
                    "TargetAzurePs": "LatestVersion",
                    "CustomTargetAzurePs": ""
                }
            }, {
                "taskId": "1e244d32-2dd4-4165-96fb-b7441ca9331e",
                "version": "1.*",
                "name": "Azure Key Vault: sampleuservault",
                "refName": "",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceName": "e4e2ef4b-8289-41a6-ba7c-92ca469700aa",
                    "KeyVaultName": "sampleuservault",
                    "SecretsFilter": "*"
                }
            }, {
                "taskId": "94a74903-f93f-4075-884f-dc11f34058b4",
                "version": "2.*",
                "name": "Azure Deployment:Create Or Update Resource Group action on sampleuser-datafactory",
                "refName": "",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceName": "e4e2ef4b-8289-41a6-ba7c-92ca469700aa",
                    "action": "Create Or Update Resource Group",
                    "resourceGroupName": "sampleuser-datafactory",
                    "location": "East US",
                    "templateLocation": "Linked artifact",
                    "csmFileLink": "",
                    "csmParametersFileLink": "",
                    "csmFile": "$(System.DefaultWorkingDirectory)/Dev/ARMTemplateForFactory.json",
                    "csmParametersFile": "$(System.DefaultWorkingDirectory)/Dev/ARMTemplateParametersForFactory.json",
                    "overrideParameters": "-factoryName \"$(factoryName)\" -linkedService1_connectionString \"$(linkedService1-connectionString)\" -linkedService2_connectionString \"$(linkedService2-connectionString)\"",
                    "deploymentMode": "Incremental",
                    "enableDeploymentPrerequisites": "None",
                    "deploymentGroupEndpoint": "",
                    "project": "",
                    "deploymentGroupName": "",
                    "copyAzureVMTags": "true",
                    "outputVariable": "",
                    "deploymentOutputs": ""
                }
            }, {
                "taskId": "72a1931b-effb-4d2e-8fd8-f8472a07cb62",
                "version": "2.*",
                "name": "Azure PowerShell script: FilePath",
                "refName": "",
                "enabled": true,
                "alwaysRun": false,
                "continueOnError": false,
                "timeoutInMinutes": 0,
                "definitionType": "task",
                "overrideInputs": {},
                "condition": "succeeded()",
                "inputs": {
                    "ConnectedServiceNameSelector": "ConnectedServiceNameARM",
                    "ConnectedServiceName": "",
                    "ConnectedServiceNameARM": "16a37943-8b58-4c2f-a3d6-052d6f032a07",
                    "ScriptType": "FilePath",
                    "ScriptPath": "$(System.DefaultWorkingDirectory)/Dev/deployment.ps1",
                    "Inline": "param(\n$x,\n$y,\n$z)\nwrite-host \"----------\"\nwrite-host $x\nwrite-host $y\nwrite-host $z | ConvertTo-SecureString\nwrite-host \"----------\"",
                    "ScriptArguments": "-rootFolder \"$(System.DefaultWorkingDirectory)/Dev/\" -DataFactoryName $(factoryname) -predeployment $false",
                    "TargetAzurePs": "LatestVersion",
                    "CustomTargetAzurePs": ""
                }
            }]
        }],
        "environmentOptions": {
            "emailNotificationType": "OnlyOnFailure",
            "emailRecipients": "release.environment.owner;release.creator",
            "skipArtifactsDownload": false,
            "timeoutInMinutes": 0,
            "enableAccessToken": false,
            "publishDeploymentStatus": true,
            "badgeEnabled": false,
            "autoLinkWorkItems": false
        },
        "demands": [],
        "conditions": [{
            "name": "ReleaseStarted",
            "conditionType": 1,
            "value": ""
        }],
        "executionPolicy": {
            "concurrencyCount": 1,
            "queueDepthCount": 0
        },
        "schedules": [],
        "retentionPolicy": {
            "daysToKeep": 30,
            "releasesToKeep": 3,
            "retainBuild": true
        },
        "processParameters": {
            "dataSourceBindings": [{
                "dataSourceName": "AzureRMWebAppNamesByType",
                "parameters": {
                    "WebAppKind": "$(WebAppKind)"
                },
                "endpointId": "$(ConnectedServiceName)",
                "target": "WebAppName"
            }]
        },
        "properties": {},
        "preDeploymentGates": {
            "id": 0,
            "gatesOptions": null,
            "gates": []
        },
        "postDeploymentGates": {
            "id": 0,
            "gatesOptions": null,
            "gates": []
        },
        "badgeUrl": "https://sampleuser.vsrm.visualstudio.com/_apis/public/Release/badge/19749ef3-2f42-49b5-9696-f28b49faebcb/1/2"
    }],
    "artifacts": [{
        "sourceId": "19749ef3-2f42-49b5-9696-f28b49faebcb:a6c88f30-5e1f-4de8-b24d-279bb209d85f",
        "type": "Git",
        "alias": "Dev",
        "definitionReference": {
            "branches": {
                "id": "adf_publish",
                "name": "adf_publish"
            },
            "checkoutSubmodules": {
                "id": "",
                "name": ""
            },
            "defaultVersionSpecific": {
                "id": "",
                "name": ""
            },
            "defaultVersionType": {
                "id": "latestFromBranchType",
                "name": "Latest from default branch"
            },
            "definition": {
                "id": "a6c88f30-5e1f-4de8-b24d-279bb209d85f",
                "name": "Dev"
            },
            "fetchDepth": {
                "id": "",
                "name": ""
            },
            "gitLfsSupport": {
                "id": "",
                "name": ""
            },
            "project": {
                "id": "19749ef3-2f42-49b5-9696-f28b49faebcb",
                "name": "Prod"
            }
        },
        "isPrimary": true
    }],
    "triggers": [{
        "schedule": {
            "jobId": "b5ef09b6-8dfd-4b91-8b48-0709e3e67b2d",
            "timeZoneId": "UTC",
            "startHours": 3,
            "startMinutes": 0,
            "daysToRelease": 31
        },
        "triggerType": 2
    }],
    "releaseNameFormat": "Release-$(rev:r)",
    "url": "https://sampleuser.vsrm.visualstudio.com/19749ef3-2f42-49b5-9696-f28b49faebcb/_apis/Release/definitions/1",
    "_links": {
        "self": {
            "href": "https://sampleuser.vsrm.visualstudio.com/19749ef3-2f42-49b5-9696-f28b49faebcb/_apis/Release/definitions/1"
        },
        "web": {
            "href": "https://sampleuser.visualstudio.com/19749ef3-2f42-49b5-9696-f28b49faebcb/_release?definitionId=1"
        }
    },
    "tags": [],
    "properties": {
        "DefinitionCreationSource": {
            "$type": "System.String",
            "$value": "ReleaseNew"
        }
    }
}

Пример сценария остановки и перезагрузки триггеров и очисткиSample script to stop and restart triggers and clean up

Ниже приведен пример скрипта для остановки триггеров перед развертыванием и их последующего перезапуска.Here is a sample script to stop triggers before deployment and to restart triggers afterwards. Скрипт также содержит код для удаления ресурсов.The script also includes code to delete resources that have been removed. Чтобы установить последнюю версию Azure PowerShell, ознакомьтесь со статьей Установка Azure PowerShell в ОС Windows с помощью PowerShellGet.To install the latest version of Azure PowerShell, see Install Azure PowerShell on Windows with PowerShellGet.

param
(
    [parameter(Mandatory = $false)] [String] $rootFolder,
    [parameter(Mandatory = $false)] [String] $armTemplate,
    [parameter(Mandatory = $false)] [String] $ResourceGroupName,
    [parameter(Mandatory = $false)] [String] $DataFactoryName,
    [parameter(Mandatory = $false)] [Bool] $predeployment=$true,
    [parameter(Mandatory = $false)] [Bool] $deleteDeployment=$false
)

$templateJson = Get-Content $armTemplate | ConvertFrom-Json
$resources = $templateJson.resources

#Triggers 
Write-Host "Getting triggers"
$triggersADF = Get-AzDataFactoryV2Trigger -DataFactoryName $DataFactoryName -ResourceGroupName $ResourceGroupName
$triggersTemplate = $resources | Where-Object { $_.type -eq "Microsoft.DataFactory/factories/triggers" }
$triggerNames = $triggersTemplate | ForEach-Object {$_.name.Substring(37, $_.name.Length-40)}
$activeTriggerNames = $triggersTemplate | Where-Object { $_.properties.runtimeState -eq "Started" -and ($_.properties.pipelines.Count -gt 0 -or $_.properties.pipeline.pipelineReference -ne $null)} | ForEach-Object {$_.name.Substring(37, $_.name.Length-40)}
$deletedtriggers = $triggersADF | Where-Object { $triggerNames -notcontains $_.Name }
$triggerstostop = $triggerNames | where { ($triggersADF | Select-Object name).name -contains $_ }

if ($predeployment -eq $true) {
    #Stop all triggers
    Write-Host "Stopping deployed triggers"
    $triggerstostop | ForEach-Object { 
        Write-host "Disabling trigger " $_
        Stop-AzDataFactoryV2Trigger -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Name $_ -Force 
    }
}
else {
    #Deleted resources
    #pipelines
    Write-Host "Getting pipelines"
    $pipelinesADF = Get-AzDataFactoryV2Pipeline -DataFactoryName $DataFactoryName -ResourceGroupName $ResourceGroupName
    $pipelinesTemplate = $resources | Where-Object { $_.type -eq "Microsoft.DataFactory/factories/pipelines" }
    $pipelinesNames = $pipelinesTemplate | ForEach-Object {$_.name.Substring(37, $_.name.Length-40)}
    $deletedpipelines = $pipelinesADF | Where-Object { $pipelinesNames -notcontains $_.Name }
    #datasets
    Write-Host "Getting datasets"
    $datasetsADF = Get-AzDataFactoryV2Dataset -DataFactoryName $DataFactoryName -ResourceGroupName $ResourceGroupName
    $datasetsTemplate = $resources | Where-Object { $_.type -eq "Microsoft.DataFactory/factories/datasets" }
    $datasetsNames = $datasetsTemplate | ForEach-Object {$_.name.Substring(37, $_.name.Length-40) }
    $deleteddataset = $datasetsADF | Where-Object { $datasetsNames -notcontains $_.Name }
    #linkedservices
    Write-Host "Getting linked services"
    $linkedservicesADF = Get-AzDataFactoryV2LinkedService -DataFactoryName $DataFactoryName -ResourceGroupName $ResourceGroupName
    $linkedservicesTemplate = $resources | Where-Object { $_.type -eq "Microsoft.DataFactory/factories/linkedservices" }
    $linkedservicesNames = $linkedservicesTemplate | ForEach-Object {$_.name.Substring(37, $_.name.Length-40)}
    $deletedlinkedservices = $linkedservicesADF | Where-Object { $linkedservicesNames -notcontains $_.Name }
    #Integrationruntimes
    Write-Host "Getting integration runtimes"
    $integrationruntimesADF = Get-AzDataFactoryV2IntegrationRuntime -DataFactoryName $DataFactoryName -ResourceGroupName $ResourceGroupName
    $integrationruntimesTemplate = $resources | Where-Object { $_.type -eq "Microsoft.DataFactory/factories/integrationruntimes" }
    $integrationruntimesNames = $integrationruntimesTemplate | ForEach-Object {$_.name.Substring(37, $_.name.Length-40)}
    $deletedintegrationruntimes = $integrationruntimesADF | Where-Object { $integrationruntimesNames -notcontains $_.Name }

    #Delete resources
    Write-Host "Deleting triggers"
    $deletedtriggers | ForEach-Object { 
        Write-Host "Deleting trigger "  $_.Name
        $trig = Get-AzDataFactoryV2Trigger -name $_.Name -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName
        if ($trig.RuntimeState -eq "Started") {
            Stop-AzDataFactoryV2Trigger -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Name $_.Name -Force 
        }
        Remove-AzDataFactoryV2Trigger -Name $_.Name -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Force 
    }
    Write-Host "Deleting pipelines"
    $deletedpipelines | ForEach-Object { 
        Write-Host "Deleting pipeline " $_.Name
        Remove-AzDataFactoryV2Pipeline -Name $_.Name -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Force 
    }
    Write-Host "Deleting datasets"
    $deleteddataset | ForEach-Object { 
        Write-Host "Deleting dataset " $_.Name
        Remove-AzDataFactoryV2Dataset -Name $_.Name -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Force 
    }
    Write-Host "Deleting linked services"
    $deletedlinkedservices | ForEach-Object { 
        Write-Host "Deleting Linked Service " $_.Name
        Remove-AzDataFactoryV2LinkedService -Name $_.Name -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Force 
    }
    Write-Host "Deleting integration runtimes"
    $deletedintegrationruntimes | ForEach-Object { 
        Write-Host "Deleting integration runtime " $_.Name
        Remove-AzDataFactoryV2IntegrationRuntime -Name $_.Name -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Force 
    }

    if ($deleteDeployment -eq $true) {
        Write-Host "Deleting ARM deployment ... under resource group: " $ResourceGroupName
        $deployments = Get-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName
        $deploymentsToConsider = $deployments | Where { $_.DeploymentName -like "ArmTemplate_master*" -or $_.DeploymentName -like "ArmTemplateForFactory*" } | Sort-Object -Property Timestamp -Descending
        $deploymentName = $deploymentsToConsider[0].DeploymentName

       Write-Host "Deployment to be deleted: " $deploymentName
        $deploymentOperations = Get-AzResourceGroupDeploymentOperation -DeploymentName $deploymentName -ResourceGroupName $ResourceGroupName
        $deploymentsToDelete = $deploymentOperations | Where { $_.properties.targetResource.id -like "*Microsoft.Resources/deployments*" }

        $deploymentsToDelete | ForEach-Object { 
            Write-host "Deleting inner deployment: " $_.properties.targetResource.id
            Remove-AzResourceGroupDeployment -Id $_.properties.targetResource.id
        }
        Write-Host "Deleting deployment: " $deploymentName
        Remove-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName -Name $deploymentName
    }

    #Start Active triggers - After cleanup efforts
    Write-Host "Starting active triggers"
    $activeTriggerNames | ForEach-Object { 
        Write-host "Enabling trigger " $_
        Start-AzDataFactoryV2Trigger -ResourceGroupName $ResourceGroupName -DataFactoryName $DataFactoryName -Name $_ -Force 
    }
}

Использование пользовательских параметров с шаблоном Resource ManagerUse custom parameters with the Resource Manager template

Если вы находитесь в режиме GIT, можно переопределить свойства по умолчанию в шаблоне Resource Manager для установки свойств, параметризуются в шаблоне и свойства, которые являются фиксированными.If you are in GIT mode, you can override the default properties in your Resource Manager template to set properties that are parameterized in the template and properties that are hard-coded. Может потребоваться переопределить шаблон параметризации по умолчанию в следующих сценариях:You might want to override the default parameterization template in these scenarios:

  • Использовать автоматизированные CI/CD и вы хотите изменить некоторые свойства во время развертывания Resource Manager, но не параметризованные свойства по умолчанию.You use automated CI/CD and you want to change some properties during Resource Manager deployment, but the properties aren't parameterized by default.
  • Фабрикой настолько велико, что шаблон Resource Manager по умолчанию является недопустимым, так как она содержит более максимально допустимое параметров (256).Your factory is so large that the default Resource Manager template is invalid because it has more than the maximum allowed parameters (256).

В этих условиях, чтобы переопределить параметризации шаблона по умолчанию, создайте файл с именем arm шаблон параметров definition.json в корневой папке репозитория.Under these conditions, to override the default parameterization template, create a file named arm-template-parameters-definition.json in the root folder of the repository. Имя файла должно совпадать.The file name must exactly match. Фабрика данных пытается прочитать этот файл из любой ветви, в данный момент на портале фабрики данных Azure, а не только из ветви совместной работы.Data Factory tries to read this file from whichever branch you are currently on in the Azure Data Factory portal, not just from the collaboration branch. Можно создать или изменить его в закрытой ветке, где можно проверить изменения с помощью шаблон экспорта ARM в пользовательском Интерфейсе.You can create or edit the file from a private branch, where you can test your changes by using the Export ARM template in the UI. Затем файл можно объединить в ветвь совместной работы.Then, you can merge the file into the collaboration branch. Если файл не найден, используется шаблон по умолчанию.If no file is found, the default template is used.

Синтаксис пользовательского файла параметровSyntax of a custom parameters file

Ниже приведены некоторые рекомендации для использования при создании файла пользовательских параметров.Here are some guidelines to use when you author the custom parameters file. Этот файл состоит из раздела для каждого типа сущности: триггера, конвейера, linkedservice, dataset, integrationruntime и т. д.The file consists of a section for each entity type: trigger, pipeline, linkedservice, dataset, integrationruntime, and so on.

  • Введите путь к свойству в типе соответствующие сущности.Enter the property path under the relevant entity type.
  • Если задано имя свойства "*'', указывают, что требуется параметризовать соответствующие все свойства в нем (только до уровня первого уровня, не рекурсивно).When you set a property name to '*'', you indicate that you want to parameterize all properties under it (only down to the first level, not recursively). Можно также предоставить все исключения.You can also provide any exceptions to this.
  • При задании значения свойства в виде строки вы указываете, что хотите параметризовать свойство.When you set the value of a property as a string, you indicate that you want to parameterize the property. Используйте формат <action>:<name>:<stype>.Use the format <action>:<name>:<stype>.
    • <action> может принимать одно из следующих символов:<action> can be one of the following characters:
      • = означает, что сохранение текущего значения как значение по умолчанию для параметра.= means keep the current value as the default value for the parameter.
      • - означает, что не следует хранить значение по умолчанию для параметра.- means do not keep the default value for the parameter.
      • | является особым случаем для секретов из хранилища ключей Azure для строки подключения или разделов.| is a special case for secrets from Azure Key Vault for connection strings or keys.
    • <name> — Имя параметра.<name> is the name of the parameter. Если поле пусто, он принимает имя свойства.If it is blank, it takes the name of the property. Если значение начинается с - символа, имя сокращается.If the value starts with a - character, the name is shortened. Например AzureStorage1_properties_typeProperties_connectionString бы быть сокращено до AzureStorage1_connectionString.For example, AzureStorage1_properties_typeProperties_connectionString would be shortened to AzureStorage1_connectionString.
    • <stype> Представляет тип параметра.<stype> is the type of parameter. Если <stype> является пустым, по умолчанию используется тип string.If <stype> is blank, the default type is string. Поддерживаемые значения: string, bool, number, object, и securestring.Supported values: string, bool, number, object, and securestring.
  • Когда вы можете указать массив в файле определения, вы можете указать, что соответствующее свойство в шаблоне является массивом.When you specify an array in the definition file, you indicate that the matching property in the template is an array. Фабрика данных выполняет итерацию всех объектов в массиве с помощью определения, указанного в объекте среды выполнения интеграции в массиве.Data Factory iterates through all the objects in the array by using the definition that's specified in the Integration Runtime object of the array. Второй объект, строка, становится именем свойства, которое используется в качестве имени параметра для каждой итерации.The second object, a string, becomes the name of the property, which is used as the name for the parameter for each iteration.
  • Определение, является вспомогательным инструментом для экземпляра ресурса невозможна.It's not possible to have a definition that's specific for a resource instance. Любое определение применяется ко всем ресурсам этого типа.Any definition applies to all resources of that type.
  • По умолчанию все защищенные строки, такие как секретов Key Vault и защищенные строки, например строки подключения, ключи и маркеры, подлежащих параметризации.By default, all secure strings, such as Key Vault secrets, and secure strings, such as connection strings, keys, and tokens, are parameterized.

Пример шаблона параметризацииSample parameterization template

{
    "Microsoft.DataFactory/factories/pipelines": {
        "properties": {
            "activities": [{
                "typeProperties": {
                    "waitTimeInSeconds": "-::number",
                    "headers": "=::object"
                }
            }]
        }
    },
    "Microsoft.DataFactory/factories/integrationRuntimes": {
        "properties": {
            "typeProperties": {
                "*": "="
            }
        }
    },
    "Microsoft.DataFactory/factories/triggers": {
        "properties": {
            "typeProperties": {
                "recurrence": {
                    "*": "=",
                    "interval": "=:triggerSuffix:number",
                    "frequency": "=:-freq"
                },
                "maxConcurrency": "="
            }
        }
    },
    "Microsoft.DataFactory/factories/linkedServices": {
        "*": {
            "properties": {
                "typeProperties": {
                    "accountName": "=",
                    "username": "=",
                    "connectionString": "|:-connectionString:secureString",
                    "secretAccessKey": "|"
                }
            }
        },
        "AzureDataLakeStore": {
            "properties": {
                "typeProperties": {
                    "dataLakeStoreUri": "="
                }
            }
        }
    },
    "Microsoft.DataFactory/factories/datasets": {
        "properties": {
            "typeProperties": {
                "*": "="
            }
        }
    }
}

Объяснение:Explanation:

КонвейерыPipelines

  • Любое свойство в пути действий/typeProperties/waitTimeInSeconds параметризован.Any property in the path activities/typeProperties/waitTimeInSeconds is parameterized. Это означает, что любое действие в конвейере, имеющий свойство на уровне кода с именем waitTimeInSeconds (например, Wait действия) параметризован в виде числа, с именем по умолчанию.This means that any activity in a pipeline that has a code-level property named waitTimeInSeconds (for example, the Wait activity) is parameterized as a number, with a default name. Но он не имеет значения по умолчанию в шаблоне Resource Manager.But, it won't have a default value in the Resource Manager template. Он будет обязательный параметр во время развертывания Resource Manager.It will be a mandatory input during the Resource Manager deployment.
  • Аналогичным образом, свойство, называемую headers (например, в Web действия) является параметризованным с типом object (JObject).Similarly, a property called headers (for example, in a Web activity) is parameterized with type object (JObject). Он имеет значение по умолчанию, которое имеет то же значение, как и в фабрику источника.It has a default value, which is the same value as in the source factory.

IntegrationRuntimesIntegrationRuntimes

  • Только свойства, а все свойства, по пути typeProperties параметризуются вместе со значениями по умолчанию.Only properties, and all properties, under the path typeProperties are parameterized, with their respective default values. Например, начиная с текущей схемы, имеется два свойства в разделе IntegrationRuntimes свойства типа: computeProperties и ssisProperties.For example, as of today's schema, there are two properties under IntegrationRuntimes type properties: computeProperties and ssisProperties. Оба типа свойства создаются с помощью их значения по умолчанию и типы (объект).Both property types are created with their respective default values and types (Object).

ТриггерыTriggers

  • В разделе typeProperties, параметризуются два свойства.Under typeProperties, two properties are parameterized. Первый из них — maxConcurrency, которое указывается должен иметь значение по умолчанию и будет иметь тип string.The first one is maxConcurrency, which is specified to have a default value, and the type would be string. Он имеет имя параметра по умолчанию <entityName>_properties_typeProperties_maxConcurrency.It has the default parameter name of <entityName>_properties_typeProperties_maxConcurrency.
  • recurrence Свойство также является параметризованным.The recurrence property also is parameterized. В нем параметризовать как строки со значениями по умолчанию и имена параметров указаны все свойства, на этом уровне.Under it, all properties at that level are specified to be parameterized as strings, with default values and parameter names. Исключением является interval свойство, которое является параметризованным в качестве числовой тип и с именем параметра суффиксом <entityName>_properties_typeProperties_recurrence_triggerSuffix.An exception is the interval property, which is parameterized as number type, and with the parameter name suffixed with <entityName>_properties_typeProperties_recurrence_triggerSuffix. Аналогичным образом freq свойство представляет собой строку и параметризован в виде строки.Similarly, the freq property is a string and is parameterized as a string. Тем не менее freq свойство записывается в параметрической без значения по умолчанию.However, the freq property is parameterized without a default value. Имя является сокращено и суффикс.The name is shortened and suffixed. Например, <entityName>_freq.For example, <entityName>_freq.

LinkedServicesLinkedServices

  • Связанные службы является уникальным.Linked services is unique. Так как связанные службы и наборы данных могут быть несколько типов, можно указать настройки определенного типа.Because linked services and datasets can potentially be of several types, you can provide type-specific customization. Например, может сказать, что для всех связанных служб типа AzureDataLakeStore, определенного шаблона будет применен и для всех остальных (через *) применяется другой шаблон.For example, you might say that for all linked services of type AzureDataLakeStore, a specific template will be applied, and for all others (via *) a different template will be applied.
  • В приведенном выше примере connectionString свойство, будет параметризовано как securestring значение, он не имеет значения по умолчанию, и будет иметь параметр сокращенное имя, которое имеет суффикс connectionString.In the preceding example, the connectionString property will be parameterized as a securestring value, it won't have a default value, and it will have a shortened parameter name that's suffixed with connectionString.
  • Свойство secretAccessKey, тем не менее, может быть AzureKeyVaultSecret (например, AmazonS3 связанная служба).The property secretAccessKey, however, happens to be an AzureKeyVaultSecret (for instance, an AmazonS3 linked service). Таким образом он автоматически параметризован как секрет хранилища ключей Azure, и он извлекается из хранилища ключей, настроенные в фабрику источника.Thus, it is automatically parameterized as an Azure Key Vault secret, and it's fetched from the key vault that it's configured with in the source factory. Также можно параметризовать хранилища ключей, сам.You can also parameterize the key vault, itself.

Наборы данныхDatasets

  • Несмотря на то, что настройка определенного типа недоступна для наборов данных, конфигурации можно указать без необходимости явно *-настройки на уровне.Even though type-specific customization is available for datasets, configuration can be provided without explicitly having a *-level configuration. В приведенном выше примере все свойства набора данных в группе typeProperties параметризуются.In the preceding example, all dataset properties under typeProperties are parameterized.

Параметризация шаблона по умолчанию можно изменить, но это текущего шаблона.The default parameterization template can change, but this is the current template. Это будет полезно в том случае, если необходимо добавить одно дополнительное свойство как параметр, а также если вы не хотите потерять существующие параметризации и необходимо повторно создать их.This will be useful if you just need to add one additional property as a parameter, but also if you don’t want to lose the existing parameterizations and need to re-create them.

{
    "Microsoft.DataFactory/factories/pipelines": {
    },
    "Microsoft.DataFactory/factories/integrationRuntimes":{
        "properties": {
            "typeProperties": {
                "ssisProperties": {
                    "catalogInfo": {
                        "catalogServerEndpoint": "=",
                        "catalogAdminUserName": "=",
                        "catalogAdminPassword": {
                            "value": "-::secureString"
                        }
                    },
                    "customSetupScriptProperties": {
                        "sasToken": {
                            "value": "-::secureString"
                        }
                    }
                },
                "linkedInfo": {
                    "key": {
                        "value": "-::secureString"
                    },
                    "resourceId": "="
                }
            }
        }
    },
    "Microsoft.DataFactory/factories/triggers": {
        "properties": {
            "pipelines": [{
                    "parameters": {
                        "*": "="
                    }
                },  
                "pipelineReference.referenceName"
            ],
            "pipeline": {
                "parameters": {
                    "*": "="
                }
            },
            "typeProperties": {
                "scope": "="
            }

        }
    },
    "Microsoft.DataFactory/factories/linkedServices": {
        "*": {
            "properties": {
                "typeProperties": {
                    "accountName": "=",
                    "username": "=",
                    "userName": "=",
                    "accessKeyId": "=",
                    "servicePrincipalId": "=",
                    "userId": "=",
                    "clientId": "=",
                    "clusterUserName": "=",
                    "clusterSshUserName": "=",
                    "hostSubscriptionId": "=",
                    "clusterResourceGroup": "=",
                    "subscriptionId": "=",
                    "resourceGroupName": "=",
                    "tenant": "=",
                    "dataLakeStoreUri": "=",
                    "baseUrl": "=",
                    "database": "=",
                    "serviceEndpoint": "=",
                    "batchUri": "=",
                    "databaseName": "=",
                    "systemNumber": "=",
                    "server": "=",
                    "url":"=",
                    "aadResourceId": "=",
                    "connectionString": "|:-connectionString:secureString"
                }
            }
        },
        "Odbc": {
            "properties": {
                "typeProperties": {
                    "userName": "=",
                    "connectionString": {
                        "secretName": "="
                    }
                }
            }
        }
    },
    "Microsoft.DataFactory/factories/datasets": {
        "*": {
            "properties": {
                "typeProperties": {
                    "folderPath": "=",
                    "fileName": "="
                }
            }
        }}
}

Пример: Добавление интерактивных Databricks идентификатора кластера (из связанной службы Databricks) к файлу параметров:Example: Add a Databricks Interactive cluster ID (from a Databricks Linked Service) to the parameters file:

{
    "Microsoft.DataFactory/factories/pipelines": {
    },
    "Microsoft.DataFactory/factories/integrationRuntimes":{
        "properties": {
            "typeProperties": {
                "ssisProperties": {
                    "catalogInfo": {
                        "catalogServerEndpoint": "=",
                        "catalogAdminUserName": "=",
                        "catalogAdminPassword": {
                            "value": "-::secureString"
                        }
                    },
                    "customSetupScriptProperties": {
                        "sasToken": {
                            "value": "-::secureString"
                        }
                    }
                },
                "linkedInfo": {
                    "key": {
                        "value": "-::secureString"
                    },
                    "resourceId": "="
                }
            }
        }
    },
    "Microsoft.DataFactory/factories/triggers": {
        "properties": {
            "pipelines": [{
                    "parameters": {
                        "*": "="
                    }
                },  
                "pipelineReference.referenceName"
            ],
            "pipeline": {
                "parameters": {
                    "*": "="
                }
            },
            "typeProperties": {
                "scope": "="
            }
 
        }
    },
    "Microsoft.DataFactory/factories/linkedServices": {
        "*": {
            "properties": {
                "typeProperties": {
                    "accountName": "=",
                    "username": "=",
                    "userName": "=",
                    "accessKeyId": "=",
                    "servicePrincipalId": "=",
                    "userId": "=",
                    "clientId": "=",
                    "clusterUserName": "=",
                    "clusterSshUserName": "=",
                    "hostSubscriptionId": "=",
                    "clusterResourceGroup": "=",
                    "subscriptionId": "=",
                    "resourceGroupName": "=",
                    "tenant": "=",
                    "dataLakeStoreUri": "=",
                    "baseUrl": "=",
                    "database": "=",
                    "serviceEndpoint": "=",
                    "batchUri": "=",
                    "databaseName": "=",
                    "systemNumber": "=",
                    "server": "=",
                    "url":"=",
                    "aadResourceId": "=",
                    "connectionString": "|:-connectionString:secureString",
                    "existingClusterId": "-"
                }
            }
        },
        "Odbc": {
            "properties": {
                "typeProperties": {
                    "userName": "=",
                    "connectionString": {
                        "secretName": "="
                    }
                }
            }
        }
    },
    "Microsoft.DataFactory/factories/datasets": {
        "*": {
            "properties": {
                "typeProperties": {
                    "folderPath": "=",
                    "fileName": "="
                }
            }
        }}
}

Связанные шаблоны Resource ManagerLinked Resource Manager templates

Если вы настроили непрерывную интеграцию и развертывание (CI/CD) для своих фабрик данных, вы можете заметить, что при увеличении размера фабрики станут актуальны ограничения шаблона Resource Manager, такие как максимальное число ресурсов или максимальное количество полезных данных в ресурсе.If you've set up continuous integration and deployment (CI/CD) for your Data Factories, you may observe that, as your factory grows bigger, you run into the Resource Manager template limits, like the maximum number of resources or the maximum payload in a Resource Manager template. Для таких случаев, а также создания полного шаблона Resource Manager для фабрики фабрика данных теперь также создает связанные шаблоны Resource Manager.For scenarios like these, along with generating the full Resource Manager template for a factory, Data Factory also now generates Linked Resource Manager templates. Таким образом, полезные данные всей фабрики можно разбить на несколько файлов, чтобы не превысить упомянутые ограничения.As a result, you have the entire factory payload broken down into several files, so that you don’t run into the mentioned limits.

Если у вас настроен Git, связанные шаблоны создаются и сохраняются вместе с полными шаблонами Resource Manager в ветви adf_publish в новой папке с именем linkedTemplates.If you have Git configured, the linked templates are generated and saved alongside the full Resource Manager templates, in the adf_publish branch, under a new folder called linkedTemplates.

Папка связанных шаблонов Resource Manager

Связанные шаблоны Resource Manager обычно имеют главный шаблон и набор дочерних шаблонов, связанных с главным.The Linked Resource Manager templates usually have a master template and a set of child templates linked to the master. Родительский шаблон называется ArmTemplate_master.json, а дочерние шаблоны именуются по образцу: ArmTemplate_0.json, ArmTemplate_1.json и т. д.The parent template is called ArmTemplate_master.json, and child templates are named with the pattern ArmTemplate_0.json, ArmTemplate_1.json, and so on. Для перехода с использования полного шаблона Resource Manager на использование связанных шаблонов обновите вашу задачу CI/CD, чтобы она указывала ArmTemplate_master.json вместо ArmTemplateForFactory.json (то есть полного шаблона Resource Manager).To move over from using the full Resource Manager template to using the linked templates, update your CI/CD task to point to ArmTemplate_master.json instead of pointing to ArmTemplateForFactory.json (that is, the full Resource Manager template). Resource Manager также требует отправлять связанные шаблоны в учетную запись хранения, чтобы они были доступны в Azure во время развертывания.Resource Manager also requires you to upload the linked templates into a storage account so that they can be accessed by Azure during deployment. Дополнительные сведения см. в разделе Развертывание связанных шаблонов ARM с помощью VSTS.For more info, see Deploying Linked ARM Templates with VSTS.

Не забудьте добавить сценарии фабрики данных в конвейер CI/CD до и после завершения развертывания.Remember to add the Data Factory scripts in your CI/CD pipeline before and after the deployment task.

Если у вас не настроен Git, связанные шаблоны доступны с помощью жеста экспорта шаблона ARM.If you don’t have Git configured, the linked templates are accessible via the Export ARM template gesture.

Рекомендации для CI/CDBest practices for CI/CD

Если вы используете интеграцию Git с фабрикой данных и у вас есть конвейер CI/CD, перемещающий изменения из рабочей среды в тестовую, а затем в рабочую, рекомендуем следующее:If you're using Git integration with your data factory, and you have a CI/CD pipeline that moves your changes from Development into Test and then to Production, we recommend the following best practices:

  • Интеграция Git.Git Integration. Достаточно настроить интеграцию Git для своей фабрики данных для разработки.You are only required to configure your Development data factory with Git integration. Изменения в тестовую и рабочую среду развертываются в рамках процесса CI/CD, и им не требуется интеграция Git.Changes to Test and Production are deployed via CI/CD, and they don't need to have Git integration.

  • Сценарий CI/CD фабрики данных.Data Factory CI/CD script. Перед шагом развертывания с помощью Resource Manager в CI/CD необходимо остановить триггеры и выполнить разные виды очистки фабрики.Before the Resource Manager deployment step in CI/CD, you must take care of things like stopping the triggers, and different kind of factory cleanup. Мы советуем использовать этот сценарий, так как он выполняет все эти задачи.We recommend using this script as it takes care of all these things. Запустите сценарий один раз перед развертыванием и один раз после, используя соответствующие флаги.Run the script once before the deployment, and once after, using appropriate flags.

  • Среды выполнения интеграции и общий доступ.Integration Runtimes and sharing. Среды выполнения интеграции — это один из инфраструктурных компонентов в фабрике данных, которые реже подвергаются изменениям и похожи на всех этапах процесса CI/CD.Integration Runtimes are one of the infrastructural components in your data factory, which undergo changes less often, and are similar across all stages in your CI/CD. Поэтому Фабрика данных ожидает, что имена и типы сред выполнения интеграции одинаковы на всех этапах CI/CD.As a result, Data Factory expects you to have the same name and same type of Integration Runtimes across all stages of CI/CD. Если вам требуется совместно использовать среды выполнения интеграции на всех этапах, например, локальные среды выполнения интеграции, один из способов реализовать это — разместить локальную среду IR в тернарной фабрике (только для хранения общих сред выполнения интеграции).If you are looking to share Integration Runtimes across all stages - for instance, the Self-hosted Integration Runtimes - one way to share is by hosting the Self-hosted IR in a ternary factory, just for containing the shared Integration Runtimes. Затем можно использовать их в среде разработки, тестирования и рабочей среде как связанные среды выполнения интеграции.Then you can use them in Dev/Test/Prod as a Linked IR type.

  • Key Vault.Key Vault. При использовании рекомендуемых связанных служб на базе Azure Key Vault вы можете применять преимущества этого решения еще на одном уровне, потенциально используя отдельные хранилища ключей для рабочей среды, среды разработки и тестирования. Вы также можете настроить отдельные уровни разрешений для каждого из них.When you use the recommended Azure Key Vault based linked services, you can take its advantages one level further by potentially keeping separate key vaults for Dev/Test/Prod. You can also configure separate permission levels for each of them. Возможно, вы не хотите, чтобы у участников вашей команды были разрешения на доступ к секретам рабочей среды.You may not want your team members to have permissions to the Production secrets. Мы также рекомендуем использовать одинаковые имена секретов на всех этапах.We also recommend you to keep the same secret names across all stages. Если вы используете те же имена, вам не требуется менять свои шаблоны Resource Manager в рамках CI/CD, так как единственное, что необходимо изменить, — это имя хранилища ключей, которое является одним из параметров шаблона Resource Manager.If you keep the same names, you don't have to change your Resource Manager templates across CI/CD, since the only thing that needs to be changed is the key vault name, which is one of the Resource Manager template parameters.

Неподдерживаемые функцииUnsupported features

  • Вы не можете публиковать отдельные ресурсы, так как сущности фабрики данных зависят друг от друга.You can't publish individual resources, because data factory entities depend on each other. Например, триггеры зависят от конвейеров, конвейеры зависят от наборов данных и других конвейеров и т. д. Отслеживать меняющиеся зависимости непросто.For example, triggers depend on pipelines, pipelines depend on datasets and other pipelines, etc. Tracking changing dependencies is hard. Если бы можно было выбрать ресурсы для публикации вручную, вы могли бы выбрать только подмножество всего набора изменений, что могло бы привести к непредвиденному поведению после публикации.If it was possible to select the resources to publish manually, it would be possible to pick only a subset of the entire set of changes, which would lead to things unexpected behavior after publishing.

  • Вы не можете опубликовать из частных ветвей.You can't publish from private branches.

  • Вы не можете размещать проекты на Bitbucket.You can't host projects on Bitbucket.