aethernal-agent 0.1.10

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 (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.gitlab-ci.yml +23 -0
  4. data/.rspec +2 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +107 -0
  9. data/README.md +35 -0
  10. data/Rakefile +31 -0
  11. data/Vagrantfile +32 -0
  12. data/aethernal-agent.gemspec +45 -0
  13. data/bin/console +14 -0
  14. data/bin/run-aa-for-test +35 -0
  15. data/bin/setup +8 -0
  16. data/exe/aa-web +7 -0
  17. data/lib/aethernal_agent.rb +34 -0
  18. data/lib/aethernal_agent/apache/apache.rb +70 -0
  19. data/lib/aethernal_agent/apache/templates/aa-user.conf.erb +21 -0
  20. data/lib/aethernal_agent/app.rb +317 -0
  21. data/lib/aethernal_agent/apt.rb +30 -0
  22. data/lib/aethernal_agent/errors.rb +17 -0
  23. data/lib/aethernal_agent/filesystem.rb +178 -0
  24. data/lib/aethernal_agent/loader.rb +56 -0
  25. data/lib/aethernal_agent/manifest.rb +6 -0
  26. data/lib/aethernal_agent/operation.rb +51 -0
  27. data/lib/aethernal_agent/operation_pool.rb +46 -0
  28. data/lib/aethernal_agent/plugins/deluge/deluge.rb +65 -0
  29. data/lib/aethernal_agent/plugins/deluge/manifest.yml +51 -0
  30. data/lib/aethernal_agent/plugins/deluge/meta/deluge.png +0 -0
  31. data/lib/aethernal_agent/plugins/deluge/templates/auth.erb +2 -0
  32. data/lib/aethernal_agent/plugins/deluge/templates/core.conf.erb +95 -0
  33. data/lib/aethernal_agent/plugins/deluge/templates/deluge-web.service.erb +12 -0
  34. data/lib/aethernal_agent/plugins/deluge/templates/deluge.apache.conf.erb +9 -0
  35. data/lib/aethernal_agent/plugins/deluge/templates/deluged.service.erb +12 -0
  36. data/lib/aethernal_agent/plugins/deluge/templates/hostlist.conf.erb +14 -0
  37. data/lib/aethernal_agent/plugins/deluge/templates/web.conf.erb +24 -0
  38. data/lib/aethernal_agent/plugins/filebrowser/filebrowser.rb +45 -0
  39. data/lib/aethernal_agent/plugins/filebrowser/files/filebrowser.service +12 -0
  40. data/lib/aethernal_agent/plugins/filebrowser/manifest.yml +51 -0
  41. data/lib/aethernal_agent/plugins/filebrowser/meta/filebrowser.png +0 -0
  42. data/lib/aethernal_agent/plugins/filebrowser/templates/filebrowser.apache.conf.erb +6 -0
  43. data/lib/aethernal_agent/plugins/gitea/files/gitea.service +12 -0
  44. data/lib/aethernal_agent/plugins/gitea/gitea.rb +64 -0
  45. data/lib/aethernal_agent/plugins/gitea/manifest.yml +53 -0
  46. data/lib/aethernal_agent/plugins/gitea/meta/gitea.png +0 -0
  47. data/lib/aethernal_agent/plugins/gitea/templates/app.ini.erb +68 -0
  48. data/lib/aethernal_agent/plugins/gitea/templates/gitea.apache.conf.erb +6 -0
  49. data/lib/aethernal_agent/plugins/olaris/manifest.yml +52 -0
  50. data/lib/aethernal_agent/plugins/olaris/meta/olaris.png +0 -0
  51. data/lib/aethernal_agent/plugins/olaris/olaris.rb +35 -0
  52. data/lib/aethernal_agent/plugins/olaris/templates/olaris.apache.conf.erb +6 -0
  53. data/lib/aethernal_agent/plugins/olaris/templates/olaris.service.erb +12 -0
  54. data/lib/aethernal_agent/plugins/ombi/manifest.yml +57 -0
  55. data/lib/aethernal_agent/plugins/ombi/meta/ombi.jpeg +0 -0
  56. data/lib/aethernal_agent/plugins/ombi/ombi.rb +81 -0
  57. data/lib/aethernal_agent/plugins/ombi/templates/ombi.apache.conf.erb +6 -0
  58. data/lib/aethernal_agent/plugins/ombi/templates/ombi.service.erb +14 -0
  59. data/lib/aethernal_agent/plugins/plex/files/plex.service +26 -0
  60. data/lib/aethernal_agent/plugins/plex/manifest.yml +49 -0
  61. data/lib/aethernal_agent/plugins/plex/meta/plex.png +0 -0
  62. data/lib/aethernal_agent/plugins/plex/plex.rb +65 -0
  63. data/lib/aethernal_agent/plugins/plex/templates/Preferences.xml.erb +2 -0
  64. data/lib/aethernal_agent/plugins/radarr/files/radarr.service +13 -0
  65. data/lib/aethernal_agent/plugins/radarr/manifest.yml +68 -0
  66. data/lib/aethernal_agent/plugins/radarr/meta/radarr.png +0 -0
  67. data/lib/aethernal_agent/plugins/radarr/radarr.rb +72 -0
  68. data/lib/aethernal_agent/plugins/radarr/templates/config.xml.erb +16 -0
  69. data/lib/aethernal_agent/plugins/radarr/templates/radarr.apache.conf.erb +6 -0
  70. data/lib/aethernal_agent/plugins/sonarr/files/sonarr.service +13 -0
  71. data/lib/aethernal_agent/plugins/sonarr/manifest.yml +66 -0
  72. data/lib/aethernal_agent/plugins/sonarr/meta/sonarr.jpeg +0 -0
  73. data/lib/aethernal_agent/plugins/sonarr/sonarr.rb +70 -0
  74. data/lib/aethernal_agent/plugins/sonarr/templates/config.xml.erb +16 -0
  75. data/lib/aethernal_agent/plugins/sonarr/templates/sonarr.apache.conf.erb +6 -0
  76. data/lib/aethernal_agent/plugins/vnc/files/xstartup +9 -0
  77. data/lib/aethernal_agent/plugins/vnc/manifest.yml +41 -0
  78. data/lib/aethernal_agent/plugins/vnc/meta/vnc.png +0 -0
  79. data/lib/aethernal_agent/plugins/vnc/templates/vnc.service.erb +14 -0
  80. data/lib/aethernal_agent/plugins/vnc/vnc.rb +41 -0
  81. data/lib/aethernal_agent/systemd.rb +123 -0
  82. data/lib/aethernal_agent/template.rb +57 -0
  83. data/lib/aethernal_agent/utils.rb +107 -0
  84. data/lib/aethernal_agent/version.rb +3 -0
  85. data/lib/aethernal_agent/webserver/api.rb +77 -0
  86. data/lib/aethernal_agent/webserver/core.rb +32 -0
  87. metadata +257 -0
@@ -0,0 +1,21 @@
1
+ # AUTOMATICALLY GENERATED DON'T EDIT THIS FILE UNLESS YOU WANT TO SEE YOUR CHANGES DO _POOF_
2
+ # <%=DateTime.now %>
3
+ <VirtualHost *:80>
4
+ ServerName <%= @user %>.<%= @container_name %>.<%= @host_name %>
5
+ <% if @custom_domains.present? %>
6
+ <% @custom_domains.each do |domain| %>
7
+ ServerAlias <%= @user %>.<%= domain %>
8
+ <% end %>
9
+ <% end %>
10
+
11
+ DocumentRoot <%= @home_folder %>/www
12
+ CustomLog /var/log/apache2/<%= @user %>.base-access.log combined
13
+ ErrorLog /var/log/apache2/<%= @user %>.base-error.log
14
+ IncludeOptional users/<%= @user %>/*.conf
15
+
16
+ <Directory <%= @home_folder %>/www>
17
+ AllowOverride all
18
+ Require all granted
19
+ </Directory>
20
+
21
+ </VirtualHost>
@@ -0,0 +1,317 @@
1
+ require 'open-uri'
2
+ require 'aethernal_agent/apt'
3
+ require 'digest/sha1'
4
+ require 'aethernal_agent/filesystem'
5
+ require 'aethernal_agent/systemd'
6
+ require 'aethernal_agent/utils'
7
+ require 'aethernal_agent/errors'
8
+ require 'aethernal_agent/apache/apache'
9
+ require 'active_support'
10
+ require 'active_support/core_ext'
11
+
12
+ module AethernalAgent
13
+ class App
14
+ include AethernalAgent::Apt
15
+ include AethernalAgent::Filesystem
16
+ include AethernalAgent::Systemd
17
+ include AethernalAgent::Utils
18
+ include AethernalAgent::Errors
19
+
20
+ attr_accessor :manifest, :user, :plugin_path, :global_options
21
+
22
+ def initialize(options = {})
23
+ options = HashWithIndifferentAccess.new(options)
24
+ self.global_options = options
25
+ self.plugin_path = options[:file_path] || caller_locations(0)[1].path
26
+ self.user = options[:user]
27
+
28
+ AethernalAgent.logger.debug("initializing plugin from #{plugin_path}")
29
+ self.manifest = OpenStruct.new(YAML.load_file(File.join(File.dirname(self.plugin_path), "manifest.yml")))
30
+ end
31
+
32
+ #FIXME: Add error tracking
33
+ def install_packages(options = {})
34
+ directory(home_folder_path("/.config"), owner: self.user)
35
+ AethernalAgent.logger.info("Installing packages for #{self.manifest.name} - v#{self.manifest.version}")
36
+
37
+ if self.manifest.package.has_key?('ppa')
38
+ self.manifest.package['ppa'].each do |ppa|
39
+ AethernalAgent.logger.debug("Setting up PPA: #{ppa}")
40
+ run_command("add-apt-repository ppa:#{ppa} -y")
41
+ end
42
+ end
43
+
44
+ self.manifest.package.each_key do |package_type|
45
+ case package_type
46
+ when 'apt'
47
+ options = self.manifest.package['apt'][ubuntu_release]
48
+ AethernalAgent.logger.debug("Using apt for ubuntu #{ubuntu_release} - #{options}")
49
+ packages = options['packages']
50
+
51
+ if options.has_key?('add_sources')
52
+ AethernalAgent.logger.debug("Adding custom sources")
53
+ options['add_sources'].each do |name, source|
54
+ AethernalAgent.logger.debug("Setting up custom apt source '#{name}'")
55
+ file_path = "/etc/apt/sources.list.d/#{name}.list"
56
+
57
+ unless File.exist?(file_path)
58
+ run_command("echo '#{source['source_url']}' > #{file_path}")
59
+ else
60
+ AethernalAgent.logger.debug("Custom apt source '#{name}' already present, not rewriting.")
61
+ end
62
+ run_command("curl #{source['key_url']} | sudo apt-key add -") if source['key_url'].present?
63
+ run_command("sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys #{source['key_id']}") if source['key_id'].present?
64
+ end
65
+ apt_update
66
+ end
67
+
68
+ if packages
69
+ AethernalAgent.logger.debug("Installing packages #{packages}")
70
+ apt_package(packages: packages)
71
+ end
72
+ when 'direct_download'
73
+ opts = self.manifest.package[package_type]
74
+ target_file = File.join(app_path, opts["target_name"])
75
+ directory(app_path, owner: self.user)
76
+ AethernalAgent.logger.debug("Downloading file from '#{opts["url"]}' to '#{target_file}'")
77
+ File.open(target_file, "wb") do |saved_file|
78
+ open(opts["url"], "rb") do |read_file|
79
+ saved_file.write(read_file.read)
80
+ end
81
+ end
82
+
83
+ if opts["auto_unzip"]
84
+ unzip(opts["target_name"], delete_after: true)
85
+ elsif opts["auto_extract"]
86
+ extract(opts["target_name"], delete_after: true)
87
+ end
88
+ end
89
+ end
90
+ AethernalAgent.logger.info("Done Installing packages for #{self.manifest.name} - v#{self.manifest.version}")
91
+ return create_return_args(options)
92
+ end
93
+
94
+ def uninstall_packages(options = {})
95
+ AethernalAgent.logger.info("Uninstalling packages for #{self.manifest.name} - v#{self.manifest.version}")
96
+
97
+ self.stop
98
+ self.disable
99
+
100
+ self.manifest.package.each_key do |package_type|
101
+ case package_type
102
+ when "apt"
103
+ AethernalAgent.logger.debug("Using apt for ubuntu #{ubuntu_release}")
104
+ packages = self.manifest.package[package_type][ubuntu_release]
105
+ AethernalAgent.logger.debug("Removing packages #{packages}")
106
+ apt_package(packages: packages, action: :remove) if packages
107
+ when "direct_download"
108
+ directory(app_path, action: :delete)
109
+ end
110
+ end
111
+
112
+ return create_return_args(options)
113
+ end
114
+
115
+ def configure_app_user(options={})
116
+ errors = {}
117
+ opts, errors = ensure_action_options(__method__,options)
118
+ return {errors: errors} unless errors.empty?
119
+
120
+ if self.manifest.apache_configuration
121
+ apache = AethernalAgent::Apache.new(opts)
122
+ errors = apache.ensure_base_config(opts)
123
+ apache.write_app_config(template_path(self.manifest.apache_configuration), self.manifest.plain_name, opts[:port])
124
+ end
125
+
126
+ AethernalAgent.logger.debug("Running custom plugin code.")
127
+ yield opts if block_given?
128
+ AethernalAgent.logger.debug("Done running custom plugin code.")
129
+
130
+ AethernalAgent.logger.debug("Starting service generation.")
131
+ self.manifest.services.each do |s|
132
+ options = {service_name: "#{s}.service", user: self.user, vars: opts}
133
+ service_template = template_path("#{s}.service.erb")
134
+ if File.exists?(service_template)
135
+ AethernalAgent.logger.debug("Found service template")
136
+ options[:template] = "#{s}.service.erb"
137
+ elsif File.exists?(files_path("#{s}.service"))
138
+ AethernalAgent.logger.debug("Found service file")
139
+ options[:file] = "#{s}.service"
140
+ end
141
+
142
+ create_service_file(options)
143
+ end
144
+ AethernalAgent.logger.debug("Done with service generation.")
145
+
146
+ directory(home_folder_path("apps"), owner: self.user)
147
+
148
+ AethernalAgent.logger.debug("Done running configure_app_user")
149
+ return create_return_args(opts)
150
+ end
151
+
152
+ def remove_app_user(options={})
153
+ opts, errors = ensure_action_options(__method__,options)
154
+ return {errors: errors} unless errors.empty?
155
+
156
+ run_user_systemctl(:stop)
157
+
158
+ self.manifest.services.each do |service|
159
+ file(service_file_path("#{service}.service"), action: :delete)
160
+ end
161
+
162
+ if self.manifest.apache_configuration
163
+ apache = AethernalAgent::Apache.new(opts)
164
+ apache.remove_app_config(self.manifest.plain_name)
165
+ end
166
+
167
+ if self.is_local_install?
168
+ self.uninstall_packages(opts)
169
+ end
170
+
171
+ yield opts if block_given?
172
+
173
+ return create_return_args(opts)
174
+ end
175
+
176
+ def create_return_args(options)
177
+ res = {options: options, errors: get_errors}
178
+
179
+ if options[:errors].present?
180
+ res[:errors] << options.slice(:errors)
181
+ end
182
+
183
+ return res
184
+ end
185
+
186
+ def status(options = {})
187
+ if options[:service_name]
188
+ status = get_systemd_status(options[:service_name])
189
+ return status.to_h if status
190
+ else
191
+ stati = self.manifest.services.collect do |service|
192
+ status = get_systemd_status(service)
193
+ status.to_h if status
194
+ end
195
+
196
+ return stati
197
+ end
198
+ end
199
+
200
+ def ensure_action_options(method_name, options={})
201
+ options = HashWithIndifferentAccess.new(options.reverse_merge(global_options))
202
+
203
+ errors = {}
204
+ AethernalAgent.logger.debug "Running '#{method_name}' with options '#{options}'"
205
+ if self.manifest.actions.keys.include?(method_name.to_s)
206
+ opts = self.manifest.actions[method_name.to_s]
207
+ opts.each do |opt, reqs|
208
+ AethernalAgent.logger.debug "Checking option #{opt} - requirements: #{reqs}"
209
+
210
+ next if reqs.blank?
211
+
212
+ # The option is required but has not been supplied
213
+ if reqs.include?("required") && reqs["required"] == true
214
+ AethernalAgent.logger.debug("#{opt} is required")
215
+ if options.has_key?(opt) && !options[opt].blank?
216
+ AethernalAgent.logger.debug("required option is supplied")
217
+ else
218
+ AethernalAgent.logger.debug("required option is not supplied")
219
+ errors[opt] ||= []
220
+ errors[opt] << "is required but has not been supplied"
221
+ next
222
+ end
223
+ end
224
+
225
+ # This option should be an autogenerated string (passwords)
226
+ if reqs.include?("auto_generate") && reqs["auto_generate"] == true && (!options.has_key?(opt) || options[opt].empty?)
227
+ options[opt] = self.random_string
228
+ end
229
+
230
+ # This option should be an autogenerated port
231
+ if reqs.include?("auto_generate_port") && reqs["auto_generate_port"] == true && (!options.has_key?(opt) || options[opt].blank?)
232
+ min = reqs["min"] || 2000
233
+ max = reqs["max"] || 8000
234
+ options[opt] = random_port(min..max)
235
+ end
236
+
237
+ # The option should be a linux_user
238
+ if reqs.include?("linux_user") && reqs["linux_user"] == true
239
+ AethernalAgent.logger.debug "Checking to see if '#{options[:user]}' is a local linux user."
240
+ begin
241
+ Etc.getpwnam(options[:user])
242
+ rescue ArgumentError => e
243
+ errors[opt] ||= []
244
+ errors[opt] << e.to_s
245
+ end
246
+ end
247
+ end
248
+ else
249
+ puts "Method '#{method_name}' not defined in manifest."
250
+ end
251
+
252
+ return options, errors
253
+ end
254
+
255
+ def app_path(path=nil)
256
+ full_path = home_folder_path(File.join("apps", self.manifest.package['folder_name']))
257
+ if path
258
+ return File.join(full_path, path)
259
+ else
260
+ return full_path
261
+ end
262
+ end
263
+
264
+ def icon_sha
265
+ if self.manifest.icon.present?
266
+ return self.manifest.icon["sha256sum"]
267
+ else
268
+ return ""
269
+ end
270
+ end
271
+
272
+ def icon_file(path=nil)
273
+ if self.manifest.icon.present?
274
+ icon_path = meta_path(self.manifest.icon['name'])
275
+ if File.exist?(icon_path)
276
+ return Base64.encode64(File.read(icon_path))
277
+ end
278
+ end
279
+
280
+ return nil
281
+ end
282
+
283
+ def extract(source_file, options = {})
284
+ options.reverse_merge!(extract_to_path: self.app_path, source_folder: self.app_path, auto_detect: true, extract_as: File.extname(source_file))
285
+
286
+ extract_from = File.join(options[:source_folder], source_file)
287
+ extract_to = options[:extract_to_path]
288
+
289
+ case options[:extract_as].gsub('.', '')
290
+ when "gz", "tar"
291
+ run_command("tar -C #{extract_to} -xvf #{extract_from}")
292
+ when "zip"
293
+ run_command("unzip -od #{extract_to} #{extract_from}")
294
+ else
295
+ raise "#{options[:extract_as]} not implemented yet"
296
+ end
297
+
298
+ file(extract_from, action: :delete) if options[:delete_after]
299
+ end
300
+
301
+ def unzip(source_file)
302
+ extract(source_file, extract_as: "zip")
303
+ end
304
+
305
+ def is_local_install?
306
+ self.manifest.installation_type == 'local_install'
307
+ end
308
+
309
+ def sha_1_hash(password, salt)
310
+ sha = Digest::SHA1.new
311
+ sha.update(salt)
312
+ sha.update(password)
313
+
314
+ return sha.hexdigest
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,30 @@
1
+ module AethernalAgent
2
+ module Apt
3
+ def apt_update
4
+ system("apt update")
5
+ end
6
+
7
+ def add_apt_ppa(name)
8
+ system("add-apt-repository #{name} -y")
9
+ end
10
+
11
+ def apt_package(options = {})
12
+ action = options[:action]
13
+ action = :install if action.nil?
14
+
15
+ packages = options[:packages]
16
+ packages = packages.join(" ") if packages.is_a?(Array)
17
+
18
+ case action
19
+ when :install
20
+ # Do this with popen so we can catch error output as well as normal output for add_errors
21
+ system("DEBIAN_FRONTEND=noninteractive apt -o DPkg::Options::=--force-confdef install -qy #{packages}")
22
+ when :remove
23
+ system("DEBIAN_FRONTEND=noninteractive apt remove -qy #{packages}")
24
+ system("DEBIAN_FRONTEND=noninteractive apt autoremove -qy")
25
+ when :autoremove
26
+ system("DEBIAN_FRONTEND=noninteractive apt autoremove -qy")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ module AethernalAgent
2
+ module Errors
3
+ attr_accessor :global_errors
4
+
5
+ def add_errors(error, vars = {})
6
+ AethernalAgent.logger.debug("Adding errors: '#{error}'")
7
+ self.global_errors ||=[]
8
+ self.global_errors << {method: caller_locations(2,1)[0].label, error: error, args: vars}
9
+ end
10
+
11
+ def get_errors
12
+ errors = self.global_errors
13
+ self.global_errors = []
14
+ return errors
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,178 @@
1
+ module AethernalAgent
2
+ module Filesystem
3
+ def files_folder
4
+ File.join(File.expand_path(File.dirname(plugin_path)), "files/")
5
+ end
6
+
7
+ def files_path(file)
8
+ File.join(files_folder, file)
9
+ end
10
+
11
+ def meta_folder
12
+ File.join(File.expand_path(File.dirname(plugin_path)), "meta/")
13
+ end
14
+
15
+ def meta_path(file)
16
+ File.join(meta_folder, file)
17
+ end
18
+
19
+ def templates_folder
20
+ File.join(File.expand_path(File.dirname(plugin_path)), "templates/")
21
+ end
22
+
23
+ def template_path(file)
24
+ File.join(templates_folder, file)
25
+ end
26
+
27
+ def home_folder_path(path = nil)
28
+ if !path.nil?
29
+ File.join(Dir.home(self.user), path)
30
+ else
31
+ File.join(Dir.home(self.user))
32
+ end
33
+ end
34
+
35
+ def set_ownership(path, user, group=nil)
36
+ AethernalAgent.logger.debug("Setting ownership of '#{path}' to user '#{user}'")
37
+ begin
38
+ FileUtils.chown_R(user,group,path)
39
+ rescue SystemCallError => e
40
+ add_errors(e, path: path, user:user, group: group)
41
+ end
42
+ end
43
+
44
+ def set_permissions(path, chmod)
45
+ AethernalAgent.logger.debug("Setting chmod of '#{path}' to chmod '#{chmod}'")
46
+ begin
47
+ FileUtils.chmod(chmod, path)
48
+ rescue SystemCallError => e
49
+ add_errors(e, path: path, chmod: chmod)
50
+ end
51
+ end
52
+
53
+ def file_settings(file_path, options = {})
54
+ AethernalAgent.logger.debug "Setting file settings with options: #{options}"
55
+ set_permissions(file_path, options[:chmod]) if options[:chmod]
56
+ set_ownership(file_path, options[:owner]) if options[:owner]
57
+ end
58
+
59
+ def file(file_path, options = {})
60
+ options.reverse_merge!(action: :create)
61
+
62
+ AethernalAgent.logger.debug "Applying action #{options[:action]} on file '#{file_path}'."
63
+
64
+ if options[:action] == :delete
65
+ if File.directory?(file_path)
66
+ add_errors("File is directory, not going to remove it with file() method.", path: file_path)
67
+ elsif File.exist?(file_path)
68
+ begin
69
+ FileUtils.rm(file_path)
70
+ rescue SystemCallError => e
71
+ add_errors(e, path: file_path)
72
+ end
73
+ else
74
+ add_errors("File does not exist.", path: file_path)
75
+ end
76
+ else
77
+ set_ownership(file_path, options[:owner]) if options[:owner]
78
+ set_permissions(file_path, options[:chmod]) if options[:chmod]
79
+ end
80
+ end
81
+
82
+ def copy(source, target, options = {})
83
+ AethernalAgent.logger.debug "Applying action #{options[:action]} on file or directory '#{source}'."
84
+ if source.present? && target.present?
85
+ if File.directory?(source) || File.exist?(source)
86
+ if File.exists?(target)
87
+ add_errors("File or folder already exists.", path: target)
88
+ else
89
+ begin
90
+ if File.directory?(source)
91
+ FileUtils.cp_r(source, target)
92
+ else
93
+ FileUtils.cp(source, target)
94
+ end
95
+ rescue SystemCallError => e
96
+ add_errors(e, path: file_path)
97
+ end
98
+ end
99
+ else
100
+ add_errors("File or folder does not exist.", path: source)
101
+ end
102
+ else
103
+ add_errors("Source or destination are missing.")
104
+ end
105
+ end
106
+
107
+ def directory(path, options = {})
108
+ options.reverse_merge!(action: :create)
109
+
110
+ AethernalAgent.logger.debug "Applying action #{options[:action]} on directory '#{path}'."
111
+ if options[:action] == :create
112
+ unless File.directory?(path)
113
+ begin
114
+ FileUtils.mkdir_p(path)
115
+ rescue Errno::EEXIST, Errno::EACCES => e
116
+ add_errors(e, path: path)
117
+ return
118
+ end
119
+ else
120
+ AethernalAgent.logger.debug "#{path} folder already exist, not creating."
121
+ end
122
+
123
+ set_ownership(path, options[:owner]) if options[:owner]
124
+ set_permissions(path, options[:chmod]) if options[:chmod]
125
+ elsif options[:action] == :delete
126
+ if File.directory?(path)
127
+ begin
128
+ FileUtils.rm_r(path)
129
+ rescue Errno::EACCES => e
130
+ add_errors(e, path: path)
131
+ end
132
+ else
133
+ AethernalAgent.logger.debug "#{path} does not exist, not removing."
134
+ end
135
+ end
136
+
137
+ return true
138
+ end
139
+
140
+ def aethernal_agent_folder
141
+ end
142
+
143
+ def aethernal_agent_file(source_file, target_file_path, options = {})
144
+ AethernalAgent.logger.debug("Attempting to copy file '#{source_file}' to '#{target_file_path}'")
145
+
146
+ if File.exists?(target_file_path)
147
+ AethernalAgent.logger.debug("File already exists, not copying.")
148
+ else
149
+ begin
150
+ FileUtils.cp(File.join(files_folder,source_file), target_file_path)
151
+ rescue SystemCallError => e
152
+ AethernalAgent.logger.debug("'#{source_file}' could not be created, giving up. Error: '#{e}'")
153
+ add_errors(e,source_file: source_file, target_file_path: target_file_path)
154
+ return false
155
+ end
156
+ end
157
+
158
+ set_permissions(target_file_path, options[:chmod]) if options[:chmod]
159
+ set_ownership(target_file_path, options[:owner]) if options[:owner]
160
+ end
161
+
162
+ def write_template(in_path, out_path, vars, options={})
163
+ out_folder = File.dirname(out_path)
164
+ unless Dir.exist?(out_folder)
165
+ FileUtils.mkdir_p(out_folder)
166
+ set_permissions(out_folder, options[:chmod]) if options[:chmod]
167
+ set_ownership(out_folder, options[:owner]) if options[:owner]
168
+ end
169
+
170
+ AethernalAgent.logger.debug("Writing template '#{in_path}' to '#{out_path}'")
171
+ template = AethernalAgent::Template.new(in_path,vars, options)
172
+
173
+ if template.parse
174
+ return template.write_to(out_path)
175
+ end
176
+ end
177
+ end
178
+ end