ΠΠ΄ΡΠ°Π²Π΅ΠΉ, Π₯Π°Π±Ρ! ΠΡΠ΅Π΄ΡΡΠ°Π²ΡΠΌ Π²ΠΈ ΠΏΡΠ΅Π²ΠΎΠ΄Π° Π½Π° ΡΡΠ°ΡΠΈΡΡΠ° Π°Π²ΡΠΎΡΠ° Christopher Kuech.
ΠΠ±Π΅ΠΊΡΠ½ΠΎ-ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠ°Π½ΠΈΡΠ΅ ΠΈ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΈΡΠ΅ ΠΏΠ°ΡΠ°Π΄ΠΈΠ³ΠΌΠΈ Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°Ρ Π½Π΅ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡΠΈ Π΅Π΄Π½Π° Π·Π° Π΄ΡΡΠ³Π°, Π½ΠΎ ΠΈ Π΄Π²Π΅ΡΠ΅ ΡΠ΅ ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ°Ρ Π² PowerShell. ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ Π²ΡΠΈΡΠΊΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ½ΠΈ Π΅Π·ΠΈΡΠΈ, Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎ Π΄Π°Π»ΠΈ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΈ ΠΈΠ»ΠΈ Π½Π΅, ΡΠ°Π·ΠΏΠΎΠ»Π°Π³Π°Ρ ΡΡΡ ΡΡΠ΅Π΄ΡΡΠ²Π° Π·Π° ΡΠ°Π·ΡΠΈΡΠ΅Π½ΠΎ ΡΠ²ΡΡΠ·Π²Π°Π½Π΅ Π½Π° ΠΈΠΌΠ΅Π½Π° ΠΈ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ; ΠΠ»Π°ΡΠΎΠ²Π΅ΡΠ΅, ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π½Π° ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° (struct) ΠΈ Π·Π°ΠΏΠΈΡΠΈΡΠ΅ (record), ΡΠ° ΡΠ°ΠΌΠΎ Π΅Π΄ΠΈΠ½ ΠΏΠΎΠ΄Ρ ΠΎΠ΄. ΠΠΊΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠΌ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ΡΠΎ Π½Π° ΠΊΠ»Π°ΡΠΎΠ²Π΅ΡΠ΅ Π΄ΠΎ ΡΠ²ΡΡΠ·Π²Π°Π½Π΅ΡΠΎ Π½Π° ΠΈΠΌΠ΅Π½Π° ΠΈ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ ΠΈ ΠΈΠ·Π±ΡΠ³Π²Π°ΠΌΠ΅ "ΡΠ΅ΠΆΠΊΠΈΡΠ΅" ΠΎΠ±Π΅ΠΊΡΠ½ΠΎ-ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠ°Π½ΠΈ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΠΈ, ΠΊΠ°ΡΠΎ Π½Π°ΡΠ»Π΅Π΄ΡΠ²Π°Π½Π΅, ΠΏΠΎΠ»ΠΈΠΌΠΎΡΡΠΈΠ·ΡΠΌ ΠΈΠ»ΠΈ ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΠΎΡΡ (mutability), ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΡΠ΅ Π²ΡΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΎΡ ΡΠ΅Ρ Π½ΠΈΡΠ΅ ΠΏΡΠ΅Π΄ΠΈΠΌΡΡΠ²Π°, Π±Π΅Π· Π΄Π° ΡΡΠ»ΠΎΠΆΠ½ΡΠ²Π°ΠΌΠ΅ ΠΊΠΎΠ΄Π° ΡΠΈ. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π°, Π΄ΠΎΠ±Π°Π²ΡΠΉΠΊΠΈ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΠΈ (immutable) ΠΌΠ΅ΡΠΎΠ΄ΠΈ Π·Π° ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ²Π°Π½Π΅ Π½Π° ΡΠΈΠΏΠΎΠ²Π΅, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΎΠ±ΠΎΠ³Π°ΡΠΈΠΌ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΈΡ ΡΠΈ ΠΊΠΎΠ΄ Ρ ΠΊΠ»Π°ΡΠΎΠ²Π΅.
ΠΠ°Π³ΠΈΡΡΠ° Π½Π° ΠΊΠ°ΡΡΠΎΠ²Π΅ΡΠ΅
ΠΠ°ΡΡΠΎΠ²Π΅ΡΠ΅ ΡΠ° Π΅Π΄Π½Π° ΠΎΡ Π½Π°ΠΉ-ΠΌΠΎΡΠ½ΠΈΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ Π² PowerShell. ΠΠΎΠ³Π°ΡΠΎ ΠΏΠΎΠ΄Π»ΠΎΠΆΠΈΡΠ΅ ΡΡΠΎΠΉΠ½ΠΎΡΡ Π½Π° ΠΊΠ°ΡΡ, ΡΠ°Π·ΡΠΈΡΠ°ΡΠ΅ Π½Π° Π΄ΠΎΠ±Π°Π²Π΅Π½Π°ΡΠ° ΠΎΡ ΡΡΠ΅Π΄Π°ΡΠ° Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ Π·Π° Π½Π΅ΡΠ²Π½Π° ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΈ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ Π²ΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΎΡΡ ΠΊΠ°ΡΡ Π½Π° Π½ΠΈΠ· Π² [xml] ΡΠ΅ Ρ ΠΏΡΠΎΠΏΡΡΠ½Π΅ ΠΏΡΠ΅Π· ΠΊΠΎΠ΄Π° Π½Π° ΠΏΠ°ΡΡΠ΅ΡΠ° ΠΈ ΡΠ΅ Π³Π΅Π½Π΅ΡΠΈΡΠ° ΠΏΡΠ»Π½ΠΎ XML Π΄ΡΡΠ²ΠΎ. ΠΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΊΠ»Π°ΡΠΎΠ²Π΅ Π² ΠΊΠΎΠ΄Π° ΡΠΈ Ρ ΡΡΡΠ°ΡΠ° ΡΠ΅Π».
ΠΠ°ΡΡ Π½Π° Ρ Π΅Ρ ΡΠ°Π±Π»ΠΈΡΠΈ
ΠΠΊΠΎ Π½ΡΠΌΠ°ΡΠ΅ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΡΠΎΠ΄ΡΠ»ΠΆΠΈΡΠ΅ Π±Π΅Π· Π½Π΅Π³ΠΎ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ΠΊΠ°ΡΡ Π½Π° Ρ Π΅Ρ ΡΠ°Π±Π»ΠΈΡΠΈΡΠ΅ Π² ΡΠΈΠΏΠ° Π½Π° Π²Π°ΡΠΈΡ ΠΊΠ»Π°Ρ. ΠΠ΅ Π·Π°Π±ΡΠ°Π²ΡΠΉΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Π°ΡΡΠΈΠ±ΡΡΠΈ Π·Π° Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡ, Π·Π° Π΄Π° ΡΠ΅ Π²ΡΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Π½Π°ΠΏΡΠ»Π½ΠΎ ΠΎΡ ΡΠΎΠ·ΠΈ ΠΏΠ°ΡΠ΅ΡΠ½. ΠΡΠ²Π΅Π½ ΡΠΎΠ²Π°, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΡΠΈΠΏΠΈΠ·ΠΈΡΠ°Π½ΠΈ ΡΠ²ΠΎΠΉΡΡΠ²Π° Π½Π° ΠΊΠ»Π°ΡΠ°, Π·Π° Π΄Π° ΡΡΠ°ΡΡΠΈΡΠ°ΠΌΠ΅ Π΄ΠΎΡΠΈ ΠΏΠΎ-Π΄ΡΠ»Π±ΠΎΠΊΠ° Π»ΠΎΠ³ΠΈΠΊΠ° Π½Π° ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΈ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡ.
class Cluster {
[ValidatePattern("^[A-z]+$")]
[string] $Service
[ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
[string] $FlightingRing
[ValidateSet("EastUS", "WestUS", "NorthEurope")]
[string] $Region
[ValidateRange(0, 255)]
[int] $Index
}
[Cluster]@{
Service = "MyService"
FlightingRing = "PROD"
Region = "EastUS"
Index = 2
}ΠΡΠ²Π΅Π½ ΡΠΎΠ²Π°, ΠΊΠ°ΡΡΡΡ ΠΏΠΎΠΌΠ°Π³Π° Π΄Π° ΠΏΠΎΠ»ΡΡΠΈΡΠ΅ ΡΠΈΡΡΠ° ΠΈΠ·Ρ ΠΎΠ΄Π½Π° ΡΡΠΎΠΉΠ½ΠΎΡΡ. Π‘ΡΠ°Π²Π½Π΅ΡΠ΅ ΠΈΠ·Ρ ΠΎΠ΄Π° Π½Π° ΠΌΠ°ΡΠΈΠ²Π° ΠΎΡ Ρ Π΅Ρ ΡΠ°Π±Π»ΠΈΡΠΈ Cluster, ΠΏΡΠ΅Π΄Π°Π΄Π΅Π½ Π½Π° Format-Table Ρ ΡΠΎΠ²Π°, ΠΊΠΎΠ΅ΡΠΎ ΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈΡΠ΅, Π°ΠΊΠΎ ΠΏΡΠ΅Π΄ΠΈ ΡΠΎΠ²Π° ΠΊΠ°ΡΡΠ½Π΅ΡΠ΅ ΡΠ΅Π·ΠΈ Ρ Π΅Ρ ΡΠ°Π±Π»ΠΈΡΠΈ Π² ΠΊΠ»Π°Ρ. Π‘Π²ΠΎΠΉΡΡΠ²Π°ΡΠ° Π½Π° ΠΊΠ»Π°ΡΠ° Π²ΠΈΠ½Π°Π³ΠΈ ΡΠ΅ ΠΈΠ·Π±ΡΠΎΡΠ²Π°Ρ Π² ΡΠ΅Π΄Π°, Π² ΠΊΠΎΠΉΡΠΎ ΡΠ° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈ. ΠΠ΅ Π·Π°Π±ΡΠ°Π²ΡΠΉΡΠ΅ Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈΡΠ΅ ΠΊΠ»ΡΡΠΎΠ²Π°ΡΠ° Π΄ΡΠΌΠ° hidden ΠΏΡΠ΅Π΄ Π²ΡΠΈΡΠΊΠΈ ΡΠ²ΠΎΠΉΡΡΠ²Π°, ΠΊΠΎΠΈΡΠΎ Π½Π΅ ΡΡΡΠ±Π²Π° Π΄Π° Π±ΡΠ΄Π°Ρ Π²ΠΈΠ΄ΠΈΠΌΠΈ Π² ΠΈΠ·Ρ ΠΎΠ΄Π°.

ΠΠ°ΡΡ Π½Π° ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ
ΠΠΊΠΎ ΠΈΠΌΠ°ΡΠ΅ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ Ρ Π΅Π΄ΠΈΠ½ Π°ΡΠ³ΡΠΌΠ΅Π½Ρ, ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° ΡΡΠΎΠΉΠ½ΠΎΡΡΡΠ° ΠΊΡΠΌ Π²Π°ΡΠΈΡ ΠΊΠ»Π°Ρ ΡΠ΅ ΠΏΡΠ΅Π΄Π°Π΄Π΅ ΡΡΠΎΠΉΠ½ΠΎΡΡΡΠ° Π½Π° ΡΠΎΠ·ΠΈ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ, Π² ΠΊΠΎΠΉΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°ΡΠ΅ ΠΈΠ½ΡΡΠ°Π½ΡΠΈΡΡΠ° Π½Π° Π²Π°ΡΠΈΡ ΠΊΠ»Π°Ρ.
class Cluster {
[ValidatePattern("^[A-z]+$")]
[string] $Service
[ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
[string] $FlightingRing
[ValidateSet("EastUS", "WestUS", "NorthEurope")]
[string] $Region
[ValidateRange(0, 255)]
[int] $Index
Cluster([string] $id) {
$this.Service, $this.FlightingRing, $this.Region, $this.Index = $id -split "-"
}
}
[Cluster]"MyService-PROD-EastUS-2"ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ²Π°Π½Π΅ Π² Π½ΠΈΠ·
Π‘ΡΡΠΎ ΡΠ°ΠΊΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Π° Π½Π° ΠΊΠ»Π°ΡΠ° [string] ToString(), Π·Π° Π΄Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΠ΅ Π»ΠΎΠ³ΠΈΠΊΠ°ΡΠ° Π½Π° Π½ΠΈΠ·ΠΎΠ²ΠΎΡΠΎ ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΡΠ½Π΅ Π½Π° ΠΎΠ±Π΅ΠΊΡΠ°, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΠΏΠΎΠ»Π°ΡΠΈΡ Π½Π° Π½ΠΈΠ·ΠΎΠ²Π΅.
class Cluster {
[ValidatePattern("^[A-z]+$")]
[string] $Service
[ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
[string] $FlightingRing
[ValidateSet("EastUS", "WestUS", "NorthEurope")]
[string] $Region
[ValidateRange(0, 255)]
[int] $Index
[string] ToString() {
return $this.Service, $this.FlightingRing, $this.Region, $this.Index -join "-"
}
}
$cluster = [Cluster]@{
Service = "MyService"
FlightingRing = "PROD"
Region = "EastUS"
Index = 2
}
Write-Host "Π‘ΡΠ·Π΄Π°Π΄ΠΎΡ
ΠΌΠ΅ ΠΌΠΎΠ΄Π΅Π» Π·Π° '$cluster'"ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ²Π°Π½Π΅ Π½Π° ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½ΠΈ ΠΈΠ½ΡΡΠ°Π½ΡΠΈΠΈ
ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ²Π°Π½Π΅ΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ²Π° Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½Π° Π΄Π΅ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ. ΠΡΠΈΠΌΠ΅ΡΠΈΡΠ΅ ΠΏΠΎ-Π΄ΠΎΠ»Ρ ΡΠ΅ Π·Π°Π²ΡΡΡΠ°Ρ Ρ Π³ΡΠ΅ΡΠΊΠ°, Π°ΠΊΠΎ Π΄Π°Π½Π½ΠΈΡΠ΅ Π½Π΅ ΠΎΡΠ³ΠΎΠ²Π°ΡΡΡ Π½Π° Π½Π°ΡΠ°ΡΠ° ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ Π² Cluster.
# ΠΠ°Π»ΠΈΠ΄Π°ΡΠΈΡ ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΡΡ
Π΄Π°Π½Π½ΡΡ
[Cluster]$cluster = Get-Content "./my-cluster.json" | ConvertFrom-Json
[Cluster[]]$clusters = Import-Csv "./my-clusters.csv"ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ²Π°Π½ΠΈΡ Π² Π²Π°ΡΠΈΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π΅Π½ ΠΊΠΎΠ΄
Π€ΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΈΡΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈ ΠΏΡΡΠ²ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡ ΡΡΡΡΠΊΡΡΡΠΈ ΠΎΡ Π΄Π°Π½Π½ΠΈ, ΡΠ»Π΅Π΄ ΠΊΠΎΠ΅ΡΠΎ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠΈΡΠ°Ρ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠ°ΡΠ° ΠΊΠ°ΡΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»Π½ΠΎΡΡ ΠΎΡ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΠΈ Π²ΡΡΡ Ρ Π½Π΅ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΠΈΡΠ΅ ΡΡΡΡΠΊΡΡΡΠΈ ΠΎΡ Π΄Π°Π½Π½ΠΈ. ΠΡΠΏΡΠ΅ΠΊΠΈ ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΠ²ΠΎΡΠΎ Π²ΠΏΠ΅ΡΠ°ΡΠ»Π΅Π½ΠΈΠ΅, ΠΊΠ»Π°ΡΠΎΠ²Π΅ΡΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»Π½ΠΎ ΠΏΠΎΠΌΠ°Π³Π°Ρ Π·Π° ΠΏΠΈΡΠ°Π½Π΅ Π½Π° ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π΅Π½ ΠΊΠΎΠ΄ Π±Π»Π°Π³ΠΎΠ΄Π°ΡΠ΅Π½ΠΈΠ΅ Π½Π° ΠΌΠ΅ΡΠΎΠ΄ΠΈΡΠ΅ Π·Π° ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠ°Π½Π΅ Π½Π° ΡΠΈΠΏΠΎΠ²Π΅.
ΠΠΈΡΠ° Π»ΠΈ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π΅Π½ Powershell?
ΠΠ½ΠΎΠ³ΠΎ Ρ ΠΎΡΠ°, Π΄ΠΎΡΠ»ΠΈ ΠΎΡ C# ΠΈΠ»ΠΈ Ρ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ ΠΌΠΈΠ½Π°Π»ΠΎ, ΠΏΠΈΡΠ°Ρ Powershell, ΠΊΠΎΠΉΡΠΎ ΠΏΡΠΈΠ»ΠΈΡΠ° Π½Π° C#. ΠΠΎΡΡΡΠΏΠ²Π°ΠΉΠΊΠΈ ΡΠ°ΠΊΠ°, ΠΎΡΠΊΠ°Π·Π²Π°ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΠΈ Π·Π° ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅ ΠΈ Π²Π΅ΡΠΎΡΡΠ½ΠΎ ΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈΡΠ΅ ΠΏΠΎΠ»Π·Π° ΠΎΡ Π΄ΡΠ»Π±ΠΎΡΠΈΠ½Π½ΠΎ ΠΏΠΎΡΠ°ΠΏΡΠ½Π΅ Π² ΠΎΠ±Π΅ΠΊΡΠ½ΠΎ-ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠ°Π½ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅ Π² Powershell ΠΈΠ»ΠΈ ΠΏΠΎ-Π΄ΠΎΠ±ΡΠΎ ΠΈΠ·ΡΡΠ°Π²Π°Π½Π΅ Π½Π° ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅.
ΠΠΊΠΎ Π΄ΡΠ»Π±ΠΎΠΊΠΎ ΡΠ°Π·ΡΠΈΡΠ°ΡΠ΅ Π½Π° ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΡ Π½Π° Π½Π΅ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΠΈ Π΄Π°Π½Π½ΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ΠΊΠΎΠ½Π²Π΅ΠΉΡΠΈ (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object ΠΈ Ρ.Π½. β ΠΈΠΌΠ°ΡΠ΅ ΠΏΠΎ-ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π΅Π½ ΡΡΠΈΠ», ΠΈ ΡΠ΅ Π²ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ΡΠΎ Π½Π° ΠΊΠ»Π°ΡΠΎΠ²Π΅ΡΠ΅ Π² Powershell Π² ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π΅Π½ ΡΡΠΈΠ».
Π€ΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΠΊΠ»Π°ΡΠΎΠ²Π΅
ΠΠ°ΡΡΠΈΠ½Π³ΠΈΡΠ΅, Π²ΡΠΏΡΠ΅ΠΊΠΈ ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ Π°Π»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π΅Π½ ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ, Π²ΡΡΡΠ½ΠΎΡΡ ΡΠ° ΠΏΡΠΎΡΡΠΎ ΠΌΠ°ΠΏΠΈΠ½Π³ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²Π° Π΄ΠΎΠΌΠ΅ΠΉΠ½Π°. Π ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅ΡΠ° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΌΠ°ΠΏΠΈΡΠ°ΡΠ΅ ΠΌΠ°ΡΠΈΠ² ΠΎΡ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ForEach-Object.
Π ΠΏΡΠΈΠΌΠ΅ΡΠ° ΠΏΠΎ-Π΄ΠΎΠ»Ρ, ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΡΡ Node ΡΠ΅ ΠΈΠ·ΠΏΡΠ»Π½ΡΠ²Π° Π²ΡΠ΅ΠΊΠΈ ΠΏΡΡ, ΠΊΠΎΠ³Π°ΡΠΎ ΡΠ΅ ΠΈΠ·Π²ΡΡΡΠΈ ΠΊΠ°ΡΡΠΈΠ½Π³ Π½Π° Datum, ΠΊΠΎΠ΅ΡΠΎ Π½ΠΈ Π΄Π°Π²Π° Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΠΌ Π½Π°ΠΏΠΈΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° Π·Π½Π°ΡΠΈΡΠ΅Π»Π½ΠΎ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΊΠΎΠ΄. Π ΡΠ΅Π·ΡΠ»ΡΠ°Ρ Π½Π°ΡΠΈΡΡ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ ΡΠ΅ ΡΠΎΠΊΡΡΠΈΡΠ° Π²ΡΡΡ Ρ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΠΎΡΠΎ Π·Π°ΡΠ²ΡΠ²Π°Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈ ΠΈ Π°Π³ΡΠ΅Π³Π°ΡΠΈΡΡΠ°, Π΄ΠΎΠΊΠ°ΡΠΎ Π½Π°ΡΠΈΡΠ΅ ΠΊΠ»Π°ΡΠΎΠ²Π΅ ΠΏΠΎΠ΅ΠΌΠ°Ρ ΠΏΠ°ΡΡΠΈΠ½Π³Π° Π½Π° Π΄Π°Π½Π½ΠΈ ΠΈ Π²Π°Π»ΠΈΠ΄ΠΈΠ·Π°ΡΠΈΡΡΠ°.
# ΠΡΠΈΠΌΠ΅Ρ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΊΠ»Π°ΡΡΠΎΠ² Ρ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅ΡΠ°ΠΌΠΈ Π΄Π»Ρ separation of concerns Π² ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅ΡΠ°Ρ
class Node {
[ValidateLength(3, 7)]
[string] $Name
[ValidateSet("INT", "PPE", "PROD")]
[string] $FlightingRing
[ValidateSet("EastUS", "WestUS", "NorthEurope", "WestEurope")]
[string] $Region
Node([string] $Name) {
$Name -match "([a-z]+)(INT|PPE|PROD)([a-z]+)"
$_, $this.Service, $this.FlightingRing, $this.Region = $Matches
$this.Name = $Name
}
}
class Datum {
[string] $Name
[int] $Value
[Node] $Computer
[int] Severity() {
$this.Name -match "[0-9]+$"
return $Matches[0]
}
}
Write-Host "Urgent Security Audit Issues:"
Import-Csv "./audit-results.csv" `
| ForEach-Object {[Datum]$_} `
| Where-Object Value -gt 0 `
| Group-Object {$_.Severity()} `
| Where-Object Name -lt 2 `
| ForEach-Object Group `
| ForEach-Object Computer `
| Where-Object FlightingRing -eq "PROD" `
| Sort-Object Name, Region -UniqueΠΠΏΠ°ΠΊΠΎΠ²Π°Π½Π΅ Π½Π° ΠΊΠ»Π°Ρ Π·Π° ΠΏΠΎΠ²ΡΠΎΡΠ½Π° ΡΠΏΠΎΡΡΠ΅Π±Π°
ΠΠΈΡΠΎ Π½Π΅ Π΅ ΡΠΎΠ»ΠΊΠΎΠ²Π° Π΄ΠΎΠ±ΡΠ΅, ΠΊΠΎΠ»ΠΊΠΎΡΠΎ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°
ΠΠ° ΡΡΠΆΠ°Π»Π΅Π½ΠΈΠ΅, ΠΊΠ»Π°ΡΠΎΠ²Π΅ΡΠ΅ Π½Π΅ ΠΌΠΎΠ³Π°Ρ Π΄Π° Π±ΡΠ΄Π°Ρ Π΅ΠΊΡΠΏΠΎΡΡΠΈΡΠ°Π½ΠΈ ΠΎΡ ΠΌΠΎΠ΄ΡΠ»ΠΈΡΠ΅ ΠΏΠΎ ΡΡΡΠΈΡ Π½Π°ΡΠΈΠ½, ΠΏΠΎ ΠΊΠΎΠΉΡΠΎ ΠΌΠΎΠ³Π°Ρ ΡΡΠ½ΠΊΡΠΈΠΈΡΠ΅ ΠΈΠ»ΠΈ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈΡΠ΅; Π½ΠΎ ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π°Ρ Π½ΡΠΊΠΎΠΈ ΡΡΠΈΠΊΠΎΠ²Π΅. ΠΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, ΡΠ΅ Π²Π°ΡΠΈΡΠ΅ ΠΊΠ»Π°ΡΠΎΠ²Π΅ ΡΠ° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈ Π²ΡΠ² ΡΠ°ΠΉΠ»Π° ./my-classes.ps1
ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ dot-sourcing Π½Π° ΡΠ°ΠΉΠ»Π° Ρ ΠΊΠ»Π°ΡΠΎΠ²Π΅ΡΠ΅: . ./my-classes.ps1. Π’ΠΎΠ²Π° ΡΠ΅ ΠΈΠ·ΠΏΡΠ»Π½ΠΈ my-classes.ps1 Π² ΡΠ΅ΠΊΡΡΠ°ΡΠ° Π²ΠΈ ΠΎΠ±Π»Π°ΡΡ Π½Π° Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡ ΠΈ ΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈ Π²ΡΠΈΡΠΊΠΈ ΠΊΠ»Π°ΡΠΎΠ²Π΅ ΠΎΡ ΡΠ°ΠΉΠ»Π° ΡΠ°ΠΌ.
ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΡΠ·Π΄Π°Π΄Π΅ΡΠ΅ PowerShell ΠΌΠΎΠ΄ΡΠ», ΠΊΠΎΠΉΡΠΎ Π΅ΠΊΡΠΏΠΎΡΡΠΈΡΠ° Π²ΡΠΈΡΠΊΠΈΡΠ΅ Π²ΠΈ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΡΠΊΠΈ API (ΠΊΠΎΠΌΠ°Π½Π΄Π»Π΅ΡΠΈ) ΠΈ Π΄Π° Π·Π°Π΄Π°Π΄Π΅ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°ΡΠ° ScriptsToProcess = ". ./my-classes.ps1" Π² ΠΌΠ°Π½ΠΈΡΠ΅ΡΡΠ° Π½Π° Π²Π°ΡΠΈΡ ΠΌΠΎΠ΄ΡΠ», Ρ ΡΡΡΠΈΡ ΡΠ΅Π·ΡΠ»ΡΠ°Ρ: . ./my-classes.ps1 ΡΠ΅ ΡΠ΅ ΠΈΠ·ΠΏΡΠ»Π½ΠΈ Π² Π²Π°ΡΠ°ΡΠ° ΡΡΠ΅Π΄Π°.
ΠΠ°ΠΊΡΠ²ΡΠΎ ΠΈ Π²Π°ΡΠΈΠ°Π½Ρ Π΄Π° ΠΈΠ·Π±Π΅ΡΠ΅ΡΠ΅, Π½Π΅ Π·Π°Π±ΡΠ°Π²ΡΠΉΡΠ΅, ΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΠ°ΡΠ° ΠΎΡ ΡΠΈΠΏΠΎΠ²Π΅ Π½Π° PowerShell Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ°Π·ΡΠ΅ΡΠΈ ΡΠΈΠΏΠΎΠ²Π΅ Ρ Π΅Π΄Π½ΠΎ ΠΈ ΡΡΡΠΎ ΠΈΠΌΠ΅, Π·Π°ΡΠ΅Π΄Π΅Π½ΠΈ ΠΎΡ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΠΌΠ΅ΡΡΠ°.
ΠΠΎΡΠΈ Π°ΠΊΠΎ ΡΡΠ΅ Π·Π°ΡΠ΅Π΄ΠΈΠ»ΠΈ Π΄Π²Π° ΠΈΠ΄Π΅Π½ΡΠΈΡΠ½ΠΈ ΠΊΠ»Π°ΡΠ° Ρ Π΅Π΄Π½Π°ΠΊΠ²ΠΈ ΡΠ²ΠΎΠΉΡΡΠ²Π° ΠΎΡ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΠΌΠ΅ΡΡΠ°, ΡΠΈΡΠΊΡΠ²Π°ΡΠ΅ Π΄Π° ΡΠ΅ ΡΠ±Π»ΡΡΠΊΠ°ΡΠ΅ Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ.
ΠΡΡΡΡ Π½Π°ΠΏΡΠ΅Π΄
ΠΠ°ΠΉ-Π΄ΠΎΠ±ΡΠΈΡΡ Π½Π°ΡΠΈΠ½ Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ Ρ ΡΠ°Π·ΡΠ΅ΡΠ°Π²Π°Π½Π΅ΡΠΎ Π½Π° ΡΠΈΠΏΠΎΠ²Π΅ Π΅ Π½ΠΈΠΊΠΎΠ³Π° Π΄Π° Π½Π΅ Π΅ΠΊΡΠΏΠΎΠ·ΠΈΡΠ°ΡΠ΅ Π²Π°ΡΠΈΡΠ΅ ΠΊΠ»Π°ΡΠΎΠ²Π΅ Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅. ΠΠΌΠ΅ΡΡΠΎ Π΄Π° ΠΎΡΠ°ΠΊΠ²Π°ΡΠ΅, ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΡΡ ΡΠ΅ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠ° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ ΡΠΈΠΏ ΠΎΡ ΠΊΠ»Π°ΡΠ°, Π΅ΠΊΡΠΏΠΎΡΡΠΈΡΠ°ΠΉΡΠ΅ ΠΎΡ Π²Π°ΡΠΈΡ ΠΌΠΎΠ΄ΡΠ» ΡΡΠ½ΠΊΡΠΈΡ, ΠΊΠΎΡΡΠΎ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π²Π° ΠΎΡ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΡΠ° Π΄Π° ΡΠ΅ ΠΎΠ±Π°ΠΆΠ΄Π° Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ Π½Π° ΠΊΠ»Π°ΡΠ°. Π‘ΡΠΎΡΠ²Π΅ΡΠ½ΠΎ Π½Π° Cluster, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π΅ΠΊΡΠΏΠΎΡΡΠΈΡΠ°ΠΌΠ΅ ΡΡΠ½ΠΊΡΠΈΡ New-Cluster, ΠΊΠΎΡΡΠΎ ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ° ΡΠ΄ΠΎΠ±Π½ΠΈ Π·Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»Ρ Π½Π°Π±ΠΎΡΠΈ ΠΎΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈ ΠΈ Π²ΡΡΡΠ° Cluster.
class Cluster {
[ValidatePattern("^[A-z]+$")]
[string] $Service
[ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
[string] $FlightingRing
[ValidateSet("EastUS", "WestUS", "NorthEurope")]
[string] $Region
[ValidateRange(0, 255)]
[int] $Index
}
function New-Cluster {
[OutputType([Cluster])]
Param(
[Parameter(Mandatory, ParameterSetName = "Id", Position = 0)]
[ValidateNotNullOrEmpty()]
[string] $Id,
[Parameter(Mandatory, ParameterSetName = "Components")]
[string] $Service,
[Parameter(Mandatory, ParameterSetName = "Components")]
[string] $FlightingRing,
[Parameter(Mandatory, ParameterSetName = "Components")]
[string] $Region,
[Parameter(Mandatory, ParameterSetName = "Components")]
[int] $Index
)
if ($Id) {
$Service, $FlightingRing, $Region, $Index = $Id -split "-"
}
[Cluster]@{
Service = $Service
FlightingRing = $FlightingRing
Region = $Region
Index = $Index
}
}
Export-ModuleMember New-ClusterΠΠ°ΠΊΠ²ΠΎ ΠΎΡΠ΅ Π΄Π° ΠΏΡΠΎΡΠ΅ΡΠ°
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: habr.com
