chef 17.5.22 → 17.7.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/chef.gemspec +1 -0
  4. data/lib/chef/chef_fs/file_pattern.rb +1 -1
  5. data/lib/chef/chef_fs/path_utils.rb +1 -1
  6. data/lib/chef/data_collector/run_end_message.rb +1 -1
  7. data/lib/chef/dsl/reboot_pending.rb +1 -1
  8. data/lib/chef/exceptions.rb +10 -0
  9. data/lib/chef/provider/cron.rb +4 -1
  10. data/lib/chef/provider/git.rb +1 -1
  11. data/lib/chef/provider/ifconfig/debian.rb +1 -1
  12. data/lib/chef/provider/package/habitat.rb +1 -1
  13. data/lib/chef/provider/subversion.rb +5 -5
  14. data/lib/chef/resource/archive_file.rb +1 -1
  15. data/lib/chef/resource/chef_client_trusted_certificate.rb +1 -0
  16. data/lib/chef/resource/chocolatey_config.rb +1 -1
  17. data/lib/chef/resource/chocolatey_feature.rb +1 -1
  18. data/lib/chef/resource/chocolatey_source.rb +24 -2
  19. data/lib/chef/resource/directory.rb +1 -1
  20. data/lib/chef/resource/habitat_install.rb +5 -5
  21. data/lib/chef/resource/inspec_input.rb +7 -8
  22. data/lib/chef/resource/inspec_waiver.rb +7 -8
  23. data/lib/chef/resource/inspec_waiver_file_entry.rb +1 -1
  24. data/lib/chef/resource/kernel_module.rb +27 -2
  25. data/lib/chef/resource/macos_userdefaults.rb +45 -133
  26. data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
  27. data/lib/chef/resource/powershell_package_source.rb +234 -70
  28. data/lib/chef/resource/windows_auto_run.rb +1 -1
  29. data/lib/chef/resource/windows_dfs_namespace.rb +2 -2
  30. data/lib/chef/resource/windows_update_settings.rb +3 -3
  31. data/lib/chef/resource.rb +1 -1
  32. data/lib/chef/resource_reporter.rb +1 -1
  33. data/lib/chef/secret_fetcher/azure_key_vault.rb +62 -8
  34. data/lib/chef/secret_fetcher.rb +0 -1
  35. data/lib/chef/version.rb +1 -1
  36. data/lib/chef/win32/version.rb +2 -1
  37. data/spec/functional/dsl/reboot_pending_spec.rb +3 -3
  38. data/spec/functional/dsl/registry_helper_spec.rb +1 -1
  39. data/spec/functional/resource/dsc_script_spec.rb +2 -2
  40. data/spec/functional/resource/macos_userdefaults_spec.rb +119 -0
  41. data/spec/functional/resource/powershell_package_source_spec.rb +5 -6
  42. data/spec/functional/resource/registry_spec.rb +81 -81
  43. data/spec/functional/win32/registry_spec.rb +8 -8
  44. data/spec/unit/data_collector_spec.rb +24 -1
  45. data/spec/unit/dsl/reboot_pending_spec.rb +1 -1
  46. data/spec/unit/mixin/default_paths_spec.rb +1 -1
  47. data/spec/unit/mixin/securable_spec.rb +3 -3
  48. data/spec/unit/provider/cron_spec.rb +45 -0
  49. data/spec/unit/provider/package/rubygems_spec.rb +5 -5
  50. data/spec/unit/provider/package/windows_spec.rb +1 -1
  51. data/spec/unit/provider/registry_key_spec.rb +4 -4
  52. data/spec/unit/provider/service/windows_spec.rb +5 -5
  53. data/spec/unit/provider/subversion_spec.rb +4 -4
  54. data/spec/unit/provider/windows_env_spec.rb +1 -1
  55. data/spec/unit/provider/zypper_repository_spec.rb +1 -1
  56. data/spec/unit/resource/chef_client_trusted_certificate_spec.rb +14 -0
  57. data/spec/unit/resource/chocolatey_config_spec.rb +1 -1
  58. data/spec/unit/resource/chocolatey_feature_spec.rb +1 -1
  59. data/spec/unit/resource/chocolatey_source_spec.rb +1 -1
  60. data/spec/unit/resource/kernel_module_spec.rb +2 -1
  61. data/spec/unit/resource/macos_user_defaults_spec.rb +36 -96
  62. data/spec/unit/resource/powershell_package_source_spec.rb +63 -62
  63. data/spec/unit/resource/registry_key_spec.rb +10 -10
  64. data/spec/unit/resource/windows_auto_run_spec.rb +1 -1
  65. data/spec/unit/resource/windows_feature_powershell_spec.rb +1 -1
  66. data/spec/unit/resource/windows_firewall_rule_spec.rb +2 -2
  67. data/spec/unit/resource/windows_task_spec.rb +3 -3
  68. data/spec/unit/resource_reporter_spec.rb +2 -2
  69. data/spec/unit/resource_spec.rb +5 -0
  70. data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +99 -20
  71. data/spec/unit/util/backup_spec.rb +1 -1
  72. data/spec/unit/win32/registry_spec.rb +3 -3
  73. metadata +21 -6
@@ -17,6 +17,7 @@
17
17
 
18
18
  require_relative "../resource"
19
19
  require "chef-utils/dist" unless defined?(ChefUtils::Dist)
20
+ require "corefoundation" if RUBY_PLATFORM.match?(/darwin/)
20
21
  autoload :Plist, "plist"
21
22
 
22
23
  class Chef
@@ -78,173 +79,84 @@ class Chef
78
79
  required: true
79
80
 
80
81
  property :host, [String, Symbol],
81
- description: "Set either :current or a hostname to set the user default at the host level.",
82
+ description: "Set either :current, :all or a hostname to set the user default at the host level.",
82
83
  desired_state: false,
83
- introduced: "16.3"
84
+ introduced: "16.3",
85
+ coerce: proc { |value| to_cf_host(value) }
84
86
 
85
87
  property :value, [Integer, Float, String, TrueClass, FalseClass, Hash, Array],
86
88
  description: "The value of the key. Note: With the `type` property set to `bool`, `String` forms of Boolean true/false values that Apple accepts in the defaults command will be coerced: 0/1, 'TRUE'/'FALSE,' 'true'/false', 'YES'/'NO', or 'yes'/'no'.",
87
- required: [:write],
88
- coerce: proc { |v| v.is_a?(Hash) ? v.transform_keys(&:to_s) : v } # make sure keys are all strings for comparison
89
+ required: [:write]
89
90
 
90
91
  property :type, String,
91
92
  description: "The value type of the preference key.",
92
93
  equal_to: %w{bool string int float array dict},
93
- desired_state: false
94
+ desired_state: false,
95
+ deprecated: true
94
96
 
95
- property :user, String,
96
- description: "The system user that the default will be applied to.",
97
- desired_state: false
97
+ property :user, [String, Symbol],
98
+ description: "The system user that the default will be applied to. Set :current for current user, :all for all users or pass a valid username",
99
+ desired_state: false,
100
+ coerce: proc { |value| to_cf_user(value) }
98
101
 
99
102
  property :sudo, [TrueClass, FalseClass],
100
103
  description: "Set to true if the setting you wish to modify requires privileged access. This requires passwordless sudo for the `/usr/bin/defaults` command to be setup for the user running #{ChefUtils::Dist::Infra::PRODUCT}.",
101
104
  default: false,
102
- desired_state: false
105
+ desired_state: false,
106
+ deprecated: true
103
107
 
104
108
  load_current_value do |new_resource|
105
- Chef::Log.debug "#load_current_value: shelling out \"#{defaults_export_cmd(new_resource).join(" ")}\" to determine state"
106
- state = shell_out(defaults_export_cmd(new_resource), user: new_resource.user)
109
+ Chef::Log.debug "#load_current_value: attempting to read \"#{new_resource.domain}\" value from preferences to determine state"
107
110
 
108
- if state.error? || state.stdout.empty?
109
- Chef::Log.debug "#load_current_value: #{defaults_export_cmd(new_resource).join(" ")} returned stdout: #{state.stdout} and stderr: #{state.stderr}"
110
- current_value_does_not_exist!
111
- end
111
+ pref = get_preference(new_resource)
112
+ current_value_does_not_exist! if pref.nil?
112
113
 
113
- plist_data = ::Plist.parse_xml(state.stdout)
114
-
115
- # handle the situation where the key doesn't exist in the domain
116
- if plist_data.key?(new_resource.key)
117
- key new_resource.key
118
- else
119
- current_value_does_not_exist!
120
- end
121
-
122
- value plist_data[new_resource.key]
123
- end
124
-
125
- #
126
- # The defaults command to export a domain
127
- #
128
- # @return [Array] defaults command
129
- #
130
- def defaults_export_cmd(resource)
131
- state_cmd = ["/usr/bin/defaults"]
132
-
133
- if resource.host == "current"
134
- state_cmd.concat(["-currentHost"])
135
- elsif resource.host # they specified a non-nil value, which is a hostname
136
- state_cmd.concat(["-host", resource.host])
137
- end
138
-
139
- state_cmd.concat(["export", resource.domain, "-"])
140
- state_cmd
114
+ key new_resource.key
115
+ value pref
141
116
  end
142
117
 
143
118
  action :write, description: "Write the value to the specified domain/key." do
144
119
  converge_if_changed do
145
- cmd = defaults_modify_cmd
146
- Chef::Log.debug("Updating defaults value by shelling out: #{cmd.join(" ")}")
147
-
148
- shell_out!(cmd, user: new_resource.user)
120
+ Chef::Log.debug("Updating defaults value for #{new_resource.key} in #{new_resource.domain}")
121
+ CF::Preferences.set!(new_resource.key, new_resource.value, new_resource.domain, new_resource.user, new_resource.host)
149
122
  end
150
123
  end
151
124
 
152
125
  action :delete, description: "Delete a key from a domain." do
153
126
  # if it's not there there's nothing to remove
154
- return unless current_resource
127
+ return if current_resource.nil?
155
128
 
156
129
  converge_by("delete domain:#{new_resource.domain} key:#{new_resource.key}") do
157
-
158
- cmd = defaults_modify_cmd
159
- Chef::Log.debug("Removing defaults key by shelling out: #{cmd.join(" ")}")
160
-
161
- shell_out!(cmd, user: new_resource.user)
130
+ Chef::Log.debug("Removing defaults key: #{new_resource.key}")
131
+ CF::Preferences.set!(new_resource.key, nil, new_resource.domain, new_resource.user, new_resource.host)
162
132
  end
163
133
  end
164
134
 
165
- action_class do
166
- #
167
- # The command used to write or delete delete values from domains
168
- #
169
- # @return [Array] Array representation of defaults command to run
170
- #
171
- def defaults_modify_cmd
172
- cmd = ["/usr/bin/defaults"]
173
-
174
- if new_resource.host == :current
175
- cmd.concat(["-currentHost"])
176
- elsif new_resource.host # they specified a non-nil value, which is a hostname
177
- cmd.concat(["-host", new_resource.host])
178
- end
179
-
180
- cmd.concat([action.to_s, new_resource.domain, new_resource.key])
181
- cmd.concat(processed_value) if action == :write
182
- cmd.prepend("sudo") if new_resource.sudo
183
- cmd
184
- end
185
-
186
- #
187
- # convert the provided value into the format defaults expects
188
- #
189
- # @return [array] array of values starting with the type if applicable
190
- #
191
- def processed_value
192
- type = new_resource.type || value_type(new_resource.value)
193
-
194
- # when dict this creates an array of values ["Key1", "Value1", "Key2", "Value2" ...]
195
- cmd_values = ["-#{type}"]
196
-
197
- case type
198
- when "dict"
199
- cmd_values.concat(new_resource.value.flatten)
200
- when "array"
201
- cmd_values.concat(new_resource.value)
202
- when "bool"
203
- cmd_values.concat(bool_to_defaults_bool(new_resource.value))
204
- else
205
- cmd_values.concat([new_resource.value])
206
- end
207
-
208
- cmd_values
209
- end
135
+ def get_preference(new_resource)
136
+ CF::Preferences.get(new_resource.key, new_resource.domain, new_resource.user, new_resource.host)
137
+ end
210
138
 
211
- #
212
- # defaults booleans on the CLI must be 'TRUE' or 'FALSE' so convert various inputs to that
213
- #
214
- # @param [String, Integer, Boolean] input <description>
215
- #
216
- # @return [String] TRUE or FALSE
217
- #
218
- def bool_to_defaults_bool(input)
219
- return ["TRUE"] if [true, "TRUE", "1", "true", "YES", "yes"].include?(input)
220
- return ["FALSE"] if [false, "FALSE", "0", "false", "NO", "no"].include?(input)
221
-
222
- # make sure it's very clear bad input was given
223
- raise ArgumentError, "#{input} cannot be converted to a boolean value for use with Apple's defaults command. Acceptable values are: 'TRUE', 'YES', 'true, 'yes', '0', true, 'FALSE', 'false', 'NO', 'no', '1', or false."
139
+ # Return valid hostname based on the input from host property
140
+ def to_cf_host(value)
141
+ case value
142
+ when :all
143
+ CF::Preferences::ALL_HOSTS
144
+ when :current
145
+ CF::Preferences::CURRENT_HOST
146
+ else
147
+ value
224
148
  end
149
+ end
225
150
 
226
- #
227
- # convert ruby type to defaults type
228
- #
229
- # @param [Integer, Float, String, TrueClass, FalseClass, Hash, Array] value The value being set
230
- #
231
- # @return [string, nil] the type value used by defaults or nil if not applicable
232
- #
233
- def value_type(value)
234
- case value
235
- when true, false
236
- "bool"
237
- when Integer
238
- "int"
239
- when Float
240
- "float"
241
- when Hash
242
- "dict"
243
- when Array
244
- "array"
245
- when String
246
- "string"
247
- end
151
+ # Return valid username based on the input from user property
152
+ def to_cf_user(value)
153
+ case value
154
+ when :all
155
+ CF::Preferences::ALL_USERS
156
+ when :current
157
+ CF::Preferences::CURRENT_USER
158
+ else
159
+ value
248
160
  end
249
161
  end
250
162
  end
@@ -226,7 +226,7 @@ class Chef
226
226
  end
227
227
 
228
228
  def ca_private_key
229
- if new_resource.csr_file.nil?
229
+ if new_resource.ca_key_file.nil?
230
230
  key
231
231
  else
232
232
  OpenSSL::PKey.read ::File.read(new_resource.ca_key_file), new_resource.ca_key_pass
@@ -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 repository."
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: "The name of the package source.",
117
+ description: "A label that names your package source.",
32
118
  name_property: true
33
119
 
34
- property :url, String,
35
- description: "The URL to the package source.",
36
- required: [:register]
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 :trusted, [TrueClass, FalseClass],
39
- description: "Whether or not to trust packages from this source.",
40
- default: false
124
+ property :source_location, String,
125
+ introduced: "17.6",
126
+ description: "The URL to the location to retrieve modules from."
41
127
 
42
- property :provider_name, String,
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 for this source. Only valid if the provider is `PowerShellGet`."
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
- url status["url"]
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
- action :register, description: "Registers and updates the PowerShell package source." do
74
- # TODO: Ensure package provider is installed?
75
- if psrepository_cmdlet_appropriate?
76
- if package_source_exists?
77
- converge_if_changed :url, :trusted, :publish_location, :script_source_location, :script_publish_location do
78
- update_cmd = build_ps_repository_command("Set", new_resource)
79
- res = powershell_exec(update_cmd)
80
- raise "Failed to update #{new_resource.source_name}: #{res.errors}" if res.error?
81
- end
82
- else
83
- converge_by("register source: #{new_resource.source_name}") do
84
- register_cmd = build_ps_repository_command("Register", new_resource)
85
- res = powershell_exec(register_cmd)
86
- raise "Failed to register #{new_resource.source_name}: #{res.errors}" if res.error?
87
- end
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
- if package_source_exists?
91
- converge_if_changed :url, :trusted, :provider_name do
92
- update_cmd = build_package_source_command("Set", new_resource)
93
- res = powershell_exec(update_cmd)
94
- raise "Failed to update #{new_resource.source_name}: #{res.errors}" if res.error?
95
- end
96
- else
97
- converge_by("register source: #{new_resource.source_name}") do
98
- register_cmd = build_package_source_command("Register", new_resource)
99
- res = powershell_exec(register_cmd)
100
- raise "Failed to register #{new_resource.source_name}: #{res.errors}" if res.error?
101
- end
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
- if package_source_exists?
108
- unregister_cmd = "Get-PackageSource -Name '#{new_resource.source_name}' | Unregister-PackageSource"
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 psrepository_cmdlet_appropriate?
123
- new_resource.provider_name == "PowerShellGet"
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
- cmd = "#{cmdlet_type}-PSRepository -Name '#{new_resource.source_name}'"
128
- cmd << " -SourceLocation '#{new_resource.url}'" if new_resource.url
129
- cmd << " -InstallationPolicy '#{new_resource.trusted ? "Trusted" : "Untrusted"}'"
130
- cmd << " -PublishLocation '#{new_resource.publish_location}'" if new_resource.publish_location
131
- cmd << " -ScriptSourceLocation '#{new_resource.script_source_location}'" if new_resource.script_source_location
132
- cmd << " -ScriptPublishLocation '#{new_resource.script_publish_location}'" if new_resource.script_publish_location
133
- cmd << " | Out-Null"
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
- cmd = "#{cmdlet_type}-PackageSource -Name '#{new_resource.source_name}'"
139
- cmd << " -Location '#{new_resource.url}'" if new_resource.url
140
- cmd << " -Trusted:#{new_resource.trusted ? "$true" : "$false"}"
141
- cmd << " -ProviderName '#{new_resource.provider_name}'" if new_resource.provider_name
142
- cmd << " | Out-Null"
143
- cmd
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(name)
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 '#{name}' -ErrorAction SilentlyContinue) {
156
- if ((Get-PackageSource -Name '#{name}').ProviderName -eq 'PowerShellGet') {
157
- (Get-PSRepository -Name '#{name}') | Select @{n='source_name';e={$_.Name}}, @{n='url';e={$_.SourceLocation}},
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 '#{name}') | Select @{n='source_name';e={$_.Name}}, @{n='url';e={$_.Location}},
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
@@ -88,7 +88,7 @@ class Chef
88
88
  # @return [String]
89
89
  def registry_path
90
90
  { machine: "HKLM", user: "HKCU" }[new_resource.root] + \
91
- '\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run'
91
+ "\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
92
92
  end
93
93
  end
94
94
  end
@@ -38,7 +38,7 @@ class Chef
38
38
 
39
39
  property :full_users, Array,
40
40
  description: "Determines which users should have full access to the share.",
41
- default: ['BUILTIN\\administrators']
41
+ default: ["BUILTIN\\administrators"]
42
42
 
43
43
  property :change_users, Array,
44
44
  description: "Determines which users should have change access to the share.",
@@ -50,7 +50,7 @@ class Chef
50
50
 
51
51
  property :root, String,
52
52
  description: "The root from which to create the DFS tree. Defaults to C:\\DFSRoots.",
53
- default: 'C:\\DFSRoots'
53
+ default: "C:\\DFSRoots"
54
54
 
55
55
  action :create, description: "Creates the dfs namespace on the server." do
56
56
  directory file_path do