3
votes

I am trying to execute a powershell script (that I am uploading to the storage account using the Azure Storage Client Library for .NET) from a task that runs within a Batch pool.

I know that I am uploading the powershell script correctly (I can verify this by logging onto Azure and verifying that the .ps1 script exists within the storage account), and that the Pool, Job and Task are created correctly, however I suspect that the actual command I am sending to the task is incorrect and that is why my task is error-ing. (This is the string named powershellTask in the code example below)

    List<CloudTask> tasks = new List<CloudTask>();
    string inputFileName = inputFiles[0].FilePath;
    string powershellTask = $"powershell {inputFileName}";
    CloudTask task = new CloudTask("Test-Powershell-Execution-Task", 
       powershellTask);
    task.ResourceFiles = new List<ResourceFile> {inputFiles[0]};
    tasks.Add(task);
    batchClient.JobOperations.AddTask(JobId, tasks);

The powershell script was previously uploaded to the azure storage earlier in the code (and I can verify that this has been uploaded correctly):

foreach (string filePath in inputFilePaths)
{
    inputFiles.Add(UploadFileToContainer(blobClient, inputContainerName, filePath));
}

private static ResourceFile UploadFileToContainer(CloudBlobClient blobClient, string containerName, string filePath)
{
    Console.WriteLine("Uploading file {0} to container [{1}]...", filePath, containerName);

    string blobName = Path.GetFileName(filePath);
    filePath = Path.Combine(Environment.CurrentDirectory, filePath);

        CloudBlobContainer container = 
            blobClient.GetContainerReference(containerName);
            CloudBlockBlob blobData = container.GetBlockBlobReference(blobName);
            blobData.UploadFromFileAsync(filePath).Wait();

            SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy
            {
                SharedAccessExpiryTime = DateTime.UtcNow.AddHours(2),
                Permissions = SharedAccessBlobPermissions.Read
            };

            // Construct the SAS URL for blob
            string sasBlobToken = blobData.GetSharedAccessSignature(sasConstraints);
            string blobSasUri = String.Format("{0}{1}", blobData.Uri, sasBlobToken);

            return ResourceFile.FromUrl(blobSasUri, filePath);
}

The pool, job and task is all created correctly. However when I click into my task on Azure I get the message. "There is an error encountered when processing your request, please try again" Azure appears to be giving me no further info on what is wrong with the request. When I terminate the task, I cannot get any further info as terminating the task throws an exception. "Exception thrown trying determine information from completed tasks Message: Operation returned an invalid status code 'Conflict'"

If anyone has any ideas or can point me in the direction of further documentation around uploading and executing powershell scripts in azure batch processes, that would be really appreciated. Thank you!

EDIT: Thanks to @Hydraxy for the reply below and allowing me to progress a little further with this (was really helpful, especially telling me NOT to delete the task at the end of the code).

The task, as was correctly surmised, WAS working. Trouble was my code was only attempting to parse the stdout.txt, and not the stderr.txt.

When I checked the stderr.txt on the Azure portal, I saw my error:

Invoke-Sqlcmd : The term 'Invoke-Sqlcmd' is not recognized as the name of a cmdlet, function, 
script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
At D:\Dev\codebase\BatchesInAzure\BatchesInAzure\bin\Debug\netcoreapp2.1\BatchesInAzure.ps1:1 
char:1
+ Invoke-Sqlcmd -ServerInstance "dev-database" -Database "Dayinsure.Ap ...
+ ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Invoke-Sqlcmd:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

So it looks, as I suspected that my powershell script is incorrect. I have executed this script in powershell locally and it always returns results. Is the Invoke-SqlCmd not supported in Azure?

Thought it might be helpful to share the contents of the BatchesInAzure.ps1 file I am uploading and trying to execute (have removed server names, usernames & passwords for obvious reasons).

Invoke-Sqlcmd -ServerInstance "my-database-server" -Database "my-lovely-database" -Username "database-user" -Password "super-secure-password" -Query "SELECT GetDate() as TimeOfQuery"
1

1 Answers

0
votes

I am not sure that your task actually failed. It's possible you hit some intermittent error when navigating to the task page in the UI.

The error you got when terminating the task: "Message: Operation returned an invalid status code 'Conflict'" suggests that the task was likely already completed when you tried to terminate it. You should be able to check the task.ExecutionInformation to view the exit code of the task, or use a UI like the Azure portal to look at the results.

Can you share a screenshot of the portal page where you saw the error?

Also if you reproduce the issue and leave the task around (i.e. don't delete the job and task) I can help debug further if the problem is still happening. Note that you're not charged for leaving jobs/tasks around so there's no cost to doing this. Once we've diagnosed what's wrong then you can delete it.