Working everything.
Dev

Dev commited on 2018-06-17 09:01:35
Showing 5 changed files, with 50 additions and 37 deletions.

... ...
@@ -10,17 +10,20 @@
10 10
     desired_state: installed
11 11
 
12 12
 - files:
13
-  - path: /tmp/hello_world.php
13
+  - path: /var/www/html/index.php
14 14
     owner: dev
15 15
     group: dev
16 16
     mode: '0664'
17 17
     local_file: /home/dev/src/rcm/resources/hello_world.php
18 18
     desired_state: present
19 19
 
20
+  - path: /var/www/html/index.html
21
+    desired_state: absent
22
+
20 23
 - services:
21 24
   - name: apache2
22 25
     dependencies:
23 26
     - packages:
24 27
       - name: libapache2-mod-php
25 28
     - files:
26
-      - path: /tmp/hello_world.php
29
+      - path: /var/www/html/index.php
... ...
@@ -19,10 +19,10 @@ module RCM
19 19
       @logger.debug("Setting owner as #{file.owner}:#{file.group} and mode as #{file.mode} on #{file.path}")
20 20
       # Will throw exception if something poopy happens
21 21
       ::FileUtils.chown(file.owner, file.group, file.path)
22
-      ::FileUtils.chmod(file.mode, file.path)
22
+      ::FileUtils.chmod(file.mode.to_i, file.path)
23 23
 
24 24
       file.changed = true
25
-      file
25
+      0
26 26
     end
27 27
 
28 28
     def copy(file)
... ...
@@ -30,10 +30,18 @@ module RCM
30 30
       @logger.debug("Ensuring #{dir} exsits.")
31 31
       ::FileUtils.mkdir_p(dir)
32 32
       @logger.debug("Copying #{file.src_path} to #{file.path}.")
33
-      ::FileUtils.copy(file.src_path, file.path, remove_destination: true)
34 33
 
34
+      begin
35
+        ::FileUtils.copy_entry(file.src_path, file.path, remove_destination:  true)
36
+      rescue
37
+        error_msg = "Could not copy #{file.src_path} to #{file.path}."
38
+        @logger.fatal(error_msg)
39
+        return 1
40
+      end
41
+
42
+      file.state = ::RCM::File::PRESENT
35 43
       file.changed = true
36
-      file
44
+      0
37 45
     end
38 46
 
39 47
     def remove(file)
... ...
@@ -41,8 +49,9 @@ module RCM
41 49
 
42 50
       @logger.debug("Removing #{file.path}.")
43 51
       ::FileUtils.rm(file.path)
52
+      file.state = ::RCM::File::ABSENT
44 53
       file.changed = true
45
-      file
54
+      0
46 55
     end
47 56
 
48 57
     def initialize(logger)
... ...
@@ -54,7 +63,7 @@ module RCM
54 63
       uids = get_id_to_name_mapping('/etc/passwd')
55 64
       gids = get_id_to_name_mapping('/etc/group')
56 65
       wanted_files.each do |path, p|
57
-        f = ::RCM::File.new('', '', '', '', '')
66
+        f = ::RCM::File.new(path, '', '', '', '', ::RCM::File::ABSENT)
58 67
         # Put in an empty object if file does not exist
59 68
         unless ::File.exist?(path)
60 69
           got[path] = f
... ...
@@ -66,6 +75,7 @@ module RCM
66 75
         f.owner = uids[f_stat.uid.to_s]
67 76
         f.group = gids[f_stat.gid.to_s]
68 77
         f.mode = f_stat.mode.to_s(8)[-4, 4]
78
+        f.state = ::RCM::File::PRESENT
69 79
         got[path] = f
70 80
       end
71 81
 
... ...
@@ -27,8 +27,11 @@ module RCM
27 27
     def restart(service)
28 28
       @logger.debug("Restarting #{service.name}")
29 29
       status = ::RCM.cmd("#{SYS_SERVICE_MGR} #{service.name} restart")
30
-      error_msg = "Failed to restart #{service.name}.\n\nstderr:\n#{status.error}\n\nstdout:\n#{status.output}"
30
+      unless status[:exit_code] == 0
31
+        error_msg = "Failed to restart #{service.name}.\n\nstderr:\n#{status[:error]}\n\nstdout:\n#{status[:output]}"
31 32
         @logger.fatal(error_msg)
32 33
       end
34
+
35
+    end
33 36
   end
34 37
 end
... ...
@@ -2,26 +2,32 @@ require 'fileutils'
2 2
 
3 3
 module RCM
4 4
   class File
5
-    attr_accessor :path, :owner, :group, :mode, :src_path, :changed
5
+    attr_accessor :path, :owner, :group, :mode, :state, :src_path, :changed
6
+
7
+    PRESENT = 'present'.freeze
8
+    ABSENT = 'absent'.freeze
6 9
 
7 10
     def ==(other)
8 11
       return false unless other.is_a?(RCM::File)
9 12
 
10
-      return false if @path.empty? || other.path.empty?
13
+      # Paths are same and status is absent for both
14
+      return true if @state == ABSENT && other.state == ABSENT && @path == other.path
11 15
 
12
-      ::FileUtils.compare_file(@path, other.path) &&
13 16
       @owner == other.owner &&
14 17
           @group == other.group &&
15
-          @mode == other.mode
18
+          @mode == other.mode &&
19
+          @state == other.state &&
20
+          ::FileUtils.compare_file(@path, other.path)
16 21
 
17 22
     end
18 23
 
19
-    def initialize(path, owner, group, mode, src_path)
24
+    def initialize(path, owner, group, mode, src_path, state)
20 25
       @path = path
21 26
       @owner = owner
22 27
       @group = group
23 28
       @mode = mode
24 29
       @src_path = src_path
30
+      @state = state
25 31
       @changed = false
26 32
     end
27 33
 
... ...
@@ -75,9 +75,11 @@ module RCM
75 75
   end
76 76
 
77 77
   def self.parse_files(markup)
78
+    valid_file_states = [::RCM::File::PRESENT, ::RCM::File::ABSENT]
78 79
     markup.each do |d|
79
-      raise "\n\n'#{d['local_file']}' is not readable.\n\n" unless ::File.readable?(d['local_file'])
80
-      f = RCM::File.new(d['path'], d['owner'], d['group'], d['mode'], d['local_file'])
80
+      raise "\n\nFile state can only be one of #{valid_file_states.join (', ')}" if (valid_file_states | [d['desired_state']]).empty?
81
+      raise "\n\n'#{d['local_file']}' is not readable.\n\n" if d['desired_state'] == ::RCM::File::PRESENT && !::File.readable?(d['local_file'])
82
+      f = RCM::File.new(d['path'], d['owner'], d['group'], d['mode'], d['local_file'], d['desired_state'])
81 83
       @@wanted[FILES][d['path']] = f
82 84
     end
83 85
   end
... ...
@@ -173,38 +175,27 @@ module RCM
173 175
     @@wanted[FILES].each do |path, file_obj|
174 176
       file_on_fs = @@got[FILES][path]
175 177
 
178
+      if file_on_fs.state == ::RCM::File::PRESENT && file_obj.state == ::RCM::File::ABSENT
179
+        @@logger.info("#{path} is present on disk when it should not be. Removing...")
180
+        @@file_mgr.remove(file_obj)
181
+        next
182
+      end
183
+
176 184
       if file_on_fs == file_obj
177
-        @@logger.info("#{path} is in expected state.")
185
+        @@logger.info("#{path} is in expected state (#{file_on_fs.state}).")
178 186
         next
179 187
       end
180 188
 
181
-      # try to do minimal changes by finding what is different
182
-      if file_on_fs.path.empty?
183
-        # for files, we're not doing explicit state maintenance like we are doing for packages
184
-        # If file is on disk, file obj will contain the path.
185 189
       @@logger.info("#{path} is not present on disk.")
186
-        @@file_mgr.copy(file_obj)
187
-        @@file_mgr.apply_attributes(file_obj)
188
-      elsif file_on_fs.mode != file_obj.mode ||
189
-          file_on_fs.owner != file_obj.owner ||
190
-          file_on_fs.group != file_obj.group
191
-        @@logger.debug("Attributes on #{path} are not in expected state.")
192
-        @@file_mgr.apply_attributes(file_obj)
193
-      elsif !::File.cmp(file_obj.src_path, path)
194
-        @@logger.debug("File contents don't match, even though #{path} is on disk.")
195
-        @@file_mgr.remove(file_obj)
196
-        @@file_mgr.copy(file_obj)
197
-        @@file_mgr.apply_attributes(file_obj)
198
-      end
190
+      status = @@file_mgr.copy(file_obj)
191
+      @@file_mgr.apply_attributes(file_obj) if status == 0
199 192
 
200
-      # Set the version correctly
201
-      @@crackalackin[FILES].push(file_obj)
202 193
     end
203 194
   end
204 195
 
205 196
   def self.restart_services_if_needed
206 197
     @@wanted[SERVICES].values.each do |svc_obj|
207
-      @@svc_manager.restart(svc_obj) if @@svc_mgr.dependencies_changed?(svc_obj)
198
+      @@svc_mgr.restart(svc_obj) if @@svc_mgr.dependencies_changed?(svc_obj)
208 199
     end
209 200
   end
210 201
 
211 202