├── .gitattributes ├── .gitignore ├── .gitmodules ├── Functions ├── Casting.Tests.ps1 ├── Casting.ps1 ├── Shadow-Copy.Tests.ps1 ├── Shadow-Copy.ps1 ├── Validator-Functions.Tests.ps1 ├── Validator-Functions.ps1 ├── YamlDotNet-Integration.Tests.ps1 └── YamlDotNet-Integration.ps1 ├── LICENSE ├── Libs ├── YamlDotNet.Configuration.dll ├── YamlDotNet.Converters.dll ├── YamlDotNet.Core.dll └── YamlDotNet.RepresentationModel.dll ├── PowerYaml.Tests.ps1 ├── PowerYaml.nuspec ├── PowerYaml.psm1 ├── README.md ├── package.ps1 └── vendor └── tools └── NuGet.exe /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Pester"] 2 | path = Pester 3 | url = git@github.com:scottmuc/Pester.git 4 | -------------------------------------------------------------------------------- /Functions/Casting.Tests.ps1: -------------------------------------------------------------------------------- 1 | $pwd = Split-Path -Parent $MyInvocation.MyCommand.Path 2 | $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests", "") 3 | . "$pwd\$sut" 4 | 5 | if ($PSVersionTable.PSVersion -ge "3.0") { return } 6 | 7 | Describe "when accessing a yaml scalar value of '5'" { 8 | $patched = Add-CastingFunctionsForPosh2 ("5") 9 | 10 | Context "and I do not attempt to cast it" { 11 | It "returns a string" { 12 | $patched.GetType().Name | Should Be "string" 13 | } 14 | } 15 | 16 | Context "and I attempt to cast it as an integer" { 17 | It "returns a value that is of type integer" { 18 | $patched.ToInt().GetType().Name | Should Be "Int32" 19 | } 20 | } 21 | 22 | Context "and I attempt to cast it as a long" { 23 | It "returns a value that is of type long" { 24 | $patched.ToLong().GetType().Name | Should Be "Int64" 25 | } 26 | } 27 | 28 | Context "and I attempt to cast it as a double" { 29 | It "returns a value that is a double" { 30 | $patched.ToDouble().GetType().Name | Should Be "Double" 31 | } 32 | } 33 | 34 | Context "and I attempt to cast it as a decimal" { 35 | It "returns a value that is a decimal" { 36 | $patched.ToDecimal().GetType().Name | Should Be "Decimal" 37 | } 38 | } 39 | 40 | Context "and I attempt to cast it as a byte" { 41 | It "returns a value that is a byte" { 42 | $patched.ToByte().GetType().Name | Should Be "Byte" 43 | } 44 | } 45 | } 46 | 47 | Describe "when accessing boolean values" { 48 | 49 | Context "and I'm attempting to cast the value 'true'" { 50 | $patched = Add-CastingFunctionsForPosh2("true") 51 | 52 | It "return a value that is a boolean" { 53 | $patched.ToBoolean().GetType().Name | Should Be "Boolean" 54 | } 55 | 56 | It "returns a value that is true" { 57 | $patched.ToBoolean() | Should Be $true 58 | } 59 | } 60 | 61 | Context "and I'm attempting to cast the value 'false'" { 62 | $patched = Add-CastingFunctionsForPosh2("false") 63 | 64 | It "return a value that is a boolean" { 65 | $patched.ToBoolean().GetType().Name | Should Be "Boolean" 66 | } 67 | 68 | It "returns a value that is false" { 69 | $patched.ToBoolean() | Should Be $false 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Functions/Casting.ps1: -------------------------------------------------------------------------------- 1 | function Add-CastingFunctions($value) { 2 | if ($PSVersionTable.PSVersion -ge "3.0") { return $value } 3 | return Add-CastingFunctionsForPosh2($value) 4 | } 5 | 6 | function Add-CastingFunctionsForPosh2($value) { 7 | return Add-Member -InputObject $value -Name ToInt ` 8 | -MemberType ScriptMethod -PassThru -Value ` 9 | { [int] $this } | 10 | Add-Member -Name ToLong ` 11 | -MemberType ScriptMethod -PassThru -Value ` 12 | { [long] $this } | 13 | Add-Member -Name ToDouble ` 14 | -MemberType ScriptMethod -PassThru -Value ` 15 | { [double] $this } | 16 | Add-Member -Name ToDecimal ` 17 | -MemberType ScriptMethod -PassThru -Value ` 18 | { [decimal] $this } | 19 | Add-Member -Name ToByte ` 20 | -MemberType ScriptMethod -PassThru -Value ` 21 | { [byte] $this } | 22 | Add-Member -Name ToBoolean ` 23 | -MemberType ScriptMethod -PassThru -Value ` 24 | { [System.Boolean]::Parse($this) } 25 | } 26 | -------------------------------------------------------------------------------- /Functions/Shadow-Copy.Tests.ps1: -------------------------------------------------------------------------------- 1 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path 2 | $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".") 3 | . "$here\$sut" 4 | 5 | Describe "Shadow-Copy" { 6 | 7 | Setup -File "testfile" 8 | $isolatedShadowPath = "$TestDrive\poweryaml\shadow" 9 | 10 | It "copies a file to a transient location" { 11 | Shadow-Copy -File "$TestDrive\testfile" -ShadowPath $isolatedShadowPath 12 | "$isolatedShadowPath\testfile" | Should Exist 13 | } 14 | 15 | It "returns a path to the shadow copied file" { 16 | $shadow = Shadow-Copy -File "$TestDrive\testfile" -ShadowPath $isolatedShadowPath 17 | $shadow | Should Be "$isolatedShadowPath\testfile" 18 | } 19 | 20 | It "does not complain if trying to overwrite locked files" { 21 | $file = [System.io.File]::Open("$isolatedShadowPath\testfile", 'Open', 'Read', 'None') 22 | $shadow = Shadow-Copy -File "$TestDrive\testfile" -ShadowPath $isolatedShadowPath 23 | $file.Close() 24 | "made it here, therefore no errors" | Should Be "made it here, therefore no errors" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Functions/Shadow-Copy.ps1: -------------------------------------------------------------------------------- 1 | function Shadow-Copy($file, $shadowPath = "$($env:TEMP)\poweryaml\shadow") { 2 | 3 | if (-not (Test-Path $shadowPath ) ) { 4 | New-Item $shadowPath -ItemType directory | Out-Null 5 | } 6 | 7 | try { 8 | Copy-Item $file $shadowPath -Force -ErrorAction SilentlyContinue 9 | } catch { 10 | "Attempted to write over locked file, continuing..." | Write-Debug 11 | } 12 | 13 | $fileName = (Get-Item $file).Name 14 | "$shadowPath\$fileName" 15 | } 16 | -------------------------------------------------------------------------------- /Functions/Validator-Functions.Tests.ps1: -------------------------------------------------------------------------------- 1 | $pwd = Split-Path -Parent $MyInvocation.MyCommand.Path 2 | $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests", "") 3 | . "$pwd\$sut" 4 | 5 | Describe "Detect-Tab" { 6 | 7 | It "should return the line number the first TAB character is found on" { 8 | $lines = @() 9 | $lines += "valide: yaml" 10 | $lines += " `t " 11 | $line_number_tab_is_in = 2 12 | 13 | $result = Detect-Tab $lines 14 | $result | Should Be $line_number_tab_is_in 15 | } 16 | 17 | It "should return 0 if no TAB character is found in text" { 18 | $result = Detect-Tab " " 19 | $result | Should Be 0 20 | } 21 | } 22 | 23 | Describe "Validate-File" { 24 | 25 | Setup -File "exists.yml" 26 | 27 | It "should return false if a file does not exist" { 28 | $result = Validate-File "some non existent file" 29 | $result | Should Be $false 30 | } 31 | 32 | It "should return true for a file that does exist and does not contain a TAB character" { 33 | $result = Validate-File "$TestDrive\exists.yml" 34 | $result | Should Be $true 35 | } 36 | } 37 | 38 | Describe "Validating a file with tabs" { 39 | 40 | Setup -File "bad.yml" " `t " 41 | 42 | It "should return false" { 43 | Trap [Exception] { 44 | Write-Host caught error 45 | } 46 | $result = Validate-File "$TestDrive\bad.yml" 47 | $result | Should Be $false 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Functions/Validator-Functions.ps1: -------------------------------------------------------------------------------- 1 | function Validate-File([string] $file) { 2 | $file_exists = Test-Path $file 3 | if (-not $file_exists) { 4 | "ERROR: '$file' does not exist" | Write-Error 5 | return $false 6 | } 7 | 8 | $lines_in_file = [System.IO.File]::ReadAllLines($file) 9 | $line_tab_detected = Detect-Tab $lines_in_file 10 | 11 | if ($line_tab_detected -gt 0) { 12 | "ERROR in '$file'`nTAB detected on line $line_tab_detected" | Write-Error 13 | return $false 14 | } 15 | 16 | return $true 17 | } 18 | 19 | function Detect-Tab($lines) { 20 | for($i = 0; $i -lt $lines.count; $i++) { 21 | [string] $line = $lines[$i] 22 | if ($line.Contains("`t")) { 23 | return ($i + 1) 24 | } 25 | } 26 | 27 | return 0 28 | } 29 | -------------------------------------------------------------------------------- /Functions/YamlDotNet-Integration.Tests.ps1: -------------------------------------------------------------------------------- 1 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path 2 | . "$here\Casting.ps1" 3 | . "$here\Shadow-Copy.ps1" 4 | . "$here\YamlDotNet-Integration.ps1" 5 | 6 | $libDir = "$here\..\Libs" 7 | Describe "Load-YamlDotNetLibraries" { 8 | 9 | Setup -Dir "Libs" 10 | Copy-Item "$libDir\*.dll" "$TestDrive\Libs" 11 | 12 | It "loads assemblies in a way that the dll's can be deleted after loading" { 13 | $testLibDir = "$TestDrive\Libs" 14 | Load-YamlDotNetLibraries $testLibDir 15 | Remove-Item $testLibDir -Recurse 16 | $testLibDir | Should Not Exist 17 | } 18 | } 19 | 20 | #Note The rest of the tests are dependent on the above test passing :-( 21 | Describe "Convert-YamlScalarNodeToValue" { 22 | 23 | It "takes a YamlScalar and converts it to a value type" { 24 | $node = New-Object YamlDotNet.RepresentationModel.YamlScalarNode 5 25 | $result = Convert-YamlScalarNodeToValue $node 26 | 27 | $result | Should Be 5 28 | } 29 | } 30 | 31 | Describe "Convert-YamlSequenceNodeToList" { 32 | 33 | It "taks a YamlSequence and converts it to an array" { 34 | $yaml = Get-YamlDocumentFromString "---`n- single item`n- second item" 35 | 36 | $result = Convert-YamlSequenceNodeToList $yaml.RootNode 37 | $result.count | Should Be 2 38 | } 39 | 40 | } 41 | 42 | Describe "Convert-YamlMappingNodeToHash" { 43 | 44 | It "takes a YamlMappingNode and converts it to a hash" { 45 | $yaml = Get-YamlDocumentFromString "---`nkey1: value1`nkey2: value2" 46 | 47 | $result = Convert-YamlMappingNodeToHash $yaml.RootNode 48 | $result.keys.count | Should Be 2 49 | } 50 | 51 | } 52 | 53 | Describe "Get-YamlDocumentFromString" { 54 | 55 | It "will return a YamlDocument if given proper YAML" { 56 | $document = Get-YamlDocumentFromString "---" 57 | $document.GetType().Name | Should Be "YamlDocument" 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Functions/YamlDotNet-Integration.ps1: -------------------------------------------------------------------------------- 1 | function Load-YamlDotNetLibraries([string] $dllPath, $shadowPath = "$($env:TEMP)\poweryaml\shadow") { 2 | gci $dllPath | % { 3 | $shadow = Shadow-Copy -File $_.FullName -ShadowPath $shadowPath 4 | [Reflection.Assembly]::LoadFrom($shadow) 5 | } | Out-Null 6 | } 7 | 8 | function Get-YamlStream([string] $file) { 9 | $streamReader = [System.IO.File]::OpenText($file) 10 | $yamlStream = New-Object YamlDotNet.RepresentationModel.YamlStream 11 | 12 | $yamlStream.Load([System.IO.TextReader] $streamReader) 13 | $streamReader.Close() 14 | return $yamlStream 15 | } 16 | 17 | function Get-YamlDocument([string] $file) { 18 | $yamlStream = Get-YamlStream $file 19 | $document = $yamlStream.Documents[0] 20 | return $document 21 | } 22 | 23 | function Get-YamlDocumentFromString([string] $yamlString) { 24 | $stringReader = new-object System.IO.StringReader($yamlString) 25 | $yamlStream = New-Object YamlDotNet.RepresentationModel.YamlStream 26 | $yamlStream.Load([System.IO.TextReader] $stringReader) 27 | 28 | $document = $yamlStream.Documents[0] 29 | return $document 30 | } 31 | 32 | function Explode-Node($node) { 33 | if ($node.GetType().Name -eq "YamlScalarNode") { 34 | return Convert-YamlScalarNodeToValue $node 35 | } elseif ($node.GetType().Name -eq "YamlMappingNode") { 36 | return Convert-YamlMappingNodeToHash $node 37 | } elseif ($node.GetType().Name -eq "YamlSequenceNode") { 38 | return Convert-YamlSequenceNodeToList $node 39 | } 40 | } 41 | 42 | function Convert-YamlScalarNodeToValue($node) { 43 | return Add-CastingFunctions($node.Value) 44 | } 45 | 46 | function Convert-YamlMappingNodeToHash($node) { 47 | $hash = @{} 48 | $yamlNodes = $node.Children 49 | 50 | foreach($key in $yamlNodes.Keys) { 51 | $hash[$key.Value] = Explode-Node $yamlNodes[$key] 52 | } 53 | 54 | return $hash 55 | } 56 | 57 | function Convert-YamlSequenceNodeToList($node) { 58 | $list = @() 59 | $yamlNodes = $node.Children 60 | 61 | foreach($yamlNode in $yamlNodes) { 62 | $list += Explode-Node $yamlNode 63 | } 64 | 65 | return $list 66 | } 67 | 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011 Scott Muc and Manoj Mahalingam 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Libs/YamlDotNet.Configuration.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottmuc/PowerYaml/2de22fb0e62a982b1264ee6b7aa7eb61ce7c64c4/Libs/YamlDotNet.Configuration.dll -------------------------------------------------------------------------------- /Libs/YamlDotNet.Converters.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottmuc/PowerYaml/2de22fb0e62a982b1264ee6b7aa7eb61ce7c64c4/Libs/YamlDotNet.Converters.dll -------------------------------------------------------------------------------- /Libs/YamlDotNet.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottmuc/PowerYaml/2de22fb0e62a982b1264ee6b7aa7eb61ce7c64c4/Libs/YamlDotNet.Core.dll -------------------------------------------------------------------------------- /Libs/YamlDotNet.RepresentationModel.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottmuc/PowerYaml/2de22fb0e62a982b1264ee6b7aa7eb61ce7c64c4/Libs/YamlDotNet.RepresentationModel.dll -------------------------------------------------------------------------------- /PowerYaml.Tests.ps1: -------------------------------------------------------------------------------- 1 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path 2 | Import-Module $here\PowerYaml.psm1 -Force 3 | 4 | Describe "PoweYaml when parsing strings" { 5 | 6 | It "Obtains a HashTable given a yaml hash" { 7 | $yaml = Get-Yaml -FromString "key: value" 8 | $yaml.GetType().Name | Should Be "HashTable" 9 | } 10 | 11 | It "Obtains an Object[] given a yaml array" { 12 | $yaml = Get-Yaml -FromString "- test`n- test2" 13 | $yaml.GetType().Name | Should Be "Object[]" 14 | } 15 | } 16 | 17 | Describe "Using Power Yaml to read a file" { 18 | Setup -File "sample.yml" "test: value" 19 | 20 | It "Can read the file and get the value" { 21 | $yaml = Get-Yaml -FromFile "$TestDrive\sample.yml" 22 | $yaml.test | Should Be "value" 23 | } 24 | } 25 | 26 | Describe "Using Power Yaml to convert integer scalars" { 27 | if ($PSVersionTable.PSVersion -ge "3.0") { return } 28 | 29 | It "Obtains an int given an integer value" { 30 | $yaml = Get-Yaml -FromString "key: 5" 31 | $yaml.key.ToInt().GetType().Name | Should Be "Int32" 32 | } 33 | } 34 | 35 | Remove-Module PowerYaml 36 | -------------------------------------------------------------------------------- /PowerYaml.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PowerYaml 5 | 1.0.3 6 | PowerYaml 7 | A module to help parse YAML documents 8 | powershell yaml 9 | Scott Muc 10 | https://github.com/scottmuc/PowerYaml 11 | http://www.apache.org/licenses/LICENSE-2.0.html 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /PowerYaml.psm1: -------------------------------------------------------------------------------- 1 | . $PSScriptRoot\Functions\Casting.ps1 2 | . $PSScriptRoot\Functions\Shadow-Copy.ps1 3 | . $PSScriptRoot\Functions\YamlDotNet-Integration.ps1 4 | . $PSScriptRoot\Functions\Validator-Functions.ps1 5 | 6 | <# 7 | .Synopsis 8 | Returns an object that can be dot navigated 9 | 10 | .Parameter FromFile 11 | File reference to a yaml document 12 | 13 | .Parameter FromString 14 | Yaml string to be converted 15 | #> 16 | function Get-Yaml([string] $FromString = "", [string] $FromFile = "") { 17 | if ($FromString -ne "") { 18 | $yaml = Get-YamlDocumentFromString $FromString 19 | } elseif ($FromFile -ne "") { 20 | if ((Validate-File $FromFile)) { 21 | $yaml = Get-YamlDocument -file $FromFile 22 | } 23 | } 24 | 25 | return Explode-Node $yaml.RootNode 26 | } 27 | 28 | Load-YamlDotNetLibraries (Join-Path $PSScriptRoot -ChildPath "Libs") 29 | Export-ModuleMember -Function Get-Yaml 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **PowerYaml is no longer maintained! Please check out the following alternatives** 2 | 3 | * https://github.com/Phil-Factor/PSYaml 4 | * https://github.com/cloudbase/powershell-yaml 5 | * https://github.com/cdhunt/PowerYaml (a fork of this repository) 6 | 7 | Please send me PRs to update this `README` if there are other ones. I know this repository generally shows up 8 | pretty high up in search engine results for `powershell yaml` queries. 9 | -------------------------------------------------------------------------------- /package.ps1: -------------------------------------------------------------------------------- 1 | 2 | if (Test-Path "build") { 3 | Remove-Item "build" -Recurse -Force 4 | } 5 | 6 | mkdir build 7 | vendor\tools\nuget pack PowerYaml.nuspec -OutputDirectory build 8 | -------------------------------------------------------------------------------- /vendor/tools/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scottmuc/PowerYaml/2de22fb0e62a982b1264ee6b7aa7eb61ce7c64c4/vendor/tools/NuGet.exe --------------------------------------------------------------------------------