############# # # Auteur : Hubert Cornet # date : 13 avril 2022 # # description du script : intérroge l'API d'OPCON # ############# # Variable et argment dans le lancement du script Param( [string] $OpScheduleDate = "", [string] $OpJobStatus = "", [string] $OpConUser = "ocadm", [string] $OpConPassword, [string] $ServerUrl = "https://10.78.56.27:443" ) clear # Fonction Function Ignore-SelfSignedCerts { add-type -TypeDefinition @" 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 } # Function Invoke-OpConRestMethod { Param( [ValidateNotNullorEmpty()] [String]$Uri, [ValidateNotNullorEmpty()] [String]$Method, [object]$Body = $null ) If (!$Global:OpconRESTApiUrl -or !$Global:OpconRESTApiAuthHeader) { Write-Warning "No values for Opcon REST Api. Please use Logon-OpConApi before using cmdlet." throw [System.Exception] "Invalid OpCon REST API Values" } $uri = $Global:OpconRESTApiUrl + $Uri Write-Verbose ("Envoi de la requete Web ...") Try { If ($Body -eq $null) { $response = Invoke-RestMethod -Method $Method -Uri $uri -Headers $Global:OpconRESTApiAuthHeader -ErrorVariable $RestException } Else { $Body = ConvertTo-Json $Body -Depth 99 $response = Invoke-RestMethod -Method $Method -Uri $uri -Headers $Global:OpconRESTApiAuthHeader -Body $Body -ContentType 'application/json; charset=utf-8' -ErrorVariable $RestException } Write-Verbose ("`n") Write-Verbose("RESPONSE :") Write-Verbose(ConvertTo-Json $response -Depth 9) return $response } Catch { Write-Warning ("Erreur") Write-Warning ("Status Code : " + $_.Exception.Response.StatusCode.value__) Write-Warning ("Status Description : " + $_.Exception.Response.StatusDescription) $opconApiError = ConvertFrom-Json $_.ErrorDetails.Message Write-Warning ("Erreur Code : " + $opconApiError.code) Write-Warning ("Erreur Message : " + $opconApiError.message) throw ##exit $_.Exception.Response.StatusCode.value__ } } # Function Get-OpConApiToken { [cmdletbinding()] Param( [string] $Url, [string] $User, [string] $Password ) $tokensUri = -join($Url, "/api/tokens") Write-Host ("Recuperation du token autorisation ...") Write-Host ("Api: " + $tokensUri) Write-Host ("Utilisateur: " + $User) $tokenObject = @{ user = @{ loginName = $User password = $Password } tokenType = @{ type = "User" } } Try { Ignore-SelfSignedCerts $token = Invoke-RestMethod -Method Post -Uri $tokensUri -Body (ConvertTo-Json $tokenObject) -ContentType 'application/json; charset=utf-8' -ErrorVariable $RestException } Catch { ## $error = ConvertFrom-Json $RestException.ErrorDetails.Message ##Write-Host ("Unable to fetch token for user '" + $user + "'") ##Write-Host ("Error Code: " + $error.code) ##Write-Host ("Message: " + $error.message) Write-Host ("Status Code : " + $_.Exception.Response.StatusCode.value__) Write-Host ("Status Description : " + $_.Exception.Response.StatusDescription) Write-Host ("Message : " + $_[0].message) ##$Global:OpConRESTAPIException = $_ throw ##exit $_.Exception.Response.StatusCode.value__ } Write-Host ("Token recu avec succes, Id : " + $token.id + ", Valide jusqu a : " + $token.validUntil) return $token } # Function Get-OpConApiAuthHeader { Param( [string] $Token ) $authHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $authHeader.Add("Authorization", ("Token " + $Token)) return $authHeader } # Function Login-RestApi { [cmdletbinding()] Param( [string] $ApiUrl, [string] $OpConUser, [string] $OpConPassword ) Write-Verbose ("Parametres =") Write-Verbose ("ApiUrl: " + $ApiUrl) Write-Verbose ("OpConUser: " + $OpConUser) Write-Verbose ("OpConPassword: (hidden)") $ApiUrl = $ApiUrl.ToLower().TrimEnd("/").TrimEnd("/api") Write-Host ("Connexion a OPCON REST API: " + $ApiUrl) $Global:OpconRESTApiUrl = $ApiUrl $Global:OpconRESTApiUser = $OpConUser $Global:OpConRESTApiPassword = $OpConPassword $token = Get-OpConApiToken -Url $ApiUrl -User $OpConUser -Password $OpConPassword $Global:OpconRESTApiToken = $token.id $Global:OpconRESTApiAuthHeader = Get-OpConApiAuthHeader -Token $token.id Write-Host ('Token stocke avec succes pour de futurs appels dans la session.') } Function HistoryJobDay { [cmdletbinding()] Param( [string] $Dates, [string] $JobName ) $JobDayListFull = New-Object System.Collections.Generic.List[System.Object] Try { #$JobName = "PlanDeProdRéel_C1-60MinutesAprèsMidi_CNT[C1-SS-FR-FluxAX_DHB_AttARV_Prod]|C2-DHB_DAX_DHB_REF_OFR_ART_CFG-STB-DHB" #$JobName = "" #$Dates = "2022-04-20" #$jobNameParam = [System.Web.HttpUtility]::UrlEncode($jobName) $jobUri = -join("/api/jobhistories?uniqueJobIds=$jobName&from=$Dates&to=$Dates") #write-host "1 " $jobUri $uri = $Global:OpconRESTApiUrl + $jobUri #write-host "2 " $uri #$jobdayResponse = Invoke-OpConRestMethod -Uri $jobUri -Method GET -ContentType "application/json"-Headers $Global:OpconRESTApiAuthHeader -ErrorVariable $RestException; $jobdayResponse = Invoke-RestMethod -Method GET -Uri $uri -Headers $Global:OpconRESTApiAuthHeader -ContentType 'application/json' -ErrorVariable $RestException #write-host "3 " $jobdayResponse.id #https://10.78.56.27/api/jobhistories?uniqueJobIds=$JobName&from=$Dates&to=$Dates #https://10.78.56.27/api/jobhistories?uniqueJobIds=PlanDeProdR%C3%A9el_C1-60MinutesApr%C3%A8sMidi_CNT%5BC1-SS-FR-FluxAX_DHB_AttARV_Prod%5D%7CC1-DHB_DAX_DHB_DAX_DHB_CMC_SUV_LIG_CDE_CLI-STB-DHB&from=2022-04-13&to=2022-04-13 #https://10.78.56.27/api/jobhistories?uniqueJobIds=PlanDeProdRéel_C1-60MinutesAprèsMidi_CNT[C1-SS-FR-FluxAX_DHB_AttARV_Prod]|C1-DHB_DAX_DHB_DAX_DHB_CMC_SUV_LIG_CDE_CLI-STB-DHB&from=2022-04-13&to=2022-04-13 #https://10.78.56.27/api/jobhistories?uniqueJobIds=C9-SC-GRP-EXP-ReportingOpcon_C9-ExtractionDesCommandesAvecUneLivraisonEnJPlus1-CNT-EXP[C9-SS-FR-TSM-EXP-ExtractionCommandJPlus1]|C9-ArchiveExtraction-SQL-EXP&from=2022-04-13&to=2022-04-13 If (($jobdayResponse.Length -Ne 1) -And ($jobdayResponse.Length -Ne 0)) { Foreach($JobDay in $JobDayResponse) { #write-host $JobDay #$entry= "$($JobDay.schedule.name) - $($JobDay.id)" $JobDayListFull.Add($JobDay) #$JobDayListFull.Add(@{id = $JobDay.id}) #Write-Host ("Job name : $($JobDay.id)") } $sizeDay = $jobdayResponse.Length; $JobDayListFullsize = $JobDayListFull.Count Write-Host ("Partiel/Total nombre de job recuperer : $sizeDay/$JobDayListFullsize") } } Catch [Exception] { write-host $_ write-host $_.Exception.Message } return, $JobDayListFull } Function GetJobListToUpdateInTrances { [cmdletbinding()] Param( [string] $Status, [string] $Dates, [string] $JobType ) $offset =0; # start from $size=0; # number of jobs retrieved each call $limit=5000; # max number of record x trance $jobListFull = New-Object System.Collections.Generic.List[System.Object] Write-Host ("===> Commence a recuperer des jobs dans la limite de $limit ") Do{ $jobUri = -join("/api/dailyJobs/?dates=$Dates&scheduleIds=$($daily.id)&status=$Status&jobType=$JobType&limit=$limit&offset=$offset") #$jobUri = -join($Url, "/api/dailyJobs/?dates=$Dates&scheduleIds=$($daily.id)&status=$Status&jobType=$JobType&limit=$limit&offset=$offset") #$jobUri = -join($Url, "/api/dailyJobs/?dates=$Dates&scheduleIds=$($daily.id)&jobType=$JobType&limit=$limit&offset=$offset") $jobResponse = Invoke-OpConRestMethod -Uri $jobUri -Method GET -ContentType "application/json"-Headers $Global:OpconRESTApiAuthHeader -ErrorVariable $RestException; #Write-Host ("Job URI : $($jobUri)") Foreach($job in $jobResponse) { #$entry= "$($job.schedule.name) - $($job.id)" $jobListFull.Add($job) #$jobListFull.Add(@{id = $job.id}) #Write-Host ("Job name : $($job.id)") } $size = $jobResponse.Length; $jobListFullsize = $jobListFull.Count Write-Host ("Partiel/Total nombre recuperer : $size/$jobListFullsize") $offset+=$limit; If ($size -lt $limit) { $size = 0; } # If is necessary a delay between calls uncomment and tune the line below # Start-Sleep -s 5 }While ($size -gt 0) If ($jobListFull.Count -gt 0) { Write-host ("Jobs total recuperer : $($jobListFull.Count)") } return, $jobListFull } # Function TryParseDate { [cmdletbinding()] Param( [object] $inDate, [string] $format ) $outDate = "" Try { $outDate =[datetime]::parseexact($($inDate), $($format),$null) } Catch { $outDate = "?" } return $outDate } # Function DisplayDailyJobs { [cmdletbinding()] Param( [string] $Status, [string] $Action, [string] $Dates, [string] $JobType ) [int]$Rows = 0 [int]$RowsOK = 0 [int]$RowsCancelled = 0 [int]$RowsSkipped = 0 [int]$RowsFailed = 0 [int]$RowsRun = 0 [int]$Percentage_Ok = 0 [int]$Percentage_Skipped = 0 [int]$Percentage_Cancelled = 0 [int]$Percentage_Failed = 0 [int]$Percentage_Run = 0 [int]$RowsStartRetard = 0 [int]$RowsEndRetard = 0 #Get job list to update in trances $jobList = GetJobListToUpdateInTrances -Status $Status -Dates $Dates -JobType $JobType #$lst = jobList.chunked(3) [int]$Total = $jobList.Count Foreach($job in $jobList) { [int]$Rows = [int]$Rows + 1 [int]$Pourcentage =[int]$Rows * 100 / [int]$Total Write-Progress -Activity "Analyse du contenu OPCON pour la journée $Dates" -Status "Job : $Rows sur $Total :" -PercentComplete $Pourcentage #$dt = [datetime]::parseexact($($job.schedule.date), 'yyyy-MM-ddTHH:mm:ss.fffffffzzz',$null) $dt = TryParseDate -inDate $job.schedule.date -format 'yyyy-MM-ddTHH:mm:ss.fffffffzzz' $StartTimeProgrammed = TryParseDate -inDate $job.computedStartTime.ProgrammedFor -format 'yyyy-MM-ddTHH:mm:ss.fffffffzzz' $StartTimeTime =TryParseDate -inDate $job.computedStartTime.time -format 'yyyy-MM-ddTHH:mm:ss.fffffffzzz' $StartTimeTimeEstimated = "" If ($job.computedStartTime.isEstimated -contains "True") { $StartTimeTimeEstimated = "*" } $EndTimeProgrammed = TryParseDate -inDate $job.computedEndTime.ProgrammedFor -format 'yyyy-MM-ddTHH:mm:ss.fffffffzzz' $EndTimeTime = TryParseDate -inDate $job.computedEndTime.time -format 'yyyy-MM-ddTHH:mm:ss.fffffffzzz' $EndTimeTimeEstimated = "" If ($job.computedEndTime.isEstimated -contains "True") { $EndTimeTimeEstimated = "*" } $DurationEstimated = "" If ($job.computedDuration.isEstimated -contains "True") { $DurationEstimated = "*" } $DateStr = $dt.ToString("dd/MM/yyyy") $htmlCellStyle = "" If ($job.status.description -Contains "Failed") { $htmlCellStyle = "style='background:#FF0000'" $RowsFailed = $RowsFailed + 1 } ElseIf ($job.status.description -Contains "Skipped") { $htmlCellStyle = "style='background:#F000FF'" $RowsSkipped = $RowsSkipped + 1 } ElseIf ($job.status.description -Contains "Cancelled") { $htmlCellStyle = "style='background:#0017FF'" $RowsCancelled = $RowsCancelled + 1 } ElseIf ($job.status.description -Contains "Job Running") { $htmlCellStyle = "style='background:#000000;color:white'" $RowsRun = $RowsRun + 1 } Else { $RowsOK = $RowsOK + 1 } $htmlCellStyleStartRetard = "" $htmlCellStyleEndRetard = "" If ($job.status.description -NotContains "Skipped") { If ($StartTimeTime -NotContains "?") { $RetardStart = New-TimeSpan -start $StartTimeTime -End $StartTimeProgrammed $RetardEnd = New-TimeSpan -start $EndTimeTime -End $EndTimeProgrammed $htmlCellStyleStartRetard = "" If ($RetardStart.TotalMinutes -lt 0 ) { $htmlCellStyleStartRetard = "style='background:#C3D50F'" } ElseIf ($RetardStart.TotalMinutes -eq 0 ) { $htmlCellStyleStartRetard = "" } ElseIf ($RetardStart.TotalMinutes -gt 0 ) { $htmlCellStyleStartRetard = "style='background:#0FD536'" $RowsStartRetard = $RowsStartRetard + 1 } Else { $htmlCellStyleStartRetard = "" } $htmlCellStyleEndRetard = "" If ($RetardEnd.TotalMinutes -lt 0 ) { $htmlCellStyleEndRetard = "style='background:#C3D50F'" } ElseIf ($RetardEnd.TotalMinutes -eq 0 ) { $htmlCellStyleEndRetard = "" } ElseIf ($RetardEnd.TotalMinutes -gt 0 ) { $htmlCellStyleEndRetard = "style='background:#0FD536'" $RowsEndRetard = $RowsEndRetard + 1 } Else { $htmlCellStyleEndRetard = "" } } } $DataRow = " $($DateStr) $($job.schedule.name) $($job.name) $($job.primaryMachine.name) $($job.jobType.description) $($job.status.description) $($StartTimeProgrammed) $($EndTimeProgrammed) $($StartTimeTime) $($StartTimeTimeEstimated) $($EndTimeTime) $($EndTimeTimeEstimated) $($job.computedDuration.duration/1000/60) $($DurationEstimated) " $FinalData += $DataRow $jobSearch = $job.schedule.name+"|"+$job.name $ListSousJob = HistoryJobDay -Dates $Dates -JobName $jobSearch If ($ListSousJob.Count -ne 0) { Foreach($SousJob in ($ListSousJob|Select -skip 1)) { $SousStartTimeTime =TryParseDate -inDate $SousJob.jobStartTime -format 'yyyy-MM-ddTHH:mm:ss.fffffffzzz' $SousEndTimeTime = TryParseDate -inDate $SousJob.jobTermination -format 'yyyy-MM-ddTHH:mm:ss.fffffffzzz' If ($SousJob.jobstatus.description -Contains "Failed") { $htmlCellStyle = "style='background:#FF0000'" $RowsFailed = $RowsFailed + 1 } ElseIf ($SousJob.jobstatus.description -Contains "Skipped") { $htmlCellStyle = "style='background:#F000FF'" $RowsSkipped = $RowsSkipped + 1 } ElseIf ($SousJob.jobstatus.description -Contains "Cancelled") { $htmlCellStyle = "style='background:#0017FF'" $RowsCancelled = $RowsCancelled + 1 } ElseIf ($SousJob.jobstatus.description -Contains "Job Running") { $htmlCellStyle = "style='background:#000000;color:white'" $RowsRun = $RowsRun + 1 } Else { $RowsOK = $RowsOK + 1 } $DataRow = " $($DateStr) $($job.schedule.name) $($job.name) $($job.primaryMachine.name) $($job.jobType.description) $($SousJob.jobstatus.description) $($StartTimeProgrammed) $($EndTimeProgrammed) $($SousStartTimeTime) $($SousEndTimeTime) $($SousJob.Duration/1000/60) " $FinalData += $DataRow [int]$Rows = [int]$Rows + 1 [int]$Total = [int]$Total + 1 } } } (Get-Content -path HtmlTemplate.html -Raw) -replace 'ROWS_PLACE_HOLDER',$FinalData | Out-File -FilePath Rapport-$OpScheduleDate-tmp-01.html (Get-Content -path Rapport-$OpScheduleDate-tmp-01.html -Raw) -replace 'ROWS_OK_NUMBER',$RowsOK | Out-File -FilePath Rapport-$OpScheduleDate-tmp-02.html (Get-Content -path Rapport-$OpScheduleDate-tmp-02.html -Raw) -replace 'ROWS_SKIPPED_NUMBER',$RowsSkipped | Out-File -FilePath Rapport-$OpScheduleDate-tmp-03.html (Get-Content -path Rapport-$OpScheduleDate-tmp-03.html -Raw) -replace 'ROWS_CANCELLED_NUMBER',$RowsCancelled | Out-File -FilePath Rapport-$OpScheduleDate-tmp-04.html (Get-Content -path Rapport-$OpScheduleDate-tmp-04.html -Raw) -replace 'ROWS_FAILED_NUMBER',$RowsFailed | Out-File -FilePath Rapport-$OpScheduleDate-tmp-05.html (Get-Content -path Rapport-$OpScheduleDate-tmp-05.html -Raw) -replace 'ROWS_RUN_NUMBER',$RowsRun | Out-File -FilePath Rapport-$OpScheduleDate-tmp-06.html (Get-Content -path Rapport-$OpScheduleDate-tmp-06.html -Raw) -replace 'ROWS_NUMBER',$Rows | Out-File -FilePath Rapport-$OpScheduleDate-tmp-07.html $Percentage_Ok = ($RowsOK * 100 ) / $Rows $Percentage_Skipped = ($RowsSkipped * 100 ) / $Rows $Percentage_Cancelled = ($RowsCancelled * 100 ) / $Rows $Percentage_Failed = ($RowsFailed * 100 ) / $Rows $Percentage_Run = ($RowsRun * 100 ) / $Rows (Get-Content -path Rapport-$OpScheduleDate-tmp-07.html -Raw) -replace 'PERCENTAGE_OK_NUMBER',$Percentage_Ok | Out-File -FilePath Rapport-$OpScheduleDate-tmp-08.html (Get-Content -path Rapport-$OpScheduleDate-tmp-08.html -Raw) -replace 'PERCENTAGE_SKIPPED_NUMBER',$Percentage_Skipped | Out-File -FilePath Rapport-$OpScheduleDate-tmp-09.html (Get-Content -path Rapport-$OpScheduleDate-tmp-09.html -Raw) -replace 'PERCENTAGE_CANCELLED_NUMBER',$Percentage_Cancelled | Out-File -FilePath Rapport-$OpScheduleDate-tmp-10.html (Get-Content -path Rapport-$OpScheduleDate-tmp-10.html -Raw) -replace 'PERCENTAGE_FAILED_NUMBER',$Percentage_Failed | Out-File -FilePath Rapport-$OpScheduleDate-tmp-11.html (Get-Content -path Rapport-$OpScheduleDate-tmp-11.html -Raw) -replace 'PERCENTAGE_RUN_NUMBER',$Percentage_Run | Out-File -FilePath Rapport-$OpScheduleDate-tmp-12.html (Get-Content -path Rapport-$OpScheduleDate-tmp-12.html -Raw) -replace 'ROWS_START_Retard',$RowsStartRetard | Out-File -FilePath Rapport-$OpScheduleDate-tmp-13.html (Get-Content -path Rapport-$OpScheduleDate-tmp-13.html -Raw) -replace 'ROWS_END_Retard',$RowsEndRetard | Out-File -FilePath Rapport-$OpScheduleDate.html Remove-Item Rapport-$OpScheduleDate-tmp-*.html -Force -Confirm:$False } # $SecPass = $null; $clearPassword = "" If ($OpConPassword.Length -eq 0 ) { $SecPass = Read-Host 'Quel est le mot de passe ?' -AsSecureString $clearPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto( [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecPass)) } Else { $clearPassword = $OpConPassword } Login-RestApi -ApiUrl $ServerUrl -OpConUser $OpConUser -OpConPassword $clearPassword DisplayDailyJobs -Status $OpJobStatus -Dates $OpScheduleDate -JobType "" Invoke-Item .\Rapport-$OpScheduleDate.html