iapi-idlc-sdk-pfm 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +6 -0
  7. data/Jenkinsfile +21 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +37 -0
  10. data/Rakefile +6 -0
  11. data/bin/pfm +8 -0
  12. data/docs/GettingStarted.md +299 -0
  13. data/iapi-idlc-sdk-pfm.gemspec +50 -0
  14. data/lib/iapi-idlc-sdk-pfm/builtin_commands.rb +12 -0
  15. data/lib/iapi-idlc-sdk-pfm/cli.rb +150 -0
  16. data/lib/iapi-idlc-sdk-pfm/command/apply.rb +86 -0
  17. data/lib/iapi-idlc-sdk-pfm/command/base.rb +255 -0
  18. data/lib/iapi-idlc-sdk-pfm/command/build.rb +121 -0
  19. data/lib/iapi-idlc-sdk-pfm/command/configure.rb +41 -0
  20. data/lib/iapi-idlc-sdk-pfm/command/destroy.rb +77 -0
  21. data/lib/iapi-idlc-sdk-pfm/command/exec.rb +24 -0
  22. data/lib/iapi-idlc-sdk-pfm/command/format.rb +64 -0
  23. data/lib/iapi-idlc-sdk-pfm/command/generate.rb +83 -0
  24. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/base.rb +50 -0
  25. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/server_build.rb +58 -0
  26. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/Berksfile +3 -0
  27. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/.kitchen.yml +21 -0
  28. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/README.md +146 -0
  29. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/test-fixture-recipe.rb +8 -0
  30. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/chefignore +107 -0
  31. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/cookbook_readmes/README-policy.md +9 -0
  32. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/cookbook_readmes/README.md +54 -0
  33. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/delivery-config.json +12 -0
  34. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/delivery-project.toml +36 -0
  35. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/gitignore +21 -0
  36. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/README.md +24 -0
  37. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/README.md +27 -0
  38. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +7 -0
  39. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +6 -0
  40. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +8 -0
  41. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/data_bags/README.md +56 -0
  42. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/data_bags/example/example_item.json +4 -0
  43. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/dot-chef-repo.txt +6 -0
  44. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/environments/README.md +9 -0
  45. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/environments/example.json +13 -0
  46. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/policies/README.md +24 -0
  47. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/roles/README.md +9 -0
  48. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/roles/example.json +13 -0
  49. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/spec_helper.rb +2 -0
  50. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/spec_helper_policyfile.rb +2 -0
  51. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/metadata.rb +7 -0
  52. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/app.rb +89 -0
  53. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/attribute.rb +12 -0
  54. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/build_cookbook.rb +182 -0
  55. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/cookbook.rb +144 -0
  56. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/cookbook_file.rb +24 -0
  57. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/lwrp.rb +23 -0
  58. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/policyfile.rb +8 -0
  59. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/recipe.rb +51 -0
  60. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/repo.rb +67 -0
  61. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/template.rb +32 -0
  62. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -0
  63. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.apachev2.erb +201 -0
  64. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -0
  65. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -0
  66. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -0
  67. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/Policyfile.rb.erb +25 -0
  68. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/README.md.erb +4 -0
  69. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/attribute.rb.erb +0 -0
  70. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/Berksfile.erb +7 -0
  71. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/metadata.rb.erb +10 -0
  72. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/recipe.rb.erb +8 -0
  73. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/cookbook_file.erb +0 -0
  74. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/inspec_default_test.rb.erb +18 -0
  75. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/kitchen.yml.erb +26 -0
  76. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/kitchen_policyfile.yml.erb +33 -0
  77. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/metadata.rb.erb +20 -0
  78. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/provider.rb.erb +0 -0
  79. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/recipe.rb.erb +5 -0
  80. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/recipe_spec.rb.erb +22 -0
  81. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/repo/gitignore.erb +128 -0
  82. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/resource.rb.erb +0 -0
  83. data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/template.erb +0 -0
  84. data/lib/iapi-idlc-sdk-pfm/command/generator_commands.rb +34 -0
  85. data/lib/iapi-idlc-sdk-pfm/command/package.rb +118 -0
  86. data/lib/iapi-idlc-sdk-pfm/command/plan.rb +96 -0
  87. data/lib/iapi-idlc-sdk-pfm/command/templates/app/files/config/client.rb.template +9 -0
  88. data/lib/iapi-idlc-sdk-pfm/command/templates/app/files/config/init.ps1.userdata +16 -0
  89. data/lib/iapi-idlc-sdk-pfm/command/templates/base/files/config/client.rb.template +9 -0
  90. data/lib/iapi-idlc-sdk-pfm/command/templates/base/files/config/init.ps1.userdata +219 -0
  91. data/lib/iapi-idlc-sdk-pfm/command/validate.rb +85 -0
  92. data/lib/iapi-idlc-sdk-pfm/command/validator_commands/base.rb +65 -0
  93. data/lib/iapi-idlc-sdk-pfm/command/validator_commands/infrastructure.rb +46 -0
  94. data/lib/iapi-idlc-sdk-pfm/command/validator_commands/server_build.rb +135 -0
  95. data/lib/iapi-idlc-sdk-pfm/command/validator_commands.rb +32 -0
  96. data/lib/iapi-idlc-sdk-pfm/commands_map.rb +61 -0
  97. data/lib/iapi-idlc-sdk-pfm/generator.rb +52 -0
  98. data/lib/iapi-idlc-sdk-pfm/helpers.rb +49 -0
  99. data/lib/iapi-idlc-sdk-pfm/settings.rb +205 -0
  100. data/lib/iapi-idlc-sdk-pfm/validator.rb +52 -0
  101. data/lib/iapi-idlc-sdk-pfm/version.rb +4 -0
  102. data/lib/iapi-idlc-sdk-pfm.rb +27 -0
  103. metadata +442 -0
@@ -0,0 +1,219 @@
1
+ <powershell>
2
+ # Configure a Windows host for remote management with Ansible
3
+ # -----------------------------------------------------------
4
+ #
5
+ # This script checks the current WinRM/PSRemoting configuration and makes the
6
+ # necessary changes to allow Ansible to connect, authenticate and execute
7
+ # PowerShell commands.
8
+ #
9
+ # Set $VerbosePreference = "Continue" before running the script in order to
10
+ # see the output messages.
11
+ # Set $SkipNetworkProfileCheck to skip the network profile check. Without
12
+ # specifying this the script will only run if the device's interfaces are in
13
+ # DOMAIN or PRIVATE zones. Provide this switch if you want to enable winrm on
14
+ # a device with an interface in PUBLIC zone.
15
+ #
16
+ # Written by Trond Hindenes <trond@hindenes.com>
17
+ # Updated by Chris Church <cchurch@ansible.com>
18
+ # Updated by Michael Crilly <mike@autologic.cm>
19
+ #
20
+ # Version 1.0 - July 6th, 2014
21
+ # Version 1.1 - November 11th, 2014
22
+ # Version 1.2 - May 15th, 2015
23
+
24
+ Param (
25
+ [string]$SubjectName = $env:COMPUTERNAME,
26
+ [int]$CertValidityDays = 365,
27
+ [switch]$SkipNetworkProfileCheck,
28
+ $CreateSelfSignedCert = $true
29
+ )
30
+
31
+ Function New-LegacySelfSignedCert
32
+ {
33
+ Param (
34
+ [string]$SubjectName,
35
+ [int]$ValidDays = 365
36
+ )
37
+
38
+ $name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1"
39
+ $name.Encode("CN=$SubjectName", 0)
40
+
41
+ $key = New-Object -COM "X509Enrollment.CX509PrivateKey.1"
42
+ $key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
43
+ $key.KeySpec = 1
44
+ $key.Length = 1024
45
+ $key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
46
+ $key.MachineContext = 1
47
+ $key.Create()
48
+
49
+ $serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1"
50
+ $serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
51
+ $ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1"
52
+ $ekuoids.Add($serverauthoid)
53
+ $ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
54
+ $ekuext.InitializeEncode($ekuoids)
55
+
56
+ $cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1"
57
+ $cert.InitializeFromPrivateKey(2, $key, "")
58
+ $cert.Subject = $name
59
+ $cert.Issuer = $cert.Subject
60
+ $cert.NotBefore = (Get-Date).AddDays(-1)
61
+ $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays)
62
+ $cert.X509Extensions.Add($ekuext)
63
+ $cert.Encode()
64
+
65
+ $enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1"
66
+ $enrollment.InitializeFromRequest($cert)
67
+ $certdata = $enrollment.CreateRequest(0)
68
+ $enrollment.InstallResponse(2, $certdata, 0, "")
69
+
70
+ # Return the thumbprint of the last installed certificate;
71
+ # This is needed for the new HTTPS WinRM listerner we're
72
+ # going to create further down.
73
+ Get-ChildItem "Cert:\LocalMachine\my"| Sort-Object NotBefore -Descending | Select -First 1 | Select -Expand Thumbprint
74
+ }
75
+
76
+ # Setup error handling.
77
+ Trap
78
+ {
79
+ $_
80
+ Exit 1
81
+ }
82
+ $ErrorActionPreference = "Stop"
83
+
84
+ # Detect PowerShell version.
85
+ If ($PSVersionTable.PSVersion.Major -lt 3)
86
+ {
87
+ Throw "PowerShell version 3 or higher is required."
88
+ }
89
+
90
+ # Find and start the WinRM service.
91
+ Write-Verbose "Verifying WinRM service."
92
+ If (!(Get-Service "WinRM"))
93
+ {
94
+ Throw "Unable to find the WinRM service."
95
+ }
96
+ ElseIf ((Get-Service "WinRM").Status -ne "Running")
97
+ {
98
+ Write-Verbose "Starting WinRM service."
99
+ Start-Service -Name "WinRM" -ErrorAction Stop
100
+ }
101
+
102
+ # WinRM should be running; check that we have a PS session config.
103
+ If (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\localhost\Listener)))
104
+ {
105
+ if ($SkipNetworkProfileCheck) {
106
+ Write-Verbose "Enabling PS Remoting without checking Network profile."
107
+ Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop
108
+ }
109
+ else {
110
+ Write-Verbose "Enabling PS Remoting"
111
+ Enable-PSRemoting -Force -ErrorAction Stop
112
+ }
113
+ }
114
+ Else
115
+ {
116
+ Write-Verbose "PS Remoting is already enabled."
117
+ }
118
+
119
+ # Make sure there is a SSL listener.
120
+ $listeners = Get-ChildItem WSMan:\localhost\Listener
121
+ If (!($listeners | Where {$_.Keys -like "TRANSPORT=HTTPS"}))
122
+ {
123
+ # HTTPS-based endpoint does not exist.
124
+ If (Get-Command "New-SelfSignedCertificate" -ErrorAction SilentlyContinue)
125
+ {
126
+ $cert = New-SelfSignedCertificate -DnsName $SubjectName -CertStoreLocation "Cert:\LocalMachine\My"
127
+ $thumbprint = $cert.Thumbprint
128
+ Write-Host "Self-signed SSL certificate generated; thumbprint: $thumbprint"
129
+ }
130
+ Else
131
+ {
132
+ $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName
133
+ Write-Host "(Legacy) Self-signed SSL certificate generated; thumbprint: $thumbprint"
134
+ }
135
+
136
+ # Create the hashtables of settings to be used.
137
+ $valueset = @{}
138
+ $valueset.Add('Hostname', $SubjectName)
139
+ $valueset.Add('CertificateThumbprint', $thumbprint)
140
+
141
+ $selectorset = @{}
142
+ $selectorset.Add('Transport', 'HTTPS')
143
+ $selectorset.Add('Address', '*')
144
+
145
+ Write-Verbose "Enabling SSL listener."
146
+ New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset
147
+ }
148
+ Else
149
+ {
150
+ Write-Verbose "SSL listener is already active."
151
+ }
152
+
153
+ # Check for basic authentication.
154
+ $basicAuthSetting = Get-ChildItem WSMan:\localhost\Service\Auth | Where {$_.Name -eq "Basic"}
155
+ If (($basicAuthSetting.Value) -eq $false)
156
+ {
157
+ Write-Verbose "Enabling basic auth support."
158
+ Set-Item -Path "WSMan:\localhost\Service\Auth\Basic" -Value $true
159
+ }
160
+ Else
161
+ {
162
+ Write-Verbose "Basic auth is already enabled."
163
+ }
164
+
165
+ # Configure firewall to allow WinRM HTTPS connections.
166
+ $fwtest1 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS"
167
+ $fwtest2 = netsh advfirewall firewall show rule name="Allow WinRM HTTPS" profile=any
168
+ If ($fwtest1.count -lt 5)
169
+ {
170
+ Write-Verbose "Adding firewall rule to allow WinRM HTTPS."
171
+ netsh advfirewall firewall add rule profile=any name="Allow WinRM HTTPS" dir=in localport=5986 protocol=TCP action=allow
172
+ }
173
+ ElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5))
174
+ {
175
+ Write-Verbose "Updating firewall rule to allow WinRM HTTPS for any profile."
176
+ netsh advfirewall firewall set rule name="Allow WinRM HTTPS" new profile=any
177
+ }
178
+ Else
179
+ {
180
+ Write-Verbose "Firewall rule already exists to allow WinRM HTTPS."
181
+ }
182
+
183
+ # Test a remoting connection to localhost, which should work.
184
+ $httpResult = Invoke-Command -ComputerName "localhost" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue
185
+ $httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
186
+
187
+ $httpsResult = New-PSSession -UseSSL -ComputerName "localhost" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue
188
+
189
+ If ($httpResult -and $httpsResult)
190
+ {
191
+ Write-Verbose "HTTP: Enabled | HTTPS: Enabled"
192
+ }
193
+ ElseIf ($httpsResult -and !$httpResult)
194
+ {
195
+ Write-Verbose "HTTP: Disabled | HTTPS: Enabled"
196
+ }
197
+ ElseIf ($httpResult -and !$httpsResult)
198
+ {
199
+ Write-Verbose "HTTP: Enabled | HTTPS: Disabled"
200
+ }
201
+ Else
202
+ {
203
+ Throw "Unable to establish an HTTP or HTTPS remoting session."
204
+ }
205
+ Write-Verbose "PS Remoting has been successfully configured for Ansible."
206
+
207
+ # Change the Administrator password to something temporary for provisioning.
208
+ # This will be changed back to something secure on deployment, so we can safely
209
+ # store this password in plain text in SCM.
210
+ $user = "Administrator"
211
+ $pass = 'Aut0m@t0r'
212
+ $newpass = [ADSI]"WinNT://localhost/$user,user"
213
+ $newpass.SetPassword($pass)
214
+ $newpass.SetInfo()
215
+
216
+ # Turn off PowerShell execution policy restrictions
217
+ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine
218
+
219
+ </powershell>
@@ -0,0 +1,85 @@
1
+ require 'iapi-idlc-sdk-pfm/command/base'
2
+ require 'iapi-idlc-sdk-pfm/command/validator_commands'
3
+ require 'iapi-idlc-sdk-pfm/command/validator_commands/base'
4
+ require 'iapi-idlc-sdk-pfm/command/validator_commands/server_build'
5
+ require 'iapi-idlc-sdk-pfm/command/validator_commands/infrastructure'
6
+
7
+ module Pfm
8
+ module Command
9
+ class Validate < Base
10
+
11
+ ValidatorCommand = Struct.new(:name, :class_name, :description)
12
+
13
+ def self.validators
14
+ @validators ||= []
15
+ end
16
+
17
+ def self.validator(name, class_name, description)
18
+ validators << ValidatorCommand.new(name, class_name, description)
19
+ end
20
+
21
+ validator('server-build', :ServerBuild, 'Validate a server build repo')
22
+ validator('infrastructure', :Infrastructure, 'Validate an infrastructure repo')
23
+
24
+ def self.banner_headline
25
+ <<-E
26
+ Usage: pfm validate VALIDATOR [options]
27
+ Available validators:
28
+ E
29
+ end
30
+
31
+ def self.validator_list
32
+ justify_size = validators.map { |g| g.name.size }.max + 2
33
+ validators.map { |g| " #{g.name.to_s.ljust(justify_size)}#{g.description}" }.join("\n")
34
+ end
35
+
36
+ def self.banner
37
+ banner_headline + validator_list + "\n"
38
+ end
39
+
40
+ # pfm validate app path/to/basename --skel=path/to/skeleton --example
41
+ # pfm validate file name [path/to/cookbook_root] (inferred from cwd) --from=source_file
42
+
43
+ def initialize(*args)
44
+ super
45
+ end
46
+
47
+ def run(params)
48
+ if validator_spec = validator_for(params[0])
49
+ params.shift
50
+ validator = ValidatorCommands.build(validator_spec.class_name, params)
51
+ validator.run
52
+ else
53
+ msg(banner)
54
+ 1
55
+ end
56
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
57
+ # Pfm::Command::Base also handles this error in the same way, but it
58
+ # does not have access to the correct option parser, so it cannot print
59
+ # the usage correctly. Therefore, invalid CLI usage needs to be handled
60
+ # here.
61
+ err("ERROR: #{e.message}\n")
62
+ msg(validator.opt_parser)
63
+ 1
64
+ end
65
+
66
+ def validator_for(arg)
67
+ self.class.validators.find { |g| g.name.to_s == arg }
68
+ end
69
+
70
+ # In the Base class, this is defined to be true if any args match "-h" or
71
+ # "--help". Here we override that behavior such that if the first
72
+ # argument is a valid validator name, like `pfm validate server-build -h`,
73
+ # we delegate the request to the specified validator.
74
+ def needs_help?(params)
75
+ return false if have_validator?(params[0])
76
+ super
77
+ end
78
+
79
+ def have_validator?(name)
80
+ self.class.validators.map { |g| g.name.to_s }.include?(name)
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,65 @@
1
+ require "idlc-sdk-pfm/command/validator_commands"
2
+
3
+ module Pfm
4
+ module Command
5
+ module ValidatorCommands
6
+ class ValidationError < StandardError; end
7
+
8
+ class Base < Command::Base
9
+ attr_reader :params
10
+ attr_reader :errors
11
+
12
+ options.merge!(SharedValidatorOptions.options)
13
+
14
+ def initialize(params)
15
+ super()
16
+ @params_valid = true
17
+ @errors = []
18
+ @params = params
19
+ @failure = false
20
+
21
+ @reports_dir = "#{Pfm::Settings.new.config_directory}/tests/reports"
22
+ @artifacts_dir = "#{Pfm::Settings.new.config_directory}/tests/artifacts"
23
+ end
24
+
25
+ def setup_context; end
26
+
27
+ def read_and_validate_params
28
+ arguments = parse_options(@params)
29
+
30
+ case arguments.size
31
+ when 0
32
+ @params_valid = (@config[:validator_name] == 'infrastructure')
33
+
34
+ when 1
35
+ @params_valid = build_exists?
36
+
37
+ when 2
38
+
39
+ else
40
+ @params_valid = false
41
+ end
42
+ end
43
+
44
+ def params_valid?
45
+ @params_valid
46
+ end
47
+
48
+ def use_circle_ci?
49
+ @params.include?('-c') || @params.include?('--circle-ci')
50
+ end
51
+
52
+ def setup_artifacts_dirs
53
+ if use_circle_ci?
54
+ @reports_dir = ENV['CIRCLE_TEST_REPORTS']
55
+ @artifacts_dir = ENV['CIRCLE_ARTIFACTS']
56
+ return
57
+ end
58
+
59
+ FileUtils.mkdir_p(@reports_dir)
60
+ FileUtils.mkdir_p(@artifacts_dir)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,46 @@
1
+ module Pfm
2
+ module Command
3
+ module ValidatorCommands
4
+ class Infrastructure < Base
5
+ banner 'Usage: pfm validate infrastructure [options]'
6
+
7
+ option :app_release,
8
+ short: '-a VERSION',
9
+ long: '--app-release VERSION',
10
+ description: 'Application Version Number to Deploy',
11
+ default: ''
12
+
13
+ options.merge!(SharedValidatorOptions.options)
14
+
15
+ def run
16
+ @config[:validator_name] = 'infrastructure'
17
+
18
+ read_and_validate_params
19
+ setup_artifacts_dirs
20
+
21
+ if params_valid?
22
+ deploy_setup
23
+ validate
24
+ # @workspace.cleanup causing bundler issues
25
+ 0
26
+ else
27
+ errors.each { |error| err("Error: #{error}") }
28
+ parse_options(params)
29
+ msg(opt_parser)
30
+ 1
31
+ end
32
+ rescue ValidationError => e
33
+ err("ERROR: #{e}")
34
+ 1
35
+ end
36
+
37
+ def validate
38
+ Terraform::Binary.validate(@workspace.tmp_dir.to_s)
39
+ msg('Verified repository..')
40
+ rescue Terraform::Binary::Command::CommandFailure
41
+ raise ValidationError, 'Failures reported during validation!'
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,135 @@
1
+ module Pfm
2
+ module Command
3
+ module ValidatorCommands
4
+ class ServerBuild < Base
5
+ banner 'Usage: pfm validate server-build BUILD_NAME [options]'
6
+
7
+ option :build_version,
8
+ short: '-b VERSION',
9
+ long: '--build-version VERSION',
10
+ description: 'override version number of build',
11
+ default: nil
12
+
13
+ option :build_template,
14
+ short: '-t TEMPLATE',
15
+ long: '--build-template TEMPLATE',
16
+ description: 'The Build Template to use. Defaults to build.json',
17
+ default: 'build.json'
18
+
19
+ option :build_metadata,
20
+ short: '-m METADATA_FILE',
21
+ long: '--build-metadata METADATA_FILE',
22
+ description: 'The build metadata file to use. Defaults to \'metadata\'',
23
+ default: 'metadata'
24
+
25
+ options.merge!(SharedValidatorOptions.options)
26
+
27
+ def run
28
+ read_and_validate_params
29
+ setup_artifacts_dirs
30
+
31
+ if params_valid?
32
+ build_setup
33
+ validate
34
+ # @workspace.cleanup causing bundler issues
35
+ 0
36
+ else
37
+ errors.each { |error| err("Error: #{error}") }
38
+ parse_options(params)
39
+ msg(opt_parser)
40
+ 1
41
+ end
42
+ rescue ValidationError => e
43
+ err("ERROR: #{e}")
44
+ 1
45
+ end
46
+
47
+ def validate
48
+ lint_packer
49
+ lint_chef
50
+ unit_test
51
+
52
+ raise ValidationError, 'Failures reported during validation!' if @failure
53
+ msg('Verified repository..')
54
+ end
55
+
56
+ def lint_packer
57
+ Packer::Binary.validate("#{@build_config.dump_build_vars} #{@config[:build_template]}")
58
+ rescue Packer::Binary::Command::CommandFailure
59
+ @failure = true
60
+ end
61
+
62
+ def lint_chef
63
+ base_path = 'chef'
64
+ cookbooks_dir = 'cookbooks'
65
+
66
+ # Loop through the base directory looking through all of the cookbooks
67
+ # for unit tests
68
+ Dir.entries(base_path).each do |dir|
69
+ next unless File.directory? "#{base_path}/#{dir}/#{cookbooks_dir}"
70
+ next if dir.to_s == 'vendor'
71
+
72
+ Dir.entries("#{base_path}/#{dir}/#{cookbooks_dir}").each do |cookbook|
73
+ next unless File.directory? "#{base_path}/#{dir}/#{cookbooks_dir}/#{cookbook}"
74
+ # skip directories eg. '.' and '..'
75
+ next if cookbook.to_s == '.' || cookbook.to_s == '..'
76
+
77
+ # Run the syntax and semantics checkers
78
+ msg("\nRunning Rubocop on #{cookbook} cookbook")
79
+
80
+ # Copy in global .foodcritic file if set
81
+ debug("copying #{SETTINGS['RUBOCOP_RULES_FILE']} to #{Dir.pwd}")
82
+ system("cp #{SETTINGS['RUBOCOP_RULES_FILE']} #{Dir.pwd}") if File.exist? SETTINGS['RUBOCOP_RULES_FILE']
83
+
84
+ gem_path = `bundle show rubocop-junit-formatter`.strip!
85
+ system("rubocop \\
86
+ --format html -o #{@artifacts_dir}/rubocop/#{cookbook}_rubocop_output.html \\
87
+ -r #{gem_path}/lib/rubocop/formatter/junit_formatter.rb \\
88
+ --format RuboCop::Formatter::JUnitFormatter -o #{@reports_dir}/rubocop/#{cookbook}_junit.xml \\
89
+ #{base_path}/#{dir}/#{cookbooks_dir}/#{cookbook}") || @failure = true
90
+
91
+ msg("Running Foodcritic on #{cookbook} cookbook")
92
+ ENV['FOODCRITIC_JUNIT_OUTPUT_DIR'] = "#{@reports_dir}/foodcritic"
93
+ ENV['FOODCRITIC_JUNIT_OUTPUT_FILE'] = "#{cookbook}_foodcritic_junit.xml"
94
+
95
+ # Copy in global .foodcritic file if set
96
+ debug("copying #{SETTINGS['FOODCRITIC_RULES_FILE']} to #{Dir.pwd}")
97
+ system("cp #{SETTINGS['FOODCRITIC_RULES_FILE']} #{base_path}/#{dir}/#{cookbooks_dir}/#{cookbook}") if File.exist? SETTINGS['FOODCRITIC_RULES_FILE']
98
+
99
+ # Capure output but also fail if applicable
100
+ system("foodcritic #{base_path}/#{dir}/#{cookbooks_dir}/#{cookbook} -C > #{cookbook}_foodcritic.out") || @failure = true
101
+ system("foodcritic-junit < #{cookbook}_foodcritic.out")
102
+ end
103
+ end
104
+ end
105
+
106
+ def unit_test
107
+ # load chefspec here as it load chef and can take a long time on some systems
108
+ # so we only want to load it when we absolutely need it
109
+ require 'chefspec'
110
+ base_path = 'chef'
111
+ cookbooks_dir = 'cookbooks'
112
+
113
+ # Loop through the base directory looking through all of the cookbooks
114
+ # for unit tests
115
+ Dir.entries(base_path).each do |dir|
116
+ next unless File.directory? "#{base_path}/#{dir}/#{cookbooks_dir}"
117
+ next if dir.to_s == 'vendor'
118
+
119
+ Dir.entries("#{base_path}/#{dir}/#{cookbooks_dir}").each do |cookbook|
120
+ next unless File.directory? "#{base_path}/#{dir}/#{cookbooks_dir}/#{cookbook}"
121
+ # skip directories eg. '.' and '..'
122
+ next if cookbook.to_s == '.' || cookbook.to_s == '..'
123
+
124
+ # run rspec unit tests
125
+ Dir.chdir("#{base_path}/#{dir}/#{cookbooks_dir}/#{cookbook}") do
126
+ msg("\nRunning unit tests for #{cookbook} cookbook")
127
+ system("rspec -r rspec_junit_formatter --format progress --format RspecJunitFormatter -o #{@reports_dir}/rspec/#{cookbook}_junit.xml") || @failure = true
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,32 @@
1
+ require 'mixlib/cli'
2
+ require 'rbconfig'
3
+ require 'pathname'
4
+ require 'iapi-idlc-sdk-pfm/command/base'
5
+ require 'iapi-idlc-sdk-pfm/validator'
6
+
7
+ module Pfm
8
+ module Command
9
+ # ## SharedValidatorOptions
10
+ #
11
+ # These CLI options are shared amongst the validator commands
12
+ module SharedValidatorOptions
13
+ include Mixlib::CLI
14
+
15
+ option :circle_ci,
16
+ short: '-c',
17
+ long: '--circle-ci',
18
+ description: 'Use Circle Ci artifact output directories',
19
+ boolean: true,
20
+ default: false
21
+ end
22
+
23
+ # ## ValidatorCommands
24
+ #
25
+ # This module is the namespace for all subcommands of `pfm validate`
26
+ module ValidatorCommands
27
+ def self.build(class_name, params)
28
+ const_get(class_name).new(params)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,61 @@
1
+ module Pfm
2
+ class CommandsMap
3
+ NULL_ARG = Object.new
4
+
5
+ CommandSpec = Struct.new(:name, :constant_name, :require_path, :description)
6
+
7
+ class CommandSpec
8
+
9
+ def instantiate
10
+ require require_path
11
+ command_class = Pfm::Command.const_get(constant_name)
12
+ command_class.new
13
+ end
14
+
15
+ end
16
+
17
+ attr_reader :command_specs
18
+
19
+ def initialize
20
+ @command_specs = {}
21
+ end
22
+
23
+ def builtin(name, constant_name, require_path: NULL_ARG, desc: "")
24
+ if null?(require_path)
25
+ snake_case_path = name.tr("-", "_")
26
+ require_path = "iapi-idlc-sdk-pfm/command/#{snake_case_path}"
27
+ end
28
+ command_specs[name] = CommandSpec.new(name, constant_name, require_path, desc)
29
+ end
30
+
31
+ def instantiate(name)
32
+ spec_for(name).instantiate
33
+ end
34
+
35
+ def have_command?(name)
36
+ command_specs.key?(name)
37
+ end
38
+
39
+ def command_names
40
+ command_specs.keys
41
+ end
42
+
43
+ def spec_for(name)
44
+ command_specs[name]
45
+ end
46
+
47
+ private
48
+
49
+ def null?(argument)
50
+ argument.equal?(NULL_ARG)
51
+ end
52
+ end
53
+
54
+ def self.commands_map
55
+ @commands_map ||= CommandsMap.new
56
+ end
57
+
58
+ def self.commands
59
+ yield commands_map
60
+ end
61
+ end
@@ -0,0 +1,52 @@
1
+ module Pfm
2
+ module Generator
3
+ # This is here to hold attr_accessor data for Generator context variables
4
+ class Context
5
+ def self.add_attr(name)
6
+ @attributes ||= []
7
+
8
+ unless @attributes.include?(name)
9
+ @attributes << name
10
+ attr_accessor(name)
11
+ end
12
+ end
13
+
14
+ def self.reset
15
+ return if @attributes.nil?
16
+
17
+ @attributes.each do |attr|
18
+ remove_method(attr)
19
+ end
20
+
21
+ @attributes = nil
22
+ end
23
+ end
24
+
25
+ def self.reset
26
+ @context = nil
27
+ end
28
+
29
+ def self.context
30
+ @context ||= Context.new
31
+ end
32
+
33
+ def self.add_attr_to_context(name, value = nil)
34
+ sym_name = name.to_sym
35
+ Pfm::Generator::Context.add_attr(sym_name)
36
+ Pfm::Generator::TemplateHelper.delegate_to_app_context(sym_name)
37
+ context.public_send("#{sym_name}=", value)
38
+ end
39
+
40
+ module TemplateHelper
41
+ def self.delegate_to_app_context(name)
42
+ define_method(name) do
43
+ Pfm::Generator.context.public_send(name)
44
+ end
45
+ end
46
+
47
+ def year
48
+ Time.now.year
49
+ end
50
+ end
51
+ end
52
+ end