chef 17.5.22-universal-mingw32 → 17.6.15-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/resource/archive_file.rb +1 -1
- data/lib/chef/resource/inspec_input.rb +7 -8
- data/lib/chef/resource/inspec_waiver.rb +6 -7
- data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
- data/lib/chef/resource/powershell_package_source.rb +234 -70
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/version.rb +2 -1
- data/spec/functional/resource/powershell_package_source_spec.rb +5 -6
- data/spec/unit/resource/powershell_package_source_spec.rb +63 -62
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1af2f5d07eb0aced716be1b85c74bc9a6599c7fb432e7ec6a46d10fdffbfc78
|
4
|
+
data.tar.gz: 335f5b9d300e0a2102247247262b4a579467df2ff50bd373ee9d2360d4e88c0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 780e3a4d4b93171175ac1b19b8beb4f359c929f292a0f384f6c5783cadb0cc0af96339147b57baa3b83edd33def12b7de6126968a998df0b2a105dd2814cfde6
|
7
|
+
data.tar.gz: 65dd63d76bd8ea7cc3e04b60c995e5454e04a18af294d7722e9b739efdd75b6a5cbdc30c2624e204dc2909625bbf7fac4dfd8928d005d7b0604bb819ab584d02
|
@@ -82,7 +82,7 @@ class Chef
|
|
82
82
|
default: false
|
83
83
|
|
84
84
|
property :strip_components, Integer,
|
85
|
-
description: "Remove the specified number of leading path elements.
|
85
|
+
description: "Remove the specified number of leading path elements. Pathnames with fewer elements will be silently skipped. This behaves similarly to tar's --strip-components command line argument.",
|
86
86
|
introduced: "17.5",
|
87
87
|
default: 0
|
88
88
|
|
@@ -56,13 +56,13 @@ class Chef
|
|
56
56
|
end
|
57
57
|
```
|
58
58
|
|
59
|
-
**Add an InSpec input to the Compliance Phase using a TOML, JSON or YAML file**:
|
59
|
+
**Add an InSpec input to the Compliance Phase using a TOML, JSON, or YAML file**:
|
60
60
|
|
61
61
|
```ruby
|
62
62
|
inspec_input "/path/to/my/input.yml"
|
63
63
|
```
|
64
64
|
|
65
|
-
**Add an InSpec input to the Compliance Phase using a TOML, JSON or YAML file, using the 'name' property**:
|
65
|
+
**Add an InSpec input to the Compliance Phase using a TOML, JSON, or YAML file, using the 'name' property**:
|
66
66
|
|
67
67
|
```ruby
|
68
68
|
inspec_input "setting my input" do
|
@@ -70,12 +70,11 @@ class Chef
|
|
70
70
|
end
|
71
71
|
```
|
72
72
|
|
73
|
-
Note that the inspec_input resource does not update and will not fire notifications (similar to the log resource).
|
74
|
-
the resource while not causing the updated resource count to be larger than zero.
|
75
|
-
|
76
|
-
possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use and pure ruby
|
77
|
-
|
78
|
-
on other resources.
|
73
|
+
Note that the **inspec_input** resource does not update and will not fire notifications (similar to the log resource). This is done to preserve the ability to use
|
74
|
+
the resource while not causing the updated resource count to be larger than zero. Since the resource does not update the state of the managed node, this behavior
|
75
|
+
is still consistent with the configuration management model. Instead, you should use events to observe configuration changes for the compliance phase. It is
|
76
|
+
possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use, and you should use pure ruby
|
77
|
+
conditionals instead. Compliance configuration should be independent of other resources and should only be conditional based on state/attributes, not other resources.
|
79
78
|
DOC
|
80
79
|
|
81
80
|
property :name, [ Hash, String ]
|
@@ -62,7 +62,7 @@ class Chef
|
|
62
62
|
end
|
63
63
|
```
|
64
64
|
|
65
|
-
**Add an InSpec waiver to the Compliance Phase using an arbitrary YAML, JSON or TOML file**:
|
65
|
+
**Add an InSpec waiver to the Compliance Phase using an arbitrary YAML, JSON, or TOML file**:
|
66
66
|
|
67
67
|
```ruby
|
68
68
|
# files ending in .yml or .yaml that exist are parsed as YAML
|
@@ -101,12 +101,11 @@ class Chef
|
|
101
101
|
end
|
102
102
|
```
|
103
103
|
|
104
|
-
Note that the inspec_waiver resource does not update and will not fire notifications (similar to the log resource).
|
105
|
-
the resource while not causing the updated resource count to be larger than zero.
|
106
|
-
|
107
|
-
possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use and pure ruby
|
108
|
-
|
109
|
-
on other resources.
|
104
|
+
Note that the **inspec_waiver** resource does not update and will not fire notifications (similar to the log resource). This is done to preserve the ability to use
|
105
|
+
the resource while not causing the updated resource count to be larger than zero. Since the resource does not update the state of the managed node, this behavior
|
106
|
+
is still consistent with the configuration management model. Instead, you should use events to observe configuration changes for the compliance phase. It is
|
107
|
+
possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use, and you should use pure ruby
|
108
|
+
conditionals instead. Compliance configuration should be independent of other resources and should only be conditional based on state/attributes, not other resources.
|
110
109
|
DOC
|
111
110
|
|
112
111
|
property :control, String,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# Author:: Tor Magnus Rakvåg (tm@intility.no)
|
2
|
+
# Author:: John McCrae (john.mccrae@progress.com)
|
2
3
|
# Copyright:: 2018, Intility AS
|
3
4
|
# License:: Apache License, Version 2.0
|
4
5
|
#
|
@@ -24,29 +25,110 @@ class Chef
|
|
24
25
|
|
25
26
|
provides :powershell_package_source
|
26
27
|
|
27
|
-
description "Use the **powershell_package_source** resource to register a PowerShell package
|
28
|
+
description "Use the **powershell_package_source** resource to register a PowerShell package source and a Powershell package provider. There are 2 distinct objects we care about here. The first is a Package Source like a PowerShell Repository or a Nuget Source. The second object is a provider that PowerShell uses to get to that source with, like PowerShellGet, Nuget, Chocolatey, etc. "
|
28
29
|
introduced "14.3"
|
30
|
+
examples <<~DOC
|
31
|
+
**Add a new PSRepository that is not trusted and which requires credentials to connect to**:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
powershell_package_source 'PowerShellModules' do
|
35
|
+
source_name "PowerShellModules"
|
36
|
+
source_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
37
|
+
publish_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
38
|
+
trusted false
|
39
|
+
user "someuser@somelocation.io"
|
40
|
+
password "my_password"
|
41
|
+
provider_name "PSRepository"
|
42
|
+
action :register
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
**Add a new Package Source that uses Chocolatey as the Package Provider**:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
powershell_package_source 'PowerShellModules' do
|
50
|
+
source_name "PowerShellModules"
|
51
|
+
source_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
52
|
+
publish_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
53
|
+
trusted true
|
54
|
+
provider_name "chocolatey"
|
55
|
+
action :register
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
**Add a new PowerShell Script source that is trusted**:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
powershell_package_source 'MyDodgyScript' do
|
63
|
+
source_name "MyDodgyScript"
|
64
|
+
script_source_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
65
|
+
script_publish_location "https://pkgs.dev.azure.com/some-org/some-project/_packaging/some_feed/nuget/v2"
|
66
|
+
trusted true
|
67
|
+
action :register
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
**Update my existing PSRepository to make it Trusted after all**:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
powershell_package_source 'MyPSModule' do
|
75
|
+
source_name "MyPSModule"
|
76
|
+
trusted true
|
77
|
+
action :set
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
**Update a Nuget package source with a new name and make it trusted**:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
powershell_package_source 'PowerShellModules -> GoldFishBowl' do
|
85
|
+
source_name "PowerShellModules"
|
86
|
+
new_name "GoldFishBowl"
|
87
|
+
provider_name "Nuget"
|
88
|
+
trusted true
|
89
|
+
action :set
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
**Update a Nuget package source with a new name when the source is secured with a username and password**:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
powershell_package_source 'PowerShellModules -> GoldFishBowl' do
|
97
|
+
source_name "PowerShellModules"
|
98
|
+
new_name "GoldFishBowl"
|
99
|
+
trusted true
|
100
|
+
user "user@domain.io"
|
101
|
+
password "some_secret_password"
|
102
|
+
action :set
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
**Unregister a package source**:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
powershell_package_source 'PowerShellModules' do
|
110
|
+
source_name "PowerShellModules"
|
111
|
+
action :unregister
|
112
|
+
end
|
113
|
+
```
|
114
|
+
DOC
|
29
115
|
|
30
116
|
property :source_name, String,
|
31
|
-
description: "
|
117
|
+
description: "A label that names your package source.",
|
32
118
|
name_property: true
|
33
119
|
|
34
|
-
property :
|
35
|
-
|
36
|
-
|
120
|
+
property :new_name, String,
|
121
|
+
introduced: "17.6",
|
122
|
+
description: "Used to change the name of a standard package source."
|
37
123
|
|
38
|
-
property :
|
39
|
-
|
40
|
-
|
124
|
+
property :source_location, String,
|
125
|
+
introduced: "17.6",
|
126
|
+
description: "The URL to the location to retrieve modules from."
|
41
127
|
|
42
|
-
|
43
|
-
equal_to: %w{ Programs msi NuGet msu PowerShellGet psl chocolatey },
|
44
|
-
validation_message: "The following providers are supported: 'Programs', 'msi', 'NuGet', 'msu', 'PowerShellGet', 'psl' or 'chocolatey'",
|
45
|
-
description: "The package management provider for the source.",
|
46
|
-
default: "NuGet"
|
128
|
+
alias :url :source_location
|
47
129
|
|
48
130
|
property :publish_location, String,
|
49
|
-
description: "The URL where modules will be published to
|
131
|
+
description: "The URL where modules will be published to. Only valid if the provider is `PowerShellGet`."
|
50
132
|
|
51
133
|
property :script_source_location, String,
|
52
134
|
description: "The URL where scripts are located for this source. Only valid if the provider is `PowerShellGet`."
|
@@ -54,6 +136,24 @@ class Chef
|
|
54
136
|
property :script_publish_location, String,
|
55
137
|
description: "The location where scripts will be published to for this source. Only valid if the provider is `PowerShellGet`."
|
56
138
|
|
139
|
+
property :trusted, [TrueClass, FalseClass],
|
140
|
+
description: "Whether or not to trust packages from this source. Used when creating a NON-PSRepository Package Source",
|
141
|
+
default: false
|
142
|
+
|
143
|
+
property :user, String,
|
144
|
+
introduced: "17.6",
|
145
|
+
description: "A username that, as part of a credential object, is used to register a repository or other package source with."
|
146
|
+
|
147
|
+
property :password, String,
|
148
|
+
introduced: "17.6",
|
149
|
+
description: "A password that, as part of a credential object, is used to register a repository or other package source with."
|
150
|
+
|
151
|
+
property :provider_name, String,
|
152
|
+
equal_to: %w{ Programs msi NuGet msu PowerShellGet psl chocolatey winget },
|
153
|
+
validation_message: "The following providers are supported: 'Programs', 'msi', 'NuGet', 'msu', 'PowerShellGet', 'psl', 'chocolatey' or 'winget'",
|
154
|
+
description: "The package management provider for the package source. The default is PowerShellGet and this option need only be set otherwise in specific use cases.",
|
155
|
+
default: "NuGet"
|
156
|
+
|
57
157
|
load_current_value do
|
58
158
|
cmd = load_resource_state_script(source_name)
|
59
159
|
repo = powershell_exec!(cmd)
|
@@ -62,7 +162,9 @@ class Chef
|
|
62
162
|
else
|
63
163
|
status = repo.result
|
64
164
|
end
|
65
|
-
|
165
|
+
source_name status["source_name"]
|
166
|
+
new_name status["new_name"]
|
167
|
+
source_location status["source_location"]
|
66
168
|
trusted status["trusted"]
|
67
169
|
provider_name status["provider_name"]
|
68
170
|
publish_location status["publish_location"]
|
@@ -70,97 +172,159 @@ class Chef
|
|
70
172
|
script_publish_location status["script_publish_location"]
|
71
173
|
end
|
72
174
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
175
|
+
# Notes:
|
176
|
+
# There are 2 objects we care about with this code. 1) The Package Provider which can be Nuget, PowerShellGet, Chocolatey, et al. 2) The PackageSource where the files we want access to live. The Package Provider gets us access to the Package Source.
|
177
|
+
# Per the Microsoft docs you can only have one provider for one source. Enter the PSRepository. It is a sub-type of Package Source.
|
178
|
+
# If you register a new PSRepository you get both a PSRepository object AND a Package Source object which are distinct. If you call "Get-PSRepository -Name 'PSGallery'" from powershell, notice that the Packageprovider is Nuget
|
179
|
+
# now go execute "Get-PackageSource -Name 'PSGallery'" and notice that the PackageProvider is PowerShellGet. If you set a new PSRepository without specifying a PackageProvider ("Register-PSRepository -Name 'foo' -source...") the command will create both
|
180
|
+
# a PackageSource and a PSRepository with different providers.
|
181
|
+
|
182
|
+
# Unregistering a PackageSource (unregister-packagesource -name 'foo') where that source is also a PSRepository also causes that object to delete as well. This makes sense as PSRepository is a sub-type of packagesource.
|
183
|
+
# All PSRepositories are PackageSources, and all PackageSources with Provider PowerShellGet are PSRepositories. They are 2 different views of the same object.
|
184
|
+
|
185
|
+
action :register, description: "Registers a PowerShell package source." do
|
186
|
+
package_details = get_package_source_details
|
187
|
+
output = package_details.result
|
188
|
+
if output == "PSRepository" || output == "PackageSource"
|
189
|
+
action_set
|
190
|
+
elsif new_resource.provider_name.downcase.strip == "powershellget"
|
191
|
+
converge_by("register source: #{new_resource.source_name}") do
|
192
|
+
register_cmd = build_ps_repository_command("Register", new_resource)
|
193
|
+
res = powershell_exec(register_cmd)
|
194
|
+
raise "Failed to register #{new_resource.source_name}: #{res.errors}" if res.error?
|
88
195
|
end
|
89
196
|
else
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
197
|
+
converge_by("register source: #{new_resource.source_name}") do
|
198
|
+
register_cmd = build_package_source_command("Register", new_resource)
|
199
|
+
res = powershell_exec(register_cmd)
|
200
|
+
raise "Failed to register #{new_resource.source_name}: #{res.errors}" if res.error?
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
action :set, description: "Updates an existing PSRepository or Package Source" do
|
206
|
+
package_details = get_package_source_details
|
207
|
+
output = package_details.result
|
208
|
+
if output == "PSRepository"
|
209
|
+
converge_if_changed :source_location, :trusted, :publish_location, :script_source_location, :script_publish_location, :source_name do
|
210
|
+
set_cmd = build_ps_repository_command("Set", new_resource)
|
211
|
+
res = powershell_exec(set_cmd)
|
212
|
+
raise "Failed to Update #{new_resource.source_name}: #{res.errors}" if res.error?
|
213
|
+
end
|
214
|
+
elsif output == "PackageSource"
|
215
|
+
converge_if_changed :source_location, :trusted, :new_name, :provider_name do
|
216
|
+
set_cmd = build_package_source_command("Set", new_resource)
|
217
|
+
res = powershell_exec(set_cmd)
|
218
|
+
raise "Failed to Update #{new_resource.source_name}: #{res.errors}" if res.error?
|
102
219
|
end
|
103
220
|
end
|
104
221
|
end
|
105
222
|
|
106
223
|
action :unregister, description: "Unregisters the PowerShell package source." do
|
107
|
-
|
108
|
-
|
224
|
+
package_details = get_package_source_details
|
225
|
+
output = package_details.result
|
226
|
+
if output == "PackageSource" || output == "PSRepository"
|
227
|
+
unregister_cmd = "Unregister-PackageSource -Name '#{new_resource.source_name}'"
|
109
228
|
converge_by("unregister source: #{new_resource.source_name}") do
|
110
|
-
res = powershell_exec(unregister_cmd)
|
229
|
+
res = powershell_exec!(unregister_cmd)
|
111
230
|
raise "Failed to unregister #{new_resource.source_name}: #{res.errors}" if res.error?
|
112
231
|
end
|
232
|
+
else
|
233
|
+
logger.warn("*****************************************")
|
234
|
+
logger.warn("Failed to unregister #{new_resource.source_name}: Package Source does not exist")
|
235
|
+
logger.warn("*****************************************")
|
113
236
|
end
|
114
237
|
end
|
115
238
|
|
116
239
|
action_class do
|
117
|
-
def package_source_exists?
|
118
|
-
cmd = powershell_exec!("(Get-PackageSource -Name '#{new_resource.source_name}' -ErrorAction SilentlyContinue).Name")
|
119
|
-
!cmd.result.empty? && cmd.result.to_s.downcase.strip == new_resource.source_name.downcase
|
120
|
-
end
|
121
240
|
|
122
|
-
def
|
123
|
-
|
241
|
+
def get_package_source_details
|
242
|
+
powershell_exec! <<~EOH
|
243
|
+
$package_details = Get-PackageSource -Name '#{new_resource.source_name}' -ErrorAction SilentlyContinue
|
244
|
+
if ($package_details.ProviderName -match "PowerShellGet"){
|
245
|
+
return "PSRepository"
|
246
|
+
}
|
247
|
+
elseif ($package_details.ProviderName ) {
|
248
|
+
return "PackageSource"
|
249
|
+
}
|
250
|
+
elseif ($null -eq $package_details)
|
251
|
+
{
|
252
|
+
return "Unregistered"
|
253
|
+
}
|
254
|
+
EOH
|
124
255
|
end
|
125
256
|
|
126
257
|
def build_ps_repository_command(cmdlet_type, new_resource)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
258
|
+
if new_resource.trusted == true
|
259
|
+
install_policy = "Trusted"
|
260
|
+
else
|
261
|
+
install_policy = "Untrusted"
|
262
|
+
end
|
263
|
+
if new_resource.user && new_resource.password
|
264
|
+
cmd = "$user = '#{new_resource.user}';"
|
265
|
+
cmd << "[securestring]$secure_password = Convertto-SecureString -String '#{new_resource.password}' -AsPlainText -Force;"
|
266
|
+
cmd << "$Credentials = New-Object System.Management.Automation.PSCredential -Argumentlist ($user, $secure_password);"
|
267
|
+
cmd << "#{cmdlet_type}-PSRepository -Name '#{new_resource.source_name}'"
|
268
|
+
cmd << " -SourceLocation '#{new_resource.source_location}'" if new_resource.source_location
|
269
|
+
cmd << " -InstallationPolicy '#{install_policy}'"
|
270
|
+
cmd << " -PublishLocation '#{new_resource.publish_location}'" if new_resource.publish_location
|
271
|
+
cmd << " -ScriptSourceLocation '#{new_resource.script_source_location}'" if new_resource.script_source_location
|
272
|
+
cmd << " -ScriptPublishLocation '#{new_resource.script_publish_location}'" if new_resource.script_publish_location
|
273
|
+
cmd << " -Credential $Credentials"
|
274
|
+
cmd << " | Out-Null"
|
275
|
+
else
|
276
|
+
cmd = "#{cmdlet_type}-PSRepository -Name '#{new_resource.source_name}'"
|
277
|
+
cmd << " -SourceLocation '#{new_resource.source_location}'" if new_resource.source_location
|
278
|
+
cmd << " -InstallationPolicy '#{install_policy}'"
|
279
|
+
cmd << " -PublishLocation '#{new_resource.publish_location}'" if new_resource.publish_location
|
280
|
+
cmd << " -ScriptSourceLocation '#{new_resource.script_source_location}'" if new_resource.script_source_location
|
281
|
+
cmd << " -ScriptPublishLocation '#{new_resource.script_publish_location}'" if new_resource.script_publish_location
|
282
|
+
cmd << " | Out-Null"
|
283
|
+
end
|
134
284
|
cmd
|
135
285
|
end
|
136
286
|
|
137
287
|
def build_package_source_command(cmdlet_type, new_resource)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
288
|
+
if new_resource.user && new_resource.password
|
289
|
+
cmd = "$user = '#{new_resource.user}';"
|
290
|
+
cmd << "[securestring]$secure_password = Convertto-SecureString -String '#{new_resource.password}' -AsPlainText -Force;"
|
291
|
+
cmd << "$Credentials = New-Object System.Management.Automation.PSCredential -Argumentlist ($user, $secure_password);"
|
292
|
+
cmd << "#{cmdlet_type}-PackageSource -Name '#{new_resource.source_name}'"
|
293
|
+
cmd << " -Location '#{new_resource.source_location}'" if new_resource.source_location
|
294
|
+
cmd << " -Trusted" if new_resource.trusted
|
295
|
+
cmd << " -ProviderName '#{new_resource.provider_name}'" if new_resource.provider_name
|
296
|
+
cmd << " -Credential $credentials"
|
297
|
+
cmd << " | Out-Null"
|
298
|
+
cmd
|
299
|
+
else
|
300
|
+
cmd = "#{cmdlet_type}-PackageSource -Name '#{new_resource.source_name}'"
|
301
|
+
cmd << " -NewName '#{new_resource.new_name}'" if new_resource.new_name
|
302
|
+
cmd << " -Location '#{new_resource.source_location}'" if new_resource.source_location
|
303
|
+
cmd << " -Trusted" if new_resource.trusted
|
304
|
+
cmd << " -ProviderName '#{new_resource.provider_name}'" if new_resource.provider_name
|
305
|
+
cmd << " | Out-Null"
|
306
|
+
cmd
|
307
|
+
end
|
144
308
|
end
|
145
309
|
end
|
146
310
|
end
|
147
311
|
|
148
312
|
private
|
149
313
|
|
150
|
-
def load_resource_state_script(
|
314
|
+
def load_resource_state_script(source_name)
|
151
315
|
<<-EOH
|
152
316
|
$PSDefaultParameterValues = @{
|
153
317
|
"*:WarningAction" = "SilentlyContinue"
|
154
318
|
}
|
155
|
-
if(Get-PackageSource -Name '#{
|
156
|
-
if ((Get-PackageSource -Name '#{
|
157
|
-
(Get-PSRepository -Name '#{
|
319
|
+
if(Get-PackageSource -Name '#{source_name}' -ErrorAction SilentlyContinue) {
|
320
|
+
if ((Get-PackageSource -Name '#{source_name}').ProviderName -eq 'PowerShellGet') {
|
321
|
+
(Get-PSRepository -Name '#{source_name}') | Select @{n='source_name';e={$_.Name}}, @{n='source_location';e={$_.SourceLocation}},
|
158
322
|
@{n='trusted';e={$_.Trusted}}, @{n='provider_name';e={$_.PackageManagementProvider}}, @{n='publish_location';e={$_.PublishLocation}},
|
159
323
|
@{n='script_source_location';e={$_.ScriptSourceLocation}}, @{n='script_publish_location';e={$_.ScriptPublishLocation}}
|
160
324
|
}
|
161
325
|
else {
|
162
|
-
(Get-PackageSource -Name '#{
|
163
|
-
@{n='provider_name';e={$_.ProviderName}}, @{n='trusted';e={$_.IsTrusted}}
|
326
|
+
(Get-PackageSource -Name '#{source_name}') | Select @{n='source_name';e={$_.Name}}, @{n='new_name';e={$_.Name}}, @{n='source_location';e={$_.Location}},
|
327
|
+
@{n='provider_name';e={$_.ProviderName}}, @{n='trusted';e={$_.IsTrusted}}, @{n='publish_location';e={$_.PublishLocation}}
|
164
328
|
}
|
165
329
|
}
|
166
330
|
EOH
|
data/lib/chef/version.rb
CHANGED
data/lib/chef/win32/version.rb
CHANGED
@@ -49,7 +49,8 @@ class Chef
|
|
49
49
|
private_class_method :method_name_from_marketing_name
|
50
50
|
|
51
51
|
WIN_VERSIONS = {
|
52
|
-
"Windows Server
|
52
|
+
"Windows Server 2022" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 20348 } },
|
53
|
+
"Windows Server 2019" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 17763 && build_number < 20348 } },
|
53
54
|
"Windows 10" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type == VER_NT_WORKSTATION } },
|
54
55
|
"Windows Server 2016" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number <= 14393 } },
|
55
56
|
"Windows 8.1" => { major: 6, minor: 3, callable: lambda { |product_type, suite_mask, build_number| product_type == VER_NT_WORKSTATION } },
|
@@ -22,7 +22,7 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
|
|
22
22
|
include Chef::Mixin::PowershellExec
|
23
23
|
|
24
24
|
let(:source_name) { "fake" }
|
25
|
-
let(:
|
25
|
+
let(:source_location) { "https://www.nuget.org/api/v2" }
|
26
26
|
let(:trusted) { true }
|
27
27
|
|
28
28
|
let(:run_context) do
|
@@ -32,7 +32,7 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
|
|
32
32
|
subject do
|
33
33
|
new_resource = Chef::Resource::PowershellPackageSource.new("test powershell package source", run_context)
|
34
34
|
new_resource.source_name source_name
|
35
|
-
new_resource.
|
35
|
+
new_resource.source_location source_location
|
36
36
|
new_resource.trusted trusted
|
37
37
|
new_resource.provider_name provider_name
|
38
38
|
new_resource
|
@@ -61,7 +61,7 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
|
|
61
61
|
it "updates an existing package source if changed" do
|
62
62
|
subject.run_action(:register)
|
63
63
|
subject.trusted !trusted
|
64
|
-
subject.run_action(:
|
64
|
+
subject.run_action(:set)
|
65
65
|
expect(subject).to be_updated_by_last_action
|
66
66
|
end
|
67
67
|
end
|
@@ -73,9 +73,8 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
|
|
73
73
|
expect(get_installed_package_source_name).to be_empty
|
74
74
|
end
|
75
75
|
|
76
|
-
it "does not unregister the package source if not
|
77
|
-
subject.run_action(:unregister)
|
78
|
-
expect(subject).not_to be_updated_by_last_action
|
76
|
+
it "does not unregister the package source if not installed" do
|
77
|
+
expect { subject.run_action(:unregister) }.to_not raise_error
|
79
78
|
end
|
80
79
|
end
|
81
80
|
end
|
@@ -33,14 +33,15 @@ describe Chef::Resource::PowershellPackageSource do
|
|
33
33
|
expect(resource.action).to eql([:register])
|
34
34
|
end
|
35
35
|
|
36
|
-
it "supports :register and :unregister actions" do
|
36
|
+
it "supports :register, :set and :unregister actions" do
|
37
37
|
expect { resource.action :register }.not_to raise_error
|
38
|
+
expect { resource.action :set }.not_to raise_error
|
38
39
|
expect { resource.action :unregister }.not_to raise_error
|
39
40
|
end
|
40
41
|
|
41
42
|
it "the url property accepts strings" do
|
42
|
-
resource.
|
43
|
-
expect(resource.
|
43
|
+
resource.source_location("https://mygallery.company.co/api/v2/")
|
44
|
+
expect(resource.source_location).to eql("https://mygallery.company.co/api/v2/")
|
44
45
|
end
|
45
46
|
|
46
47
|
it "the trusted property accepts true and false" do
|
@@ -54,7 +55,7 @@ describe Chef::Resource::PowershellPackageSource do
|
|
54
55
|
expect(resource.trusted).to eql(false)
|
55
56
|
end
|
56
57
|
|
57
|
-
it "provider_name accepts 'Programs', 'msi', 'NuGet', 'msu', 'PowerShellGet', 'psl', 'chocolatey'" do
|
58
|
+
it "provider_name accepts 'Programs', 'msi', 'NuGet', 'msu', 'PowerShellGet', 'psl', 'chocolatey', 'winget'" do
|
58
59
|
expect { resource.provider_name("Programs") }.not_to raise_error
|
59
60
|
expect { resource.provider_name("msi") }.not_to raise_error
|
60
61
|
expect { resource.provider_name("NuGet") }.not_to raise_error
|
@@ -62,6 +63,7 @@ describe Chef::Resource::PowershellPackageSource do
|
|
62
63
|
expect { resource.provider_name("PowerShellGet") }.not_to raise_error
|
63
64
|
expect { resource.provider_name("psl") }.not_to raise_error
|
64
65
|
expect { resource.provider_name("chocolatey") }.not_to raise_error
|
66
|
+
expect { resource.provider_name("winget") }.not_to raise_error
|
65
67
|
end
|
66
68
|
|
67
69
|
it "the publish_location property accepts strings" do
|
@@ -70,75 +72,76 @@ describe Chef::Resource::PowershellPackageSource do
|
|
70
72
|
end
|
71
73
|
|
72
74
|
it "the script_source_location property accepts strings" do
|
73
|
-
resource.
|
74
|
-
expect(resource.
|
75
|
+
resource.script_source_location("https://mygallery.company.co/api/v2/scripts")
|
76
|
+
expect(resource.script_source_location).to eql("https://mygallery.company.co/api/v2/scripts")
|
75
77
|
end
|
76
78
|
|
77
79
|
it "the script_publish_location property accepts strings" do
|
78
|
-
resource.
|
79
|
-
expect(resource.
|
80
|
+
resource.script_publish_location("https://mygallery.company.co/api/v2/scripts")
|
81
|
+
expect(resource.script_publish_location).to eql("https://mygallery.company.co/api/v2/scripts")
|
80
82
|
end
|
81
83
|
|
82
84
|
describe "#build_ps_repository_command" do
|
83
85
|
before do
|
84
86
|
resource.source_name("MyGallery")
|
85
|
-
resource.
|
87
|
+
resource.source_location("https://github.com/chef/powershell_test")
|
88
|
+
resource.provider_name("PowerShellGet")
|
86
89
|
end
|
87
90
|
|
88
91
|
context "#register" do
|
89
92
|
it "builds a minimal command" do
|
90
|
-
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
93
|
+
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' | Out-Null")
|
91
94
|
end
|
92
95
|
|
93
96
|
it "builds a command with trusted set to true" do
|
94
97
|
resource.trusted(true)
|
95
|
-
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
98
|
+
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Trusted' | Out-Null")
|
96
99
|
end
|
97
100
|
|
98
101
|
it "builds a command with a publish location" do
|
99
|
-
resource.publish_location("https://
|
100
|
-
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
102
|
+
resource.publish_location("https://github.com/chef/powershell_test/package")
|
103
|
+
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' -PublishLocation 'https://github.com/chef/powershell_test/package' | Out-Null")
|
101
104
|
end
|
102
105
|
|
103
106
|
it "builds a command with a script source location" do
|
104
|
-
resource.script_source_location("https://
|
105
|
-
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
107
|
+
resource.script_source_location("https://github.com/chef/powershell_test/scripts")
|
108
|
+
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' -ScriptSourceLocation 'https://github.com/chef/powershell_test/scripts' | Out-Null")
|
106
109
|
end
|
107
110
|
|
108
111
|
it "builds a command with a script publish location" do
|
109
|
-
resource.script_publish_location("https://
|
110
|
-
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
112
|
+
resource.script_publish_location("https://github.com/chef/powershell_test/scripts/package")
|
113
|
+
expect(provider.build_ps_repository_command("Register", resource)).to eql("Register-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' -ScriptPublishLocation 'https://github.com/chef/powershell_test/scripts/package' | Out-Null")
|
111
114
|
end
|
112
115
|
end
|
113
116
|
|
114
117
|
context "#set" do
|
115
118
|
it "builds a minimal command" do
|
116
|
-
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
119
|
+
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' | Out-Null")
|
117
120
|
end
|
118
121
|
|
119
122
|
it "builds a command to change the url" do
|
120
|
-
resource.
|
123
|
+
resource.source_location("https://othergallery.company.co/api/v2/")
|
121
124
|
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://othergallery.company.co/api/v2/' -InstallationPolicy 'Untrusted' | Out-Null")
|
122
125
|
end
|
123
126
|
|
124
127
|
it "builds a command with trusted set to true" do
|
125
128
|
resource.trusted(true)
|
126
|
-
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
129
|
+
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Trusted' | Out-Null")
|
127
130
|
end
|
128
131
|
|
129
132
|
it "builds a command with a publish location" do
|
130
|
-
resource.publish_location("https://
|
131
|
-
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
133
|
+
resource.publish_location("https://github.com/chef/powershell_test/package")
|
134
|
+
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' -PublishLocation 'https://github.com/chef/powershell_test/package' | Out-Null")
|
132
135
|
end
|
133
136
|
|
134
137
|
it "builds a command with a script source location" do
|
135
|
-
resource.script_source_location("https://
|
136
|
-
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
138
|
+
resource.script_source_location("https://github.com/chef/powershell_test/scripts")
|
139
|
+
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' -ScriptSourceLocation 'https://github.com/chef/powershell_test/scripts' | Out-Null")
|
137
140
|
end
|
138
141
|
|
139
142
|
it "builds a command with a script publish location" do
|
140
|
-
resource.script_publish_location("https://
|
141
|
-
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://
|
143
|
+
resource.script_publish_location("https://github.com/chef/powershell_test/scripts/package")
|
144
|
+
expect(provider.build_ps_repository_command("Set", resource)).to eql("Set-PSRepository -Name 'MyGallery' -SourceLocation 'https://github.com/chef/powershell_test' -InstallationPolicy 'Untrusted' -ScriptPublishLocation 'https://github.com/chef/powershell_test/scripts/package' | Out-Null")
|
142
145
|
end
|
143
146
|
end
|
144
147
|
end
|
@@ -146,74 +149,72 @@ describe Chef::Resource::PowershellPackageSource do
|
|
146
149
|
describe "#build_package_source_command" do
|
147
150
|
before do
|
148
151
|
resource.source_name("NuGet")
|
149
|
-
resource.
|
152
|
+
resource.source_location("http://nuget.org/api/v2/")
|
150
153
|
end
|
151
154
|
|
152
155
|
context "#register" do
|
153
156
|
it "builds a minimal command" do
|
154
|
-
expect(provider.build_package_source_command("Register", resource)).to eql("Register-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -
|
157
|
+
expect(provider.build_package_source_command("Register", resource)).to eql("Register-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -ProviderName 'NuGet' | Out-Null")
|
155
158
|
end
|
156
159
|
|
157
160
|
it "builds a command with trusted set to true" do
|
158
161
|
resource.trusted(true)
|
159
|
-
expect(provider.build_package_source_command("Register", resource)).to eql("Register-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -Trusted
|
162
|
+
expect(provider.build_package_source_command("Register", resource)).to eql("Register-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -Trusted -ProviderName 'NuGet' | Out-Null")
|
160
163
|
end
|
161
164
|
|
162
165
|
it "builds a command with a different provider" do
|
163
166
|
resource.source_name("choco")
|
164
|
-
resource.
|
167
|
+
resource.source_location("https://chocolatey.org/api/v2/")
|
165
168
|
resource.provider_name("chocolatey")
|
166
|
-
expect(provider.build_package_source_command("Register", resource)).to eql("Register-PackageSource -Name 'choco' -Location 'https://chocolatey.org/api/v2/' -
|
169
|
+
expect(provider.build_package_source_command("Register", resource)).to eql("Register-PackageSource -Name 'choco' -Location 'https://chocolatey.org/api/v2/' -ProviderName 'chocolatey' | Out-Null")
|
167
170
|
end
|
168
171
|
end
|
169
172
|
|
170
173
|
context "#set" do
|
171
174
|
it "builds a minimal command" do
|
172
|
-
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -
|
175
|
+
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -ProviderName 'NuGet' | Out-Null")
|
173
176
|
end
|
174
177
|
|
175
178
|
it "builds a command to change the url" do
|
176
|
-
resource.
|
177
|
-
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'NuGet' -Location 'https://nuget.company.co/api/v2/' -
|
179
|
+
resource.source_location("https://nuget.company.co/api/v2/")
|
180
|
+
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'NuGet' -Location 'https://nuget.company.co/api/v2/' -ProviderName 'NuGet' | Out-Null")
|
178
181
|
end
|
179
182
|
|
180
183
|
it "builds a command with trusted set to true" do
|
181
184
|
resource.trusted(true)
|
182
|
-
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -Trusted
|
185
|
+
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'NuGet' -Location 'http://nuget.org/api/v2/' -Trusted -ProviderName 'NuGet' | Out-Null")
|
183
186
|
end
|
184
187
|
|
185
188
|
it "builds a command with a different provider" do
|
186
189
|
resource.source_name("choco")
|
187
|
-
resource.
|
190
|
+
resource.source_location("https://chocolatey.org/api/v2/")
|
188
191
|
resource.provider_name("chocolatey")
|
189
|
-
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'choco' -Location 'https://chocolatey.org/api/v2/' -
|
192
|
+
expect(provider.build_package_source_command("Set", resource)).to eql("Set-PackageSource -Name 'choco' -Location 'https://chocolatey.org/api/v2/' -ProviderName 'chocolatey' | Out-Null")
|
190
193
|
end
|
191
194
|
end
|
192
195
|
end
|
193
196
|
|
194
|
-
describe "
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
end
|
218
|
-
end
|
197
|
+
# describe "get_package_source_details" do
|
198
|
+
# before do
|
199
|
+
# resource.source_name("MyGallery")
|
200
|
+
# resource.source_location("http://nuget.org/api/v2/")
|
201
|
+
# provider.build_package_source_command("Register", resource)
|
202
|
+
# end
|
203
|
+
|
204
|
+
# # stub a call to the package_source_details
|
205
|
+
# expect(provider).to receive(:get_package_source_details).and_return("PackageSource")
|
206
|
+
# it "returns packagesource if it exists" do
|
207
|
+
# # dbl = double("testing PackageSource")
|
208
|
+
# # let(source_name)
|
209
|
+
# # # allow(provider).to receive(:powershell_exec!).with("(Get-PackageSource -Name 'MyGallery' -ErrorAction SilentlyContinue).Name").and_return(double("powershell_exec!", result: "PackageSource"))
|
210
|
+
# # resource.source_name("MyGallery")
|
211
|
+
# expect(provider.get_package_source_details.result).to eql("PackageSource")
|
212
|
+
# end
|
213
|
+
|
214
|
+
# it "returns unregistered if it doesn't exist" do
|
215
|
+
# # allow(provider).to receive(:powershell_exec!).with("(Get-PackageSource -Name 'Foo' -ErrorAction SilentlyContinue).Name").and_return(double("powershell_exec!", result: ""))
|
216
|
+
# resource.source_name("Foo")
|
217
|
+
# expect(provider.get_package_source_details.result).to eql("Unregistered")
|
218
|
+
# end
|
219
|
+
# end
|
219
220
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 17.
|
4
|
+
version: 17.6.15
|
5
5
|
platform: universal-mingw32
|
6
6
|
authors:
|
7
7
|
- Adam Jacob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-config
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 17.
|
19
|
+
version: 17.6.15
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 17.
|
26
|
+
version: 17.6.15
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: chef-utils
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 17.
|
33
|
+
version: 17.6.15
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 17.
|
40
|
+
version: 17.6.15
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: train-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|