diff --git a/build/vsts-prerequisites.ps1 b/build/vsts-prerequisites.ps1 index 96195b19..68dda50d 100644 --- a/build/vsts-prerequisites.ps1 +++ b/build/vsts-prerequisites.ps1 @@ -1,8 +1,8 @@ Write-Host "Working on the machine named: $($env:computername)" Write-Host "The user running is: $($env:UserName)" -# $modules = @("PSFramework", "Azure.Storage", "AzureAd", "PSNotification", "PSOAuthHelper", "PowerShellGet", "PackageManagement","ImportExcel","PSScriptAnalyzer") -$modules = @("PSFramework", "PSScriptAnalyzer", "Azure.Storage", "AzureAd", "PSNotification", "PSOAuthHelper", "ImportExcel") +# $modules = @("PSFramework", "Az.Storage", "AzureAd", "PSNotification", "PSOAuthHelper", "PowerShellGet", "PackageManagement","ImportExcel","PSScriptAnalyzer") +$modules = @("PSFramework", "PSScriptAnalyzer", "Az.Storage", "AzureAd", "PSNotification", "PSOAuthHelper", "ImportExcel") Install-Module "Pester" -MaximumVersion 4.99.99 -Force -Confirm:$false -Scope CurrentUser -AllowClobber -SkipPublisherCheck diff --git a/build/vsts-validate.ps1 b/build/vsts-validate.ps1 index 1b13aa98..e17d06b2 100644 --- a/build/vsts-validate.ps1 +++ b/build/vsts-validate.ps1 @@ -17,7 +17,7 @@ Write-Host "Working on the machine named: $($env:computername)" Write-Host "The user running is: $($env:UserName)" -$modules = @("PSFramework", "PSScriptAnalyzer", "Azure.Storage", "AzureAd", "PSNotification", "PSOAuthHelper", "ImportExcel") +$modules = @("PSFramework", "PSScriptAnalyzer", "Az.Storage", "AzureAd", "PSNotification", "PSOAuthHelper", "ImportExcel") foreach ($item in $modules) { $module = Get-Module -Name $item -ErrorAction SilentlyContinue diff --git a/d365fo.tools/d365fo.tools.psd1 b/d365fo.tools/d365fo.tools.psd1 index 73e6fee5..1e1a01a8 100644 --- a/d365fo.tools/d365fo.tools.psd1 +++ b/d365fo.tools/d365fo.tools.psd1 @@ -27,9 +27,9 @@ # this module. # To enable the GitHub dependency graph, changes should be synchronized with # https://github.com/d365collaborative/d365fo.tools/blob/master/.github/workflows/dependencies.yml - RequiredModules = @( - @{ ModuleName = 'PSFramework'; ModuleVersion = '1.0.12' } - , @{ ModuleName = 'Azure.Storage'; ModuleVersion = '4.4.0' } + RequiredModules = @( + @{ ModuleName = 'PSFramework'; ModuleVersion = '1.0.12' } + , @{ ModuleName = 'Az.Storage'; ModuleVersion = '1.11.0' } , @{ ModuleName = 'AzureAd'; ModuleVersion = '2.0.1.16' } , @{ ModuleName = 'PSNotification'; ModuleVersion = '0.5.3' } , @{ ModuleName = 'PSOAuthHelper'; ModuleVersion = '0.3.0' } diff --git a/d365fo.tools/functions/get-d365azurestoragefile.ps1 b/d365fo.tools/functions/get-d365azurestoragefile.ps1 index 838ebc24..8bdad4fd 100644 --- a/d365fo.tools/functions/get-d365azurestoragefile.ps1 +++ b/d365fo.tools/functions/get-d365azurestoragefile.ps1 @@ -92,33 +92,27 @@ function Get-D365AzureStorageFile { if ([string]::IsNullOrEmpty($SAS)) { Write-PSFMessage -Level Verbose -Message "Working against Azure Storage Account with AccessToken" - $storageContext = new-AzureStorageContext -StorageAccountName $AccountId.ToLower() -StorageAccountKey $AccessToken + $storageContext = New-AzStorageContext -StorageAccountName $AccountId.ToLower() -StorageAccountKey $AccessToken } else { Write-PSFMessage -Level Verbose -Message "Working against Azure Storage Account with SAS" $conString = $("BlobEndpoint=https://{0}.blob.core.windows.net/;QueueEndpoint=https://{0}.queue.core.windows.net/;FileEndpoint=https://{0}.file.core.windows.net/;TableEndpoint=https://{0}.table.core.windows.net/;SharedAccessSignature={1}" -f $AccountId.ToLower(), $SAS) - $storageContext = new-AzureStorageContext -ConnectionString $conString + $storageContext = New-AzStorageContext -ConnectionString $conString } - $cloudStorageAccount = [Microsoft.WindowsAzure.Storage.CloudStorageAccount]::Parse($storageContext.ConnectionString) - - $blobClient = $cloudStorageAccount.CreateCloudBlobClient() - - $blobcontainer = $blobClient.GetContainerReference($Container); - try { - $files = $blobcontainer.ListBlobs() | Sort-Object -Descending { $_.Properties.LastModified } + $files = Get-AzStorageBlob -Container $($Container.ToLower()) -Context $storageContext | Sort-Object -Descending { $_.Properties.LastModified } if ($Latest) { - $files | Select-Object -First 1 | Select-PSFObject -TypeName D365FO.TOOLS.Azure.Blob "name", @{Name = "Size"; Expression = {[PSFSize]$_.Properties.Length}}, "IsDeleted", @{Name = "LastModified"; Expression = {[Datetime]::Parse($_.Properties.LastModified)}} + $files | Select-Object -First 1 | Select-PSFObject -TypeName D365FO.TOOLS.Azure.Blob "name", @{Name = "Size"; Expression = { [PSFSize]$_.Length } }, @{Name = "LastModified"; Expression = { [Datetime]::Parse($_.LastModified) } } } else { foreach ($obj in $files) { if ($obj.Name -NotLike $Name) { continue } - $obj | Select-PSFObject -TypeName D365FO.TOOLS.Azure.Blob "name", @{Name = "Size"; Expression = {[PSFSize]$_.Properties.Length}}, "IsDeleted", @{Name = "LastModified"; Expression = {[Datetime]::Parse($_.Properties.LastModified)}} + $obj | Select-PSFObject -TypeName D365FO.TOOLS.Azure.Blob "name", @{Name = "Size"; Expression = { [PSFSize]$_.Length } }, @{Name = "LastModified"; Expression = { [Datetime]::Parse($_.LastModified) } } } } } diff --git a/d365fo.tools/functions/invoke-d365azurestoragedownload.ps1 b/d365fo.tools/functions/invoke-d365azurestoragedownload.ps1 index 83f61990..50a91327 100644 --- a/d365fo.tools/functions/invoke-d365azurestoragedownload.ps1 +++ b/d365fo.tools/functions/invoke-d365azurestoragedownload.ps1 @@ -29,6 +29,9 @@ .PARAMETER Latest Instruct the cmdlet to download the latest file from Azure regardless of name + .PARAMETER Force + Instruct the cmdlet to overwrite the local file if it already exists + .PARAMETER EnableException This parameters disables user-friendly warnings and enables the throwing of exceptions This is less user friendly, but allows catching exceptions in calling scripts @@ -87,7 +90,6 @@ function Invoke-D365AzureStorageDownload { [Parameter(Mandatory = $false)] [string] $SAS = $Script:AzureStorageSAS, - [Parameter(Mandatory = $false)] [Alias('Blob')] [Alias('Blobname')] [string] $Container = $Script:AzureStorageContainer, @@ -96,13 +98,14 @@ function Invoke-D365AzureStorageDownload { [Alias('Name')] [string] $FileName, - [Parameter(Mandatory = $false)] [string] $Path = $Script:DefaultTempPath, [Parameter(Mandatory = $true, ParameterSetName = 'Latest', Position = 4 )] [Alias('GetLatest')] [switch] $Latest, + [switch] $Force, + [switch] $EnableException ) @@ -120,7 +123,7 @@ function Invoke-D365AzureStorageDownload { } } PROCESS { - if (Test-PSFFunctionInterrupt) {return} + if (Test-PSFFunctionInterrupt) { return } Invoke-TimeSignal -Start @@ -129,41 +132,40 @@ function Invoke-D365AzureStorageDownload { if ([string]::IsNullOrEmpty($SAS)) { Write-PSFMessage -Level Verbose -Message "Working against Azure Storage Account with AccessToken" - $storageContext = new-AzureStorageContext -StorageAccountName $AccountId.ToLower() -StorageAccountKey $AccessToken + $storageContext = New-AzStorageContext -StorageAccountName $AccountId.ToLower() -StorageAccountKey $AccessToken } else { Write-PSFMessage -Level Verbose -Message "Working against Azure Storage Account with SAS" $conString = $("BlobEndpoint=https://{0}.blob.core.windows.net/;QueueEndpoint=https://{0}.queue.core.windows.net/;FileEndpoint=https://{0}.file.core.windows.net/;TableEndpoint=https://{0}.table.core.windows.net/;SharedAccessSignature={1}" -f $AccountId.ToLower(), $SAS) - $storageContext = new-AzureStorageContext -ConnectionString $conString + $storageContext = New-AzStorageContext -ConnectionString $conString } - $cloudStorageAccount = [Microsoft.WindowsAzure.Storage.CloudStorageAccount]::Parse($storageContext.ConnectionString) - - $blobClient = $cloudStorageAccount.CreateCloudBlobClient() - - $blobContainer = $blobClient.GetContainerReference($Container.ToLower()); - Write-PSFMessage -Level Verbose -Message "Start download from Azure Storage Account" if ($Latest) { - $files = $blobContainer.ListBlobs() - $File = ($files | Sort-Object -Descending { $_.Properties.LastModified } | Select-Object -First 1) - - $NewFile = Join-Path $Path $($File.Name) + $files = Get-AzStorageBlob -Container $($Container.ToLower()) -Context $storageContext - $File.DownloadToFile($NewFile, [System.IO.FileMode]::Create) + $File = ($files | Sort-Object -Descending { $_.LastModified } | Select-Object -First 1) $FileName = $File.Name + + Write-PSFMessage -Level Verbose -Message "Filename is: $FileName" + + $NewFile = Join-Path $Path $($File.Name) + + $null = Get-AzStorageBlobContent -Container $($Container.ToLower()) -Blob $File.Name -Destination $NewFile -Context $storageContext -Force:$Force } else { + + Write-PSFMessage -Level Verbose -Message "Filename is: $FileName" + $NewFile = Join-Path $Path $FileName - $blockBlob = $blobContainer.GetBlockBlobReference($FileName); - $blockBlob.DownloadToFile($NewFile, [System.IO.FileMode]::Create) + $null = Get-AzStorageBlobContent -Container $($Container.ToLower()) -Blob $FileName -Destination $NewFile -Context $storageContext -Force:$Force } - Get-Item -Path $NewFile | Select-PSFObject "Name as Filename", @{Name = "Size"; Expression = {[PSFSize]$_.Length}}, "LastWriteTime as LastModified", "Fullname as File" + Get-Item -Path $NewFile | Select-PSFObject "Name as Filename", @{Name = "Size"; Expression = { [PSFSize]$_.Length } }, "LastWriteTime as LastModified", "Fullname as File" } catch { $messageString = "Something went wrong while downloading the file from Azure." @@ -176,5 +178,5 @@ function Invoke-D365AzureStorageDownload { } } - END {} + END { } } \ No newline at end of file diff --git a/d365fo.tools/functions/invoke-d365azurestorageupload.ps1 b/d365fo.tools/functions/invoke-d365azurestorageupload.ps1 index f76ffb2a..9145f97c 100644 --- a/d365fo.tools/functions/invoke-d365azurestorageupload.ps1 +++ b/d365fo.tools/functions/invoke-d365azurestorageupload.ps1 @@ -28,7 +28,10 @@ If the parameter is left empty, the commandlet will try to automatically determined the value based on the file's extension. If the parameter is left empty and the value cannot be automatically be determined, Azure storage will automatically assign "application/octet-stream" as the content type. Valid media type values can be found here: https://www.iana.org/assignments/media-types/media-types.xhtml - + + .PARAMETER Force + Instruct the cmdlet to overwrite the file in the container if it already exists + .PARAMETER DeleteOnUpload Switch to tell the cmdlet if you want the local file to be deleted after the upload completes @@ -95,6 +98,8 @@ function Invoke-D365AzureStorageUpload { [Parameter(Mandatory = $false)] [string] $ContentType, + [switch] $Force, + [switch] $DeleteOnUpload, [switch] $EnableException @@ -112,26 +117,24 @@ function Invoke-D365AzureStorageUpload { if (Test-PSFFunctionInterrupt) { return } Invoke-TimeSignal -Start + + $FileName = Split-Path -Path $Filepath -Leaf try { if ([string]::IsNullOrEmpty($SAS)) { Write-PSFMessage -Level Verbose -Message "Working against Azure Storage Account with AccessToken" - $storageContext = new-AzureStorageContext -StorageAccountName $AccountId.ToLower() -StorageAccountKey $AccessToken + $storageContext = New-AzStorageContext -StorageAccountName $AccountId.ToLower() -StorageAccountKey $AccessToken } else { $conString = $("BlobEndpoint=https://{0}.blob.core.windows.net/;QueueEndpoint=https://{0}.queue.core.windows.net/;FileEndpoint=https://{0}.file.core.windows.net/;TableEndpoint=https://{0}.table.core.windows.net/;SharedAccessSignature={1}" -f $AccountId.ToLower(), $SAS) Write-PSFMessage -Level Verbose -Message "Working against Azure Storage Account with SAS" -Target $conString - $storageContext = new-AzureStorageContext -ConnectionString $conString + $storageContext = New-AzStorageContext -ConnectionString $conString } - $cloudStorageAccount = [Microsoft.WindowsAzure.Storage.CloudStorageAccount]::Parse($storageContext.ConnectionString) - - $blobClient = $cloudStorageAccount.CreateCloudBlobClient() - - $blobContainer = $blobClient.GetContainerReference($Container.ToLower()); + Write-PSFMessage -Level Verbose -Message "Start uploading the file to Azure" if ([string]::IsNullOrEmpty($ContentType)) { $ContentType = [System.Web.MimeMapping]::GetMimeMapping($Filepath) # Available since .NET4.5, so it can be used with PowerShell 5.0 and higher. @@ -139,16 +142,7 @@ function Invoke-D365AzureStorageUpload { Write-PSFMessage -Level Verbose -Message "Content Type is automatically set to value: $ContentType" } - Write-PSFMessage -Level Verbose -Message "Start uploading the file to Azure" - - $FileName = Split-Path $Filepath -Leaf - $blockBlob = $blobContainer.GetBlockBlobReference($FileName) - - if (![string]::IsNullOrEmpty($ContentType)) { - $blockBlob.Properties.ContentType = $ContentType - } - - $blockBlob.UploadFromFile($Filepath) + $null = Set-AzStorageBlobContent -Context $storageContext -File $Filepath -Container $($Container.ToLower()) -Properties @{"ContentType" = $ContentType} -Force:$Force if ($DeleteOnUpload) { Remove-Item $Filepath -Force @@ -170,5 +164,5 @@ function Invoke-D365AzureStorageUpload { } } - END {} + END { } } \ No newline at end of file diff --git a/d365fo.tools/xml/d365fo.tools.Format.ps1xml b/d365fo.tools/xml/d365fo.tools.Format.ps1xml index faf8aea4..bac63b4a 100644 --- a/d365fo.tools/xml/d365fo.tools.Format.ps1xml +++ b/d365fo.tools/xml/d365fo.tools.Format.ps1xml @@ -158,9 +158,6 @@ 12 Right - - 9 - 30 @@ -174,9 +171,6 @@ Size - - IsDeleted - LastModified