how to increment and save variable in azure devops pipeline - variables

Anyone know how can I increment the value of a variable under some conditions, (for example only if the pipeline succeeded) and save it for next build?
Example:
I set a variable: number=5.
If the pipeline succeeded and job number 2 ran, I want number=6 on the next build.
Is this possible?

You can set the value of your variable by using following command:
Bash
echo "##vso[task.setvariable variable=number;]newValue"
PowerShell
Write-Host "##vso[task.setvariable variable=number;]newValue"
Basically, your number will be set to the newValue after running this command.

how to increment and save variable in azure devops pipeline
Since you could not use the counter, you could try to use the REST API Definitions - Update to update the variable:
PUT https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=5.0
The test scripts:
$url = "https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=6.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
Write-Host "Pipeline = $($pipeline | ConvertTo-Json -Depth 100)"
$counter = [int]$pipeline.variables.Test.value
$counter++
$pipeline.variables.Test.value = $counter
####****************** update the modified object **************************
$json = #($pipeline) | ConvertTo-Json -Depth 99
$updatedef = Invoke-RestMethod -Uri $url -Method Put -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"}
write-host "=========================================================="
Write-host "The value of Varialbe 'Test' is updated to" $updatedef.variables.Test.value
Note: We neeed to declare the variable type as int before we can use ++
$counter = [int]$pipeline.variables.Test.value
$counter++
If you met any premission issue, please refer this thead for some more details.

Related

Invoke-AzVMRunCommand as a job

I am trying to use Invoke-AzVMRunCommand as a job. when I executed below script the job is created and executed successfully but I am failing to write the output like which job result belongs to which vm.
Invoke-AzVMRunCommand is used to invoke a command on a particular VM. You should have this information beforehand.
Here is some information on -AsJob parameter
https://learn.microsoft.com/en-us/powershell/module/az.compute/invoke-azvmruncommand?view=azps-2.6.0#parameters
As suggested by AmanGarg-MSFT, you should have that information before hand. You can use a hashtable $Jobs to store the server name and Invoke-AzVMRunCommand output and later iterate through using the $Jobs.GetEnumerator().
$Jobs = #{}
$Servers = "Server01","Server02"
[System.String]$ScriptBlock = {Get-Process}
$FileName = "RunScript.ps1"
Out-File -FilePath $FileName -InputObject $ScriptBlock -NoNewline
$Servers | ForEach-Object {
$vm = Get-AzVM -Name $_
$Jobs.Add($_,(Invoke-AzVMRunCommand -ResourceGroupName $vm.ResourceGroupName -Name $_ -CommandId 'RunPowerShellScript' -ScriptPath $FileName -AsJob))
}

RabbitMQ Web Interface - doesn't show queue until queue read?

I have a Powershell that sends a message to Rabbit-MQ. I've seen the same from BizTalk. The new queue name does not show up on the web interface until a message is retrieved from that queue at least one time. Is this the normal process? I don't understand why it wouldn't show up as soon as data was written to it.
Similar, I seem to be noticing that I can't store records in the queue until it is read once. I'm sending to an exchange with a routing key. If I write a program and send 5 messages there, the queue doesn't show up in RabbitMQ. But once I create a program to read/listen to that queue, from then on it shows up with the count of messages.
Sample Powershell Code:
Import-Module PSRabbitMQ
Set-RabbitMQConfig -ComputerName localhost
$User = "myuser"
#The second command uses the ConvertTo-SecureString cmdlet to create a secure string from a plain text password. The command uses the *AsPlainText* parameter to indicate that the string is plain text and the *Force* parameter to confirm that you understand the risks of using plain text.
$PWord = ConvertTo-SecureString -String "mypassword" -AsPlainText -Force
#The third command uses the New-Object cmdlet to create a **PSCredential** object from the values in the $User and $PWord variables.
$CredRabbit = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User, $PWord
#Set some common parameters we will always use:
$Params = #{
Credential = $CredRabbit
}
$Exchange = "MyExchange"
$RoutingKey = "NealTest3"
$showDate = Get-Date -DisplayHint Date
$numMessagesPerRun = 5
for ($j=1; $j -le $numMessagesPerRun; $j++)
{
$message = "Hello at date/time= $showDate " + $j
Write-Host "Message = $message"
Send-RabbitMQMessage -Exchange $Exchange -Key $RoutingKey -InputObject $message -vhost base -Persistent #Params
}
$showDate = Get-Date -DisplayHint Date
Write-Host "Ended $showDate"
My Queue: NealTest3 will not show up when I do "rabbitmqctl list_queues -p base" until I run another Powershell to consume at least one message from that queue.
Code from second program to read the queue (left out the same logon info):
Start-RabbitMqListener -Exchange $Exchange `
-Key $QueueName `
-QueueName $QueueName `
-AutoDelete $false `
-vhost base `
#Params | % {
#$req = $_ | ConvertFrom-Json
$req = $_
$counter = $counter + 1
Write-Host $counter + " " + $req
}
It reads the 5 messages I put there, even though the queue in theory didn't exist, according to the list_queues.

How to get Build Successes details including Associated Changes and Associated Work Items from TFS 2015 in .txt file? Which API should I have to use

TFS build successes URL
I have to write AssocoatedChanges and Associated WorkItems in txt file after build success. Team foundation providing any API which will give build details response?
You can use the REST API to get build details including Associated Changes and Associated Work Items:
Associated Changes:
GET https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/changes?api-version={version}
Associated Work Items:
POST https://{instance}/DefaultCollection/{project}/_apis/build/builds/{buildId}/workitems?api-version={version}
Please see Get build details for details.
UPDATE:
You can use below PowerShell script to get the build details including Associated Changes and Associated Work Items from TFS 2015 in .txt file (Just specify the correct parameters):
Param(
[string]$collectionurl = "http://server:8080/tfs/defaultcollection",
[string]$project = "0323ScrumTFVC",
[string]$BuildID = "1",
[string]$user = "username",
[string]$token = "password",
[string]$FilePath = 'C:\temp.txt'
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
#BaseUrl
$WITbaseUrl = "$collectionurl/$project/_apis/build/builds/$($BuildID)/workitems"
$ChangebaseUrl = "$collectionurl/$project/_apis/build/builds/$($BuildID)/changes"
#Response
$WITresponse = (Invoke-RestMethod -Uri $WITbaseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value
$Changeresponse = (Invoke-RestMethod -Uri $ChangebaseUrl -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}).value
#Output the Associated Work items to a text file.
$WITrequests = #()
foreach($WITrequest in $WITresponse){
$customObject = new-object PSObject -property #{
"WorkitemID" = $WITrequest.id
"WorkitemURL" = $WITrequest.url
}
$WITrequests += $customObject
}
$WITrequests | Select `
WorkitemID,
WorkitemURL | Out-File -FilePath $FilePath -Width 200
#Output the Associated Changes to the text file.
$Changerequests = #()
foreach($Changerequest in $Changeresponse){
$customObject = new-object PSObject -property #{
"ChangesetID" = $Changerequest.id
"Comments" = $Changerequest.message
"Author" = $Changerequest.author.uniqueName
"Timestamp" = $Changerequest.timestamp
"Location" = $Changerequest.location
}
$Changerequests += $customObject
}
$Changerequests | Select `
ChangesetID,
Comments,
Author,
Timestamp,
Location | Out-File -FilePath $FilePath -Width 200 -Append # (with -Append, the contents will increment to txt file )

How to delete mail items using office 365 REST API in provided powershell script sample

I have been trying to find a solution to this problem for quite a while now and nothing I've found seems to work. I am hoping to use this script:
##-----------------------------------------------------##
## PICK AUTH Method ##
##-----------------------------------------------------##
## HARD CODING PSW ##
#$password = ConvertTo-SecureString "xxx" -AsPlainText -Force
#$cred = New-Object System.Management.Automation.PSCredential "xxx#xxx.onmicrosofot.com",$password
## USER PROMPT PSW ##
#$cred = Get-Credential
##-----------------------------------------------------##
## END PICK
##-----------------------------------------------------##
$url = "https://outlook.office365.com/api/v1.0/me/messages"
$date = "2014-11-21"
## Get all messages that have attachments where received date is greater than $date
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived ge " + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "c:\Temp\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
}
That I found from link - TechNet Office 365 Scripts
I can get the script to work fine, it connects to mailbox and downloads the attachments for emails specified after the date variable. Problem is that I would like to run this on an hourly schedule and delete previously processed emails so that their attachments are not stripped on consecutive runs.
I've tried lots of different commands to delete the email with no success and also tried altering the $messageQuery to include only items within a specific date range but can't get anything working.
Can anyone provide the correct syntax for the delete command in powershell and an example of how to use it in this context please?
Thanks
Rich
UPDATE - I think adding in:
$query2 = $url + "/" + $message.Id
And
Invoke-RestMethod $query2 -Credential $cred -Method Delete
Is getting me closer but I now get operation timed out.
UPDATE - Full code as it stands and as requested:
##-----------------------------------------------------##
## PICK AUTH Method ##
##-----------------------------------------------------##
## HARD CODING PSW ##
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential "email#address.co.uk",$password
## USER PROMPT PSW ##
##$cred = Get-Credential
##-----------------------------------------------------##
## END PICK
##-----------------------------------------------------##
#$url = "https://outlook.office365.com/api/v1.0/me/messages"
$url = "https://outlook.office365.com/EWS/ODATA/me/messages"
$today = Get-Date -format yyyy-MM-dd
$date = (Get-Date).AddDays(-2).ToString("yyyy-MM-dd")
## Set date and query
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived lt " + $today #+ " and DateTimeReceived gt" + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$query2 = $url + "/" + $message.Id
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "\\SomePath\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
Invoke-RestMethod $query2 -Credential $cred -Method Delete -TimeoutSec 100
}
#Move pdf files to another folder
#Move-Item '\\SomePath\*.pdf' '\\SomePath'
#Then delete any existing files from directory
#Remove-Item '\\SomePath\*'
I tried to alter the date section to allow for a start and end date so the script could be run once a day, do the extraction but not reprocess attachments from previous days but ran into issues working out the syntax to alter the $messageQuery.
Response from running the script is:
Invoke-RestMethod : The operation has timed out.
At C:\Scripts\EmailExtractServiceContract365.ps1:26 char:13
+ $messages = Invoke-RestMethod $messageQuery -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Not an answer
Use Fiddler to capture the request. Use the https://outlook.office365.com/api/v1.0/me/messages endpoint. The other one has been deprecated (I think). Post your sanitized request/response here.
Your script is probably not the problem
I got the script to work fine; it finds an email with attachment, saves the attachment, then deletes the email. I'm not sure what is going on in your environment until I see the requests (remove the auth headers if you post the request). I only changed the $today value to capture emails with attachments today.
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential "user#contoso.com",$password
$url = "https://outlook.office365.com/api/v1.0/me/messages"
$today = (Get-Date).AddDays(1).ToString("yyyy-MM-dd")
$date = (Get-Date).AddDays(-2).ToString("yyyy-MM-dd")
## Set date and query
$messageQuery = "" + $url + "?`$select=Id&`$filter=HasAttachments eq true and DateTimeReceived lt " + $today #+ " and DateTimeReceived gt" + $date
$messages = Invoke-RestMethod $messageQuery -Credential $cred
## Loop through each results
foreach ($message in $messages.value)
{
# get attachments and save to file system
$query = $url + "/" + $message.Id + "/attachments"
$query2 = $url + "/" + $message.Id
$attachments = Invoke-RestMethod $query -Credential $cred
# in case of multiple attachments in email
foreach ($attachment in $attachments.value)
{
$attachment.Name
$path = "C:\temp\" + $attachment.Name
$Content = [System.Convert]::FromBase64String($attachment.ContentBytes)
Set-Content -Path $path -Value $Content -Encoding Byte
}
Invoke-RestMethod $query2 -Credential $cred -Method Delete -TimeoutSec 100
}
REQUEST
Here's what the request and response should look like to delete the email.
DELETE https://outlook.office365.com/api/v1.0/me/messages/AAMkADBjYXXXXXXXXXX= HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.0.10586.0
Authorization: XXXXXXXXXXXXXXXXXXXXXXXXX
Host: outlook.office365.com
Cookie: ClientId=CQA
Content-Length: 0
RESPONSE
HTTP/1.1 204 No Content

Access ASANA via windows powershell using APIKEY

I have created this following two codes in powershell to access ASANA.
But both of them dont work. I always get this error
"The remote server returned an error: (401) Unauthorized."
Any help appreciated. If you have a working C# code that can connect to any secure server with only APIKey, please post it. I could convert it to powershell code.
Code 1
Function Get-WebResponseString
{
param (
[Parameter(Mandatory=$true)]
[String]$Url,
[Parameter(Mandatory=$true)]
[String]$Method,
[Parameter(Mandatory=$false)]
[System.Net.NetworkCredential]$Credential
)
$Request = [System.Net.WebRequest]::Create($Url)
$Request.Method = $Method
$Request.ContentType = "application/x-www-form-urlencoded";
if ($Credential -ne $null)
{
$Request.Credentials = $credential
write-host "****" -foregroundcolor blue
}
$Response = $Request.GetResponse()
$StreamReader = New-Object System.IO.StreamReader $Response.GetResponseStream()
$StreamReader.ReadToEnd()
}
$Url = "https://app.asana.com/api/1.0/tasks"
$Username = "MMuthusamy#xxxxxx.xom"
$apikey="xxxxxxxxx"
$credential = New-Object System.Net.NetworkCredential #($Username, $apikey)
Get-WebResponseString -Url $Url -Credential $credential -Method "GET"
Code 2
$sha = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$apikey="xxxxxxx"
#Add colon
$authinfo=$apikey+":";
$string1 = $authinfo
Write-Host $string1 -ForeGroundColor Green
#Encoding format
$enc = [system.Text.Encoding]::UTF8
#get bytes
$data1 = $enc.GetBytes($string1)
#Encode
$result1 = $sha.ComputeHash($data1)
#convert to 64 bit
$mykey=[System.Convert]::ToBase64String($result1)
Write-Host $mykey -ForeGroundColor Green
$url = "https://app.asana.com/api/1.0/tasks"
$url="https://app.asana.com/api/1.0/users"
$request = [System.Net.WebRequest]::Create($url)
$authorization = "Authorization: Basic " + $myKey
Write-Host $authorization -ForeGroundColor Green
$request.Headers.Add($authorization)
#$request.Headers.Add("Authorization: BASIC $mykey")
$response = $request.GetResponse()
Write-Host $Response -ForeGroundColor Green
(I work at Asana)
The 401 header is a clue that the problem lies somewhere in your authorization header.
The HTTP Basic Auth spec does not call for a SHA1 hash of the username:password. It's just straight base64 encoding of that string. Try passing $authinfo to your call to ToBase64String instead of hashed data.