From a80432a0961f3860c1fc0dc0540675b67aaaa4e5 Mon Sep 17 00:00:00 2001 From: trievangelist Date: Mon, 13 Jan 2014 11:56:17 -0600 Subject: [PATCH 1/3] Refactoring net_share provider to support Ruby 1.9.3+ Ruby 1.9.3 no longer provides an each method for String objects. Switching to use each_line method. @onyxmaster submitted Issue #1 providing original fix. --- modules/net_share/lib/puppet/provider/net_share/net_share.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/net_share/lib/puppet/provider/net_share/net_share.rb b/modules/net_share/lib/puppet/provider/net_share/net_share.rb index 630e238..1fcc485 100644 --- a/modules/net_share/lib/puppet/provider/net_share/net_share.rb +++ b/modules/net_share/lib/puppet/provider/net_share/net_share.rb @@ -73,7 +73,7 @@ def self.query(name) properties[:ensure] = :present - output.each do |line| + output.each_line do |line| break if line.rstrip.length == 0 last_name = name From 79766a3748b47e1181ef6121d0e6f8817e49554e Mon Sep 17 00:00:00 2001 From: trievangelist Date: Mon, 13 Jan 2014 13:30:44 -0600 Subject: [PATCH 2/3] Refactor net_share type to munge permissions correctly Permissions property on the net_share type was trying to munge an array of values using a collect method deprecated in Puppet 3.x. Changed munge block on permissions property to treat each value as a string. @onyxmaster submitted Issue #1 providing original fix. --- modules/net_share/lib/puppet/type/net_share.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/net_share/lib/puppet/type/net_share.rb b/modules/net_share/lib/puppet/type/net_share.rb index ce4171e..1a6e5f5 100644 --- a/modules/net_share/lib/puppet/type/net_share.rb +++ b/modules/net_share/lib/puppet/type/net_share.rb @@ -51,10 +51,8 @@ def property_matches?(current, desired) desc "An array of permissions. Example: ['computer\\user,full', 'computer\\user2,change', 'computer\\user3,read']" munge do |value| - value.collect do |item| - user, access = item.split(',', 2) - "#{user.strip},#{access.strip.downcase}" - end + user, access = value.split(',', 2) + "#{user.strip},#{access.strip.downcase}" end end From 0d49a0710bf2cd8e2be9894f6c9cce45c18f5c52 Mon Sep 17 00:00:00 2001 From: johnburns320 Date: Fri, 17 Jan 2014 14:56:15 -0600 Subject: [PATCH 3/3] Restructure folders to match standards --- modules/net_share/Modulefile => Modulefile | 16 +- .../puppet/provider/net_share/net_share.rb | 338 +++++++++--------- .../lib => lib}/puppet/type/net_share.rb | 140 ++++---- .../net_share/tests => tests}/net_share.pp | 16 +- 4 files changed, 255 insertions(+), 255 deletions(-) rename modules/net_share/Modulefile => Modulefile (97%) rename {modules/net_share/lib => lib}/puppet/provider/net_share/net_share.rb (96%) rename {modules/net_share/lib => lib}/puppet/type/net_share.rb (96%) rename {modules/net_share/tests => tests}/net_share.pp (96%) diff --git a/modules/net_share/Modulefile b/Modulefile similarity index 97% rename from modules/net_share/Modulefile rename to Modulefile index 3f69d9c..99a6a7c 100644 --- a/modules/net_share/Modulefile +++ b/Modulefile @@ -1,8 +1,8 @@ -name 'simondean-net_share' -version '0.1.2' -summary 'Windows network share module' -description 'Module for configuring Windows network file shares. Uses the \'net share\' command. ' -project_page 'https://github.com/simondean/puppet-net_share' -license 'Apache License, Version 2.0' -author 'Simon Dean' -source 'https://github.com/simondean/puppet-net_share' +name 'simondean-net_share' +version '0.1.2' +summary 'Windows network share module' +description 'Module for configuring Windows network file shares. Uses the \'net share\' command. ' +project_page 'https://github.com/simondean/puppet-net_share' +license 'Apache License, Version 2.0' +author 'Simon Dean' +source 'https://github.com/simondean/puppet-net_share' diff --git a/modules/net_share/lib/puppet/provider/net_share/net_share.rb b/lib/puppet/provider/net_share/net_share.rb similarity index 96% rename from modules/net_share/lib/puppet/provider/net_share/net_share.rb rename to lib/puppet/provider/net_share/net_share.rb index 1fcc485..5e18c6b 100644 --- a/modules/net_share/lib/puppet/provider/net_share/net_share.rb +++ b/lib/puppet/provider/net_share/net_share.rb @@ -1,169 +1,169 @@ -Puppet::Type.type(:net_share).provide(:net_share) do - desc "Windows network share" - - confine :operatingsystem => :windows - defaultfor :operatingsystem => :windows - - commands :net => File.join(ENV['SystemRoot'] || 'c:/windows', 'system32/net.exe') - - mk_resource_methods - - # Match resources to providers where the resource name matches the provider name - def self.prefetch(resources) - resources.each do |name, resource| - provider = new(query(name)) - - if provider - resource.provider = provider - else - resource.provider = new(:ensure => :absent) - end - end - end - - def initialize(*args) - super - - # Make a duplicate of the properties so we can compare them during a flush - @initial_properties = @property_hash.dup - end - - def exists? - @property_hash[:ensure] != :absent - end - - def create - @property_hash[:ensure] = :present - end - - def destroy - @property_hash[:ensure] = :absent - end - - def flush - if @property_hash[:ensure] != :absent - if @initial_properties[:ensure] != :absent - info "deleting and recreating net_share '#{name}'" - execute_delete - end - - execute_create - else - execute_delete - end - - @property_hash.clear - @initial_properties.clear - end - - private - def self.query(name) - cmd = [command(:net), 'share', name] - output = execute(cmd, { :failonfail => false }) - - properties = {} - properties[:name] = name - - if $?.exitstatus == 2 - properties[:ensure] = :absent - return properties - elsif $?.exitstatus != 0 - raise ExecutionFailure, "Execution of '#{cmd.join(' ')}' returned #{$?.exitstatus}: #{output}" - end - - properties[:ensure] = :present - - output.each_line do |line| - break if line.rstrip.length == 0 - - last_name = name - name = line[0..17].rstrip - value = line[18..-1].rstrip - - if name.length == 0 - name = last_name - end - - case name - when 'Path' - properties[:path] = value - when 'Remark' - properties[:remark] = value - when 'Maximum users' - if value == 'No limit' - properties[:maximumusers] = :unlimited - else - properties[:maximumusers] = value.to_i - end - when 'Caching' - case value - when 'Caching disabled' - value = :none - when 'Manual caching of documents' - value = :manual - when 'Automatic caching of documents' - value = :documents - when 'Automatic caching of programs and documents' - value = :programs - else - raise Puppet::Error, "Unrecognised Caching value '#{value}'" - end - - properties[:cache] = value - when 'Permission' - properties[:permissions] ||= [] - - user, access = value.split(',', 2) - permission = "#{user.strip},#{access.strip.downcase}" - - properties[:permissions] << permission - end - end - - properties - end - - def execute_create - net(*(['share', "#{resource[:name]}=#{resource[:path]}"] + get_property_args())) - end - - def execute_delete - net('share', resource[:name], '/delete') - end - - def get_property_args() - args = [] - - self.class.resource_type.validproperties.each do |name| - if name != :ensure - value = @resource.should(name) - - unless value.nil? - case name - when :path - when :remark - args << "/remark:#{value}" - when :maximumusers - if value == :unlimited - args << "/unlimited" - else - args << "/users:#{value}" - end - when :cache - args << "/cache:#{value}" - when :permissions - value.each do |user_permissions| - args << "/grant:#{user_permissions}" - end - else - raise Puppet::Error, "Unrecognised property '#{name}'" - end - end - - @property_hash[name] = value - end - end - - args - end -end +Puppet::Type.type(:net_share).provide(:net_share) do + desc "Windows network share" + + confine :operatingsystem => :windows + defaultfor :operatingsystem => :windows + + commands :net => File.join(ENV['SystemRoot'] || 'c:/windows', 'system32/net.exe') + + mk_resource_methods + + # Match resources to providers where the resource name matches the provider name + def self.prefetch(resources) + resources.each do |name, resource| + provider = new(query(name)) + + if provider + resource.provider = provider + else + resource.provider = new(:ensure => :absent) + end + end + end + + def initialize(*args) + super + + # Make a duplicate of the properties so we can compare them during a flush + @initial_properties = @property_hash.dup + end + + def exists? + @property_hash[:ensure] != :absent + end + + def create + @property_hash[:ensure] = :present + end + + def destroy + @property_hash[:ensure] = :absent + end + + def flush + if @property_hash[:ensure] != :absent + if @initial_properties[:ensure] != :absent + info "deleting and recreating net_share '#{name}'" + execute_delete + end + + execute_create + else + execute_delete + end + + @property_hash.clear + @initial_properties.clear + end + + private + def self.query(name) + cmd = [command(:net), 'share', name] + output = execute(cmd, { :failonfail => false }) + + properties = {} + properties[:name] = name + + if $?.exitstatus == 2 + properties[:ensure] = :absent + return properties + elsif $?.exitstatus != 0 + raise ExecutionFailure, "Execution of '#{cmd.join(' ')}' returned #{$?.exitstatus}: #{output}" + end + + properties[:ensure] = :present + + output.each_line do |line| + break if line.rstrip.length == 0 + + last_name = name + name = line[0..17].rstrip + value = line[18..-1].rstrip + + if name.length == 0 + name = last_name + end + + case name + when 'Path' + properties[:path] = value + when 'Remark' + properties[:remark] = value + when 'Maximum users' + if value == 'No limit' + properties[:maximumusers] = :unlimited + else + properties[:maximumusers] = value.to_i + end + when 'Caching' + case value + when 'Caching disabled' + value = :none + when 'Manual caching of documents' + value = :manual + when 'Automatic caching of documents' + value = :documents + when 'Automatic caching of programs and documents' + value = :programs + else + raise Puppet::Error, "Unrecognised Caching value '#{value}'" + end + + properties[:cache] = value + when 'Permission' + properties[:permissions] ||= [] + + user, access = value.split(',', 2) + permission = "#{user.strip},#{access.strip.downcase}" + + properties[:permissions] << permission + end + end + + properties + end + + def execute_create + net(*(['share', "#{resource[:name]}=#{resource[:path]}"] + get_property_args())) + end + + def execute_delete + net('share', resource[:name], '/delete') + end + + def get_property_args() + args = [] + + self.class.resource_type.validproperties.each do |name| + if name != :ensure + value = @resource.should(name) + + unless value.nil? + case name + when :path + when :remark + args << "/remark:#{value}" + when :maximumusers + if value == :unlimited + args << "/unlimited" + else + args << "/users:#{value}" + end + when :cache + args << "/cache:#{value}" + when :permissions + value.each do |user_permissions| + args << "/grant:#{user_permissions}" + end + else + raise Puppet::Error, "Unrecognised property '#{name}'" + end + end + + @property_hash[name] = value + end + end + + args + end +end diff --git a/modules/net_share/lib/puppet/type/net_share.rb b/lib/puppet/type/net_share.rb similarity index 96% rename from modules/net_share/lib/puppet/type/net_share.rb rename to lib/puppet/type/net_share.rb index 1a6e5f5..02bb6f7 100644 --- a/modules/net_share/lib/puppet/type/net_share.rb +++ b/lib/puppet/type/net_share.rb @@ -1,70 +1,70 @@ -Puppet::Type.newtype(:net_share) do - @doc = "Windows network share" - - class CaseInsensitiveProperty < Puppet::Property - def insync?(is) - raise Puppet::Error, "Invalid value for attribute '#{name}', must be an array" unless @should.is_a?(Array) - - (is.length == @should.length) and (is.zip(@should).all? { |a, b| property_matches?(a, b) }) - end - - def property_matches?(current, desired) - current.to_s.casecmp(desired.to_s) == 0 - end - end - - ensurable - - newparam(:name) do - desc "Network share name. " - end - - newproperty(:path) do - desc "File system path to be shared. Will be auto-required. " - end - - newproperty(:remark) do - desc "Comments stored against the share. " - end - - newproperty(:maximumusers) do - desc "Maximum number of users that can concurrently access the share. Valid values are 'unlimited' or a number. " - - newvalues(:unlimited, /^[1-9][0-9]*$/) - - munge do |value| - if value.casecmp('unlimited') == 0 - :unlimited - else - value.to_s - end - end - end - - newproperty(:cache) do - desc "Caching. " - - newvalues(:manual, :documents, :programs, :branchcache, :none) - end - - newproperty(:permissions, :parent => CaseInsensitiveProperty, :array_matching => :all) do - desc "An array of permissions. Example: ['computer\\user,full', 'computer\\user2,change', 'computer\\user3,read']" - - munge do |value| - user, access = value.split(',', 2) - "#{user.strip},#{access.strip.downcase}" - end - end - - autorequire(:file) do - self[:path] - end - - validate do - if self[:ensure] != :absent - [:path].each do |attribute| - raise Puppet::Error, "Attribute '#{attribute}' is mandatory" unless self[attribute] - end - end - end -end +Puppet::Type.newtype(:net_share) do + @doc = "Windows network share" + + class CaseInsensitiveProperty < Puppet::Property + def insync?(is) + raise Puppet::Error, "Invalid value for attribute '#{name}', must be an array" unless @should.is_a?(Array) + + (is.length == @should.length) and (is.zip(@should).all? { |a, b| property_matches?(a, b) }) + end + + def property_matches?(current, desired) + current.to_s.casecmp(desired.to_s) == 0 + end + end + + ensurable + + newparam(:name) do + desc "Network share name. " + end + + newproperty(:path) do + desc "File system path to be shared. Will be auto-required. " + end + + newproperty(:remark) do + desc "Comments stored against the share. " + end + + newproperty(:maximumusers) do + desc "Maximum number of users that can concurrently access the share. Valid values are 'unlimited' or a number. " + + newvalues(:unlimited, /^[1-9][0-9]*$/) + + munge do |value| + if value.casecmp('unlimited') == 0 + :unlimited + else + value.to_s + end + end + end + + newproperty(:cache) do + desc "Caching. " + + newvalues(:manual, :documents, :programs, :branchcache, :none) + end + + newproperty(:permissions, :parent => CaseInsensitiveProperty, :array_matching => :all) do + desc "An array of permissions. Example: ['computer\\user,full', 'computer\\user2,change', 'computer\\user3,read']" + + munge do |value| + user, access = value.split(',', 2) + "#{user.strip},#{access.strip.downcase}" + end + end + + autorequire(:file) do + self[:path] + end + + validate do + if self[:ensure] != :absent + [:path].each do |attribute| + raise Puppet::Error, "Attribute '#{attribute}' is mandatory" unless self[attribute] + end + end + end +end diff --git a/modules/net_share/tests/net_share.pp b/tests/net_share.pp similarity index 96% rename from modules/net_share/tests/net_share.pp rename to tests/net_share.pp index 9a47bf7..e12a7b1 100644 --- a/modules/net_share/tests/net_share.pp +++ b/tests/net_share.pp @@ -1,8 +1,8 @@ -net_share {'PuppetTest': - ensure => present, - path => 'c:\puppet_test', - remark => 'PuppetTest', - maximumusers => unlimited, - cache => none, - permissions => ["host\\PuppetTest,full", "host\\PuppetTest2,full"], -} +net_share {'PuppetTest': + ensure => present, + path => 'c:\puppet_test', + remark => 'PuppetTest', + maximumusers => unlimited, + cache => none, + permissions => ["host\\PuppetTest,full", "host\\PuppetTest2,full"], +}