Automate Adding an Artifact Repository in Azure DevTest Labs


Acknowledgement: This post is contributed by Elizabeth Maher, Senior Software Engineer in Customer Success Team. She’s been working on a solution to help our customers to adopt Azure DevTest Labs.

DevTest Labs allow users to add a tool to a newly created or previously created VM in lab via artifacts. Artifacts are defined in a JSON file loaded from GitHub or VSTS Git repository. The public artifact repository, backed by the DevTest Lab Team’s GitHub repository, provides many common tools for both Windows and Linux. Teams and organizations can also add the ability to easily install specific tools which may not available in the public artifact repository. That is where the ability to add an artifact repository source comes in handy. See ‘Add a Git artifact repository to a lab’ for instructions how to add an artifact repository source using the Azure Portal.

As they say, anything you want to repeat is worth scripting. This blog post will cover how to script the task of adding a custom artifact repository using Azure Resource Management templates and Azure PowerShell. You can choose either of them based on your personal preference. With these scripts, you will be able to automate the creation of team DevTest Lab instances or automate the addition of a new artifact sources to several DevTest Lab instances easily.

Using Azure Resource Management Templates

Azure Resource Management (ARM) templates are JSON files that describe resources in Azure that you would like to create. See Authoring Azure Resource Manager templates for a nice overview on the subject.

Template

We will need to gather some basic information to correctly create artifact repository source. That will include the artifact display name, repository type, URI to repository and folder to artifacts. This will all be gathered using the parameters with a few default values to make the template easier to use.

{

"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",

"contentVersion": "1.0.0.0",

"parameters": {

/*Lab information */

"labName": {

"type": "string"

},

"artifactRepositoryDisplayName": {

"type": "string",

"defaultValue": "Team Repository"

},

"artifactRepoUri": {

"type": "string"

},

"artifactRepoBranch": {

"type": "string",

"defaultValue": "master"

},

"artifactRepoFolder": {

"type": "string",

"defaultValue": "Artifacts/"

},

"artifactRepoType": {

"type": "string",

"allowedValues": [ "VsoGit", "GitHub" ]

},

"artifactRepoSecurityToken": {

"type": "securestring"

}

},

"variables": {

"artifactRepositoryName": "[concat('Repo-', uniqueString(subscription().subscriptionId))]"

},

"resources": [

{

"apiVersion": "2016-05-15",

"type": "Microsoft.DevTestLab/labs",

"name": "[parameters('labName')]",

"location": "[resourceGroup().location]",

"resources": [

{

"apiVersion": "2016-05-15",

"name": "[variables('artifactRepositoryName')]",

"type": "artifactSources",

"dependsOn": [

"[resourceId('Microsoft.DevTestLab/labs', parameters('labName'))]"

],

"properties": {

"uri": "[parameters('artifactRepoUri')]",

"folderPath": "[parameters('artifactRepoFolder')]",

"branchRef": "[parameters('artifactRepoBranch')]",

"displayName": "[parameters('artifactRepositoryDisplayName')]",

"securityToken": "[parameters('artifactRepoSecurityToken')]",

"sourceType": "[parameters('artifactRepoType')]",

"status": "Enabled"

}

}

]

}

],

"outputs": {

"labId": {

"type": "string",

"value": "[resourceId('Microsoft.DevTestLab/labs', parameters('labName'))]"

}

}

}

The template will create a DevTest Lab instance, if it does not exist already. Then an artifact repository source will be created, if it doesn’t exist already. This template will create an internal name for the lab automatically using the uniqueString function, but you can modify the script to explicitly set the artifact repository source name, which is the identifier.

The template will return the resourceId for the lab that has been modified or created.

Required Parameters

Most of the parameters do have smart defaults, but there are a few values that must be specified. We must specify the lab name, artifact repository URI and the artifact repository security token. See Add a Git artifact repository to a lab for instructions to get the security token. For GitHub, go to personal settings, choose personal access token under the Developer settings menu on the left and click the Generate new token button. For VSO Git, select security in the dropdown under your user name, and click the Add button on the Personal access tokens page.

The resource group in the parameters because that will be done when we deploy the template.

{

"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",

"contentVersion": "1.0.0.0",

"parameters": {

"labName": {

"value": "MyLab1"

},

"artifactRepoUri": {

"value": "https://MyProject1.visualstudio.com/DefaultCollection/_git/TeamArtifacts"

},

"artifactRepoType": {

"value": "VsoGit"

},

"artifactRepoSecurityToken": {

"value": "1111111111111111111111111111111111111"

}

}

}

Deploy the Template

There are a few ways to deploy the template to Azure and have the resource created, if it doesn’t exist, or updated, if it does exist. See Deploy resources with Resource Manager templates and Azure PowerShell, Deploy resources with Resource Manager templates and Azure CLI, Deploy resources with Resource Manager templates and Azure portal or Deploy resources with Resource Manager templates and Resource Manager REST API for detailed instructions how to do this.

Let’s go ahead and see how to deploy the template in PowerShell. Cmdlets used to deploy the template are context specific, so current tenant and current subscription are used. Use Set-AzureRMContext before deploying the template, if needed, to change context.

First we need to create the resource group using New-AzureRmResourceGroup. If the resource group you want to use already exists, skip this step.

New-AzureRmResourceGroup -Name ‘MyLabResourceGroup1’ -Location ‘westus’

Next we need to create a deployment to the resource group using New-AzureRmResourceGroupDeployment. This is the cmdlet that will apply the resource changes to Azure. Several resource deployments can be made to any given resource group. If you are deploying several times to the same resource group, make sure the name of each deployment is unique.

New-AzureRmResourceGroupDeployment `

-Name 'MyLabResourceGroup-Deployment1' `

-ResourceGroupName ‘MyLabResourceGroup1’ `

-TemplateFile ‘azuredeploy.json `

-TemplateParameterFile ‘azuredeploy.parameters.json

After New-AzureRmResourceGroupDeployment run successfully the command will output important information like the provisioning state (should be succeeded) and any outputs for the template.

Using PowerShell Cmdlets for Azure

Another way to add an Artifact Repository source is to use Azure PowerShell cmdlets. The script we are going to write requires Azure PowerShell. See How to install and configure Azure PowerShell for detailed instructions.

The goal of the script will be to gather all the information necessary to create a new artifact repository for a specified lab and then create that repository. Let’s take it one step at a time.

  1. Gather the information needed to identify the lab.
  2. Gather the information needed to create the artifact repository.
  3. Get the resource for the lab. We will need further information from the lab to complete our task.
  4. Prepare properties to be used in New-AzureRMResource. Each set of properties passed to New-AzureRMResource is specific to the type of resource being created.
  5. Use New-AzureRMResource to create new instance of DevTest Lab.

Gathering Artifact Repository Information

Gathering the information for the artifact will require us to simply ask the user for this information. See the parameter block below.

Param(

[Parameter(Mandatory=$true)]

$LabName,

[Parameter(Mandatory=$true)]

$LabResourceGroupName,

$ArtifactRepositoryName,

$ArtifactRepositoryDisplayName = 'Team Artifact Repository',

[Parameter(Mandatory=$true)]

$RepositoryUri,

$RepositoryBranch = 'master',

$FolderPath = 'Artifacts/',

[Parameter(Mandatory=$true)]

$PersonalAccessToken,

[Parameter(Mandatory=$true)]

[ValidateSet('VsoGit', 'GitHub')]

$SourceType

)

As you can see, we need to know the DevTest Lab name, resource group for the lab, repository display name, repository URI, branch, and personal access token. These properties are the same as seen in the Azure Portal when creating a new artifact repository. Instructions for obtaining the values for repository URI and personal access token can be found in Add a Git artifact repository to a lab.

The type of repository that will be used must also be specified. VsoGit or GitHub are the only accepted values.

The repository itself will need an internal name for identification, which is different that the display name that will been seen in the Azure Portal. You won’t see the internal name using the Azure Portal, but you will see it when using Azure REST APIs or AzureRM PowerShell Cmdlets. We can easily provide a name, if one is not specified by the user of our script.

#Set artifact repository name, if not set by user

if ($ArtifactRepositoryName -eq $null){

$ArtifactRepositoryName = "PrivateRepo" + (Get-Random -Maximum 999)

}

Get the Resource for the Lab

Since the artifact repository is a child resource of the lab, we are going to need more information about the lab itself when creating the artifact repository. This includes the resource name (i.e. lab name) and resource group name for the lab and the location of the lab. The easiest way to do this is use Get-AzureRMResource cmdlet as we have done in the following script.

#Get Lab Resource

$LabResource =

Get-AzureRmResource `

-ResourceType 'Microsoft.DevTestLab/labs' `

-ResourceName $LabName `

-ResourceGroupName $LabResourceGroupName

We have asked the user for the lab resource group name in the parameter block for our script. Specifying the resource group name and lab name is the easiest way to identify a lab within a subscription.

If a user needs help determining the resource group for a lab, they can use Find-AzureRMResource or Get-AzureRMResource. For simple cases, something like the below script will work. If there are several labs with similar names more than one result may be returned.

Find-AzureRmResource -ResourceType 'Microsoft.DevTestLab/labs' -ResourceNameContains $LabName

Prepare Properties for Resource Creation

We need to provide a set of properties for the repository to be successfully created. This is just a hash table of values we previously gathered. Each set of properties is unique for the type of resource being created.

$propertiesObject = @{

uri = $RepositoryUri;

folderPath = $FolderPath;

branchRef = $RepositoryBranch;

displayName = $ArtifactRepositoryDisplayName;

securityToken = $PersonalAccessToken;

sourceType = $SourceType;

status = 'Enabled'

}

Create the Repository using New-AzureRMResource

There is no DevTest Lab specific command for adding artifact repositories. The generic New-AzureRMResource cmdlet will do the job. This cmdlet needs either the ResourceId or the ResourceName and ResourceType pair to know which type of resource to create. We will use the resource name and resource type pair.

Please note, this means we will be adding a new resource to the current subscription. Use Get-AzureRMContext to see this information. Use Set-AzureRMContext to set the current tenant and subscription.

The best way to discover the resource name and resource type information is to use the Test Drive Azure REST APIs website. Check out the ‘DevTest Labs – 2016-05-15’ provider to see the available REST APIs for the DevTest Lab provider. In our case, we want to add an ArtifactsSource, so we will use the following:

ArtifactSource REST API

The resource type is everything listed after ‘providers’ in the URI, except for items listed in the curly brackets. The resource name is everything seen in the curly brackets. If more than one item is expected for the resource name, separate each item with a slash as we have done.

$resourcetype = 'Microsoft.DevTestLab/labs/artifactSources'

$resourceName = $LabName + '/' + $ArtifactRepositoryName

Now we can call New-AzureRMResource to create the new Artifact Repository. Notice we are creating the artifact repository source in the same location and under the same resource group as the lab.

$result = New-AzureRmResource -Location $LabResource.Location `

-ResourceGroupName $LabResource.ResourceGroupName `

-properties $propertiesObject -ResourceType $resourcetype `

-ResourceName $resourceName -ApiVersion 2016-05-15 -Force

Full Script

Below is the full script, including some verbose messages and comments.

New-DevTestLabArtifactRepository.ps1

<#

.SYNOPSIS

This script creates a new custom repository and adds it to an existing DevTest Lab.

.PARAMETER LabName

The name of the resource for the lab. Note, this is not the resource group for the lab.

.PARAMETER LabResourceGroupName

The name of the resource for the lab. Note, this is not the resource group for the lab.

.PARAMETER ArtifactRepositoryName

Name for the new artifact repository.

Script will create a random name for the respository if it is not specified.

.PARAMETER ArtifactRepositoryDisplayName

Display name for the artifact repository that will be added.

This is the name that will show in https://portal.azure.com when viewing all the artifact repositories for a lab.

.PARAMETER RepositoryUri

Uri to the repository.

.PARAMETER RepositoryBranch

Branch in which artifact files can be found. Defaults to 'master'.

.PARAMETER FolderPath

Folder under which artifacts can be found. Defaults to 'Artifacts/'

.PARAMETER PersonalAccessToken

Security token for access to GitHub or VSOGit repository.

See https://azure.microsoft.com/en-us/documentation/articles/devtest-lab-add-artifact-repo/ for instructions to get personal access token

.PARAMETER SourceType

Whether artifact is VSOGit or GitHub repository.

.EXAMPLE

Set-AzureRMContext -SubscriptionId 11111111-1111-1111-1111-111111111111

New-DevTestLabArtifactRepository -LabName 'MyLab' -RepositoryUri 'https://github.com/.../.../.git' -PersonalAccessToken '11111...' -SourceType 'GitHub'

.NOTES

Script uses the current AzureRm context. To set the context, use the Set-AzureRMContext cmdlet

#>

 

[CmdletBinding()]

Param(

[Parameter(Mandatory=$true)]

$LabName,

[Parameter(Mandatory=$true)]

$LabResourceGroupName,

$ArtifactRepositoryName,

$ArtifactRepositoryDisplayName `

= 'Team Artifact Repository',

[Parameter(Mandatory=$true)]

$RepositoryUri,

$RepositoryBranch = 'master',

$FolderPath = 'Artifacts/',

[Parameter(Mandatory=$true)]

$PersonalAccessToken ,

[Parameter(Mandatory=$true)]

[ValidateSet('VsoGit', 'GitHub')]

$SourceType

)

 

#Set artifact repository internal name,

# if not set by user.

if ($ArtifactRepositoryName -eq $null){

$ArtifactRepositoryName = "PrivateRepo" + (Get-Random -Maximum 999)

}

 

#Get Lab Resource

$LabResource =

Get-AzureRmResource `

-ResourceType 'Microsoft.DevTestLab/labs' `

-ResourceName $LabName `

-ResourceGroupName $LabResourceGroupName

 

Write-Verbose "Lab Name: $($LabName.Name)"

Write-Verbose "Lab Resource Group Name: $($LabResource.ResourceGroupName)"

Write-Verbose "Lab Resource Location: $($LabResource.Location)"

Write-Verbose "Artifact Repository Internal Name: $ArtifactRepositoryName"

 

#Prepare properties object for call to New-AzureRMResource

$propertiesObject = @{

uri = $RepositoryUri;

folderPath = $FolderPath;

branchRef = $RepositoryBranch;

displayName = $ArtifactRepositoryDisplayName;

securityToken = $PersonalAccessToken;

sourceType = $SourceType;

status = 'Enabled'

}

Write-Verbose @"

Properties to be passed to New-AzureRMResource:

$($propertiesObject | Out-String)

"@

 

#Resource will be added to current subscription.

$resourcetype = 'Microsoft.DevTestLab/labs/artifactSources'

$resourceName = $LabName + '/' + $ArtifactRepositoryName

Write-Verbose "AzureRM ResourceType: $resourcetype"

Write-Verbose "AzureRM ResourceName: $resourceName"

 

Write-Verbose "Creating artifact repository '$ArtifactRepositoryDisplayName'..."

$result = New-AzureRmResource -Location $LabResource.Location `

-ResourceGroupName $LabResource.ResourceGroupName `

-properties $propertiesObject -ResourceType $resourcetype `

-ResourceName $resourceName -ApiVersion 2016-05-15 -Force

 

#Alternate implementation:

# Use resourceId rather than resourcetype and resourcename parameters.

# Using resourceId allows you to specify the $SubscriptionId rather than using the

# subscription id of Get-AzureRmContext.

#$resourceId = "/subscriptions/$SubscriptionId/resourceGroups/$($LabResource.ResourceGroupName)/providers/Microsoft.DevTestLab/labs/$LabName/artifactSources/$ArtifactRepositoryName"

#$result = New-AzureRmResource -properties $propertiesObject -ResourceId $resourceId -ApiVersion 2016-05-15 -Force

 

# Check the result

if ($result.Properties.ProvisioningState -eq "Succeeded") {

Write-Verbose ("Successfully added artifact repository source '$ArtifactRepositoryDisplayName'")

}

else {

Write-Error ("Error adding artifact repository source '$ArtifactRepositoryDisplayName'")

}

 

#Return the newly created resource so it may be used in subsequent scripts

return $result

Go ahead and give it a try! Using the script requires just a few mandatory parameters. Example below shows what needs to be done using a newly opened Azure PowerShell window.

Login-AzureRM

Set-AzureRMContext -SubscriptionId 11111111-1111-1111-1111-111111111111

New-DevTestLabArtifactRepository -LabName 'MyLab' -RepositoryUri 'https://github.com/MyUserName/myrepository.git' -PersonalAccessToken '11111...' -SourceType 'GitHub'

Conclusion

Now you know how to add a custom artifact repository to a DevTest Labs instance using either ARM templates or Azure PowerShell cmdlets. I hope this saves you time while managing your DevTest Lab instances.

Elizabeth Maher Elizabeth Maher, Senior Software Engineer

Elizabeth is part of the Visual Studio and .Net engineering team focused on Visual Studio and Azure customers. She has been at Microsoft for 14 years, working on various developer technologies.

Comments (0)

Skip to main content