# Stand-ins for the MARS agent cmdlets. Object shapes follow Get-MarsCollectorDiagnostics.ps1 # output from a real agent (2.0.9274): job times are UTC values with no UTC marking, "not set" is # 1601-01-01, ErrorInfo is always present (ErrorCode 0 = no error), Datasource is an object, and # schedule times are TimeSpans. # # . ./tests/MockMars.ps1 # ./Send-MarsBackupStatus.ps1 -ConfigPath ./my-test-config.json -DryRun # Fixed to the top of the hour, and IDs derived from times, so repeated runs see the same jobs $now = Get-Date -Minute 0 -Second 0 -Millisecond 0 $notSet = [datetime]::new(1601, 1, 1) function New-StableGuid([string]$Seed) { [guid]::new([Security.Cryptography.MD5]::Create().ComputeHash([Text.Encoding]::UTF8.GetBytes($Seed))) } # Local time -> the UTC value MARS reports, with Kind Unspecified like the real objects function ConvertTo-MarsTime([datetime]$Local) { [datetime]::SpecifyKind($Local.ToUniversalTime(), [DateTimeKind]::Unspecified) } function New-MockErrorInfo([int]$Code = 0, $Params = @()) { [pscustomobject]@{ DetailedErrorCode = 0; DetailedErrorSource = $null; ErrorCode = $Code; ErrorParamList = $Params } } function New-MockDatasource($Name, [uint64]$Done, [uint64]$FailedBytes = 0, [uint64]$FailedFiles = 0, $ErrorInfo = (New-MockErrorInfo)) { [pscustomobject]@{ ByteProgress = [pscustomobject]@{ Changed = $Done; Failed = $FailedBytes; Progress = $Done; Total = 2TB } Datasource = [pscustomobject]@{ DataSourceName = $Name; DataSourceId = 6310158806455554328 } ErrorInfo = $ErrorInfo FileProgress = [pscustomobject]@{ Changed = 100; CurrentFile = ''; Failed = $FailedFiles; Progress = 100; Total = 100 } JobState = 'Completed' } } function New-MockJob($Type, [datetime]$Start, $End, $State, $Datasources = @(), $ErrorInfo = (New-MockErrorInfo), $FailedFileLog = '') { $endValue = if ($End) { ConvertTo-MarsTime $End } else { $notSet } [pscustomobject]@{ IsRetried = $false JobId = New-StableGuid "$Type|$($Start.Ticks)" JobType = $Type DisplayTime = $Start # the only local time on the object JobStatus = [pscustomobject]@{ DatasourceStatus = $Datasources EndTime = $endValue ErrorInfo = $ErrorInfo FailedFileLog = $FailedFileLog JobState = $State StartTime = ConvertTo-MarsTime $Start } } } $global:MockMarsRunning = @( (New-MockJob 'Backup' $now.AddMinutes(-10) $null 'InProgress' @((New-MockDatasource 'E:\' 2GB))) ) $global:MockMarsPrevious = @( (New-MockJob 'Backup' $now.AddHours(-12) $now.AddHours(-11.5) 'Completed' @((New-MockDatasource 'E:\' 523407872))), # Completed, but some files failed (New-MockJob 'Backup' $now.AddHours(-36) $now.AddHours(-35) 'Completed' @( (New-MockDatasource 'E:\' 3GB 40MB 12)) -FailedFileLog 'C:\Program Files\Microsoft Azure Recovery Services Agent\Temp\Errors.log'), (New-MockJob 'Backup' $now.AddHours(-30) $now.AddHours(-29.5) 'Failed' @() ` (New-MockErrorInfo 100050 @([pscustomobject]@{ Name = 'Volume'; Value = 'E:' }))), (New-MockJob 'Recovery' $now.AddHours(-5) $now.AddHours(-4) 'Completed'), # a restore: must be ignored (New-MockJob 'Backup' $now.AddDays(-5) $now.AddDays(-5).AddHours(1) 'Completed') # outside 48h lookback ) # Every day at 21:00 local, as on the real server $global:MockMarsSchedule = [pscustomobject]@{ ScheduleRunDays = [DayOfWeek[]](0..6) ScheduleRunTimes = [timespan[]]@([timespan]::FromHours(21)) ScheduleWeeklyFrequency = 1 TypeOfBackupSchedule = 'Daily' } function Get-OBJob { param([int]$Previous) if ($PSBoundParameters.ContainsKey('Previous')) { $global:MockMarsPrevious } else { $global:MockMarsRunning } } function Get-OBPolicy { [pscustomobject]@{ PolicyName = 'policy'; BackupSchedule = $global:MockMarsSchedule } } function Get-OBSchedule { param($Policy) $global:MockMarsSchedule } function Get-OBSystemStatePolicy { $null } # none configured, as on the real server