Step-by-Step Guide: Using Azure Functions, Docker, and ACI for PAC
Commands
Overview
This guide walks you through the process of executing PAC commands using a custom
Docker container and Azure services. We will utilize an Azure Function as an orchestrator, a
Docker container hosting the Power Platform CLI (PAC), and an Azure Container Instance
(ACI) to execute the commands in a controlled environment. All input parameters and file
locations will be dynamically handled.
Prerequisites
Before proceeding, ensure you have the following:
- An Azure account with access to Azure Functions, ACR, and ACI.
- Visual Studio or Visual Studio Code for coding.
- Docker installed on your local machine.
- Azure CLI installed and configured.
Step 1: Create the Dockerfile
1. Create a new file named `Dockerfile` in your project directory.
2. Add the following content to the Dockerfile:
# Use a base Windows Server Core image with .NET 7 runtime
FROM [Link]/dotnet/aspnet:7.0-windowsservercore-ltsc2022
# Download and install Power Platform CLI
ADD [Link] C:\[Link]
RUN msiexec /i C:\[Link] /quiet /qn /norestart
RUN del C:\[Link]
# Set the working directory
WORKDIR /app
# Copy the PowerShell script into the container
COPY execute_pac_commands.ps1 /app/execute_pac_commands.ps1
# Define the entry point to run the script
ENTRYPOINT ["powershell", "/app/execute_pac_commands.ps1"]
Step 2: Create the PowerShell Script
1. Create a file named `execute_pac_commands.ps1` in the same project directory as the
Dockerfile.
2. Add the following script content to handle PAC commands:
param (
[string]$clientId,
[string]$clientSecret,
[string]$tenantId,
[string]$url,
[string]$blobZipFileUrl,
[string]$blobSolutionFolderUrl
)
# Authenticate using Service Principal
Write-Host "Authenticating with pac CLI..."
pac auth create --clientId $clientId --clientSecret $clientSecret --tenantId $tenantId --url
$url
# Download the solution zip file from Blob Storage
Write-Host "Downloading solution zip file from Blob Storage..."
Invoke-WebRequest -Uri $blobZipFileUrl -OutFile "./[Link]"
# Download the solution folder from Blob Storage and extract it
Write-Host "Downloading solution folder zip file from Blob Storage..."
Invoke-WebRequest -Uri $blobSolutionFolderUrl -OutFile "./solution_folder.zip"
Expand-Archive -Path "./solution_folder.zip" -DestinationPath "./solution_folder"
# Pack the solution
Write-Host "Packing the solution..."
pac solution pack --zipfile "./[Link]" --folder "./solution_folder"
# Import the solution
Write-Host "Importing the solution..."
pac solution import --path "./[Link]"
Step 3: Build and Push the Docker Image
1. Open a terminal or command prompt and navigate to your project directory where the
Dockerfile is located.
2. Run the following command to build the Docker image:
`docker build -t [Link]/powerplatform-pac-cli:latest .`
- Replace `yourregistry` with your Azure Container Registry name.
3. Log in to your Azure Container Registry using:
`az acr login --name yourregistry`
4. Push the image to ACR:
`docker push [Link]/powerplatform-pac-cli:latest`
Step 4: Create the Azure Function to Trigger ACI
1. Create a new Azure Function project in Visual Studio or Visual Studio Code using the
HTTP trigger template.
2. Replace the function code with the following to trigger the ACI:
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
using [Link];
public static class TriggerPacContainerFunction
{
[FunctionName("TriggerPacContainer")]
public static async Task<IActionResult> Run(
[HttpTrigger([Link], "post", Route = null)] HttpRequest req,
ILogger log)
{
[Link]("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader([Link]).ReadToEndAsync();
dynamic data = [Link](requestBody);
string clientId = data?.clientId;
string clientSecret = data?.clientSecret;
string tenantId = data?.tenantId;
string url = data?.url;
string blobZipFileUrl = data?.blobZipFileUrl;
string blobSolutionFolderUrl = data?.blobSolutionFolderUrl;
var containerGroupName = "paccli-container-group";
var containerName = "paccli-container";
var imageName = "[Link]/powerplatform-pac-cli:latest";
var location = "WestUS";
var credential = new DefaultAzureCredential();
var client = new ContainerInstanceManagementClient("<your-subscription-id>",
credential);
var containerGroup = new ContainerGroupData(location)
{
Containers =
{
new ContainerInstanceContainer(containerName, new
ContainerInstanceContainerProperties()
{
Image = imageName,
EnvironmentVariables =
{
new EnvironmentVariable("clientId", clientId),
new EnvironmentVariable("clientSecret", clientSecret),
new EnvironmentVariable("tenantId", tenantId),
new EnvironmentVariable("url", url),
new EnvironmentVariable("blobZipFileUrl", blobZipFileUrl),
new EnvironmentVariable("blobSolutionFolderUrl", blobSolutionFolderUrl)
},
Resources = new ContainerResourceRequirements
{
Requests = new ContainerResourceRequests
{
Cpu = 1,
MemoryInGB = 2
}
}
})
},
RestartPolicy = [Link]
};
await [Link]("<resource-group-name>",
containerGroupName, containerGroup);
return new OkObjectResult("Container instance created and started successfully.");
}
}
Step 5: Deploy and Test
1. Deploy the Azure Function to Azure.
2. Use Postman or a similar HTTP client to send a POST request to the function URL with the
following JSON body:
{
"clientId": "your-client-id",
"clientSecret": "your-client-secret",
"tenantId": "your-tenant-id",
"url": "[Link]
"blobZipFileUrl":
"[Link]
"blobSolutionFolderUrl":
"[Link]
}