ResilioConnect.psm1
function ConvertFrom-UnixTime ($unxtime) # internal { $res = (Get-Date 01.01.1970) + ([System.TimeSpan]::fromseconds($unxtime)) return $res } # -------------------------------------------------------------------------------------------------------------------------------- function ConvertTo-UnixTime ([datetime]$time) # internal { $res = [long]((New-TimeSpan -Start (Get-Date "01/01/1970") -End $time).TotalSeconds) return $res } # -------------------------------------------------------------------------------------------------------------------------------- function Initialize-ConnectJobBlob { <# .SYNOPSIS Call this function to start a Resilio Connect job creation .DESCRIPTION This function prepares a blob object which represents all properties for the upcoming job creation. New call will wipe out all the properties already loaded into blob object. All consequent call of Add-*ToBlob keep adding data until you call New-ConnectJobFromBlob function which actually creates Resilio Connect job based on accumulated data. .PARAMETER Name Job name. Can be any. Can be later used to automatically create paths for agents or groups participating in the job. .PARAMETER JobType Specifies type of a job. .PARAMETER Description Description of a job. Optional. .PARAMETER ProfileID ID of the job profile to use. Leave empty to use default job profile. .LINK https://connect.resilio.com/hc/en-us/articles/115001080024-Synchronization-job https://connect.resilio.com/hc/en-us/articles/115001070190-Distribution-job https://connect.resilio.com/hc/en-us/articles/115001070170-Consolidation-Job https://connect.resilio.com/hc/en-us/articles/115001080544-Script-job #> param ( [Parameter(Mandatory = $true)] [string]$Name, [ValidateSet("sync", "script", "distribution", "consolidation")] [Parameter(Mandatory = $true)] [string]$JobType, [string]$Description, [int]$ProfileID ) $script:cjblob = New-Object System.Object $script:cjblob | Add-Member -NotePropertyName "name" -NotePropertyValue $Name $script:cjblob | Add-Member -NotePropertyName "type" -NotePropertyValue $JobType if ($Description) { $script:cjblob | Add-Member -NotePropertyName "description" -NotePropertyValue $Description } if ($ProfileID) { $script:cjblob | Add-Member -NotePropertyName "profile_id" -NotePropertyValue $ProfileID } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Add-GroupToBlob { <# .SYNOPSIS Adds group with paths to send / receive data to job object. .DESCRIPTION Call this function if you want to add a group of agents in the upcoming job creation. Note, that Initialize-ConnectJobBlob must be called before you call this function. This function can be called multiple times for adding more groups. .PARAMETER GroupID Identified of a group to add. Can be piped from Find-Groups call. .PARAMETER Macro Specified path Macro for the group inside this job. Can take values of %FOLDERS_STORAGE%", "%HOME%", "%USERPROFILE%", "%DOWNLOADS%" .PARAMETER WinPath Specifies path for Windows machines in the group. If Macro specified, the path must be relative. .PARAMETER OsxPath Specifies path for OS X machines in the group. If Macro specified, the path must be relative. .PARAMETER LinuxPath Specifies path for Linux machines in the group. If Macro specified, the path must be relative. .PARAMETER AutoPath Forces to set up all paths automatically equal to job name .PARAMETER Permission Specifies access level of that group to the data. Can be "rw, ro, srw, sro". s* values represent selective sync and are only applicable to Sync job type. For distribution and consolidation jobs rw represents source and ro represents destination. .LINK https://connect.resilio.com/hc/en-us/articles/115001069970-Path-Macros #> param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$GroupID, [string]$Macro = "", [string]$WinPath = "", [string]$OsxPath = "", [string]$LinuxPath = "", [switch]$AutoPath, [ValidateSet("ro", "rw", "sro", "srw")] [Parameter(Mandatory = $true)] [string]$Permission ) BEGIN { if ($AutoPath) { $WinPath = $script:cjblob.name $OsxPath = $script:cjblob.name $LinuxPath = $script:cjblob.name } } PROCESS { $group = New-Object System.Object $group | Add-Member -NotePropertyName "id" -NotePropertyValue $GroupID $group | Add-Member -NotePropertyName "permission" -NotePropertyValue $Permission $resiliopath = New-Object System.Object if (![System.String]::IsNullOrEmpty($Macro)) { $resiliopath | Add-Member -NotePropertyName "macro" -NotePropertyValue $Macro } $resiliopath | Add-Member -NotePropertyName "win" -NotePropertyValue $WinPath $resiliopath | Add-Member -NotePropertyName "osx" -NotePropertyValue $OsxPath $resiliopath | Add-Member -NotePropertyName "linux" -NotePropertyValue $LinuxPath $group | Add-Member -NotePropertyName "path" -NotePropertyValue $resiliopath if (!$script:cjblob.groups) { $groups = @() $groups += $group $script:cjblob | Add-Member -NotePropertyName "groups" -NotePropertyValue $groups } else { $script:cjblob.groups += $group } } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Add-AgentToBlob { <# .SYNOPSIS Adds agent with paths to send / receive data to job object. .DESCRIPTION Call this function if you want to add an agent in the upcoming job creation. Note, that Initialize-ConnectJobBlob must be called before you call this function. This function can be called multiple times for adding more agents. .PARAMETER AgentID Identifies an agent to add. Can be piped from Find-Agents call. .PARAMETER Macro Specified path Macro for the agent inside this job. Can take values of %FOLDERS_STORAGE%", "%HOME%", "%USERPROFILE%", "%DOWNLOADS%" .PARAMETER WinPath Specifies path for the agent if it is Windows machine. If Macro specified, the path must be relative. .PARAMETER OsxPath Specifies path for the agent if it is OS X machine. If Macro specified, the path must be relative. .PARAMETER LinuxPath Specifies path for the agent if it is Linux machine. If Macro specified, the path must be relative. .PARAMETER AutoPath Forces to set up all paths automatically equal to job name .PARAMETER Permission Specifies access level of that agent to the data. Can be "rw, ro, srw, sro". s* values represent selective sync and are only applicable to Sync job type. For distribution and consolidation jobs rw represents source and ro represents destination. .LINK https://connect.resilio.com/hc/en-us/articles/115001069970-Path-Macros #> param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$AgentID, [string]$Macro = "", [string]$WinPath = "", [string]$OsxPath = "", [string]$LinuxPath = "", [switch]$AutoPath, [ValidateSet("ro", "rw", "sro", "srw")] [Parameter(Mandatory = $true)] [string]$Permission ) BEGIN { if ($AutoPath) { $WinPath = $script:cjblob.name $OsxPath = $script:cjblob.name $LinuxPath = $script:cjblob.name } } PROCESS { $agent = New-Object System.Object $agent | Add-Member -NotePropertyName "id" -NotePropertyValue $AgentID $agent | Add-Member -NotePropertyName "permission" -NotePropertyValue $Permission $resiliopath = New-Object System.Object if (![System.String]::IsNullOrEmpty($Macro)) { $resiliopath | Add-Member -NotePropertyName "macro" -NotePropertyValue $Macro } $resiliopath | Add-Member -NotePropertyName "win" -NotePropertyValue $WinPath $resiliopath | Add-Member -NotePropertyName "osx" -NotePropertyValue $OsxPath $resiliopath | Add-Member -NotePropertyName "linux" -NotePropertyValue $LinuxPath $agent | Add-Member -NotePropertyName "path" -NotePropertyValue $resiliopath if (!$script:cjblob.agents) { $agents = @() $agents += $agent $script:cjblob | Add-Member -NotePropertyName "agents" -NotePropertyValue $agents } else { $script:cjblob.agents += $agent } } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Add-ScriptToBlob { <# .SYNOPSIS Adds triggers to the distribution and consolidation job or script to the script job. .DESCRIPTION Call this function if you want to add a trigger to the distribution or consolidation job. Also use it if you need to set a script for the scrip job. Note, that Initialize-ConnectJobBlob must be called before you call this function. Function pushes required script inside the job object, which is used later in New-ConnectJobFromBlob call. Function can be called multiple times to add scripts for different operating systems or different trigger conditions. .PARAMETER OS Specified which OS the script you are adding is targeted for. .PARAMETER ScriptBody Script itself. Can be multi-line string. .PARAMETER ShellPath. Path to the shell to execute script. Don't specify for standard shell. .PARAMETER ScriptFileExtension Extension for the script temp file. Don't specify for standard shell. .PARAMETER ScriptType Set this parameter to "scriptjob" if the script you are adding is a script for script job. Set to "pre_indexing", "post_download" or "complete" if the script is actually a trigger for distribution or consolidation job. .PARAMETER Powershell Set this switch if your script is a powershell script for Windows. This will automatically set proper values for ShellPath and ScriptFileExtension #> param ( [ValidateSet("linux", "win", "osx")] [Parameter(Mandatory = $true)] [string]$OS, [Parameter(Mandatory = $true)] [string]$ScriptBody, [string]$ShellPath, [string]$ScriptFileExtension, [ValidateSet("pre_indexing", "post_download", "complete", "scriptjob")] [Parameter(Mandatory = $true)] [string]$ScriptType, [switch]$PowerShell ) if ($PowerShell -and $OS -eq "win") { $ShellPath = "powershell -NoProfile -ExecutionPolicy Bypass -NonInteractive -InputFormat None -File" $ScriptFileExtension = "ps1" } $scriptprops = New-Object System.Object $scriptprops | Add-Member -NotePropertyName "script" -NotePropertyValue "$ScriptBody" if (![System.String]::IsNullOrEmpty($ShellPath)) { $scriptprops | Add-Member -NotePropertyName "shell" -NotePropertyValue "$ShellPath" } if (![System.String]::IsNullOrEmpty($ScriptFileExtension)) { $scriptprops | Add-Member -NotePropertyName "ext" -NotePropertyValue "$ScriptFileExtension" } if ($ScriptType -eq "scriptjob") # Add script for scripjob here { if (!$script:cjblob.script) { $scriptobj = New-Object System.Object $script:cjblob | Add-Member -NotePropertyName "script" -NotePropertyValue $scriptobj } $script:cjblob.script | Add-Member -NotePropertyName $OS -NotePropertyValue $scriptprops -Force return } # If this is not a scripjob, add it to proper "triggers" section if (!$script:cjblob.triggers) { $scriptobj = New-Object System.Object $script:cjblob | Add-Member -NotePropertyName "triggers" -NotePropertyValue $scriptobj } if (!$script:cjblob.triggers."$ScriptType") { $scriptobj = New-Object System.Object $script:cjblob.triggers | Add-Member -NotePropertyName "$ScriptType" -NotePropertyValue $scriptobj } $script:cjblob.triggers."$ScriptType" | Add-Member -NotePropertyName $OS -NotePropertyValue $scriptprops -Force } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Add-SchedulerToBlob { <# .SYNOPSIS Use this function to add scheduler to the object representing job .DESCRIPTION This function allows set up scheduler in the object representing job. Scheduler can be very flexible therefore there are many ways to run this function. Every run discards previous scheduler from the job object and replaces it with a new one. Note, that Initialize-ConnectJobBlob must be called before you call this function. Actual scheduler type depends on the parameters you use call it with. .PARAMETER EveryXMinutes Creates a scheduler to run job every X amount of minutes. .PARAMETER EveryXHours Creates a scheduler to run job every X amount of hours. .PARAMETER EveryXDays Creates a scheduler to run job every X amount of days. Must be used together with EveryXDaysAt to specify job run time. .PARAMETER EveryXDaysAt Specifies a time to run a job. Must be used together with EveryXDays to specify period of job startup. .PARAMETER WeeklyOnDays Creates a scheduler to run job on selected days of the week. Must be used together with WeeklyAtTimes. This parameter must be an array of integer, where each number represents a day of week starting from zero representing Sunday, one representing Monday, etc. .PARAMETER WeeklyAtTimes Specifies a time to run job. Must be used together with WeeklyOnDays. This parameter must be array of DateTime (or strings convertable to DateTime) where each entry represents a time to start a job on a day chosen with WeeklyOnDays. .PARAMETER StartOn Optional. Specifies a time when scheduler becomes active. .PARAMETER StopOn Optional. Specifies a time when scheduler stops working. .PARAMETER SkipIfRunning Set parameter to prevent scheduler re-starting the job when a new time to start comes and the previous run is still going. .EXAMPLE Add-SchedulerToBlob -EveryXDays 10 -EveryXDaysAt "10:00" Sets up scheduler to run job every 10 days at 10:00 .EXAMPLE Add-SchedulerToBlob -EveryXMinutes 30 -StartOn "2019-09-16" -StopOn "2019-09-30 23:59" Sets up scheduler to run job every 30 minutes, effective from Sep 16 2019 to end of September same year .EXAMPLE Add-SchedulerToBlob -OnceAt "2019-09-17 15:13" Sets up scheduler to run job only once on 2019-09-17 at 15:13 .EXAMPLE Add-SchedulerToBlob -WeeklyOnDays (0, 2, 3) -WeeklyAtTimes ("9:00", "15:00") -SkipIfRunning Sets up scheduler to run job every Sunday, Tuesday, Wednesdat at 9:00 and 15:00 and also not to spawn new job run if previous one is still going .LINK https://connect.resilio.com/hc/en-us/articles/115001070190-Distribution-job https://connect.resilio.com/hc/en-us/articles/115001070170-Consolidation-Job https://connect.resilio.com/hc/en-us/articles/115001080544-Script-job #> param ( [Parameter(ParameterSetName = "EveryXMinutes")] [int]$EveryXMinutes, [Parameter(ParameterSetName = "EveryXHours")] [int]$EveryXHours, [Parameter(ParameterSetName = "EveryXDays")] [int]$EveryXDays, [Parameter(ParameterSetName = "EveryXDays")] [datetime]$EveryXDaysAt, [Parameter(ParameterSetName = "OnceAt")] [datetime]$OnceAt, [Parameter(ParameterSetName = "Weekly")] [array]$WeeklyOnDays, [Parameter(ParameterSetName = "Weekly")] [array]$WeeklyAtTimes, [Parameter(ParameterSetName = "EveryXMinutes")] [Parameter(ParameterSetName = "EveryXHours")] [Parameter(ParameterSetName = "EveryXDays")] [Parameter(ParameterSetName = "Weekly")] [datetime]$StartOn, [Parameter(ParameterSetName = "EveryXMinutes")] [Parameter(ParameterSetName = "EveryXHours")] [Parameter(ParameterSetName = "EveryXDays")] [Parameter(ParameterSetName = "Weekly")] [datetime]$StopOn, [Parameter(ParameterSetName = "EveryXMinutes")] [Parameter(ParameterSetName = "EveryXHours")] [Parameter(ParameterSetName = "EveryXDays")] [Parameter(ParameterSetName = "Weekly")] [switch]$SkipIfRunning ) $schdobj = New-Object System.Object if ($SkipIfRunning) { $schdobj | Add-Member -NotePropertyName "skip_if_running" -NotePropertyValue $true } if ($StartOn) { $schdobj | Add-Member -NotePropertyName "start" -NotePropertyValue (ConvertTo-UnixTime $StartOn) } if ($StopOn) { $schdobj | Add-Member -NotePropertyName "finish" -NotePropertyValue (ConvertTo-UnixTime $StopOn) } if ($EveryXMinutes) { $schdobj | Add-Member -NotePropertyName "type" -NotePropertyValue "minutes" $schdobj | Add-Member -NotePropertyName "every" -NotePropertyValue $EveryXMinutes $script:cjblob | Add-Member -NotePropertyName "scheduler" -NotePropertyValue $schdobj -Force return } if ($EveryXHours) { $schdobj | Add-Member -NotePropertyName "type" -NotePropertyValue "hourly" $schdobj | Add-Member -NotePropertyName "every" -NotePropertyValue $EveryXHours $script:cjblob | Add-Member -NotePropertyName "scheduler" -NotePropertyValue $schdobj -Force return } if ($EveryXDays) { $datesec = $EveryXDaysAt.Hour*3600 + $EveryXDaysAt.Minute*60 + $EveryXDaysAt.Second $schdobj | Add-Member -NotePropertyName "type" -NotePropertyValue "daily" $schdobj | Add-Member -NotePropertyName "every" -NotePropertyValue $EveryXDays $schdobj | Add-Member -NotePropertyName "time" -NotePropertyValue $datesec $script:cjblob | Add-Member -NotePropertyName "scheduler" -NotePropertyValue $schdobj -Force return } if ($OnceAt) { $schdobj | Add-Member -NotePropertyName "type" -NotePropertyValue "once" $schdobj | Add-Member -NotePropertyName "time" -NotePropertyValue ConvertTo-UnixTime($OnceAt) $script:cjblob | Add-Member -NotePropertyName "scheduler" -NotePropertyValue $schdobj -Force return } if ($WeeklyOnDays) { $timesArray = @() foreach ($TimeStr in $WeeklyAtTimes) { $Time = [datetime]$TimeStr $TimeInSec = $Time.Hour * 3600 + $Time.Minute * 60 + $Time.Second $timesArray += $TimeInSec } $schdobj | Add-Member -NotePropertyName "type" -NotePropertyValue "weekly" $schdobj | Add-Member -NotePropertyName "days" -NotePropertyValue $WeeklyOnDays $schdobj | Add-Member -NotePropertyName "time" -NotePropertyValue $timesArray $script:cjblob | Add-Member -NotePropertyName "scheduler" -NotePropertyValue $schdobj -Force return } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function New-ConnectJobFromBlob { <# .SYNOPSIS Call this function to create new job. Ensure to initilize and push necessary data to a blob. .DESCRIPTION This function is intended to create a new Resilio Connect job. Before calling this function ensure to also call: - InitializeConnectJobBlob to give job a name and type - AddAgentToBlob or AddGroupToBlob to assign some agents to the job .EXAMPLE PS> Initialize-ConnectJobBlob -Name "_Cadabra Test" -JobType "distribution" PS> Add-AgentToBlob -AgentID 145 -WinPath "C:\MyTestData" -Permission rw PS> Add-GroupToBlob -GroupID 8 -Macro "%DOWNLOADS%" -AutoPath -Permission ro PS> Add-SchedulerToBlob -EveryXMinutes 30 -StartOn "2019-09-16" -StopOn "2019-09-30 23:59" PS> New-ConnectJobFromBlob This set of calls will cause Management Console to create a new job with Agent 145 as a source, Group with ID 8 as a destination .LINK https://www.resilio.com/api/documentation/#api-Jobs-CreateJob #> $json = ($script:cjblob | ConvertTo-Json -Depth 10) Write-Host $json Invoke-ConnectFunction -Method POST -RestPath "jobs" -JSON $json -ErrorAction Stop } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Remove-AgentFromJobRun { <# .SYNOPSIS Function intended to remove agent(s) from ongoing job runs .DESCRIPTION Use the function to remove agent(s) from ongoing job runs .PARAMETER JobRunID Set to specify which job run you want to modify .PARAMETER AgentID Specify AgentID to remove from job run. This parameter can be piped and accept multiple agent IDs .LINK https://www.resilio.com/api/documentation/#api-Runs-StopRunOnAgents #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [int]$JobRunID, [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$AgentID ) BEGIN { $agentlist = @() } PROCESS { $agentlist += $AgentID } END { $json = ConvertTo-Json $agentlist Invoke-ConnectFunction -Method PUT -RestPath "runs/$JobRunID/agents/stop" -JSON $json -ErrorAction Stop } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Add-AgentToJobRun { <# .SYNOPSIS Function intended to add agent(s) to ongoing job runs .DESCRIPTION Use the function to add agent(s) to ongoing job runs .PARAMETER JobRunID Set to specify which job run you want agents to join .PARAMETER AgentID Set as a single int or array of ints (if you want to add many agents) to specify which agents you want to run to the job run. .PARAMETER Macro Specify macro preceding the path for job data .PARAMETER WinPath Specify path for windows machines being added to the job run .PARAMETER OSXPath Specify path for OS X machines being added to the job run .PARAMETER LinuxPath Specify path for Linux machines being added to the job run .OUTPUTS The function returns OK or throws exception #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [int]$JobRunID, [Parameter(Mandatory = $true, ValueFromPipeline=$true)] [int]$AgentID, [string]$Macro = "", [string]$WinPath = "", [string]$OsxPath = "", [string]$LinuxPath = "", [switch]$AutoPath ) BEGIN { $JobRun = Find-ConnectJobRuns -JobRunID $JobRunID -ActiveOnly -ReturnObject if ($AutoPath) { $WinPath = $JobRun.name $OsxPath = $JobRun.name $LinuxPath = $JobRun.name } if (!$JobRun) { throw "Job run with ID $JobRunID not found" } $jsonobj = @() $runs = 0 } PROCESS { $agentobj = New-Object System.Object $agentobj | Add-Member -NotePropertyName "id" -NotePropertyValue $AgentID $pathobj = New-Object System.Object if ($Macro) { $pathobj | Add-Member -NotePropertyName "macro" -NotePropertyValue $macro } $pathobj | Add-Member -NotePropertyName "win" -NotePropertyValue $winpath $pathobj | Add-Member -NotePropertyName "osx" -NotePropertyValue $osxpath $pathobj | Add-Member -NotePropertyName "linux" -NotePropertyValue $linuxpath $agentobj | Add-Member -NotePropertyName "path" -NotePropertyValue $pathobj $jsonobj += $agentobj $runs++ } END { $json = $jsonobj | ConvertTo-Json if ($runs -eq 1) { $json = "[$json]" } Invoke-ConnectFunction -Method POST -RestPath "runs/$JobRunID/agents" -JSON $json -ErrorAction Stop } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Invoke-ConnectFunction { <# .SYNOPSIS Function intended to call a generic rest function of MC .DESCRIPTION Use the function to call any other non-implemented function of MC Console API .PARAMETER RestPath Specifies route for the API call (appended to base_url specified in Initialize-ResilioMCConnection .PARAMETER Method Specify the REST method .PARAMETER JSON Specify JSON of the content (or leave empty if none) .OUTPUTS The function returns the body of message returned by MC server #> [CmdletBinding()] param ( [string]$RestPath, [string]$Method, [string]$JSON ) try { if (!$JSON) { $response = Invoke-RestMethod -Method $Method -uri "$base_url/$RestPath" -Headers @{ "Authorization" = "Token $API_token" } -ContentType "Application/json" } else { $response = Invoke-RestMethod -Method $Method -uri "$base_url/$RestPath" -Headers @{ "Authorization" = "Token $API_token" } -ContentType "Application/json" -Body:$JSON } } catch [System.Net.WebException] { Write-Debug "WebException fulltext is: $_" if ($_.Exception.Response.StatusCode.value__) { $errortext = "Error code: $($_.Exception.Response.StatusCode.value__)" $result = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($result) $reader.BaseStream.Position = 0 $reader.DiscardBufferedData() $responseBody = $reader.ReadToEnd(); $errortext = "$errortext ; Response body is: $responseBody" $errorcat = "InvalidData" $response = $responseBody } else { $errortext = $_.Exception.Status $errorcat = "ConnectionError" } #$PSCmdlet.WriteError($errortext) #to reset a $? var to false Write-Error -Message $errortext -Category $errorcat -TargetObject $_ #return $responseBody #throw $_ } catch { throw "Some unknown error happened while performing REST request" } return $response } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Find-ConnectJobRuns { <# .SYNOPSIS Function intended to get list of job runs matching the filter .DESCRIPTION Use the function to get list of job run IDs or job run objects matching the job id or job name .PARAMETER JobID Specifies id of the job to filter our job runs .PARAMETER JobName Specifies the job name to filter our job runs .PARAMETER OnlyOne Will force to throw exception if more than one job run matches the filter. .PARAMETER ActiveOnly Forces to only find ongoing job runs .PARAMETER ReturnObject Forces function to return job run object(s) instead of id(s) .OUTPUTS The funtion will throw exception if fails by any reason. Otherwise returns an array of job IDs. .LINK https://www.resilio.com/api/documentation/#api-Runs-GetRuns #> [CmdletBinding()] param ( [Parameter(ParameterSetName = "ByJobID", Mandatory = $true)] [Parameter(ParameterSetName = "ByJobRunID")] [Parameter(ParameterSetName = "ByName")] [int]$JobID = -1, [SupportsWildcards()] [Parameter(ParameterSetName = "ByJobID")] [Parameter(ParameterSetName = "ByJobRunID")] [Parameter(ParameterSetName = "ByName", Mandatory = $true)] [string]$JobName, [Parameter(ParameterSetName = "ByJobID")] [Parameter(ParameterSetName = "ByJobRunID", Mandatory = $true)] [Parameter(ParameterSetName = "ByName")] [int]$JobRunID = -1, [switch]$OnlyOne, [switch]$ActiveOnly, [switch]$ReturnObject ) if ($JobRunID -ne -1) { $units = Invoke-ConnectFunction -Method GET -RestPath "runs/$JobRunID" -ErrorAction Stop if ($ActiveOnly -and $units.status -ne 'working') { $units = @() } return $units } $units = Get-ConnectJobRuns if ($JobID -eq -1) { $searchfield = "name" $searchvalue = $JobName } else { $searchfield = "job_id" $searchvalue = $JobID } if ($ActiveOnly) { $matching_jobruns = Find-ConnectObjects -ObjectList $units -FieldName $searchfield -FieldValue $searchvalue -ReturnObject return Find-ConnectObjects -ObjectList $matching_jobruns -FieldName "active" -FieldValue "True" -OnlyOne:$OnlyOne -ReturnObject:$ReturnObject } else { return Find-ConnectObjects -ObjectList $units -FieldName $searchfield -FieldValue $searchvalue -OnlyOne:$OnlyOne -ReturnObject:$ReturnObject } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Get-ConnectJobRuns { [CmdletBinding()] param () $offset = 0 $pagelimit = 100 $jobruns = @() $jobrunspage = Invoke-ConnectFunction -Method GET -RestPath "runs?offset=$offset&limit=$pagelimit" -ErrorAction Stop while ($jobrunspage.data.length -gt 0) { $jobruns += $jobrunspage.data $offset += $pagelimit $jobrunspage = Invoke-ConnectFunction -Method GET -RestPath "runs?offset=$offset&limit=$pagelimit" -ErrorAction Stop } return $jobruns } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Get-ConnectJobStatusForAgent { <# .SYNOPSIS Function intended to return an agent status for particular job .DESCRIPTION Use the function to know current status of the agent participating in chosen job. .PARAMETER JobID Specifies identifier of Job. .PARAMETER AgentID Specifies identifier of Agent to query. .OUTPUTS The funtion will throw exception if fails by any reason, or the object if succeeds .LINK https://www.resilio.com/api/documentation/#api-Jobs-JobAgent #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [int]$JobID, [Parameter(Mandatory = $true)] [int]$AgentID ) $status = Invoke-ConnectFunction -Method GET -RestPath "/jobs/$JobID/agents/$AgentID" -ErrorVariable myerr if ($myerr.Exception.Response.StatusCode.value__) { if ($myerr.Exception.Response.StatusCode.value__ -eq 404) { $status = @{ } $status['status'] = "aborted" return $status } throw $myerr } return $status } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Get-Agents { <# .SYNOPSIS Function intended to return a list of agents .DESCRIPTION Use the function to get full list of Agents Management Console knows of. .OUTPUTS The funtion will throw exception if fails by any reason, or the object if succeeds .LINK https://www.resilio.com/api/documentation/#api-Agents-GetAgents #> [CmdletBinding()] param () return Invoke-ConnectFunction -Method GET -RestPath "agents" -ErrorAction Stop } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Get-Groups { <# .SYNOPSIS Function intended to return a list of groups .DESCRIPTION Use the function to get full list of Groups Management Console knows of. .OUTPUTS The funtion will throw exception if fails by any reason, or the object if succeeds .LINK https://www.resilio.com/api/documentation/#api-Groups-GetGroups #> [CmdletBinding()] param () return Invoke-ConnectFunction -Method GET -RestPath "groups" -ErrorAction Stop } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Get-ConnectJobs { <# .SYNOPSIS Function intended to return a list of jobs .DESCRIPTION Use the function to get full list of jobs Management Console knows of. .OUTPUTS The funtion will throw exception if fails by any reason, or the object if succeeds .LINK https://www.resilio.com/api/documentation/#api-Groups-GetGroups #> [CmdletBinding()] param () return Invoke-ConnectFunction -Method GET -RestPath "jobs" -ErrorAction Stop } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Set-AgentsToGroup { <# .SYNOPSIS Function intended to assign a list of agents to a group .DESCRIPTION Use the function to set a new list of agents to the group. New list overwrites the existing one .PARAMETER GroupID GroupID specifies the ID of a group to be changed .PARAMETER AgentsID AgentsID can be single agent ID or array of agents IDs to be assigned to a group. .OUTPUTS The funtion will throw exception if fails by any reason, or exit if succeeds. .LINK https://www.resilio.com/api/documentation/#api-Groups-UpdateGroup #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [int]$GroupID, [Parameter(Mandatory = $true)] $AgentsID ) $agentslist = @() foreach ($agent_id in $AgentsID) { $item = "`{`"id`":$agent_id`}" $agentslist += $item } $json = "{`"agents`":[$($agentslist -join ",")]}" Invoke-ConnectFunction -Method PUT -RestPath "groups/$GroupID" -JSON $json -ErrorAction Stop } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Add-AgentTag { <# .SYNOPSIS Function adds specified tag + value pair to one or many agents .DESCRIPTION Use this function to update agent's tags. If tag already exists, it just updates the value. If it does not exit, then it's added. Function can be called with array of agent IDs to add a tag to many agents with a single call. .PARAMETER AgentID Specify an agent ID or an array of agent IDs to get tag added to .PARAMETER Name Specify tag name. Only use latin and underscore symbols .PARAMETER Value Specify new / updated tag value. .LINK https://connect.resilio.com/hc/en-us/articles/115001069730-Using-Agent-Tags .LINK https://www.resilio.com/api/documentation/#api-Agents-UpdateAgent #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$AgentID, [Parameter(Mandatory = $true)] [string]$Name, [string]$Value ) PROCESS { $agenttags = (Find-Agents -AgentID $AgentID).tags $foundtags = $agenttags | Where-Object name -EQ $Name if ($foundtags) { $foundtags.value = $Value } else { $tmp = New-Object System.Object $tmp | Add-Member -NotePropertyName "name" -NotePropertyValue $Name $tmp | Add-Member -NotePropertyName "value" -NotePropertyValue $Value $agenttags += $tmp } $json = $agenttags | ConvertTo-Json $json = "{`"tags`":$json}" Invoke-ConnectFunction -Method PUT -RestPath "agents/$AgentID" -JSON $json -ErrorAction Stop } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Add-AgentToGroup { <# .SYNOPSIS Function intended to add a list of agents to a group .DESCRIPTION Use the function to add new agent(s) to the group. New list adds to the agents already in the group .PARAMETER GroupID GroupID specifies the ID of a group to be changed .PARAMETER AgentID AgentsID can be single agent ID or array of agents IDs to be assigned to a group. .OUTPUTS The funtion will throw exception if fails by any reason, or exit if succeeds. .LINK https://www.resilio.com/api/documentation/#api-Groups-UpdateGroup #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [int]$GroupID, [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $AgentID ) BEGIN { $group = Find-Groups -GroupID $GroupID $agentslist = @() foreach ($agent_id in $group.agents) { $item = "`{`"id`":$($agent_id.id)`}" $agentslist += $item } } PROCESS { $item = "`{`"id`":$AgentID`}" $agentslist += $item } END { $json = "{`"agents`":[$($agentslist -join ",")]}" Invoke-ConnectFunction -Method PUT -RestPath "groups/$GroupID" -JSON $json -ErrorAction Stop } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Remove-AgentFromGroup { <# .SYNOPSIS Function intended to remove a list of agents from the group .DESCRIPTION Use the function to remove agents from the group. The absense of the agent in a group will not cause an error. .PARAMETER GroupID GroupID specifies the ID of a group to be changed .PARAMETER AgentID AgentsID can be single agent ID or array of agents IDs to be removed from the group. .OUTPUTS The funtion will throw exception if fails by any reason, or exit if succeeds. .LINK https://www.resilio.com/api/documentation/#api-Groups-UpdateGroup #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [int]$GroupID, [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$AgentID ) BEGIN { $group = Find-Groups -GroupID $GroupID $agentslist = New-Object System.Collections.ArrayList $agentsstringlist = @() foreach ($agent_id in $group.agents) #Build the arraylist of existing agents { $agentslist.Add($agent_id.id) } } PROCESS { $agentslist.Remove($AgentID) # Then remove all of the necessray agents from there } END { foreach ($agent_id in $agentslist) #build a list to be merged in a single json { $item = "`{`"id`":$($agent_id)`}" $agentsstringlist += $item } $json = "{`"agents`":[$($agentsstringlist -join ",")]}" Invoke-ConnectFunction -Method PUT -RestPath "groups/$GroupID" -JSON $json -ErrorAction Stop } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Find-ConnectObjects # got used to be internal function { param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $ObjectList, [string]$FieldName='name', [string]$FieldValue, [switch]$ReturnObject, [switch]$OnlyOne ) $matching_units = @() foreach ($unit in $ObjectList) { if ($unit."$FieldName" -like $FieldValue) { if ($ReturnObject) { $matching_units += $unit } else { $matching_units += $unit.id } } } if ($OnlyOne.IsPresent) { if ($matching_units.Length -eq 0) { throw "No objects found, must be one" } if ($matching_units.Length -gt 1) { throw "Several objects found, must be one" } return $matching_units[0] } return $matching_units } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Find-Groups { <# .SYNOPSIS Function intended to get list of groups matching the GroupName filter .DESCRIPTION Use the function to get list of group ids matching the GroupName parameter .PARAMETER GroupName Specifies the filter for groups to be found. Ignored if GroupID is specified. .PARAMETER GroupID Specifies ID of the group to be found .PARAMETER OnlyOne Will force to throw exception if more than one group matches the filter. .OUTPUTS The funtion will throw exception if fails by any reason. Otherwise returns an array of group IDs. .LINK https://www.resilio.com/api/documentation/#api-Groups-GetGroups #> [CmdletBinding()] param ( [SupportsWildcards()] [string]$GroupName, [int]$GroupID = -1, [switch]$OnlyOne, [switch]$ReturnObject ) if ($GroupID -eq -1) { $units = Get-Groups return Find-ConnectObjects -ObjectList $units -FieldValue $GroupName -OnlyOne:$OnlyOne -ReturnObject:$ReturnObject } else { return Invoke-ConnectFunction -Method GET -RestPath "groups/$GroupID" -ErrorAction Stop } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Find-Agents { <# .SYNOPSIS Function intended to get list of agents matching the name filter .DESCRIPTION Use the function to get list of agent IDs matching the AgentName parameter .PARAMETER AgentName Specifies the filter for agents to be found. Parameter ignored if AgentID specified. .PARAMETER AgentID Specifies the Agent ID to be found .PARAMETER OnlyOne Will force to throw exception if more than one agent matches the filter. .OUTPUTS The funtion will throw exception if fails by any reason. Otherwise returns an array of agent IDs. .LINK https://www.resilio.com/api/documentation/#api-Agents-GetAgents #> [CmdletBinding()] param ( [SupportsWildcards()] [string]$AgentName, [int]$AgentID = -1, [switch]$OnlyOne, [switch]$ReturnObject ) if ($AgentID -eq -1) { $units = Get-Agents return Find-ConnectObjects -ObjectList $units -FieldValue $AgentName -OnlyOne:$OnlyOne -ReturnObject:$ReturnObject } else { return Invoke-ConnectFunction -Method GET -RestPath "agents/$AgentID" -ErrorAction Stop } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Find-ConnectJobs { <# .SYNOPSIS Function intended to get list of jobs matching the name filter .DESCRIPTION Use the function to get list of job IDs matching the AgentName parameter .PARAMETER JobName Specifies the filter for agents to be found .PARAMETER OnlyOne Will force to throw exception if more than one job matches the filter. .OUTPUTS The funtion will throw exception if fails by any reason. Otherwise returns an array of job IDs. .LINK https://www.resilio.com/api/documentation/#api-Agents-GetAgents #> [CmdletBinding()] param ( [SupportsWildcards()] [string]$JobName, [int]$JobID = -1, [switch]$OnlyOne, [switch]$ReturnObject ) if ($JobID -ne -1) { return Invoke-ConnectFunction -Method GET -RestPath "jobs/$JobID" } $units = Get-ConnectJobs return Find-ConnectObjects -ObjectList $units -FieldValue $JobName -OnlyOne:$OnlyOne -ReturnObject:$ReturnObject } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Start-ConnectJob { <# .SYNOPSIS Function intended to start job(s) .DESCRIPTION Use the function to start job by ID or by name. When name is used, it can start single job or multiple ones .PARAMETER JobName Specifies the filter for jobs to be started .PARAMETER JobID Specifies the ID of a job to be started. Can be piped for multiple jobs .PARAMETER Agents Optional parameter. Allows to run job only on selected agent(s) .OUTPUTS The funtion will throw exception if fails by any reason. No return value. .LINK https://www.resilio.com/api/documentation/#api-Runs-CreateRun #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$JobID, [array]$AgentID ) PROCESS { if ($AgentID) { $agentslist = $AgentID -Join ',' $JSON = "{`"job_id`": $JobID,`"agents`": [$agentslist]}" } else { $JSON = "{`"job_id`": $JobID}" } Invoke-ConnectFunction -Method POST -RestPath "/runs" -JSON $JSON } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Stop-ConnectJob { <# .SYNOPSIS Function intended to stop job or multiple jobs .DESCRIPTION Use the function to stop job by ID. Use Find-ConnectJobs and piping to stop multiple jobs .PARAMETER JobID Specifies the ID of a job to be stopped .OUTPUTS The funtion will throw exception if fails by any reason. No return value. .LINK https://www.resilio.com/api/documentation/#api-Runs-StopRun #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [int]$JobID ) BEGIN { $activeruns = Find-ConnectJobRuns -JobName "*" -ActiveOnly -ReturnObject } PROCESS { $myrun = $activeruns | Where-Object job_id -EQ $JobID if ($myrun) { Invoke-ConnectFunction -Method PUT -RestPath "runs/$($myrun.id)/stop" } } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Remove-ConnectJob { <# .SYNOPSIS Function intended to delete job(s) .DESCRIPTION Use the function to remove one or many jobs by job ID. Accepts piped input for multiple jobs .PARAMETER JobID Specifies the ID of a job to be started. Can be piped for multiple jobs .OUTPUTS The funtion will throw exception if fails by any reason. No return value. .LINK https://www.resilio.com/api/documentation/#api-Jobs-DeleteJob .EXAMPLE Find-ConnectJobs -JobName "Test*" | Remove-ConnectJob Will cause to delete all jobs starting from "Test..." #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$JobID ) PROCESS { Invoke-ConnectFunction -Method DELETE -RestPath "/jobs/$JobID" } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Remove-Agent { <# .SYNOPSIS Removes Agent from Management Console .DESCRIPTION Forces Management Console to "forget" the agent. Note, that agent will attempt to reconnect using its bootstrap token and might appear again. .PARAMETER AgentID Specify Agent ID. Pipe multiple IDs if there are many. .LINK https://www.resilio.com/api/documentation/#api-Agents-DeleteAgent #> param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [int]$AgentID ) PROCESS { Invoke-ConnectFunction -Method DELETE -RestPath "agents/$AgentID" -ErrorAction Stop } } # -------------------------------------------------------------------------------------------------------------------------------- function Update-ConnectJob { <# .SYNOPSIS Function intended to change connect job parameters .DESCRIPTION Use the function to change job(s) parameters. Use ID to specify job or pipe list of IDs for multiple change .PARAMETER JobID Specifies the ID of a job to be updated .PARAMETER ParamName Specifies the name of parameter to be updated in the job .PARAMETER ParamValue Specifies new value of parameter .PARAMETER NoQuotes Enforces to skip quotes around parameter value (used for non-string values) .OUTPUTS The funtion will throw exception if fails by any reason. No return value. .LINK https://www.resilio.com/api/documentation/#api-Jobs-UpdateJob #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline)] [int]$JobID, [Parameter(Mandatory = $true)] [string]$ParamName, [Parameter(Mandatory = $true)] [string]$ParamValue, [switch]$NoQuotes ) PROCESS { if ($NoQuotes.IsPresent) { $prepared_json = "{`"$ParamName`":$ParamValue}" } else { $prepared_json = "{`"$ParamName`":`"$ParamValue`"}" } Invoke-ConnectFunction -Method PUT -RestPath "/jobs/$JobID" -JSON $prepared_json } } #----------------------------------------------------------------------------------------------------------------------------------------------------- function Initialize-ResilioMCConnection { <# .SYNOPSIS Function sets up connection to Management Console over API .DESCRIPTION Use the function to specify connection properties for Management Console. The function does not actually do any REST calls, just saves the settings in current runspace .PARAMETER Host Specifies hostname (or IP) and port separated by colon .PARAMETER Token Specifies the API token to be used when making API calls. Token must be generated in API section of Management Console. .LINK https://www.resilio.com/api/documentation/#api-Jobs-UpdateJob .EXAMPLE Initialize-ResilioMCConnection -Host 127.0.0.1:8443 -Token QQXQ5NGUNBJU3KFMD7SOD6AMRFAG6H2J This call tells module to connect to API via localhost, port 8443 .EXAMPLE Initialize-ResilioMCConnection -Host MyFancyServer.mycompany.org:8443 -Token QQXQ5NGUNBJU3KFMD7SOD6AMRFAG6H2J This call tells module to connect to API via MyFancyServer.mycompany.org DNS name, port 8443 #> param ( [Parameter(Mandatory = $true)] [string]$Host, [Parameter(Mandatory = $true)] [string]$Token ) $script:MC_host_and_port = $Host $script:API_token = $Token $script:base_url = "https://$Host/api/v2" } #----------------------------------------------------------------------------------------------------------------------------------------------------- ######################## Ignoring cert check error callback ##################### 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 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Ssl3, [Net.SecurityProtocolType]::Tls, [Net.SecurityProtocolType]::Tls11, [Net.SecurityProtocolType]::Tls12 #################################################################################### $MC_host_and_port = "" $API_token = "" $base_url = "https://$Host/api/v2" $cjblob = New-Object System.Object |