Sunday, January 13, 2019

Using Azure Container Instance (ACI) to run a console container job using powershell and Azure CLI

Overview

The PowerShell script below uses the Azure CLI, and start the container jrottenberg/ffmpeg and execute the console app  ffmpeg that will extract a thumb nail for an mp4 file.
Both file names are passed as parameters
The 2 files are located on an azure share file and mounted in the container.

The script checks for the existence of each azure resource before creating it.

The script is inspired by the pluralsight class "Azure Container Instances: Getting Started" by Mark Heath.

PowerShell Script Output:
#
# MAIN
#
cls
$fileName  = "vsCode.SyntaxPlanning.Demo.mp4"
$localFile = "C:\DVT\AzureContainerInstance\$fileName"

"Starting thumb nail extraction process Video: $localFile"


# Create Resource group
$resourceGroup = "aciVideoManipulationResourceGroup"
$location      = "eastus"

ExecCode "create resource group $resourceGroup - $location " `
{ az group create -n $resourceGroup -l $location } `
{ (az group exists -n $resourceGroup) }

# Create storage
$storageAccountName = "acivideomanipulation" # $(Get-Random -Minimum 1000 -Maximum 100000)

ExecCode "create storage $storageAccountName" `
{ az storage account create -g $resourceGroup -n $storageAccountName --sku Standard_LRS } `
{ -not ((az storage account check-name  -n $storageAccountName --query "nameAvailable" ) -eq "true") }

# Get storage connection string to upload and download file from the storage
ExecCode "get connection string for $storageAccountName" { 
    $storageConnectionString = az storage account show-connection-string -g $resourceGroup -n $storageAccountName --query "connectionString" -o tsv
    $env:AZURE_STORAGE_CONNECTION_STRING = $storageConnectionString
}

# Create file share in the storage
$shareName = "acivideomanipulationshare"
ExecCode "create file share $shareName" `
{ az storage share create -n $shareName } `
{ ( az storage share exists -n $shareName --query "exists" ) }

# Upload video file to process
ExecCode "upload file:$localFile to share:$shareName" {
    az storage file upload -s $shareName --source "$localFile"
}

# Get the storage key to be passed to the container so the container can mount the file share
ExecCode "get storage key for $storageAccountName" {
    $global:storageKey = $(az storage account keys list -g $resourceGroup -n $storageAccountName --query "[0].value" -o tsv)        
}


# Create the container
$containerGroupName = "transcode"     # Container name
$containerName = "jrottenberg/ffmpeg" # from Docker hub container
$mountedFolder = "/mnt/azfile" # Folder on the container

# Command to be executed by the container after start time.
$commandLine = "ffmpeg -i $mountedFolder/$filename -vf ""thumbnail,scale=640:360"" -frames:v 1 $mountedFolder/thumb.png"

ExecCode "start container" {

    az container create `
        -g $resourceGroup `
        -n $containerGroupName `
        --image $containerName `
        --restart-policy never `
        --azure-file-volume-account-name $storageAccountName `
        --azure-file-volume-account-key "$storageKey" `
        --azure-file-volume-share-name $shareName `
        --azure-file-volume-mount-path "$mountedFolder" `
        --command-line $commandLine
}

ExecCode "check container start status" {

    $status = ToBool(az container show -g $resourceGroup -n $containerGroupName --query "provisioningState" -o tsv)
    Write-Host "Container start status:$status"
}

ExecCode "check container console output/logs" {
    az container logs -g $resourceGroup -n $containerGroupName
}

ExecCode "check for thumb nail output file" {
    
    az storage file list -s $shareName -o table # Check the azure storage file

    $fileFound = (az storage file exists -s $shareName -p "thumb.png" --query "exists")

    # download the created file thumb.png
    $downloadThumbnailPath = ".\thumb.png" 
    az storage file download -s $shareName -p "thumb.png" --dest $downloadThumbnailPath
    Start-Process $downloadThumbnailPath
}

ExecCode "delete container $containerGroupName" {
    az container delete -g $resourceGroup -n $containerGroupName -y
}


ExecCode "delete Resource Group $resourceGroup" {
    # az group delete -n $resourceGroup -y
}

Utility

function ToBool([string] $val) {
    if($val.ToLowerInvariant() -eq "true") {
        return $true
    }
    else {
        return $false
    }
}

function ExecCode($message, $blockOfCode, $blockOfCodeExist) {
    Write-Host ""
    Write-Host "About to $message" -ForegroundColor Cyan
    Try
    {
        $exist = ""
        if($blockOfCodeExist -ne $null) {
            $exist = ToBool ( &$blockOfCodeExist )
        }
        if(!$exist) {
            &$blockOfCode
        }
        else {
            Write-Host "Already exists"
        }        
    }
    Catch
    {
        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        Write-Error "Failed:$message, $ErrorMessage, $FailedItem"
        Break
    }
    Write-Host "$message - Done"
}


No comments:

Post a Comment