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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/.yardopts +3 -0
- data/Gemfile +6 -0
- data/Jenkinsfile +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +37 -0
- data/Rakefile +6 -0
- data/bin/pfm +8 -0
- data/docs/GettingStarted.md +299 -0
- data/iapi-idlc-sdk-pfm.gemspec +50 -0
- data/lib/iapi-idlc-sdk-pfm/builtin_commands.rb +12 -0
- data/lib/iapi-idlc-sdk-pfm/cli.rb +150 -0
- data/lib/iapi-idlc-sdk-pfm/command/apply.rb +86 -0
- data/lib/iapi-idlc-sdk-pfm/command/base.rb +255 -0
- data/lib/iapi-idlc-sdk-pfm/command/build.rb +121 -0
- data/lib/iapi-idlc-sdk-pfm/command/configure.rb +41 -0
- data/lib/iapi-idlc-sdk-pfm/command/destroy.rb +77 -0
- data/lib/iapi-idlc-sdk-pfm/command/exec.rb +24 -0
- data/lib/iapi-idlc-sdk-pfm/command/format.rb +64 -0
- data/lib/iapi-idlc-sdk-pfm/command/generate.rb +83 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/base.rb +50 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/server_build.rb +58 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/Berksfile +3 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/.kitchen.yml +21 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/README.md +146 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/build_cookbook/test-fixture-recipe.rb +8 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/chefignore +107 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/cookbook_readmes/README-policy.md +9 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/cookbook_readmes/README.md +54 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/delivery-config.json +12 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/delivery-project.toml +36 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/gitignore +21 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/README.md +24 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/README.md +27 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/attributes/default.rb +7 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/metadata.rb +6 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/cookbooks/example/recipes/default.rb +8 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/data_bags/README.md +56 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/data_bags/example/example_item.json +4 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/dot-chef-repo.txt +6 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/environments/README.md +9 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/environments/example.json +13 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/policies/README.md +24 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/roles/README.md +9 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/repo/roles/example.json +13 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/spec_helper.rb +2 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/files/default/spec_helper_policyfile.rb +2 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/metadata.rb +7 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/app.rb +89 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/attribute.rb +12 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/build_cookbook.rb +182 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/cookbook.rb +144 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/cookbook_file.rb +24 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/lwrp.rb +23 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/policyfile.rb +8 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/recipe.rb +51 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/repo.rb +67 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/recipes/template.rb +32 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.all_rights.erb +3 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.apachev2.erb +201 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.gplv2.erb +339 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.gplv3.erb +674 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/LICENSE.mit.erb +21 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/Policyfile.rb.erb +25 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/README.md.erb +4 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/attribute.rb.erb +0 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/Berksfile.erb +7 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/metadata.rb.erb +10 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/build_cookbook/recipe.rb.erb +8 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/cookbook_file.erb +0 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/inspec_default_test.rb.erb +18 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/kitchen.yml.erb +26 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/kitchen_policyfile.yml.erb +33 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/metadata.rb.erb +20 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/provider.rb.erb +0 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/recipe.rb.erb +5 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/recipe_spec.rb.erb +22 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/repo/gitignore.erb +128 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/resource.rb.erb +0 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands/skeletons/code_generator/templates/default/template.erb +0 -0
- data/lib/iapi-idlc-sdk-pfm/command/generator_commands.rb +34 -0
- data/lib/iapi-idlc-sdk-pfm/command/package.rb +118 -0
- data/lib/iapi-idlc-sdk-pfm/command/plan.rb +96 -0
- data/lib/iapi-idlc-sdk-pfm/command/templates/app/files/config/client.rb.template +9 -0
- data/lib/iapi-idlc-sdk-pfm/command/templates/app/files/config/init.ps1.userdata +16 -0
- data/lib/iapi-idlc-sdk-pfm/command/templates/base/files/config/client.rb.template +9 -0
- data/lib/iapi-idlc-sdk-pfm/command/templates/base/files/config/init.ps1.userdata +219 -0
- data/lib/iapi-idlc-sdk-pfm/command/validate.rb +85 -0
- data/lib/iapi-idlc-sdk-pfm/command/validator_commands/base.rb +65 -0
- data/lib/iapi-idlc-sdk-pfm/command/validator_commands/infrastructure.rb +46 -0
- data/lib/iapi-idlc-sdk-pfm/command/validator_commands/server_build.rb +135 -0
- data/lib/iapi-idlc-sdk-pfm/command/validator_commands.rb +32 -0
- data/lib/iapi-idlc-sdk-pfm/commands_map.rb +61 -0
- data/lib/iapi-idlc-sdk-pfm/generator.rb +52 -0
- data/lib/iapi-idlc-sdk-pfm/helpers.rb +49 -0
- data/lib/iapi-idlc-sdk-pfm/settings.rb +205 -0
- data/lib/iapi-idlc-sdk-pfm/validator.rb +52 -0
- data/lib/iapi-idlc-sdk-pfm/version.rb +4 -0
- data/lib/iapi-idlc-sdk-pfm.rb +27 -0
- 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
|