wright 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +8 -0
  3. data/README.md +2 -0
  4. data/Rakefile +6 -0
  5. data/bin/wright +6 -0
  6. data/lib/wright/cli.rb +68 -0
  7. data/lib/wright/dsl.rb +1 -1
  8. data/lib/wright/provider/directory.rb +17 -12
  9. data/lib/wright/provider/file.rb +24 -17
  10. data/lib/wright/provider/group/darwin_directory_service.rb +1 -8
  11. data/lib/wright/provider/group/gnu_passwd.rb +0 -1
  12. data/lib/wright/provider/group.rb +6 -12
  13. data/lib/wright/provider/package/apt.rb +9 -21
  14. data/lib/wright/provider/package/homebrew.rb +5 -18
  15. data/lib/wright/provider/package.rb +22 -11
  16. data/lib/wright/provider/symlink.rb +17 -22
  17. data/lib/wright/provider/user/darwin_directory_service.rb +65 -0
  18. data/lib/wright/provider/user/gnu_passwd.rb +6 -7
  19. data/lib/wright/provider/user.rb +6 -12
  20. data/lib/wright/provider.rb +20 -2
  21. data/lib/wright/resource/directory.rb +19 -20
  22. data/lib/wright/resource/file.rb +19 -15
  23. data/lib/wright/resource/symlink.rb +1 -0
  24. data/lib/wright/resource/user.rb +2 -1
  25. data/lib/wright/resource.rb +1 -1
  26. data/lib/wright/util/file_owner.rb +61 -0
  27. data/lib/wright/util/file_permissions.rb +21 -30
  28. data/lib/wright/util/stolen_from_activesupport.rb +1 -1
  29. data/lib/wright/util/user.rb +48 -23
  30. data/lib/wright/util.rb +10 -6
  31. data/lib/wright/version.rb +1 -1
  32. data/lib/wright.rb +1 -0
  33. data/man/wright.1 +202 -0
  34. data/spec/cli/shebang.rb +3 -0
  35. data/spec/cli_spec.rb +64 -0
  36. data/spec/dsl_spec.rb +8 -3
  37. data/spec/provider/group/darwin_directory_service_spec.rb +3 -2
  38. data/spec/provider/package/apt/apt-cache_policy_abcde.stdout +7 -0
  39. data/spec/provider/package/apt/apt-cache_policy_htop.stdout +6 -0
  40. data/spec/provider/package/apt/apt-cache_policy_not-a-real-package.return +1 -0
  41. data/spec/provider/package/apt_spec.rb +17 -211
  42. data/spec/provider/package/homebrew_spec.rb +11 -164
  43. data/spec/provider/package_spec.rb +151 -7
  44. data/spec/provider/user/darwin_directory_service/dscl-delete-user.return +1 -0
  45. data/spec/provider/user/darwin_directory_service/dscl-delete-user.stderr +0 -0
  46. data/spec/provider/user/darwin_directory_service/dscl-delete-user.stdout +0 -0
  47. data/spec/provider/user/darwin_directory_service/dscl-new-user-full-name.return +1 -0
  48. data/spec/provider/user/darwin_directory_service/dscl-new-user-full-name.stderr +0 -0
  49. data/spec/provider/user/darwin_directory_service/dscl-new-user-full-name.stdout +0 -0
  50. data/spec/provider/user/darwin_directory_service/dscl-new-user-home.return +1 -0
  51. data/spec/provider/user/darwin_directory_service/dscl-new-user-home.stderr +0 -0
  52. data/spec/provider/user/darwin_directory_service/dscl-new-user-home.stdout +0 -0
  53. data/spec/provider/user/darwin_directory_service/dscl-new-user-password.return +1 -0
  54. data/spec/provider/user/darwin_directory_service/dscl-new-user-password.stderr +0 -0
  55. data/spec/provider/user/darwin_directory_service/dscl-new-user-password.stdout +0 -0
  56. data/spec/provider/user/darwin_directory_service/dscl-new-user-primary-group.return +1 -0
  57. data/spec/provider/user/darwin_directory_service/dscl-new-user-primary-group.stderr +0 -0
  58. data/spec/provider/user/darwin_directory_service/dscl-new-user-primary-group.stdout +0 -0
  59. data/spec/provider/user/darwin_directory_service/dscl-new-user-shell.return +1 -0
  60. data/spec/provider/user/darwin_directory_service/dscl-new-user-shell.stderr +0 -0
  61. data/spec/provider/user/darwin_directory_service/dscl-new-user-shell.stdout +0 -0
  62. data/spec/provider/user/darwin_directory_service/dscl-new-user-uid.return +1 -0
  63. data/spec/provider/user/darwin_directory_service/dscl-new-user-uid.stderr +0 -0
  64. data/spec/provider/user/darwin_directory_service/dscl-new-user-uid.stdout +0 -0
  65. data/spec/provider/user/darwin_directory_service_spec.rb +167 -0
  66. data/spec/provider/user/gnu_passwd_spec.rb +5 -5
  67. data/spec/resource/directory_spec.rb +17 -15
  68. data/spec/resource/file_spec.rb +17 -15
  69. data/spec/resource_spec.rb +1 -1
  70. data/spec/spec_helpers/test_coverage.rb +1 -1
  71. data/spec/util/file_owner_spec.rb +36 -0
  72. data/spec/util/file_permissions_spec.rb +6 -6
  73. data/spec/util/user_spec.rb +0 -17
  74. data/spec/util_spec.rb +64 -5
  75. metadata +91 -41
  76. data/spec/provider/package/apt/dpkg-query_-s_abcde.stdout +0 -23
  77. data/spec/provider/package/apt/dpkg-query_-s_htop.stdout +0 -19
  78. data/spec/provider/package/apt/dpkg-query_-s_not-a-real-package.return +0 -1
  79. data/spec/provider/package/apt/dpkg-query_-s_not-a-real-package.stderr +0 -3
  80. data/spec/provider/package/apt/dpkg-query_-s_vlc.return +0 -1
  81. data/spec/provider/package/apt/dpkg-query_-s_vlc.stderr +0 -3
  82. /data/spec/provider/group/darwin_directory_service/{dseditgroup_-o_create_-i_499_newgroup.return → dseditgroup_-o_create_-i_2_newgroup.return} +0 -0
  83. /data/spec/provider/group/darwin_directory_service/{dseditgroup_-o_create_-i_499_newgroup.stderr → dseditgroup_-o_create_-i_2_newgroup.stderr} +0 -0
  84. /data/spec/provider/group/darwin_directory_service/{dseditgroup_-o_create_-i_499_newgroup.stdout → dseditgroup_-o_create_-i_2_newgroup.stdout} +0 -0
  85. /data/spec/provider/package/apt/{dpkg-query_-s_abcde.return → apt-cache_policy_abcde.return} +0 -0
  86. /data/spec/provider/package/apt/{dpkg-query_-s_abcde.stderr → apt-cache_policy_abcde.stderr} +0 -0
  87. /data/spec/provider/package/apt/{dpkg-query_-s_htop.return → apt-cache_policy_htop.return} +0 -0
  88. /data/spec/provider/package/apt/{dpkg-query_-s_htop.stderr → apt-cache_policy_htop.stderr} +0 -0
  89. /data/spec/provider/package/apt/{dpkg-query_-s_not-a-real-package.stdout → apt-cache_policy_not-a-real-package.stderr} +0 -0
  90. /data/spec/provider/package/apt/{dpkg-query_-s_vlc.stdout → apt-cache_policy_not-a-real-package.stdout} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6d159205080df87b4a9c8935b0486335c74ef84e
4
- data.tar.gz: 35cdf663151ab32900d9be2566574cfc0648f980
3
+ metadata.gz: e035155341d50577a99a8dedbc1a74c071ac65a7
4
+ data.tar.gz: fcef2683e975dcee23bf413fbc5ee66b5f4d264e
5
5
  SHA512:
6
- metadata.gz: 0dd9b03ffecb5ca5bd6bbe272f672fcd8546fdeebc7df4ac307f94148ca10312734ab99afd78720ba1d56e458e6c277424b6479decadbd0181b528fa05451316
7
- data.tar.gz: 61b6d41688576e1736bf63d9e75eb4fd25c3a5de1d480f7a546df90f8802b4e91387556b38cbcb1393a2a7094b5f72117a65ddf336a8022bb416008880009475
6
+ metadata.gz: 2cf56d882eb3350b70fe16dad983dfc9b25d89ca2c403a50874e8b39d71be4fd39e9e63f28134f3afeda334442c4f4148f7f6a10ff3515932c2bd26d0cc96acc
7
+ data.tar.gz: 54ebbd48c70c41b5699e527e4e3e1d599bb0247befe191ff1b19a7b6cf9799cad6fb659198919e5f5456c31708cc79e120038db823c78c8bc2b522c0342cef81
data/NEWS.md CHANGED
@@ -1,4 +1,12 @@
1
1
  # wright NEWS
2
+ ## 0.3.0 (2015-04-23)
3
+ - Add bin/wright
4
+ - Add wright(1) manpage
5
+ - Add OS X user provider
6
+ - Improve performance of the apt provider
7
+ - Improve error message for resources without names (#5)
8
+ - Improve error message for symlinks without target (#6)
9
+
2
10
  ## 0.2.0 (2015-03-13)
3
11
  - Add Homebrew package provider for OS X
4
12
  - Add group resource
data/README.md CHANGED
@@ -5,10 +5,12 @@ wright
5
5
  [![Build Status](https://img.shields.io/travis/sometimesfood/wright.svg?style=flat-square)][travis]
6
6
  [![Code Climate](https://img.shields.io/codeclimate/github/sometimesfood/wright.svg?style=flat-square)][codeclimate]
7
7
  [![Test Coverage](https://img.shields.io/codeclimate/coverage/github/sometimesfood/wright.svg?style=flat-square)][codeclimate]
8
+ [![Gem Dependencies](https://img.shields.io/gemnasium/sometimesfood/wright.svg?style=flat-square)][gemnasium]
8
9
 
9
10
  [gem]: https://rubygems.org/gems/wright
10
11
  [travis]: https://travis-ci.org/sometimesfood/wright
11
12
  [codeclimate]: https://codeclimate.com/github/sometimesfood/wright
13
+ [gemnasium]: https://gemnasium.com/sometimesfood/wright
12
14
 
13
15
  Lightweight configuration management.
14
16
 
data/Rakefile CHANGED
@@ -5,3 +5,9 @@ require 'rake/testtask'
5
5
  Rake::TestTask.new do |t|
6
6
  t.pattern = 'spec/**/*_spec.rb'
7
7
  end
8
+
9
+ file 'man/wright.1' => 'man/wright.1.txt' do
10
+ sh 'a2x --format manpage man/wright.1.txt'
11
+ end
12
+
13
+ task build: 'man/wright.1'
data/bin/wright ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ require 'wright/cli'
3
+
4
+ main = self
5
+ wright = Wright::CLI.new(main)
6
+ wright.run(ARGV)
data/lib/wright/cli.rb ADDED
@@ -0,0 +1,68 @@
1
+ require 'optparse'
2
+ require 'wright'
3
+
4
+ module Wright
5
+ # Wright command-line interface.
6
+ class CLI
7
+ def initialize(main)
8
+ @commands = []
9
+ @main = main
10
+ @parser = option_parser
11
+ end
12
+
13
+ # Runs a wright script with the supplied arguments.
14
+ #
15
+ # @param argv [Array<String>] the arguments passed to bin/wright
16
+ def run(argv)
17
+ arguments = parse(argv)
18
+ return if @quit
19
+
20
+ Wright.log.level = @log_level if @log_level
21
+ @main.extend Wright::DSL
22
+
23
+ run_script(arguments)
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :commands
29
+ attr_reader :log_level
30
+
31
+ def parse(argv)
32
+ # use OptionParser#order! instead of #parse! so CLI#run does not
33
+ # consume --arguments passed to wright scripts
34
+ @parser.order!(argv)
35
+ end
36
+
37
+ def run_script(arguments)
38
+ if @commands.empty? && arguments.any?
39
+ script = arguments.shift
40
+ load script
41
+ else
42
+ commands = @commands.empty? ? $stdin.read : @commands.join("\n")
43
+ @main.instance_eval(commands, '<main>', 1)
44
+ end
45
+ end
46
+
47
+ def option_parser
48
+ OptionParser.new do |opts|
49
+ opts.on('-e COMMAND', 'Run COMMAND') do |e|
50
+ @commands << e
51
+ end
52
+
53
+ opts.on('-v', '--verbose', 'Increase verbosity') do
54
+ @log_level = Wright::Logger::DEBUG
55
+ end
56
+
57
+ opts.on('-q', '--quiet', 'Decrease verbosity') do
58
+ @log_level = Wright::Logger::ERROR
59
+ end
60
+
61
+ opts.on_tail('--version', 'Show wright version') do
62
+ puts "wright version #{Wright::VERSION}"
63
+ @quit = true
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
data/lib/wright/dsl.rb CHANGED
@@ -41,7 +41,7 @@ module Wright
41
41
  def self.register_resource(resource_class)
42
42
  method_name = Util.class_to_resource_name(resource_class)
43
43
  this_module = self
44
- define_method(method_name) do |name = nil, &block|
44
+ define_method(method_name) do |name, &block|
45
45
  this_module.yield_resource(resource_class, name, &block)
46
46
  end
47
47
  end
@@ -12,14 +12,12 @@ module Wright
12
12
  #
13
13
  # @return [void]
14
14
  def create
15
- if ::File.directory?(dirname) && permissions.uptodate?
16
- Wright.log.debug "directory already created: '#{@resource.name}'"
17
- return
18
- end
19
-
20
15
  fail Errno::EEXIST, dirname if regular_file?
21
- create_directory
22
- @updated = true
16
+
17
+ dir = @resource.name
18
+ unless_uptodate(:create, "directory already created: '#{dir}'") do
19
+ create_directory
20
+ end
23
21
  end
24
22
 
25
23
  # Removes the directory.
@@ -30,16 +28,23 @@ module Wright
30
28
  fail "'#{dirname}' exists but is not a directory"
31
29
  end
32
30
 
33
- if ::File.directory?(dirname)
31
+ dir = @resource.name
32
+ unless_uptodate(:remove, "directory already removed: '#{dir}'") do
34
33
  remove_directory
35
- @updated = true
36
- else
37
- Wright.log.debug "directory already removed: '#{@resource.name}'"
38
34
  end
39
35
  end
40
36
 
41
37
  private
42
38
 
39
+ def uptodate?(action)
40
+ case action
41
+ when :create
42
+ ::File.directory?(dirname) && permissions.uptodate?
43
+ when :remove
44
+ !::File.exist?(dirname) && !::File.directory?(dirname)
45
+ end
46
+ end
47
+
43
48
  def permissions
44
49
  Wright::Util::FilePermissions.create_from_resource(@resource,
45
50
  :directory)
@@ -49,7 +54,7 @@ module Wright
49
54
  dir_permissions = permissions
50
55
  unless_dry_run("create directory: '#{@resource.name}'") do
51
56
  FileUtils.mkdir_p(dirname)
52
- dir_permissions.update
57
+ dir_permissions.update unless dir_permissions.uptodate?
53
58
  end
54
59
  end
55
60
 
@@ -2,6 +2,7 @@ require 'fileutils'
2
2
  require 'digest'
3
3
  require 'tempfile'
4
4
  require 'tmpdir'
5
+
5
6
  require 'wright/provider'
6
7
  require 'wright/util/file_permissions'
7
8
  require 'wright/util/user'
@@ -13,29 +14,26 @@ module Wright
13
14
  # Creates or updates the file.
14
15
  #
15
16
  # @return [void]
17
+ # @raise [Errno::EISDIR] if there is already a directory with
18
+ # the specified name
16
19
  def create
17
- fail Errno::EISDIR, filename if ::File.directory?(filename)
18
-
19
- if uptodate?
20
- Wright.log.debug "file already created: '#{@resource.name}'"
21
- return
20
+ fail_if_directory
21
+ file = @resource.name
22
+ unless_uptodate(:create, "file already created: '#{file}'") do
23
+ create_file
22
24
  end
23
-
24
- create_file
25
- @updated = true
26
25
  end
27
26
 
28
27
  # Removes the file.
29
28
  #
30
29
  # @return [void]
30
+ # @raise [Errno::EISDIR] if there is a directory with the
31
+ # specified name
31
32
  def remove
32
- fail Errno::EISDIR, filename if ::File.directory?(filename)
33
-
34
- if ::File.exist?(filename) || ::File.symlink?(filename)
33
+ fail_if_directory
34
+ file = @resource.name
35
+ unless_uptodate(:remove, "file already removed: '#{file}'") do
35
36
  remove_file
36
- @updated = true
37
- else
38
- Wright.log.debug "file already removed: '#{@resource.name}'"
39
37
  end
40
38
  end
41
39
 
@@ -45,7 +43,7 @@ module Wright
45
43
  file_permissions = permissions
46
44
  unless_dry_run("create file: '#{@resource.name}'") do
47
45
  write_content_to_file
48
- file_permissions.update
46
+ file_permissions.update unless file_permissions.uptodate?
49
47
  end
50
48
  end
51
49
 
@@ -85,13 +83,22 @@ module Wright
85
83
  current_checksum == target_checksum
86
84
  end
87
85
 
88
- def uptodate?
89
- content_uptodate? && permissions.uptodate?
86
+ def uptodate?(action)
87
+ case action
88
+ when :create
89
+ content_uptodate? && permissions.uptodate?
90
+ when :remove
91
+ !::File.exist?(filename) && !::File.symlink?(filename)
92
+ end
90
93
  end
91
94
 
92
95
  def filename
93
96
  ::File.expand_path(@resource.name)
94
97
  end
98
+
99
+ def fail_if_directory
100
+ fail Errno::EISDIR, filename if ::File.directory?(filename)
101
+ end
95
102
  end
96
103
  end
97
104
  end
@@ -1,4 +1,3 @@
1
- require 'wright/dry_run'
2
1
  require 'wright/provider'
3
2
  require 'wright/provider/group'
4
3
 
@@ -47,13 +46,7 @@ module Wright
47
46
 
48
47
  def next_system_gid
49
48
  system_gid_range = (1...500)
50
- used_system_gids = []
51
- Etc.group do |g|
52
- used_system_gids << g.gid if system_gid_range.include?(g.gid)
53
- end
54
- free_system_gids = system_gid_range.to_a - used_system_gids
55
- fail 'No free gids in system gid range' if free_system_gids.empty?
56
- free_system_gids.max
49
+ Wright::Util::User.next_free_gid(system_gid_range)
57
50
  end
58
51
  end
59
52
  end
@@ -1,4 +1,3 @@
1
- require 'wright/dry_run'
2
1
  require 'wright/provider'
3
2
  require 'wright/provider/group'
4
3
 
@@ -10,26 +10,20 @@ module Wright
10
10
  #
11
11
  # @return [void]
12
12
  def create
13
- if uptodate?(:create)
14
- Wright.log.debug "group already created: '#{@resource.name}'"
15
- return
13
+ group = @resource.name
14
+ unless_uptodate(:create, "group already created: '#{group}'") do
15
+ create_group
16
16
  end
17
-
18
- create_group
19
- @updated = true
20
17
  end
21
18
 
22
19
  # Removes the group.
23
20
  #
24
21
  # @return [void]
25
22
  def remove
26
- if uptodate?(:remove)
27
- Wright.log.debug "group already removed: '#{@resource.name}'"
28
- return
23
+ group = @resource.name
24
+ unless_uptodate(:remove, "group already removed: '#{group}'") do
25
+ remove_group
29
26
  end
30
-
31
- remove_group
32
- @updated = true
33
27
  end
34
28
 
35
29
  private
@@ -1,6 +1,3 @@
1
- require 'open3'
2
-
3
- require 'wright/dry_run'
4
1
  require 'wright/provider'
5
2
  require 'wright/provider/package'
6
3
 
@@ -12,33 +9,24 @@ module Wright
12
9
  class Apt < Wright::Provider::Package
13
10
  # @return [Array<String>] the installed package versions
14
11
  def installed_versions
15
- cmd = 'dpkg-query'
16
- args = ['-s', @resource.name]
17
- cmd_stdout, _, cmd_status = Open3.capture3(env, cmd, *args)
18
- installed_re = /^Status: install ok installed$/
12
+ package = @resource.name
13
+ err = "Cannot determine installed versions for package '#{package}'"
14
+ apt_policy = exec_or_fail('apt-cache', ['policy', package], err)
19
15
 
20
- if cmd_status.success? && installed_re =~ cmd_stdout
21
- /^Version: (?<version>.*)$/ =~ cmd_stdout
22
- [version]
23
- else
24
- []
25
- end
16
+ version_re = /(?!\(none\)).*/
17
+ installed_re = /^ Installed: (?<version>#{version_re})$/
18
+ match = installed_re.match(apt_policy)
19
+ match ? [match['version']] : []
26
20
  end
27
21
 
28
22
  private
29
23
 
30
24
  def install_package
31
- package = @resource.name
32
- unless_dry_run("install package: '#{package}'") do
33
- apt_get(:install, package, @resource.version)
34
- end
25
+ apt_get(:install, @resource.name, @resource.version)
35
26
  end
36
27
 
37
28
  def remove_package
38
- package = @resource.name
39
- unless_dry_run("remove package: '#{package}'") do
40
- apt_get(:remove, package)
41
- end
29
+ apt_get(:remove, @resource.name)
42
30
  end
43
31
 
44
32
  def apt_get(action, package, version = nil)
@@ -1,7 +1,6 @@
1
1
  require 'open3'
2
2
  require 'json'
3
3
 
4
- require 'wright/dry_run'
5
4
  require 'wright/provider'
6
5
  require 'wright/provider/package'
7
6
 
@@ -29,32 +28,20 @@ module Wright
29
28
  private
30
29
 
31
30
  def install_package
32
- package = @resource.name
33
- unless_dry_run("install package: '#{package}'") do
34
- brew(:install, package, @resource.version)
35
- end
31
+ brew(:install, @resource.name, @resource.version)
36
32
  end
37
33
 
38
34
  def remove_package
39
- package = @resource.name
40
- unless_dry_run("remove package: '#{package}'") do
41
- brew(:uninstall, package)
42
- end
35
+ brew(:uninstall, @resource.name)
43
36
  end
44
37
 
45
38
  def brew(action, package, version = nil)
46
39
  ignore_version(version)
47
40
 
48
- cmd = 'brew'
49
- args = [action.to_s, package]
50
-
51
- _, cmd_stderr, cmd_status = Wright::Util.bundler_clean_env do
52
- Open3.capture3(env, cmd, *args)
41
+ Wright::Util.bundler_clean_env do
42
+ error_message = "cannot #{action} package '#{package}'"
43
+ exec_or_fail('brew', [action.to_s, package], error_message)
53
44
  end
54
- return if cmd_status.success?
55
-
56
- brew_error = cmd_stderr.chomp
57
- fail %(cannot #{action} package '#{package}': "#{brew_error}")
58
45
  end
59
46
 
60
47
  def ignore_version(version)
@@ -9,26 +9,29 @@ module Wright
9
9
  #
10
10
  # @return [void]
11
11
  def install
12
- if uptodate?(:install)
13
- Wright.log.debug "package already installed: '#{@resource.name}'"
14
- return
12
+ package = @resource.name
13
+ unless_uptodate(:install, "package already installed: '#{package}'") do
14
+ unless_dry_run("install package: '#{package}'") do
15
+ install_package
16
+ end
15
17
  end
16
-
17
- install_package
18
- @updated = true
19
18
  end
20
19
 
21
20
  # Removes the package.
22
21
  #
23
22
  # @return [void]
24
23
  def remove
25
- if uptodate?(:remove)
26
- Wright.log.debug "package already removed: '#{@resource.name}'"
27
- return
24
+ package = @resource.name
25
+ unless_uptodate(:remove, "package already removed: '#{package}'") do
26
+ unless_dry_run("remove package: '#{package}'") do
27
+ remove_package
28
+ end
28
29
  end
30
+ end
29
31
 
30
- remove_package
31
- @updated = true
32
+ # @return [Array<String>] the installed package versions
33
+ def installed_versions
34
+ fail NotImplementedError
32
35
  end
33
36
 
34
37
  private
@@ -60,6 +63,14 @@ module Wright
60
63
  !installed_versions.empty?
61
64
  end
62
65
  end
66
+
67
+ def install_package
68
+ fail NotImplementedError
69
+ end
70
+
71
+ def remove_package
72
+ fail NotImplementedError
73
+ end
63
74
  end
64
75
  end
65
76
  end
@@ -10,42 +10,36 @@ module Wright
10
10
  #
11
11
  # @return [void]
12
12
  def create
13
- if exist?
14
- symlink = symlink_to_s(@resource.name, @resource.to)
15
- Wright.log.debug "symlink already created: #{symlink}"
16
- return
17
- end
18
-
19
13
  fail Errno::EEXIST, link_name if regular_file?
20
- create_link
21
- @updated = true
14
+
15
+ symlink = symlink_to_s(@resource.name, @resource.to)
16
+ unless_uptodate(:create, "symlink already created: #{symlink}") do
17
+ create_link
18
+ end
22
19
  end
23
20
 
24
21
  # Removes the symlink.
25
22
  #
26
23
  # @return [void]
27
24
  def remove
28
- if ::File.exist?(link_name) && !::File.symlink?(link_name)
29
- fail "'#{link_name}' is not a symlink"
30
- end
25
+ fail "'#{link_name}' is not a symlink" if regular_file?
31
26
 
32
- if ::File.symlink?(link_name)
27
+ symlink = @resource.name
28
+ unless_uptodate(:remove, "symlink already removed: '#{symlink}'") do
33
29
  remove_symlink
34
- @updated = true
35
- else
36
- Wright.log.debug "symlink already removed: '#{@resource.name}'"
37
30
  end
38
31
  end
39
32
 
40
33
  private
41
34
 
42
- # Checks if the specified link exists.
43
- #
44
- # Returns true if the link exists and points to the specified
45
- # target and false otherwise.
46
- def exist?
47
- ::File.symlink?(link_name) &&
48
- ::File.readlink(link_name) == link_to
35
+ def uptodate?(action)
36
+ case action
37
+ when :create
38
+ ::File.symlink?(link_name) &&
39
+ ::File.readlink(link_name) == link_to
40
+ when :remove
41
+ !::File.symlink?(link_name)
42
+ end
49
43
  end
50
44
 
51
45
  def create_link
@@ -70,6 +64,7 @@ module Wright
70
64
  end
71
65
 
72
66
  def link_to
67
+ return nil if @resource.to.nil?
73
68
  Wright::Util::File.expand_tilde_path(@resource.to)
74
69
  end
75
70
 
@@ -0,0 +1,65 @@
1
+ require 'wright/provider'
2
+ require 'wright/provider/user'
3
+
4
+ module Wright
5
+ class Provider
6
+ class User
7
+ # Darwin DirectoryService user provider. Used as a provider for
8
+ # {Resource::User} on OS X systems.
9
+ class DarwinDirectoryService < User
10
+ private
11
+
12
+ def add_user
13
+ user = @resource.name
14
+ attributes = default_attributes.merge(resource_attributes)
15
+ attributes.each do |k, v|
16
+ args = dscl_args(:create, k, v)
17
+ exec_or_fail('dscl', args, "cannot create user '#{user}'")
18
+ end
19
+ end
20
+
21
+ def update_user
22
+ user = @resource.name
23
+ resource_attributes.each do |k, v|
24
+ args = dscl_args(:create, k, v)
25
+ exec_or_fail('dscl', args, "cannot create user '#{user}'")
26
+ end
27
+ end
28
+
29
+ def delete_user
30
+ user = @resource.name
31
+ exec_or_fail('dscl',
32
+ %W(. -delete /Users/#{user}),
33
+ "cannot remove user '#{user}'")
34
+ end
35
+
36
+ def dscl_args(cmd, key, value)
37
+ %W(. -#{cmd} /Users/#{@resource.name} #{key} #{value})
38
+ end
39
+
40
+ def default_attributes
41
+ uid_range = @resource.system ? 1...500 : 500...1000
42
+ {
43
+ 'UniqueID' => Wright::Util::User.next_free_uid(uid_range),
44
+ 'UserShell' => '/bin/bash',
45
+ 'RealName' => '',
46
+ 'NFSHomeDirectory' => "/Users/#{@resource.name}",
47
+ 'PrimaryGroupID' => Wright::Util::User.group_to_gid('staff'),
48
+ 'Password' => '*'
49
+ }
50
+ end
51
+
52
+ def resource_attributes
53
+ gid = Wright::Util::User.group_to_gid(@resource.primary_group)
54
+ {
55
+ 'UniqueID' => @resource.uid,
56
+ 'UserShell' => @resource.shell,
57
+ 'RealName' => @resource.full_name,
58
+ 'NFSHomeDirectory' => @resource.home,
59
+ 'PrimaryGroupID' => gid
60
+ }.reject { |_k, v| v.nil? }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,4 +1,3 @@
1
- require 'wright/dry_run'
2
1
  require 'wright/provider'
3
2
  require 'wright/provider/user'
4
3
 
@@ -12,16 +11,16 @@ module Wright
12
11
 
13
12
  def add_user
14
13
  user = @resource.name
15
- cmd = 'useradd'
16
- args = [*user_options, user]
17
- exec_or_fail(cmd, args, "cannot create user '#{user}'")
14
+ exec_or_fail('useradd',
15
+ [*user_options, user],
16
+ "cannot create user '#{user}'")
18
17
  end
19
18
 
20
19
  def update_user
21
20
  user = @resource.name
22
- cmd = 'usermod'
23
- args = [*user_options, user]
24
- exec_or_fail(cmd, args, "cannot create user '#{user}'")
21
+ exec_or_fail('usermod',
22
+ [*user_options, user],
23
+ "cannot create user '#{user}'")
25
24
  end
26
25
 
27
26
  def user_options