Workflows
Introduction
Les workflows sont apparus avec la version 3.0 de PowerShell. Pour rappel, c’est Windows Server 2012 et Windows 8 qui ont apporté cette version. À ce moment-là, la notion de cloud était bien présente et la virtualisation avait déjà quasiment conquis toutes les entreprises. Il était donc commun de se retrouver à administrer plusieurs centaines, voire milliers de serveurs Windows. Comment procéder alors ? L’équipe PowerShell a répondu à cette question par les workflows ou flux de travail.
Les workflows sont définis et gérés par la Windows Workflow Foundation (WWF). Il s’agit d’une technologie présente dans le framework .NET depuis sa version 3. PowerShell interagit avec cette technologie via un format de données nommé XAML. On retrouve ce format dans la conception d’interfaces graphiques WPF (voir le chapitre Création d’interfaces graphiques). Le moteur WWF interprète simplement les fichiers XAML sans se soucier de leur provenance. Ce qui fait que les workflows ne sont pas spécifiques à PowerShell. Ils peuvent être utilisés par d’autres applications.
L’objectif de ce chapitre est de vous initier à l’utilisation de cette technologie tout en vous mettant en garde sur les pièges que vous pourriez rencontrer. Il s’agit...
Création d’un workflow
1. Mot-clé workflow
Pour créer un workflow, il y a un mot-clé à connaître : workflow. La syntaxe affiliée à ce mot-clé est quasiment semblable à celle d’une fonction avancée. À la différence près que l’instruction [CmdletBinding()] n’autorise que certains attributs.
Syntaxe
workflow <Verbe-Nom> {
[CmdletBinding()]
param(
<bloc de paramètre>
)
<Traitement du workflow..>
}
Le nom d’un workflow a la même forme que celui d’une fonction : Verbe-Nom. Pour plus de détails, référez-vous au chapitre Fonctions avancées.
Création du premier workflow :
workflow Demo-Workflow {
Write-Output "I am a flow"
}
L’utilisation de Write-Output est privilégiée à celle de Write-Host. En effet, cette dernière commande fait partie des restrictions qui seront vues plus loin.
Tout comme les fonctions, il est possible de lister les workflows grâce à la commande Get-Command, en lui spécifiant la valeur workflow sur le paramètre -CommandType.
PS > Get-Command -CommandType workflow
CommandType Name Version Source
----------- ---- ------- ------
workflow Demo-Workflow
Le workflow est bien présent.
2. Gestion des paramètres
Comme il a été dit, les workflows acceptent la mise en place de paramètres. Il existe plusieurs types de paramètres. On retrouve les paramètres communs, ceux contenus dans le bloc param(), et les paramètres propres aux workflows....
Restrictions
On ne peut pas faire ce que l’on veut avec les workflows. Ils ont des restrictions techniques provenant directement de leur mode de fonctionnement. Pour rappel, ils sont traduits en fichier XAML décrivant des activités, exécutés en tant que job, et transitent à travers le service WinRM. Cela fait beaucoup pour réussir à garder un mode de fonctionnement semblable à celui d’un script ou d’une fonction PowerShell standard.
Globalement, on garde ces éléments en tête quand on utilise un workflow :
-
restriction de langage
-
usage des variables limité
-
sérialisation et désérialisation des objets
-
impossible d’utiliser les alias de paramètres et l’appel des paramètres par leur position
1. Restrictions de commande
De ce fait, une partie des commandes de base de PowerShell n’ont pas leur équivalent en activité de workflow, et donc en XAML. En voici une liste non exhaustive :
Add-History |
Add-PSSnapin |
Clear-History |
Clear-Variable |
Complete-Transaction |
Connect-Wsman |
Debug-Process |
Disable-PSBreakpoint |
Disconnect-Wsman |
Enable-PSBreakpoint |
Enter-PSSession |
Exit-PSSession |
Export-Alias |
Export-Console |
Get-Alias |
Get-History |
Get-PSBreakpoint |
Get-PSCallStack |
Get-PSSnapin |
Get-Transaction |
Get-Variable |
Import-Alias |
Invoke-History |
New-Alias |
New-Variable |
Out-GridView |
Remove-PSSnapin |
Remove-Variable |
Set-Alias |
Set-PSBrealkpoint |
Set-PSDebug |
Set-StrictMode |
Set-Variable |
Start-Transaction |
Start-Transcript |
Stop-Transcript |
Trace-Command |
Undo-Transaction |
Use-Transaction |
Write-Host |
On a également l’ensemble des commandes de formatage (Format-*) qui est exclu, ainsi que toute commande demandant une action de la part de l’utilisateur.
Des commandes ne sont exécutables qu’en local :
Add-Member |
Compare-Object |
ConvertFrom-Csv |
ConvertFrom-Json |
Convert-From-StringData |
Convert-Path |
ConvertTo-Csv |
ConvertTo-Html |
ConvertTo-Json |
ConvertTo-Xml |
Foreach-Object |
Get-Host |
Get-Member |
Get-Random |
Get-Unique |
Group-Object |
Measure-Command |
Measure-Object |
New-PSSessionOption |
New-PSTransportOption |
New-TimeSpan |
Out-Default |
Out-Host |
Out-Null |
Out-String |
Select-Object |
Sort-object |
Update-List |
Where-Object |
Write-Debug |
Write-Error |
Write-Host |
Write-OutPut |
Write-Progress |
Write-Verbose |
|
2. Restrictions sur les objets
Avec la sérialisation et la désérialisation des objets, on est confronté...
Exécution en parallèle
1. Bloc parallel
Les workflows offrent la possibilité de réaliser des actions de manière simultanée. Par défaut, les activités sont réalisées de manière séquentielle. La seconde activité attend que la première ait terminé son traitement pour démarrer. Pour qu’elle démarre en parallèle, on utilise le mot-clé parallel à l’intérieur du workflow. Ce mot-clé est d’ailleurs spécifique au workflow, comme InlineScript.
Syntaxe :
workflow <verb-noun> {
parallel {
#Activité 1
#Activité 2
}
}
De manière générale, la parallélisation d’actions indépendantes les unes des autres est un véritable gain de temps. C’est bien sûr le cas dans le traitement d’un workflow.
Soit un traitement qui dure en moyenne 20 secondes, et un second 40 secondes. On obtient ainsi un traitement de 1 minute :
PS > workflow Test-WfwPara {
Start-Sleep -Second 20
Start-Sleep -Second 40
}
PS > Measure-Command { Test-WfwPara }
Days : 0
Hours : 0
Minutes : 1
Seconds : 0
Milliseconds : 750
Ticks : 607502613
TotalDays : 0,000703128024305556
TotalHours : 0,0168750725833333
TotalMinutes : 1,012504355
TotalSeconds : 60,7502613
TotalMilliseconds : 60750,2613
On introduit l’instruction parallel :
PS > workflow Test-WfwPara {
parallel...
Points de synchronisation
Un workflow a la capacité de s’inscrire sur le disque pour sauvegarder son état d’avancement. De cette manière, si un problème inattendu survient, il est possible de reprendre là où le workflow a été sauvegardé pour la dernière fois. Parmi, les problèmes inattendus, on peut trouver un redémarrage, une coupure réseau ou une coupure électrique, plus impactante.
Ces sauvegardes sont nommées checkpoints. Pour les habitués de virtualisation sous Hyper-V, ce mot est familier. Il s’agit d’une capture du disque d’une machine virtuelle à un instant donné. Pour un workflow, c’est en quelque sorte la même chose. Le workflow est inscrit dans le dossier Appdata de l’utilisateur exécutant le workflow. L’arborescence complète est $env:LocalAppData\Microsoft\Windows\PowerShell\ WF\PS\. Les checkpoints sont sauvegardés dans des fichiers au format XML. Ils sont supprimés lorsque le workflow est terminé ou supprimé.
La gestion des checkpoints se fait via trois éléments. Le premier est la commande Checkpoint-Workflow à positionner à l’intérieur du workflow. Elle demande au workflow de réaliser un checkpoint et donc une inscription sur le disque. Dans l’exemple suivant, la fonctionnalité...
Suspension d’un workflow
Dans le chapitre Jobs et parallélisation, la notion de l’état suspendu d’un job a été abordée. Ce cas se présente seulement si le job est de type PSWorkflowJob. Pour qu’un workflow entre dans un état Suspended, il existe deux possibilités. La première est l’utilisation de la commande Suspend-Job directement sur le job du workflow en cours.
Exemple de syntaxe
PS > workflow Test-WfwSuspend {
Foreach ($num in 1..10) {
$num
CheckPoint-Workflow
Start-Sleep -Seconds $num
}
}
PS > $WorkflowJob = Test-WfwSuspend -AsJob
PS > Suspend-Job -Job $WorkflowJob
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
3 Job3 PSWorkflowJob Suspending True localhost Test-...
L’utilisation de la commande Suspend-Job implique que le workflow soit lancé en tant que job grâce...
Relance d’un workflow (suite à une suspension ou à un crash)
Après qu’un workflow a été suspendu, on cherche généralement à relancer son traitement. Pour réaliser cela, on utilise la commande Resume-Job. Cette dernière, tout comme la commande Suspend-Job, n’est utilisable que sur des jobs de type PSWorkflowJob. Pour récupérer les différents jobs d’un workflow, il est possible d’appeler directement la commande Get-Job :
PS > Get-Job
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
3 Job3 PSWorkflowJob Suspending True localhost Test-...
5 Job5 PSWorkflowJob Suspending True localhost Test-...
On tente maintenant de relancer le second job :
PS > Get-Job -ID 5 | Resume-Job
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
5 Job5 PSWorkflowJob Running True localhost...
Observation du contenu d’un workflow
Comme on le dit depuis le début de ce chapitre, les workflows sont représentés sous forme XAML. Il est possible de connaître cette forme, car elle est contenue dans une propriété de l’objet workflow. Pour récupérer cet objet, on utilise la commande Get-Command et on pointe ensuite sur la propriété qui nous intéresse. Ici, il s’agit de XamlDefinition. Reprenons notre premier exemple pour éviter un affichage trop complexe à appréhender :
workflow Demo-Workflow {
Write-Output "I am a flow"
}
On utilise ensuite la commande Get-Command :
PS > Get-Command Demo-Workflow
CommandType Name Version Source
----------- ---- ------- ------
workflow Demo-Workflow
Puis, on affine l’affichage pour montrer le code XAML :
PS > Get-Command Demo-Workflow | Foreach-Object XamlDefinition
<Activity
x:Class="Microsoft.PowerShell.DynamicActivities.Activity_..."
xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activ..."
xmlns:sad="clr-namespace:System.Activities.Debugger;assem..." ...
Intégration dans un module
Les workflows se déclarent de la même manière que les fonctions. Il n’est donc pas surprenant de pouvoir les porter à travers un module. Le procédé est identique à celui mis en œuvre pour une fonction. Il suffit d’ajouter la déclaration du workflow au fichier PSM1 d’un module. Pour plus d’informations sur la création d’un module, référez-vous au chapitre Création de modules.
Exemple du contenu d’un fichier PSM1
PS > Get-Content ./MyModule.psm1
workflow Demo-Workflow {
Write-Output "I am a flow"
}
Pour utiliser le workflow, il suffit d’importer le module et de lancer la commande :
PS > Import-Module ./MyModule.psm1
PS > Demo-Workflow
I am a flow
Workflow : pour qui ? pour quoi ?
Les workflows sont un formidable outil malgré leur complexité de mise en œuvre et les limites qu’ils imposent. Toutefois, on peut sérieusement se poser la question de leur utilité aujourd’hui, surtout avec des outils comme DSC (voir le chapitre Desired State Configuration (DSC)) permettant la gestion de configuration de systèmes avec prise en charge de redémarrage. En outre, la version 6.0 Core de PowerShell ne dispose pas des workflows. Les développeurs ont dû faire un choix lors du portage de la solution vers le monde libre et ont choisi de les mettre de côté.
Pour l’ensemble de ces raisons, il est recommandé d’utiliser les workflows dans des cas précis, pour s’épargner quelques déboires :
-
Lorsque le traitement nécessite plus de 6 heures.
-
Lorsque le traitement pourrait être perturbé par des coupures réseau ou des redémarrages intempestifs.
-
Lorsque le traitement nécessite une forte parallélisation et un séquençage des actions.
-
Lorsque aucune autre solution ne répond correctement à la problématique.
Gardez quand même à l’esprit qu’un workflow passe par une mécanique complexe avant de s’exécuter réellement. Par exemple, utiliser un workflow pour récupérer...