Rest URL Is coming back as a Dead Link
Did the REST Method URI change for JIRA? Im able to do my automated backups for Confluence but starting a couple weeks ago the JIRA backups have been failing via the powershell script. They were working for about a month before that then just stopped and now i get a dead link error. Seems its the reference to the css that is failing?
Error:
Invoke-RestMethod : <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Oops, you've found a dead link. - JIRA</title><script type="text/javascript">contextPath =
"";</script><link type='text/css' rel='stylesheet' href='/static-assets/metal-all.css' media='all'><script src='/static-assets/metal-all.js'></script><!--[if lt IE 9]><link type='text/css' rel='stylesheet' href='/static-assets/metal-all-ie.css'
media='all'><script src='/static-assets/metal-all-ie.js'></script><![endif]--><!--[if IE 9]><link type='text/css' rel='stylesheet' href='/static-assets/metal-all-ie9.css' media='all'><![endif]--><meta name="decorator" content="none" /></head><body
class=" error-page error404"><script type="text/javascript">document.body.className += " js-enabled";</script><div id="page"><header id="header" role="banner"></header><!-- #header --><section id="content" role="main"><div class="aui-page-panel"><div
class="aui-page-panel-inner"><section class="aui-page-panel-content lowerContent"><div id="error-state"><span class="error-type"></span><h1>Oops, you've found a dead link.</h1><ul><li>Go back to the <a
href="javascript:window.history.back()">previous page</a></li><li>Go to the <a href="/secure/MyJiraHome.jspa">Home Page</a></li></ul></div></section><!-- .aui-page-panel-content --></div><!-- .aui-page-panel-inner --></div><!-- .aui-page-panel
--></section><!-- #content --><footer id="footer" role="contentinfo"><section class="footer-body"><div id="footer-logo"><a href="http://www.atlassian.com/" rel="nofollow">Atlassian</a></div></section></footer><!-- #footer --></div><!-- #page
--></body></html>
At C:\scripts\JIRA\jirabackup.ps1:59 char:1
+ Invoke-RestMethod -Method Post -Uri "https://$Account.atlassian.net/rest/obm/1.0 ...
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Write-Log "$($ScriptName)" "Triggering backup."
Invoke-RestMethod -Method Post -Uri "https://$Account.atlassian.net/rest/obm/1.0/runbackup" -WebSession $session -ContentType 'application/json' -Body (@{cbAttachments = $Attachments} | ConvertTo-Json -Compress) | Out-Null
Comments (52)
-
-
reporter Thanks fir the response, ill review the Issue and see if i can get it working with the updates. Much appreciated.
-
Has anyone figured out what needs to be changed in powershell?
-
I'm trying with:
Invoke-RestMethod -Method Post -Uri "https://$Account.atlassian.net/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body (@{cbAttachments="true"; "exportToCloud"="true"}| ConvertTo-Json -Compress) | Out-Null
It gives: Invoke-RestMethod : The remote server returned an error: (412) Precondition Failed.
Removing the convertTo-Json from the line provides this: Atlassian Cloud Notifications - Page Unavailable
Oops, something went wrong Please check Atlassian Status for known problems. If there are no known problems and your page hasn't appeared again in 5-10 minutes then please create a support request for assistance. Atlassian Status Create a support request Atlassian Status Release Summary Documentation Answers Atlassian
-
I don't know if anyone has got further with this - having played around it looks like the 412 error is actually a response but the json coming back to tell you doesn't get thrown in Powershell ..
I have taken the variables and converted them to a json for the body:
[$body = @{ cbAttachments='true' exportToCloud='true' } $bodyjson = $body | ConvertTo-Json
and then had to force the response to be caught and read fully ..
try { $InitiateBackup = Invoke-RestMethod -Method Post -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body $bodyjson -Verbose | ConvertTo-Json -Compress | Out-Null } catch { $InitiateBackup = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($InitiateBackup) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); } $responseBody
Then you actually can see the response - in this case I had already managed to trigger the backup so it is telling me I can't do so again .. but with a 412 Error as the response code.
{"error":"Backup frequency is limited. You cannot make another backup right now. Approximate time until next allowed backup: 47h 43m"}
Even then the rest of the script won't work as you then have to execute
Invoke-WebRequest -Method Get -WebSession $session https://$hostname/rest/backup/1/export/lastTaskId
to get the ID of the job, then run
Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/internal/2/task/progress/{id goes here}" -WebSession $session
to get this content back (once finished)
{"mediaFileId":"bec08d76-e33c-xxxxxxxx-3542760","fileName":"jira-export34xxxxxxxxxxxxxxxxx9.zip","fileSize":56465}
then you have to get this data into fields and submit those into another request to pull the backup .. which is what I am stuck on at the moment.
-
Managed to get it working albeit in an ugly fashion - the response from the ID is Json so using ConvertFrom-Json allows you to parameterise the fields and push them into the Get request. I have butchered the original script enough to get it working but can't test if the error handling works because it is now produced as a file and won't trigger the validation process but if anyone is stuck this is enough to get the download working again.
# Wait for backup to finish do { $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/internal/2/task/progress/$LatestBackupID" -WebSession $session $statusoutput = $status.result $separator = "," $option = [System.StringSplitOptions]::None $s if ($status.progress -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.progress -PercentComplete $percentage } Start-Sleep -Seconds 5 } while($status.status -ne 'Success') # Download if ([bool]($status.PSObject.Properties.Name -match "failedMessage")) { throw $status.failedMessage } $BackupDetails = $status.result | ConvertFrom-Json $JiraMediaID = $BackupDetails.mediaFileId $JiraFileName = $BackupDetails.fileName $BackupURI = "https://$hostname/plugins/servlet/export/download/$JiraMediaID/$JiraFileName" Invoke-WebRequest -Method Get -Headers @{"Accept"="*/*"} -WebSession $session -Uri $BackupURI -OutFile (Join-Path -Path $destination -ChildPath "JIRA-backup-$today.zip")
-
@mattroblin What's your # Request backup creation look like now? I see you're using $LatestBackupID in your #wait for backup to finish, but I don't see you having assigned it. I was stuck on pulling down the backupID
-
@vespene56 - looks like this .. I originally tried getting it to just use $GetBackupID.content in the next request but it wasn't happening so I had to create another variable for it to pass correctly..
$GetBackupID = Invoke-WebRequest -Method Get -WebSession $session https://$hostname/rest/backup/1/export/lastTaskId $LatestBackupID = $GetBackupID.content
-
Would someone mind posting a full view of the code as I am struggling to get this working. It was working ok before Atlassian changed the endpoints and now I can't seem to get it working and I don't know powershell at all. Thanks
-
Here you go @niallhannon - hope it helps,
$account = 'youratlassianjira' # Atlassian subdomain i.e. whateverproceeds.atlassian.net $username = 'youratlassianusername' # username without domain $password = 'youratlassianpassword' $destination = 'C:\Backups' # Location on server where script is run to dump the backup zip file. $attachments = $true # Tells the script to pull down the attachments as well $hostname = "$account.atlassian.net" $today = Get-Date -format yyyyMMdd-hhmmss $credential = New-Object System.Management.Automation.PSCredential($username, (ConvertTo-SecureString $password -AsPlainText -Force)) $string = "cbAttachments:true, exportToCloud:true" $stringbinary = [system.Text.Encoding]::Default.GetBytes($String) | %{[System.Convert]::ToString($_,2).PadLeft(8,'0') } $body = @{ cbAttachments='true' exportToCloud='true' } $bodyjson = $body | ConvertTo-Json if ($PSVersionTable.PSVersion.Major -lt 4) { throw "Script requires at least PowerShell version 4. Get it here: https://www.microsoft.com/en-us/download/details.aspx?id=40855" } # Login #Invoke-WebRequest -Method Post -Uri "https://$hostname/login" -SessionVariable session -Body @{username = $username; password = $password} | Out-Null # New Session #Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json'" Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json' # Request backup #Invoke-RestMethod -Method Post -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body @{cbAttachments="true"; "exportToCloud"="true"} | ConvertTo-Json -Compress | Out-Null try { $InitiateBackup = Invoke-RestMethod -Method Post -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body $bodyjson -Verbose | ConvertTo-Json -Compress | Out-Null } catch { $InitiateBackup = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($InitiateBackup) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); } $responseBody $GetBackupID = Invoke-WebRequest -Method Get -WebSession $session https://$hostname/rest/backup/1/export/lastTaskId $LatestBackupID = $GetBackupID.content # Wait for backup to finish do { $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/internal/2/task/progress/$LatestBackupID" -WebSession $session $statusoutput = $status.result $separator = "," $option = [System.StringSplitOptions]::None $s if ($status.progress -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.progress -PercentComplete $percentage } Start-Sleep -Seconds 5 } while($status.status -ne 'Success') # Download if ([bool]($status.PSObject.Properties.Name -match "failedMessage")) { throw $status.failedMessage } $BackupDetails = $status.result | ConvertFrom-Json $JiraMediaID = $BackupDetails.mediaFileId $JiraFileName = $BackupDetails.fileName $BackupURI = "https://$hostname/plugins/servlet/export/download/$JiraMediaID/$JiraFileName" Invoke-WebRequest -Method Get -Headers @{"Accept"="*/*"} -WebSession $session -Uri $BackupURI -OutFile (Join-Path -Path $destination -ChildPath "JIRA-backup-$today.zip")
-
Thanks @mattroblin, really appreciate that. I'll try it out.
-
@Chandrasekaran This is PowerShell - thanks Matt
-
Thanks @Matt Roblin for your quick reply. -Chandru
-
There are reports that the endpoints have changed again. I think the change is on this line ""https://$hostname/rest/internal/2/task/progress/$LatestBackupID"" where it checks for the status of the backup.
Anyone able to confirm?
Thanks
-
Hi @niallhannon - looks like they have ..
The change you refer to now has to look like this:
https://$hostname/rest/backup/1/export/getProgress?taskId=$LatestBackupID
Which now creates a different response - you then have to tag this to the end of the URL rather than pluck out the ID so slightly easier.
I have amended the script I posted the other day - looks like it is working for me. Let me know if this fixes the problem for you.
Thanks Matt
$account = 'youratlassianjira' # Atlassian subdomain i.e. whateverproceeds.atlassian.net $username = 'youratlassianusername' # username without domain $password = 'youratlassianpassword' $destination = 'C:\Backups' # Location on server where script is run to dump the backup zip file. $attachments = $true # Tells the script to pull down the attachments as well $hostname = "$account.atlassian.net" $today = Get-Date -format yyyyMMdd-hhmmss $credential = New-Object System.Management.Automation.PSCredential($username, (ConvertTo-SecureString $password -AsPlainText -Force)) $string = "cbAttachments:true, exportToCloud:true" $stringbinary = [system.Text.Encoding]::Default.GetBytes($String) | %{[System.Convert]::ToString($_,2).PadLeft(8,'0') } $body = @{ cbAttachments='true' exportToCloud='true' } $bodyjson = $body | ConvertTo-Json if ($PSVersionTable.PSVersion.Major -lt 4) { throw "Script requires at least PowerShell version 4. Get it here: https://www.microsoft.com/en-us/download/details.aspx?id=40855" } # Login #Invoke-WebRequest -Method Post -Uri "https://$hostname/login" -SessionVariable session -Body @{username = $username; password = $password} | Out-Null # New Session #Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json'" Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json' # Request backup #Invoke-RestMethod -Method Post -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body @{cbAttachments="true"; "exportToCloud"="true"} | ConvertTo-Json -Compress | Out-Null try { $InitiateBackup = Invoke-RestMethod -Method Post -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body $bodyjson -Verbose | ConvertTo-Json -Compress | Out-Null } catch { $InitiateBackup = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($InitiateBackup) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); } $responseBody $GetBackupID = Invoke-WebRequest -Method Get -WebSession $session https://$hostname/rest/backup/1/export/lastTaskId $LatestBackupID = $GetBackupID.content # Wait for backup to finish do { $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/getProgress?taskId=$LatestBackupID" -WebSession $session $statusoutput = $status.result $separator = "," $option = [System.StringSplitOptions]::None $s if ($status.progress -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.progress -PercentComplete $percentage } Start-Sleep -Seconds 5 } while($status.status -ne 'Success') # Download if ([bool]($status.PSObject.Properties.Name -match "failedMessage")) { throw $status.failedMessage } $BackupDetails = $status.result $BackupURI = "https://$hostname/plugins/servlet/$BackupDetails" Invoke-WebRequest -Method Get -Headers @{"Accept"="*/*"} -WebSession $session -Uri $BackupURI -OutFile (Join-Path -Path $destination -ChildPath "JIRA-backup-$today.zip")
-
Thanks, I'll give that a go when we can next do a backup (just did one so cant do another one for 48 hours).
Yes, just to confirm this script works perfectly, it executed this morning. I thought Atlassian enforced a minimum of 48 hours between data backup exporting but that wasn't blocked this morning for me anyways.
Thanks @mattroblin again.
-
Account Deactivated Thanks for the fix Matt. I hope you don't mind, I updated the source code to reflect your fix. Indeed we updated these internal APIs, which caused these scripts to break.
If you have any more fixes, feel free to open a pull request, and put me as a reviewer :)
Best, Jonah Turnquist Atlassian, Migration Platform Team
-
reporter Hi @jonah_turnquist
How come we are only allowed one backup per 48 hours. My company hasn't taken backup now in almost 5 days as this end point has changed but it already thinks i tried to execute my backup even though it failed on the endpoint. I cant even test if this works honestly without wasting my backup try. Is there a way to allow as many backups a day and only a one back can be downloaded per 48 hours?
-
Account Deactivated Hey Julian,
The best way to do that would be to open a support request at https://support.atlassian.com/contact/#/
They will be able to reset the 48 hour timer when you request it.
The reason for this is that backups are a highly memory and CPU intensive process - if we had people running backups too frequently, it could have negative affects on the service performance and reliability.
Keep in mind that Atlassian also backs up your data on your behalf: https://confluence.atlassian.com/cloud/data-storage-faq-873871367.html#DatastorageFAQ-Howoftenisdatabackedup
-
Account Deactivated Hi @mattroblin , I tried the script you posted and it doesnt get the error 401, instead it has a problem with the https connection. I try to translate from german: "The basic connection has been closed. No trust position could be created with the protected SSL/TLS connection." So I found something to reply that the connection is safe, but I dontt know where to put it in correctly: add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
Can someone help me out or add this to the existing backup script please? Thanks & regards
-
Hi @CeDeAdmin - it looks like it is not able to establish the trust relationship for the Atlassian cert. Not entirely sure how I would test this as I don't get any issues. Are you running this from your machine or from a server? You may be able to resolve this by adding the atlassian certs (the *.atlassian.net and the intermediary / root certs) into the Trusted Root Certificate Authorities section of your machines certification store instead of trying to tell the script to unconditionally accept the connection regardless?
-
Account Deactivated Hi @mattroblin - I'm running this on my PC with admin rights. Good idea, I added the ".atlassian.net certificate into the trusted sites now and it seems that it has not the problem I mentioned anymore, great! Now I just get stuck at the last Invoke-WebRequest at line 79 with message: "Atlassian Cloud Notifications - Page Unavailable" for "https://$hostname/plugins/servlet/$BackupDetails". Did you succeed with the same URL or is there again a change of the API endpoints made of Atlassian..?
-
Working fine for me - when it fails can you try $BackupDetails and see what the variable shows you? it is a part url so if it didn't populate on line 78 it would be an invalid url and the error would occur.
-
Hi, i tried with below script ( downloaded from bit bucket) and its not working fine and getting below error. please advice what is wrong in the URL? session
@{name=cloud.session.token; value=eyJraWQiOiJzZXNzaW9uLXNlcnZpY2VcL3Nlc3Npb24tc2VydmljZSIsImFsZyI6IlJTMjU2In0.eyJhc3... VERBOSE: POST https://myjira.atlassian.net/rest/backup/1/export/runbackup with -1-byte payload {"error":"Backup frequency is limited. You cannot make another backup right now. Approximate time until next allowed bac kup: 47h 8m"} Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again. At E:\Jira_backup\new.ps1:51 char:16 + ... tBackupID = Invoke-WebRequest -Method Get -WebSession $session https: ... +
~~~~~~~~~~~~~ + CategoryInfo : NotImplemented: (:) [Invoke-WebRequest], NotSupportedException + FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.PowerShell.Commands.InvokeWebRequestComman dInvoke-RestMethod : The remote server returned an error: (500) Internal Server Error. At E:\Jira_backup\new.ps1:57 char:15 + ... $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="applic ... +
~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc eption + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommandInvoke-RestMethod : The remote server returned an error: (500) Internal Server Error. At E:\Jira_backup\new.ps1:57 char:15 + ... $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="applic ... +
~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc eption + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand------------------Script--------------------------
$account = 'mycompany' # Atlassian subdomain i.e. whateverproceeds.atlassian.net $username = 'username' # username without domain $password = 'password' $destination = 'C:\Backups' # Location on server where script is run to dump the backup zip file. $attachments = $true # Tells the script to pull down the attachments as well
$hostname = "$account.atlassian.net" $today = Get-Date -format yyyyMMdd-hhmmss $credential = New-Object System.Management.Automation.PSCredential($username, (ConvertTo-SecureString $password -AsPlainText -Force))
$string = "cbAttachments:true, exportToCloud:true" $stringbinary = [system.Text.Encoding]::Default.GetBytes($String) | %{[System.Convert]::ToString($_,2).PadLeft(8,'0') }
$body = @{ cbAttachments='true' exportToCloud='true' } $bodyjson = $body | ConvertTo-Json
if ($PSVersionTable.PSVersion.Major -lt 4) { throw "Script requires at least PowerShell version 4. Get it here: https://www.microsoft.com/en-us/download/details.aspx?id=40855" }
# Login #Invoke-WebRequest -Method Post -Uri "https://$hostname/login" -SessionVariable session -Body @{username = $username; password = $password} | Out-Null # New Session #Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json'"
Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json'
# Request backup #Invoke-RestMethod -Method Post -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body @{cbAttachments="true"; "exportToCloud"="true"} | ConvertTo-Json -Compress | Out-Null
try {
$InitiateBackup = Invoke-RestMethod -Method Post -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body $bodyjson -Verbose | ConvertTo-Json -Compress | Out-Null
} catch { $InitiateBackup = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($InitiateBackup) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); }
$responseBody
$GetBackupID = Invoke-WebRequest -Method Get -WebSession $session https://$hostname/rest/backup/1/export/lastTaskId $LatestBackupID = $GetBackupID.content
Wait for backup to finish
do { $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/getProgress?taskId=$LatestBackupID" -WebSession $session $statusoutput = $status.result $separator = "," $option = [System.StringSplitOptions]::None $s
if ($status.progress -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.progress -PercentComplete $percentage } Start-Sleep -Seconds 5
} while($status.status -ne 'Success')
Download
if (bool) { throw $status.failedMessage }
$BackupDetails = $status.result $BackupURI = "https://$hostname/plugins/servlet/$BackupDetails"
Invoke-WebRequest -Method Get -Headers @{"Accept"="/"} -WebSession $session -Uri $BackupURI -OutFile (Join-Path -Path $destination -ChildPath "JIRA-backup-$today.zip")
-
The error returned say "Backup frequency is limited. You cannot make another backup right now. Approximate time until next allowed ba ckup: 47h 8m" - so that's fairly self explanatory?
-
reporter You can request from bitBucket support to have them reset your request frequency to allow for you to retry the script. But yes, only allowed one download try per 48 hours.
-
hi @niallhannon , thanks for your quick reply.
When i run the script, its trigger the backup and return above error I am blindly using this script. please clarify below points. 1. if the backup is running/ exist, will it not download directly ? 2. there are some other error after "Backup frequency is limited" message. is it normal behavior ?
Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again. At E:\Jira_backup\new.ps1:51 char:16 + ... tBackupID = Invoke-WebRequest -Method Get -WebSession $session https: ... +
~~~~~ + CategoryInfo : NotImplemented: (:) [Invoke-WebRequest], NotSupportedException + FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.PowerShell.Commands.InvokeWebRequestComman dInvoke-RestMethod : The remote server returned an error: (500) Internal Server Error. At E:\Jira_backup\new.ps1:57 char:15 + ... $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="applic ... +
~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc eption + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommandInvoke-RestMethod : The remote server returned an error: (500) Internal Server Error. At E:\Jira_backup\new.ps1:57 char:15 + ... $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="applic ... +
~~~~~ + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc eption + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand If a backup already exist, will it skip the backup trigger process and download the backup directly ? 2. -
This error:
"Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete"
What you need to do here is log onto the server where the script is running from (as the user that the scripts runs as) and simple open Internet Explorer and carry out the first-launch configuration as per the error message.
-
hi @niallhannon , thanks you. this issue is resolved.
One more point : As i checked, attachments, avatars, and logos are missing in the backup file. when trigger backup manually, there is an option to sellect "Include additional files (attachments, avatars, and logos) in the backup" do we need to do any changes in the script?
-
Attachments, avatars, and logos are missing in the backup file. what need to change in the script to backup all data? please advice.
-
Did you set the $attachments = $true parameter? Not sure if this does avatars and logos but does attachments.
-
Hi @mattroblin Yes, I have this parameter. but still attachments is missing in my backup file. Please check the below script and advice if need any changes. - Thank you.
$account = 'myjira' # Atlassian subdomain i.e. whateverproceeds.atlassian.net $username = 'Username' # username without domain $password = 'Password' $destination = 'E:\Jira_backup' # Location on server where script is run to dump the backup zip file. $attachments = $true # Tells the script whether or not to pull down the attachments as well
$hostname = "$account.atlassian.net" $today = Get-Date -format yyyyMMdd-hhmmss $credential = New-Object System.Management.Automation.PSCredential($username, (ConvertTo-SecureString $password -AsPlainText -Force))
$string = "cbAttachments:true, exportToCloud:true" $stringbinary = [system.Text.Encoding]::Default.GetBytes($String) | %{[System.Convert]::ToString($_,2).PadLeft(8,'0') }
$body = @{ cbAttachments='false' exportToCloud='true' } $bodyjson = $body | ConvertTo-Json
if ($PSVersionTable.PSVersion.Major -lt 4) { throw "Script requires at least PowerShell version 4. Get it here: https://www.microsoft.com/en-us/download/details.aspx?id=40855" }
New session
Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json'
Request backup
try { $InitiateBackup = Invoke-RestMethod -Method Post -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/runbackup" -WebSession $session -ContentType 'application/json' -Body $bodyjson -Verbose | ConvertTo-Json -Compress | Out-Null } catch { $InitiateBackup = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($InitiateBackup) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); }
$responseBody
$GetBackupID = Invoke-WebRequest -Method Get -WebSession $session https://$hostname/rest/backup/1/export/lastTaskId $LatestBackupID = $GetBackupID.content
Wait for backup to finish
do { $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json"} -Uri "https://$hostname/rest/backup/1/export/getProgress?taskId=$LatestBackupID" -WebSession $session $statusoutput = $status.result $separator = "," $option = [System.StringSplitOptions]::None $s
if ($status.progress -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.progress -PercentComplete $percentage } Start-Sleep -Seconds 5
} while($status.status -ne 'Success')
Download
if (bool) { throw $status.failedMessage }
$BackupDetails = $status.result $BackupURI = "https://$hostname/plugins/servlet/$BackupDetails"
Invoke-WebRequest -Method Get -Headers @{"Accept"="/"} -WebSession $session -Uri $BackupURI -OutFile (Join-Path -Path $destination -ChildPath "JIRA-backup-$today.zip")
-
reporter Hi Candrasekaran, The body has the attachments set to false.
$body = @{ cbAttachments='false'
Thanks, Julian Governale
-
So how can we change this script to work with Confluence? I'm guessing there will only be some URL changes?
-
@michaelbelos - I don't think Confluence has had the same API changes as Jira (no doubt it will at some point) but it means the script for Confluence is different ..
I can't remember where I found this one but it still seems to work.
$account = 'youratlassianjira' # Atlassian subdomain i.e. whateverproceeds.atlassian.net $username = 'youratlassianusername' # username without domain $password = 'youratlassianpassword' $destination = 'C:\Backups' # Location on server where script is run to dump the backup zip file. $attachments = $true # Tells the script to pull down the attachments as well $hostname = "$account.atlassian.net" $today = Get-Date -format yyyyMMdd-hhmmss $credential = New-Object System.Management.Automation.PSCredential($username, (ConvertTo-SecureString $password -AsPlainText -Force)) if ($PSVersionTable.PSVersion.Major -lt 4) { throw "Script requires at least PowerShell version 4. Get it here: https://www.microsoft.com/en-us/download/details.aspx?id=40855" } # Login #Invoke-WebRequest -Method Post -Uri "https://$hostname/login" -SessionVariable session -Body @{username = $username; password = $password} | Out-Null # New Session #Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json'" Invoke-RestMethod -UseBasicParsing -Method Post -Uri "https://$hostname/rest/auth/1/session" -SessionVariable session -Body (@{username = $username; password = $password} | convertTo-Json -Compress) -ContentType 'application/json' # Request backup Invoke-RestMethod -Method Post -Uri "https://$hostname/wiki/rest/obm/1.0/runbackup" -WebSession $session -ContentType 'application/json' -Body (@{cbAttachments = $attachments} | ConvertTo-Json -Compress) | Out-Null # Wait for backup to finish do { $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json"} -Uri "https://$hostname/wiki/rest/obm/1.0/getprogress" -WebSession $session if ($status.alternativePercentage -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.alternativePercentage -PercentComplete $percentage } Start-Sleep -Seconds 5 } while($status.alternativePercentage -ne '100%') # Download if ([bool]($status.PSObject.Properties.Name -match "failedMessage")) { throw $status.failedMessage } $pathName = $status.fileName if ($pathName -match "temp/filestore/(.*)") { $fileName = $Matches[1] Write-Host "Downloading: $fileName to Confluence-backup-$today.zip" $progressPreference = 'Continue' Invoke-WebRequest -Method Get -Headers @{"Accept"="*/*"} -WebSession $session -Uri "https://$hostname/wiki/download/$pathName" -OutFile (Join-Path -Path $destination -ChildPath "Confluence-backup-$today.zip") } else { throw "Attempted to download from WEBDAV directory, which is no longer supported" }
-
Thanks heaps @mattroblin that seems to mostly work, although I get a HTTP code of 406 on the Invoke-RestMethod line (with the url: /wiki/rest/obm/1.0/runbackup). The backup seemed to download, so maybe this is safe to ignore?
-
@michaelbelos - just tried it and got the same thing this morning but tried it again and it didn't happen. I haven't seen this before to be honest so it may have been something on the Atlassian side, but as you say it doesn't seem to affect the backup being produced.
-
- changed status to resolved
Obsolete: PS script in repo is newer than this issue.
-
From December 2018 we wont be able to use basic authentication (username\password) for the api and have to use an API Token to authenticate instead. Has anyone got that working with the existing script above? Thanks
-
@niallhannon ,
Have u seen below script using API tokens? - https://bitbucket.org/atlassianlabs/automatic-cloud-backup/src/master/backup-jira-api-token.sh
-
Thanks @dbonotto, I did but I was looking for a Powershell script. I'll see if I can figure out the Powershell equivalent syntax.
-
I had a quick look after I saw your post - from the looks of the deprecation notice it will stop the script from being able to use the session variable because the /rest/auth/1/session url is being killed off as well.
I think this means you therefore have to pass an authentication header for each of the Invoke-RestMethods with a Base64 encoded string which isn't quite as elegant but you can at least use the username and password variables and then use Powershell to convert it as a Base64 string and then pass that to the different web calls.
I will try and update my scripts and post something in the next few days.
-
@dbonotto - I think there might be an issue with one of the endpoints calling it with an api?
I can initiate the backup and I can check the backup using a Base64 encoded username and api key but the one in the middle that retrieves the lasttaskid - /rest/backup/1/export/lastTaskId - does not work that way. It responds with an 204 error.
I thought this might be a Powershell thing but I replicated it with a curl equivalent and is seems to do the same thing for me:
curl -s -u ${EMAIL}:${API_TOKEN} -H "Accept: application/json" -H "Content-Type: application/json" -X GET https://${HOSTNAME}.atlassian.net/rest/backup/1/export/lastTaskId
Would you mind seeing if you get the same behaviour?
Thanks Matt
-
Hi @dbonotto - did you get a chance to try this? I need to know if I have to raise this as a valid bug in the api .. Thanks Matt
-
@mattroblin I didn't have any chance to test this but I can see that in the API token script I am not using it anymore. I just get the task-id from the response when running the backup: - https://bitbucket.org/atlassianlabs/automatic-cloud-backup/src/master/backup-jira-api-token.sh
Actually, the best way to see the new endpoint (if any) is to run a backup from the UI while running the browsers developer tools.
If you don't know how to do this I can test this maybe tomorrow (hopefully it will be less busy than today :) )
-
@dbonotto - so it looks like it is pulling back the reference now so not sure if I had a typo or a stuck session before.
Jira Backup with API
$account = 'youratlassianjira' # Atlassian subdomain i.e. whateverproceeds.atlassian.net $username = 'youratlassianusername' # username without domain $apikey = 'Wh4t3v3ry0ur4P1K3y15' $destination = 'C:\Backups' # Location on server where script is run to dump the backup zip file. $attachments = $true # Tells the script to pull down the attachments as well $hostname = "$account.atlassian.net" $today = Get-Date -format yyyyMMdd-hhmmss $string = "cbAttachments:true, exportToCloud:true" $stringbinary = [system.Text.Encoding]::Default.GetBytes($String) | %{[System.Convert]::ToString($_,2).PadLeft(8,'0') } $body = @{ cbAttachments='true' exportToCloud='true' } $bodyjson = $body | ConvertTo-Json if ($PSVersionTable.PSVersion.Major -lt 4) { throw "Script requires at least PowerShell version 4. Get it here: https://www.microsoft.com/en-us/download/details.aspx?id=40855" } #Create Base64 String for username and API Key (https://confluence.atlassian.com/cloud/api-tokens-938839638.html) $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$apikey))) try { $InitiateBackup = Invoke-RestMethod -Method Post -Headers @{"Content-Type"="application/json";"Accept"="application/json";"Authorization"="Basic $base64AuthInfo"} -Uri "https://$hostname/rest/backup/1/export/runbackup" -Body $bodyjson -Verbose | ConvertTo-Json -Compress | Out-Null } catch { $InitiateBackup = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($InitiateBackup) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); } $responseBody $GetBackupID = Invoke-WebRequest -Method Get -Headers @{"Authorization"="Basic $base64AuthInfo"} https://$hostname/rest/backup/1/export/lastTaskId? $LatestBackupID = $GetBackupID.content # Wait for backup to finish do { $status = Invoke-RestMethod -Method Get -Headers @{"Content-Type"="application/json";"Accept"="application/json";"Authorization"="Basic $base64AuthInfo"} -Uri "https://$hostname/rest/backup/1/export/getProgress?taskId=$LatestBackupID" $statusoutput = $status.result $separator = "," $option = [System.StringSplitOptions]::None $s if ($status.progress -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.progress -PercentComplete $percentage } Start-Sleep -Seconds 5 } while($status.status -ne 'Success') # Download if ([bool]($status.PSObject.Properties.Name -match "failedMessage")) { throw $status.failedMessage } $BackupDetails = $status.result $BackupURI = "https://$hostname/plugins/servlet/$BackupDetails" Invoke-WebRequest -Method Get -Headers @{"Content-Type"="application/json";"Accept"="application/json";"Authorization"="Basic $base64AuthInfo"} -Uri $BackupURI -OutFile (Join-Path -Path $destination -ChildPath "JIRA-backup-$today.zip")
Confluence Backup with API
$account = 'youratlassianjira' # Atlassian subdomain i.e. whateverproceeds.atlassian.net $username = 'youratlassianusername' # username without domain $apikey = 'Wh4t3v3ry0ur4P1K3y15' $destination = 'C:\Backups' # Location on server where script is run to dump the backup zip file. $attachments = $true # Tells the script to pull down the attachments as well $hostname = "$account.atlassian.net" $today = Get-Date -format yyyyMMdd-hhmmss if ($PSVersionTable.PSVersion.Major -lt 4) { throw "Script requires at least PowerShell version 4. Get it here: https://www.microsoft.com/en-us/download/details.aspx?id=40855" } #Create Base64 String for username and API Key (https://confluence.atlassian.com/cloud/api-tokens-938839638.html) $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $username,$apikey))) # Request backup try { $InitiateBackup = Invoke-RestMethod -Method Post -Uri "https://$hostname/wiki/rest/obm/1.0/runbackup" -Headers @{"Content-Type"="application/json";"Accept"="application/json";"Authorization"="Basic $base64AuthInfo"} -Body (@{cbAttachments = $attachments} | ConvertTo-Json -Compress) | Out-Null } catch { $InitiateBackup = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($InitiateBackup) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); } $responseBody # Wait for backup to finish do { $status = Invoke-RestMethod -Method Get -Headers @{"Accept"="application/json";"Authorization"="Basic $base64AuthInfo"} -Uri "https://$hostname/wiki/rest/obm/1.0/getprogress" if ($status.alternativePercentage -match "(\d+)") { $percentage = $Matches[1] if ([int]$percentage -gt 100) { $percentage = "100" } Write-Progress -Activity 'Creating backup' -Status $status.alternativePercentage -PercentComplete $percentage } Start-Sleep -Seconds 5 } while($status.alternativePercentage -ne '100%') # Download if ([bool]($status.PSObject.Properties.Name -match "failedMessage")) { throw $status.failedMessage } $pathName = $status.fileName if ($pathName -match "temp/filestore/(.*)") { $fileName = $Matches[1] Write-Host "Downloading: $fileName to Confluence-backup-$today.zip" $progressPreference = 'Continue' Invoke-WebRequest -Method Get -Headers @{"Accept"="*/*";"Authorization"="Basic $base64AuthInfo"} -Uri "https://$hostname/wiki/download/$pathName" -OutFile (Join-Path -Path $destination -ChildPath "Confluence-backup-$today.zip") } else { throw "Attempted to download from WEBDAV directory, which is no longer supported" }
@niallhannon - if you wouldn't mind trying these out for me?
-
Nice to know it works :)
-
Hi @mattroblin,
Thanks for the script. I am seeing an error on line 44: of the JIRA Backsup script.
$GetBackupID = Invoke-WebRequest -Method Get -Headers @{"Authorization"="Basic $base64AuthInfo"} https://$hostname/rest/backup/1/export/lastTaskId?
I get a 401 unauthorised error, anyone else getting that?
-
HI @niallhannon - I am not getting a 401 - did you create the API on the same account as you were using before so it had the same permissions?
-
It might be due to the 24 hours (or is it 48 hour limit) before another backup can be done. I will try again later today.
Thanks
-
You shouldn't get a 401 for that - you do get an irritating 400 bad request however:
{"error":"Backup frequency is limited. You cannot make another backup right now. Approximate time until next allowed backup: 3h 10m"} Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
It should still work - 401 suggests it doesn't like the authentication on the second request strangely.
-
Yeah looks like I had the wrong username in my script, I thought the script had kicked off a backup so assumed the credentials were right. But I obviously missed something. Thanks for your help @mattroblin
- Log in to comment
Apparently the rest URI changed to https://$hostname/rest/backup/1/export/runbackup
I think JRACLOUD-67169 explains it, but the site is down at the moment...