aethernal-agent 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
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