wright 0.3.2 → 0.4.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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +7 -0
  3. data/README.md +60 -54
  4. data/lib/wright/cli.rb +44 -18
  5. data/lib/wright/dry_run.rb +7 -0
  6. data/lib/wright/provider/directory.rb +26 -30
  7. data/lib/wright/provider/file.rb +34 -34
  8. data/lib/wright/provider/group/darwin_directory_service.rb +8 -7
  9. data/lib/wright/provider/group/gnu_passwd.rb +5 -5
  10. data/lib/wright/provider/group.rb +53 -36
  11. data/lib/wright/provider/package/apt.rb +32 -8
  12. data/lib/wright/provider/package/homebrew.rb +6 -5
  13. data/lib/wright/provider/package/yum.rb +39 -0
  14. data/lib/wright/provider/package.rb +30 -16
  15. data/lib/wright/provider/symlink.rb +32 -33
  16. data/lib/wright/provider/user/darwin_directory_service.rb +14 -17
  17. data/lib/wright/provider/user/gnu_passwd.rb +20 -21
  18. data/lib/wright/provider/user.rb +58 -41
  19. data/lib/wright/resource/group.rb +1 -0
  20. data/lib/wright/resource/package.rb +16 -3
  21. data/lib/wright/resource/user.rb +1 -0
  22. data/lib/wright/resource.rb +4 -2
  23. data/lib/wright/util/user.rb +34 -2
  24. data/lib/wright/version.rb +1 -1
  25. data/man/wright.1 +15 -11
  26. data/spec/cli_spec.rb +18 -0
  27. data/spec/provider/group/darwin_directory_service_spec.rb +76 -220
  28. data/spec/provider/group/gnu_passwd_spec.rb +36 -189
  29. data/spec/provider/group_spec.rb +180 -27
  30. data/spec/provider/package/apt/apt-cache_policy_dmenu.return +1 -0
  31. data/spec/provider/package/apt/apt-cache_policy_dmenu.stderr +0 -0
  32. data/spec/provider/package/apt/apt-cache_policy_dmenu.stdout +4 -0
  33. data/spec/provider/package/apt/apt-cache_policy_htop.stdout +3 -3
  34. data/spec/provider/package/apt/apt-cache_policy_linux-image-3.2.0-4-amd64.return +1 -0
  35. data/spec/provider/package/apt/apt-cache_policy_linux-image-3.2.0-4-amd64.stderr +0 -0
  36. data/spec/provider/package/apt/apt-cache_policy_linux-image-3.2.0-4-amd64.stdout +6 -0
  37. data/spec/provider/package/apt/apt-cache_policy_linux-image.return +1 -0
  38. data/spec/provider/package/apt/apt-cache_policy_linux-image.stderr +0 -0
  39. data/spec/provider/package/apt/apt-cache_policy_linux-image.stdout +4 -0
  40. data/spec/provider/package/apt/apt-cache_policy_suckless-tools.return +1 -0
  41. data/spec/provider/package/apt/apt-cache_policy_suckless-tools.stderr +0 -0
  42. data/spec/provider/package/apt/apt-cache_policy_suckless-tools.stdout +6 -0
  43. data/spec/provider/package/apt/apt-cache_showpkg_dmenu.return +1 -0
  44. data/spec/provider/package/apt/apt-cache_showpkg_dmenu.stderr +0 -0
  45. data/spec/provider/package/apt/apt-cache_showpkg_dmenu.stdout +9 -0
  46. data/spec/provider/package/apt/apt-cache_showpkg_htop.return +1 -0
  47. data/spec/provider/package/apt/apt-cache_showpkg_htop.stderr +0 -0
  48. data/spec/provider/package/apt/apt-cache_showpkg_htop.stdout +20 -0
  49. data/spec/provider/package/apt/apt-cache_showpkg_linux-image.return +1 -0
  50. data/spec/provider/package/apt/apt-cache_showpkg_linux-image.stderr +0 -0
  51. data/spec/provider/package/apt/apt-cache_showpkg_linux-image.stdout +11 -0
  52. data/spec/provider/package/apt/apt-cache_showpkg_not-a-real-package.return +1 -0
  53. data/spec/provider/package/apt/apt-cache_showpkg_not-a-real-package.stderr +0 -0
  54. data/spec/provider/package/apt/apt-cache_showpkg_not-a-real-package.stdout +1 -0
  55. data/spec/provider/package/apt/apt-cache_showpkg_suckless-tools.return +1 -0
  56. data/spec/provider/package/apt/apt-cache_showpkg_suckless-tools.stderr +0 -0
  57. data/spec/provider/package/apt/apt-cache_showpkg_suckless-tools.stdout +26 -0
  58. data/spec/provider/package/apt/apt-get_--purge_remove_-qy_abcde.return +1 -0
  59. data/spec/provider/package/apt/apt-get_--purge_remove_-qy_abcde.stderr +0 -0
  60. data/spec/provider/package/apt/apt-get_--purge_remove_-qy_abcde.stdout +15 -0
  61. data/spec/provider/package/apt_spec.rb +82 -14
  62. data/spec/provider/package/homebrew/brew_install_--with-default-names_gnu-units.return +1 -0
  63. data/spec/provider/package/homebrew/brew_install_--with-default-names_gnu-units.stderr +0 -0
  64. data/spec/provider/package/homebrew/brew_install_--with-default-names_gnu-units.stdout +7 -0
  65. data/spec/provider/package/homebrew/brew_uninstall_--force_lame.return +1 -0
  66. data/spec/provider/package/homebrew/brew_uninstall_--force_lame.stderr +0 -0
  67. data/spec/provider/package/homebrew/brew_uninstall_--force_lame.stdout +1 -0
  68. data/spec/provider/package/homebrew_spec.rb +33 -6
  69. data/spec/provider/package/yum/rpm_-q_httpd.return +1 -0
  70. data/spec/provider/package/yum/rpm_-q_httpd.stderr +0 -0
  71. data/spec/provider/package/yum/rpm_-q_httpd.stdout +1 -0
  72. data/spec/provider/package/yum/rpm_-q_zsh.return +1 -0
  73. data/spec/provider/package/yum/rpm_-q_zsh.stderr +0 -0
  74. data/spec/provider/package/yum/rpm_-q_zsh.stdout +1 -0
  75. data/spec/provider/package/yum/yum_install_-y_mc-4.8.7-8.el7.return +1 -0
  76. data/spec/provider/package/yum/yum_install_-y_mc-4.8.7-8.el7.stderr +0 -0
  77. data/spec/provider/package/yum/yum_install_-y_mc-4.8.7-8.el7.stdout +37 -0
  78. data/spec/provider/package/yum/yum_install_-y_nano.return +1 -0
  79. data/spec/provider/package/yum/yum_install_-y_nano.stderr +0 -0
  80. data/spec/provider/package/yum/yum_install_-y_nano.stdout +36 -0
  81. data/spec/provider/package/yum/yum_install_-y_not-a-real-package.return +1 -0
  82. data/spec/provider/package/yum/yum_install_-y_not-a-real-package.stderr +1 -0
  83. data/spec/provider/package/yum/yum_install_-y_not-a-real-package.stdout +6 -0
  84. data/spec/provider/package/yum/yum_install_with_options.return +1 -0
  85. data/spec/provider/package/yum/yum_install_with_options.stderr +0 -0
  86. data/spec/provider/package/yum/yum_install_with_options.stdout +53 -0
  87. data/spec/provider/package/yum/yum_remove_-y_screen.return +1 -0
  88. data/spec/provider/package/yum/yum_remove_-y_screen.stderr +0 -0
  89. data/spec/provider/package/yum/yum_remove_-y_screen.stdout +31 -0
  90. data/spec/provider/package/yum/yum_remove_with_options.return +1 -0
  91. data/spec/provider/package/yum/yum_remove_with_options.stderr +0 -0
  92. data/spec/provider/package/yum/yum_remove_with_options.stdout +30 -0
  93. data/spec/provider/package/yum_spec.rb +130 -0
  94. data/spec/provider/user/darwin_directory_service_spec.rb +12 -10
  95. data/spec/provider/user/gnu_passwd_spec.rb +9 -9
  96. data/spec/provider/user_spec.rb +26 -18
  97. data/spec/resource/package_spec.rb +8 -0
  98. data/spec/resource_spec.rb +17 -9
  99. metadata +153 -16
@@ -7,13 +7,18 @@ module Wright
7
7
  # User provider. Used as a base class for {Resource::User}
8
8
  # providers.
9
9
  class User < Wright::Provider
10
- # Adds the user.
10
+ # Creates or updates the user.
11
11
  #
12
12
  # @return [void]
13
13
  def create
14
- user = @resource.name
15
- unless_uptodate(:create, "user already created: '#{user}'") do
16
- create_user
14
+ unless_uptodate(:create, "user already created: '#{user_name}'") do
15
+ unless_dry_run("create user: '#{user_name}'") do
16
+ if user_exists?
17
+ update_user
18
+ else
19
+ create_user
20
+ end
21
+ end
17
22
  end
18
23
  end
19
24
 
@@ -21,14 +26,47 @@ module Wright
21
26
  #
22
27
  # @return [void]
23
28
  def remove
24
- user = @resource.name
25
- unless_uptodate(:remove, "user already removed: '#{user}'") do
26
- remove_user
29
+ unless_uptodate(:remove, "user already removed: '#{user_name}'") do
30
+ unless_dry_run("remove user: '#{user_name}'") do
31
+ remove_user
32
+ end
27
33
  end
28
34
  end
29
35
 
30
36
  private
31
37
 
38
+ def user_name
39
+ @resource.name
40
+ end
41
+
42
+ def uid
43
+ @resource.uid
44
+ end
45
+
46
+ def primary_group
47
+ @resource.primary_group
48
+ end
49
+
50
+ def full_name
51
+ @resource.full_name
52
+ end
53
+
54
+ def groups
55
+ @resource.groups
56
+ end
57
+
58
+ def shell
59
+ @resource.shell
60
+ end
61
+
62
+ def home
63
+ @resource.home
64
+ end
65
+
66
+ def system_user?
67
+ @resource.system
68
+ end
69
+
32
70
  # @api public
33
71
  # Checks if the user is up-to-date for a given action.
34
72
  #
@@ -58,64 +96,43 @@ module Wright
58
96
  primary_group_uptodate?
59
97
  end
60
98
 
61
- def create_user
62
- unless_dry_run("create user: '#{@resource.name}'") do
63
- if user_exists?
64
- update_user
65
- else
66
- add_user
67
- end
68
- end
69
- end
70
-
71
- def remove_user
72
- unless_dry_run("remove user: '#{@resource.name}'") do
73
- delete_user
74
- end
75
- end
76
-
77
99
  def user_data
78
- Etc.getpwnam(@resource.name)
79
- rescue ArgumentError
80
- nil
100
+ Wright::Util::User.safe_getpwnam(user_name)
81
101
  end
82
102
 
83
103
  def uid_uptodate?
84
- @resource.uid.nil? || user_data.uid == @resource.uid
104
+ uid.nil? || user_data.uid == uid
85
105
  end
86
106
 
87
107
  def full_name_uptodate?
88
- @resource.full_name.nil? ||
89
- user_data.gecos.split(',').first == @resource.full_name
108
+ full_name.nil? || user_data.gecos.split(',').first == full_name
90
109
  end
91
110
 
92
111
  def groups_uptodate?
93
- return true if @resource.groups.nil?
94
- groups = []
95
- Etc.group { |g| groups << g.name if g.mem.include?(@resource.name) }
96
- groups.uniq.sort == @resource.groups.uniq.sort
112
+ return true if groups.nil?
113
+ target_groups = []
114
+ Etc.group { |g| target_groups << g.name if g.mem.include?(user_name) }
115
+ target_groups.sort.uniq == groups.sort.uniq
97
116
  end
98
117
 
99
118
  def shell_uptodate?
100
- @resource.shell.nil? || user_data.shell == @resource.shell
119
+ shell.nil? || user_data.shell == shell
101
120
  end
102
121
 
103
122
  def home_uptodate?
104
- @resource.home.nil? || user_data.dir == @resource.home
123
+ home.nil? || user_data.dir == home
105
124
  end
106
125
 
107
126
  def primary_group_uptodate?
108
- return true if @resource.primary_group.nil?
109
-
110
- gid = Wright::Util::User.group_to_gid(@resource.primary_group)
111
- user_data.gid == gid
127
+ return true if primary_group.nil?
128
+ user_data.gid == Wright::Util::User.group_to_gid(primary_group)
112
129
  end
113
130
 
114
131
  def user_exists?
115
132
  !user_data.nil?
116
133
  end
117
134
 
118
- def add_user
135
+ def create_user
119
136
  fail NotImplementedError
120
137
  end
121
138
 
@@ -123,7 +140,7 @@ module Wright
123
140
  fail NotImplementedError
124
141
  end
125
142
 
126
- def delete_user
143
+ def remove_user
127
144
  fail NotImplementedError
128
145
  end
129
146
  end
@@ -57,6 +57,7 @@ Wright::DSL.register_resource(Wright::Resource::Group)
57
57
 
58
58
  group_providers = {
59
59
  'debian' => 'Wright::Provider::Group::GnuPasswd',
60
+ 'rhel' => 'Wright::Provider::Group::GnuPasswd',
60
61
  'macosx' => 'Wright::Provider::Group::DarwinDirectoryService'
61
62
  }
62
63
  Wright::Config[:resources][:group] ||= {}
@@ -1,3 +1,5 @@
1
+ require 'forwardable'
2
+
1
3
  require 'wright/resource'
2
4
  require 'wright/dsl'
3
5
 
@@ -20,22 +22,32 @@ module Wright
20
22
  # htop.installed_versions
21
23
  # # => []
22
24
  class Package < Wright::Resource
25
+ extend Forwardable
26
+
23
27
  # @return [String] the package version to install or remove
24
28
  attr_accessor :version
25
29
 
30
+ # @return [String, Array<String>] the options passed to the
31
+ # package manager
32
+ attr_accessor :options
33
+
26
34
  # Initializes a Package.
27
35
  #
28
36
  # @param name [String] the package's name
29
37
  def initialize(name)
30
38
  super
31
39
  @version = nil
40
+ @options = nil
32
41
  @action = :install
33
42
  end
34
43
 
44
+ # @!method installed_versions
35
45
  # @return [Array<String>] the installed package versions
36
- def installed_versions
37
- @provider.installed_versions
38
- end
46
+ def_delegator :@provider, :installed_versions
47
+
48
+ # @!method installed?
49
+ # @return [Bool] +true+ if the package is installed
50
+ def_delegator :@provider, :installed?
39
51
 
40
52
  # Installs the Package.
41
53
  #
@@ -66,6 +78,7 @@ Wright::DSL.register_resource(Wright::Resource::Package)
66
78
 
67
79
  package_providers = {
68
80
  'debian' => 'Wright::Provider::Package::Apt',
81
+ 'rhel' => 'Wright::Provider::Package::Yum',
69
82
  'macosx' => 'Wright::Provider::Package::Homebrew'
70
83
  }
71
84
  Wright::Config[:resources][:package] ||= {}
@@ -70,6 +70,7 @@ Wright::DSL.register_resource(Wright::Resource::User)
70
70
 
71
71
  user_providers = {
72
72
  'debian' => 'Wright::Provider::User::GnuPasswd',
73
+ 'rhel' => 'Wright::Provider::User::GnuPasswd',
73
74
  'macosx' => 'Wright::Provider::User::DarwinDirectoryService'
74
75
  }
75
76
  Wright::Config[:resources][:user] ||= {}
@@ -123,10 +123,12 @@ module Wright
123
123
  def run_update_action
124
124
  return if @on_update.nil?
125
125
 
126
+ resource = "#{@resource_name} '#{@name}'"
127
+ notification = "run update action for #{resource}"
126
128
  if Wright.dry_run?
127
- resource = "#{@resource_name} '#{@name}'"
128
- Wright.log.info "(would) run update action for #{resource}"
129
+ Wright.log.info "(would) #{notification}"
129
130
  else
131
+ Wright.log.info notification
130
132
  @on_update.call
131
133
  end
132
134
  end
@@ -46,7 +46,7 @@ module Wright
46
46
  end
47
47
  private_class_method :to_id
48
48
 
49
- # Returns the the next free uid in a range.
49
+ # Returns the next free uid in a range.
50
50
  #
51
51
  # @param uid_range [Range] the uid range
52
52
  #
@@ -60,7 +60,7 @@ module Wright
60
60
  next_free_id(uid_range, :uid)
61
61
  end
62
62
 
63
- # Returns the the next free gid in a range.
63
+ # Returns the next free gid in a range.
64
64
  #
65
65
  # @param gid_range [Range] the gid range
66
66
  #
@@ -92,6 +92,38 @@ module Wright
92
92
  id_type == :uid ? Etc.method(:passwd) : Etc.method(:group)
93
93
  end
94
94
  private_class_method :id_iterator
95
+
96
+ # Returns a user entry.
97
+ #
98
+ # @param username [String] the name of the user
99
+ #
100
+ # @example
101
+ # Wright::Util::User.safe_getpwnam('this_user_does_not_exist')
102
+ # # => nil
103
+ #
104
+ # @return [Struct::Passwd, nil] the user entry or nil if the
105
+ # user does not exist
106
+ def self.safe_getpwnam(username)
107
+ Etc.getpwnam(username)
108
+ rescue ArgumentError
109
+ nil
110
+ end
111
+
112
+ # Returns a group entry.
113
+ #
114
+ # @param groupname [String] the name of the group
115
+ #
116
+ # @example
117
+ # Wright::Util::User.safe_getgrnam('this_group_does_not_exist')
118
+ # # => nil
119
+ #
120
+ # @return [Struct::Group, nil] the group entry or nil if the
121
+ # group does not exist
122
+ def self.safe_getgrnam(groupname)
123
+ Etc.getgrnam(groupname)
124
+ rescue ArgumentError
125
+ nil
126
+ end
95
127
  end
96
128
  end
97
129
  end
@@ -1,4 +1,4 @@
1
1
  module Wright # rubocop:disable Documentation
2
2
  # Current wright version
3
- VERSION = '0.3.2'
3
+ VERSION = '0.4.0'
4
4
  end
data/man/wright.1 CHANGED
@@ -2,12 +2,12 @@
2
2
  .\" Title: wright
3
3
  .\" Author: [see the "AUTHOR" section]
4
4
  .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
5
- .\" Date: 04/22/2015
5
+ .\" Date: 06/03/2015
6
6
  .\" Manual: \ \&
7
7
  .\" Source: \ \&
8
8
  .\" Language: English
9
9
  .\"
10
- .TH "WRIGHT" "1" "04/22/2015" "\ \&" "\ \&"
10
+ .TH "WRIGHT" "1" "06/03/2015" "\ \&" "\ \&"
11
11
  .\" -----------------------------------------------------------------
12
12
  .\" * Define some portability stuff
13
13
  .\" -----------------------------------------------------------------
@@ -48,6 +48,18 @@ Run
48
48
  as a wright script\&. When multiple commands are passed, they are joined and run in sequence\&.
49
49
  .RE
50
50
  .PP
51
+ \fB\-r\fR \fILIBRARY\fR
52
+ .RS 4
53
+ Require
54
+ \fILIBRARY\fR
55
+ before running the wright script\&. When multiple libraries are passed, they are loaded in sequence\&.
56
+ .RE
57
+ .PP
58
+ \fB\-n, \-\-dry\-run\fR
59
+ .RS 4
60
+ Enable dry\-run mode\&. In dry\-run mode, wright resources do not modify the system, but you still have to make sure your own code does not cause any unwanted changes\&.
61
+ .RE
62
+ .PP
51
63
  \fB\-v, \-\-verbose\fR
52
64
  .RS 4
53
65
  Print debugging information\&.
@@ -143,15 +155,7 @@ To install tmux and update its config file from a wright script, create the foll
143
155
  .\}
144
156
  .nf
145
157
  package \*(Aqtmux\*(Aq
146
- .fi
147
- .if n \{\
148
- .RE
149
- .\}
150
- .sp
151
- .if n \{\
152
- .RS 4
153
- .\}
154
- .nf
158
+
155
159
  file \*(Aq/etc/tmux\&.conf\*(Aq do |f|
156
160
  f\&.content = <<EOF
157
161
  unbind C\-b
data/spec/cli_spec.rb CHANGED
@@ -21,6 +21,18 @@ describe Wright::CLI do
21
21
  @cli.send(:commands).must_equal %w(foo bar)
22
22
  end
23
23
 
24
+ it 'parses -r LIBRARY' do
25
+ argv = %w(-r library1 -r library2 -rlibrary3 file.rb)
26
+ @cli.parse(argv).must_equal %w(file.rb)
27
+ @cli.send(:requires).must_equal %w(library1 library2 library3)
28
+ end
29
+
30
+ it 'parses --dry-run' do
31
+ argv = %w(--dry-run file.rb)
32
+ @cli.parse(argv).must_equal %w(file.rb)
33
+ @cli.send(:dry_run).must_equal true
34
+ end
35
+
24
36
  it 'parses --verbose' do
25
37
  argv = ['--verbose']
26
38
  @cli.parse(argv)
@@ -38,8 +50,14 @@ describe Wright::CLI do
38
50
  it 'parses --version' do
39
51
  argv = ['--version']
40
52
  expected = "wright version #{Wright::VERSION}\n"
53
+ -> { @cli.run(argv) }.must_output expected
54
+ end
41
55
 
56
+ it 'enables dry-run mode when requested to do so' do
57
+ argv = ['--dry-run', '-e', 'print Wright.dry_run?']
58
+ expected = 'true'
42
59
  -> { @cli.run(argv) }.must_output expected
60
+ Wright.instance_variable_set(:@dry_run, false)
43
61
  end
44
62
 
45
63
  it 'loads files' do