Skip to content

Commit af79c5c

Browse files
fseldowCopilot
andauthored
feat(windows): add using cache first in DownloadFileWithOras (#8289)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 61250fe commit af79c5c

4 files changed

Lines changed: 122 additions & 3 deletions

File tree

staging/cse/windows/containerdfunc.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,9 @@ function Install-Containerd {
321321

322322
Logs-To-Event -TaskName "AKS.WindowsCSE.DownloadContainerdWithOras" -TaskMessage "Start to download containerd with oras. ContainerdVersionTag: $containerdVersionTag, BootstrapProfileContainerRegistryServer: $global:BootstrapProfileContainerRegistryServer"
323323
$orasReference = "$sanitizedRegistry/aks/packages/containerd/containerd:$containerdVersionTag"
324+
$cachedFileName = Get-FileNameFromUrl -Url $ContainerdUrl
324325
try {
325-
Retry-Command -Command "DownloadFileWithOras" -Args @{Reference=$orasReference; DestinationPath=$tarfile} -Retries 5 -RetryDelaySeconds 10
326+
Retry-Command -Command "DownloadFileWithOras" -Args @{Reference=$orasReference; DestinationPath=$tarfile; CachedFile=$cachedFileName} -Retries 5 -RetryDelaySeconds 10
326327
} catch {
327328
Set-ExitCode -ExitCode $global:WINDOWS_CSE_ERROR_ORAS_PULL_CONTAINERD -ErrorMessage "Exhausted retries for oras pull $orasReference. Error: $_"
328329
}

staging/cse/windows/kubeletfunc.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,9 @@ function Get-KubePackage {
219219
}
220220
Logs-To-Event -TaskName "AKS.WindowsCSE.DownloadKubeletBinariesWithOras" -TaskMessage "Start to download kubelet binaries with oras. KubeBinariesVersion: $global:KubeBinariesVersion, BootstrapProfileContainerRegistryServer: $global:BootstrapProfileContainerRegistryServer"
221221
$orasReference = "$($global:BootstrapProfileContainerRegistryServer)/aks/packages/kubernetes/windowszip:v$($global:KubeBinariesVersion)"
222+
$cachedFileName = Get-FileNameFromUrl -Url $KubeBinariesSASURL
222223
try {
223-
Retry-Command -Command "DownloadFileWithOras" -Args @{Reference=$orasReference; DestinationPath=$zipfile} -Retries 5 -RetryDelaySeconds 10
224+
Retry-Command -Command "DownloadFileWithOras" -Args @{Reference=$orasReference; DestinationPath=$zipfile; CachedFile=$cachedFileName} -Retries 5 -RetryDelaySeconds 10
224225
} catch {
225226
Set-ExitCode -ExitCode $global:WINDOWS_CSE_ERROR_ORAS_PULL_WINDOWSZIP_FAIL -ErrorMessage "Exhausted retries for oras pull $orasReference. Error: $_"
226227
}

staging/cse/windows/networkisolatedclusterfunc.ps1

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,15 +366,43 @@ function Get-BootstrapRegistryDomainName {
366366
return $registryDomainName
367367
}
368368

369+
function Get-FileNameFromUrl {
370+
param(
371+
[Parameter(Mandatory = $true)][string]$Url
372+
)
373+
$cleanUrl = $Url.Split('?')[0]
374+
return [IO.Path]::GetFileName($cleanUrl)
375+
}
376+
369377
function DownloadFileWithOras {
370378
Param(
371379
[Parameter(Mandatory = $true)][string]
372380
$Reference,
373381
[Parameter(Mandatory = $true)][string]
374382
$DestinationPath,
375383
[Parameter(Mandatory = $false)][string]
376-
$Platform = "windows/amd64"
384+
$Platform = "windows/amd64",
385+
[Parameter(Mandatory = $false)][string]
386+
$CachedFile = ""
377387
)
388+
# If CachedFile is provided and exists, copy it to the destination path instead of downloading
389+
# If NetworkIsolatedClusterTestMode is enabled (only in e2e test), skip using cached file to ensure we cover the download logic
390+
if (-not [string]::IsNullOrWhiteSpace($CachedFile) -and (-not $global:NetworkIsolatedClusterTestMode)) {
391+
$fileName = [IO.Path]::GetFileName($CachedFile)
392+
393+
$search = @()
394+
if ($global:CacheDir -and (Test-Path $global:CacheDir)) {
395+
$search = [IO.Directory]::GetFiles($global:CacheDir, $fileName, [IO.SearchOption]::AllDirectories)
396+
}
397+
398+
if ($search.Count -ne 0) {
399+
Write-Log "Using cached version of $fileName - Copying file from $($search[0]) to $DestinationPath"
400+
Copy-Item -Path $search[0] -Destination $DestinationPath -Force
401+
return
402+
}
403+
404+
Write-Log "Cached file $fileName was not found in cache directory '$($global:CacheDir)'. Falling back to oras pull."
405+
}
378406

379407
Write-Log "Downloading $Reference to $DestinationPath via oras pull (platform=$Platform)"
380408

staging/cse/windows/networkisolatedclusterfunc.tests.ps1

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,32 @@ Describe "Get-BootstrapRegistryDomainName" {
383383
}
384384
}
385385

386+
Describe "Get-FileNameFromUrl" {
387+
It "should return file name for url without query string" {
388+
$url = "https://contoso.blob.core.windows.net/packages/windowszip.zip"
389+
390+
Get-FileNameFromUrl -Url $url | Should -Be "windowszip.zip"
391+
}
392+
393+
It "should strip query string before extracting file name" {
394+
$url = "https://contoso.blob.core.windows.net/packages/windowszip.zip?sv=2025-01-01&sig=token"
395+
396+
Get-FileNameFromUrl -Url $url | Should -Be "windowszip.zip"
397+
}
398+
399+
It "should return the last segment for nested paths" {
400+
$url = "https://contoso.blob.core.windows.net/packages/release/v1.30.0/kubernetes-node-image.tar.gz"
401+
402+
Get-FileNameFromUrl -Url $url | Should -Be "kubernetes-node-image.tar.gz"
403+
}
404+
405+
It "should return empty when url ends with slash" {
406+
$url = "https://contoso.blob.core.windows.net/packages/release/v1.30.0/"
407+
408+
Get-FileNameFromUrl -Url $url | Should -Be ""
409+
}
410+
}
411+
386412
Describe "DownloadFileWithOras" {
387413
BeforeEach {
388414
$global:OrasPath = "Mock-OrasCli"
@@ -472,4 +498,67 @@ Describe "DownloadFileWithOras" {
472498

473499
{ DownloadFileWithOras -Reference $reference -DestinationPath $destPath -Platform "linux/amd64" } | Should -Not -Throw
474500
}
501+
502+
It "should copy from cache and skip oras pull when CachedFile is provided" {
503+
$cacheRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
504+
$cacheSubDir = Join-Path $cacheRoot "nested"
505+
$cachedFileName = "windowszip.zip"
506+
$cachedFilePath = Join-Path $cacheSubDir $cachedFileName
507+
$destPath = "c:\k.zip"
508+
$reference = "myregistry.azurecr.io/aks/packages/kubernetes/windowszip:1.29.2"
509+
510+
New-Item -ItemType Directory -Path $cacheSubDir -Force | Out-Null
511+
Set-Content -Path $cachedFilePath -Value "cached-content" -NoNewline
512+
513+
$global:CacheDir = $cacheRoot
514+
$script:orasInvoked = $false
515+
function global:Mock-OrasCli {
516+
param([Parameter(ValueFromRemainingArguments = $true)]$Args)
517+
$script:orasInvoked = $true
518+
$global:LASTEXITCODE = 0
519+
}
520+
521+
Mock Copy-Item -MockWith {}
522+
523+
try {
524+
{ DownloadFileWithOras -Reference $reference -DestinationPath $destPath -CachedFile $cachedFileName } | Should -Not -Throw
525+
Assert-MockCalled -CommandName 'Copy-Item' -Exactly -Times 1 -ParameterFilter {
526+
$Path -eq $cachedFilePath -and $Destination -eq $destPath -and $Force
527+
}
528+
Assert-MockCalled -CommandName 'Move-Item' -Times 0
529+
$script:orasInvoked | Should -Be $false
530+
}
531+
finally {
532+
Remove-Item -Path $cacheRoot -Recurse -Force -ErrorAction SilentlyContinue
533+
$global:CacheDir = "c:\akse-cache"
534+
}
535+
}
536+
537+
It "should invoke oras pull and skip cache copy when CachedFile is provided but missing from cache" {
538+
$cacheRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())
539+
$cachedFileName = "windowszip.zip"
540+
$destPath = "c:\k.zip"
541+
$reference = "myregistry.azurecr.io/aks/packages/kubernetes/windowszip:1.29.2"
542+
543+
New-Item -ItemType Directory -Path $cacheRoot -Force | Out-Null
544+
545+
$global:CacheDir = $cacheRoot
546+
$script:orasInvoked = $false
547+
function global:Mock-OrasCli {
548+
param([Parameter(ValueFromRemainingArguments = $true)]$Args)
549+
$script:orasInvoked = $true
550+
$global:LASTEXITCODE = 0
551+
}
552+
553+
Mock Copy-Item -MockWith {}
554+
555+
try {
556+
{ DownloadFileWithOras -Reference $reference -DestinationPath $destPath -CachedFile $cachedFileName } | Should -Not -Throw
557+
Assert-MockCalled -CommandName 'Copy-Item' -Times 0
558+
$script:orasInvoked | Should -Be $true
559+
}
560+
finally {
561+
Remove-Item -Path $cacheRoot -Recurse -Force -ErrorAction SilentlyContinue
562+
}
563+
}
475564
}

0 commit comments

Comments
 (0)