superhosting 0.0.1 → 0.0.2

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 (248) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -0
  3. data/.travis.yml +13 -0
  4. data/Gemfile.lock +43 -7
  5. data/LICENSE.txt +4 -1
  6. data/Vagrantfile +6 -3
  7. data/bin/sx +6 -2
  8. data/bootstrap/etc/sx/default_model +1 -0
  9. data/bootstrap/etc/sx/models/base/container/docker/command +1 -0
  10. data/bootstrap/etc/sx/models/base/container/docker/user.erb +1 -0
  11. data/bootstrap/etc/sx/models/base/container/docker/volume.erb +2 -0
  12. data/bootstrap/etc/sx/models/bitrix_l/inherit +3 -0
  13. data/bootstrap/etc/sx/models/bitrix_m/inherit +3 -0
  14. data/bootstrap/etc/sx/models/bitrix_xl/inherit +3 -0
  15. data/bootstrap/etc/sx/models/common_bitrix/abstract +1 -0
  16. data/bootstrap/etc/sx/models/common_bitrix/container/mux +1 -0
  17. data/bootstrap/etc/sx/models/common_bitrix/inherit +1 -0
  18. data/bootstrap/etc/sx/models/common_bitrix/site/php/admin_value +2 -0
  19. data/bootstrap/etc/sx/models/common_bitrix/site/php/flag +1 -0
  20. data/bootstrap/etc/sx/models/common_bitrix/site/php/value +6 -0
  21. data/bootstrap/etc/sx/models/common_fcgi/abstract +1 -0
  22. data/bootstrap/etc/sx/models/common_fcgi/container/config.rb +6 -0
  23. data/bootstrap/etc/sx/models/common_fcgi/container/config_templates/supervisord.conf.erb +16 -0
  24. data/bootstrap/etc/sx/models/common_fcgi/container/docker/image +1 -0
  25. data/bootstrap/etc/sx/models/common_fcgi/container/docker/user.erb +1 -0
  26. data/bootstrap/etc/sx/models/common_fcgi/container/system_users +1 -0
  27. data/bootstrap/etc/sx/models/common_fcgi/site/config.rb +4 -0
  28. data/bootstrap/etc/sx/models/common_fcgi/site/config_templates/nginx_vhost.erb +21 -0
  29. data/bootstrap/etc/sx/models/common_joomla/abstract +1 -0
  30. data/bootstrap/etc/sx/models/common_joomla/site/php/flag +1 -0
  31. data/bootstrap/etc/sx/models/common_joomla/site/php/value +2 -0
  32. data/bootstrap/etc/sx/models/common_joomla_v2/abstract +1 -0
  33. data/bootstrap/etc/sx/models/common_joomla_v2/container/mux +1 -0
  34. data/bootstrap/etc/sx/models/common_joomla_v2/inherit +2 -0
  35. data/bootstrap/etc/sx/models/common_joomla_v3/abstract +1 -0
  36. data/bootstrap/etc/sx/models/common_joomla_v3/container/mux +1 -0
  37. data/bootstrap/etc/sx/models/common_joomla_v3/inherit +2 -0
  38. data/bootstrap/etc/sx/models/common_l/abstract +1 -0
  39. data/bootstrap/etc/sx/models/common_l/container/docker/blkio_weight +1 -0
  40. data/bootstrap/etc/sx/models/common_l/container/docker/cpu_period +1 -0
  41. data/bootstrap/etc/sx/models/common_l/container/docker/cpu_quota +1 -0
  42. data/bootstrap/etc/sx/models/common_l/container/docker/cpu_shares +1 -0
  43. data/bootstrap/etc/sx/models/common_l/container/docker/memory +1 -0
  44. data/bootstrap/etc/sx/models/common_l/container/docker/memory_swap +1 -0
  45. data/bootstrap/etc/sx/models/common_m/abstract +1 -0
  46. data/bootstrap/etc/sx/models/common_m/container/docker/blkio_weight +1 -0
  47. data/bootstrap/etc/sx/models/common_m/container/docker/cpu_period +1 -0
  48. data/bootstrap/etc/sx/models/common_m/container/docker/cpu_quota +1 -0
  49. data/bootstrap/etc/sx/models/common_m/container/docker/cpu_shares +1 -0
  50. data/bootstrap/etc/sx/models/common_m/container/docker/memory +1 -0
  51. data/bootstrap/etc/sx/models/common_m/container/docker/memory_swap +1 -0
  52. data/bootstrap/etc/sx/models/common_mail/abstract +1 -0
  53. data/bootstrap/etc/sx/models/common_mail/container/config.rb +12 -0
  54. data/bootstrap/etc/sx/models/common_mail/container/config_templates/postfwd_rules.erb +12 -0
  55. data/bootstrap/etc/sx/models/common_mail/container/config_templates/ssmtp.conf.erb +6 -0
  56. data/bootstrap/etc/sx/models/common_mail/container/mail/daily_limit +1 -0
  57. data/bootstrap/etc/sx/models/common_mail/container/mail/enabled +1 -0
  58. data/bootstrap/etc/sx/models/common_mail/container/mail/hourly_limit +1 -0
  59. data/bootstrap/etc/sx/models/common_php_l/abstract +1 -0
  60. data/bootstrap/etc/sx/models/common_php_l/container/mail/daily_limit +1 -0
  61. data/bootstrap/etc/sx/models/common_php_l/container/mail/hourly_limit +1 -0
  62. data/bootstrap/etc/sx/models/common_php_l/inherit +1 -0
  63. data/bootstrap/etc/sx/models/common_php_l/site/php/pm +1 -0
  64. data/bootstrap/etc/sx/models/common_php_l/site/php/pm_max_children +1 -0
  65. data/bootstrap/etc/sx/models/common_php_l/site/php/pm_max_spare_servers +1 -0
  66. data/bootstrap/etc/sx/models/common_php_l/site/php/pm_min_spare_servers +1 -0
  67. data/bootstrap/etc/sx/models/common_php_l/site/php/pm_start_servers +1 -0
  68. data/bootstrap/etc/sx/models/common_php_m/abstract +1 -0
  69. data/bootstrap/etc/sx/models/common_php_m/inherit +1 -0
  70. data/bootstrap/etc/sx/models/common_php_m/site/php/pm_max_children +1 -0
  71. data/bootstrap/etc/sx/models/common_php_s/abstract +1 -0
  72. data/bootstrap/etc/sx/models/common_php_s/inherit +1 -0
  73. data/bootstrap/etc/sx/models/common_php_xl/abstract +1 -0
  74. data/bootstrap/etc/sx/models/common_php_xl/container/mail/daily_limit +1 -0
  75. data/bootstrap/etc/sx/models/common_php_xl/container/mail/hourly_limit +1 -0
  76. data/bootstrap/etc/sx/models/common_php_xl/inherit +1 -0
  77. data/bootstrap/etc/sx/models/common_php_xl/site/php/pm +1 -0
  78. data/bootstrap/etc/sx/models/common_php_xl/site/php/pm_max_children +1 -0
  79. data/bootstrap/etc/sx/models/common_php_xl/site/php/pm_max_spare_servers +1 -0
  80. data/bootstrap/etc/sx/models/common_php_xl/site/php/pm_min_spare_servers +1 -0
  81. data/bootstrap/etc/sx/models/common_php_xl/site/php/pm_start_servers +1 -0
  82. data/bootstrap/etc/sx/models/common_php_xs/abstract +1 -0
  83. data/bootstrap/etc/sx/models/common_php_xs/container/mail/daily_limit +1 -0
  84. data/bootstrap/etc/sx/models/common_php_xs/container/mail/hourly_limit +1 -0
  85. data/bootstrap/etc/sx/models/common_php_xs/inherit +1 -0
  86. data/bootstrap/etc/sx/models/common_php_xs/site/php/pm_max_children +1 -0
  87. data/bootstrap/etc/sx/models/common_s/abstract +1 -0
  88. data/bootstrap/etc/sx/models/common_s/container/docker/blkio_weight +1 -0
  89. data/bootstrap/etc/sx/models/common_s/container/docker/cpu_period +1 -0
  90. data/bootstrap/etc/sx/models/common_s/container/docker/cpu_quota +1 -0
  91. data/bootstrap/etc/sx/models/common_s/container/docker/cpu_shares +1 -0
  92. data/bootstrap/etc/sx/models/common_s/container/docker/memory +1 -0
  93. data/bootstrap/etc/sx/models/common_s/container/docker/memory_swap +1 -0
  94. data/bootstrap/etc/sx/models/common_symfony/abstract +1 -0
  95. data/bootstrap/etc/sx/models/common_symfony/container/mux +1 -0
  96. data/bootstrap/etc/sx/models/common_symfony/container/system_users +1 -0
  97. data/bootstrap/etc/sx/models/common_symfony/inherit +1 -0
  98. data/bootstrap/etc/sx/models/common_symfony/site/php/flag +3 -0
  99. data/bootstrap/etc/sx/models/common_symfony/site/php/user +1 -0
  100. data/bootstrap/etc/sx/models/common_symfony/site/use_apache +1 -0
  101. data/bootstrap/etc/sx/models/common_xl/abstract +1 -0
  102. data/bootstrap/etc/sx/models/common_xl/container/docker/blkio_weight +1 -0
  103. data/bootstrap/etc/sx/models/common_xl/container/docker/cpu_shares +1 -0
  104. data/bootstrap/etc/sx/models/common_xl/container/docker/memory +1 -0
  105. data/bootstrap/etc/sx/models/common_xl/container/docker/memory_swap +1 -0
  106. data/bootstrap/etc/sx/models/common_xs/abstract +1 -0
  107. data/bootstrap/etc/sx/models/common_xs/container/docker/blkio_weight +1 -0
  108. data/bootstrap/etc/sx/models/common_xs/container/docker/cpu_period +1 -0
  109. data/bootstrap/etc/sx/models/common_xs/container/docker/cpu_quota +1 -0
  110. data/bootstrap/etc/sx/models/common_xs/container/docker/cpu_shares +1 -0
  111. data/bootstrap/etc/sx/models/common_xs/container/docker/memory +1 -0
  112. data/bootstrap/etc/sx/models/common_xs/container/docker/memory_swap +1 -0
  113. data/bootstrap/etc/sx/models/fcgi_l/inherit +3 -0
  114. data/bootstrap/etc/sx/models/fcgi_m/inherit +3 -0
  115. data/bootstrap/etc/sx/models/fcgi_s/inherit +3 -0
  116. data/bootstrap/etc/sx/models/fcgi_xl/inherit +3 -0
  117. data/bootstrap/etc/sx/models/joomla_v2_l/inherit +3 -0
  118. data/bootstrap/etc/sx/models/joomla_v2_m/inherit +3 -0
  119. data/bootstrap/etc/sx/models/joomla_v2_s/inherit +3 -0
  120. data/bootstrap/etc/sx/models/joomla_v2_xs/inherit +3 -0
  121. data/bootstrap/etc/sx/models/joomla_v3_l/inherit +3 -0
  122. data/bootstrap/etc/sx/models/joomla_v3_m/inherit +3 -0
  123. data/bootstrap/etc/sx/models/joomla_v3_s/inherit +3 -0
  124. data/bootstrap/etc/sx/models/joomla_v3_xs/inherit +3 -0
  125. data/bootstrap/etc/sx/models/symfony_l/inherit +3 -0
  126. data/bootstrap/etc/sx/models/symfony_m/inherit +3 -0
  127. data/bootstrap/etc/sx/models/symfony_xl/inherit +3 -0
  128. data/bootstrap/etc/sx/models/test/container/config.rb +4 -0
  129. data/bootstrap/etc/sx/models/test/container/config_templates/supervisord.conf.erb +16 -0
  130. data/bootstrap/etc/sx/models/test/container/docker/blkio_weight +1 -0
  131. data/bootstrap/etc/sx/models/test/container/docker/command +1 -0
  132. data/bootstrap/etc/sx/models/test/container/docker/cpu_period +1 -0
  133. data/bootstrap/etc/sx/models/test/container/docker/cpu_quota +1 -0
  134. data/bootstrap/etc/sx/models/test/container/docker/cpu_shares +1 -0
  135. data/bootstrap/etc/sx/models/test/container/docker/image +1 -0
  136. data/bootstrap/etc/sx/models/test/container/docker/memory +1 -0
  137. data/bootstrap/etc/sx/models/test/container/docker/memory_swap +1 -0
  138. data/bootstrap/etc/sx/models/test/container/docker/user.erb +1 -0
  139. data/bootstrap/etc/sx/models/test/container/docker/volume.erb +2 -0
  140. data/bootstrap/etc/sx/models/test/container/system_users +1 -0
  141. data/bootstrap/etc/sx/models/test/site/config.rb +4 -0
  142. data/bootstrap/etc/sx/models/test/site/config_templates/nginx_vhost.erb +21 -0
  143. data/bootstrap/etc/sx/models/test_with_mux/container/mux +1 -0
  144. data/bootstrap/etc/sx/models/test_with_mux/inherit +1 -0
  145. data/bootstrap/etc/sx/muxs/base/docker/command +1 -0
  146. data/bootstrap/etc/sx/muxs/php-5.3/container/docker/image +1 -0
  147. data/bootstrap/etc/sx/muxs/php-5.3/docker/image +1 -0
  148. data/bootstrap/etc/sx/muxs/php-5.3/inherit +2 -0
  149. data/bootstrap/etc/sx/muxs/php-5.5/container/docker/image +1 -0
  150. data/bootstrap/etc/sx/muxs/php-5.5/docker/image +1 -0
  151. data/bootstrap/etc/sx/muxs/php-5.5/inherit +2 -0
  152. data/bootstrap/etc/sx/muxs/php-5.6/container/docker/image +1 -0
  153. data/bootstrap/etc/sx/muxs/php-5.6/docker/image +1 -0
  154. data/bootstrap/etc/sx/muxs/php-5.6/inherit +2 -0
  155. data/bootstrap/etc/sx/muxs/php/abstract +1 -0
  156. data/bootstrap/etc/sx/muxs/php/docker/pid +1 -0
  157. data/bootstrap/etc/sx/muxs/php/docker/privileged +1 -0
  158. data/bootstrap/etc/sx/muxs/php/docker/volume +3 -0
  159. data/bootstrap/etc/sx/muxs/php/site/config.rb +10 -0
  160. data/bootstrap/etc/sx/muxs/php/site/config_templates/apache_vhost.erb +26 -0
  161. data/bootstrap/etc/sx/muxs/php/site/config_templates/nginx_vhost.erb +39 -0
  162. data/bootstrap/etc/sx/muxs/php/site/config_templates/php_fpm_pool.erb +22 -0
  163. data/bootstrap/etc/sx/muxs/php/site/php/pm +1 -0
  164. data/bootstrap/etc/sx/muxs/php/site/php/pm_max_children +1 -0
  165. data/bootstrap/etc/sx/muxs/php/site/use_apache +1 -0
  166. data/bootstrap/etc/sx/muxs/test/container/docker/image +1 -0
  167. data/bootstrap/etc/sx/muxs/test/docker/command +1 -0
  168. data/bootstrap/etc/sx/muxs/test/docker/image +1 -0
  169. data/bootstrap/etc/sx/muxs/test/inherit +1 -0
  170. data/bootstrap/etc/sx/password_strength +1 -0
  171. data/bootstrap/etc/sx/smtp_hostname +1 -0
  172. data/dockerfile/almost_base +19 -0
  173. data/dockerfile/base +18 -0
  174. data/dockerfile/mux +6 -0
  175. data/lib/superhosting.rb +39 -5
  176. data/lib/superhosting/base.rb +15 -21
  177. data/lib/superhosting/cli/base.rb +56 -40
  178. data/lib/superhosting/cli/cmd/admin_add.rb +5 -0
  179. data/lib/superhosting/cli/cmd/admin_container_list.rb +4 -0
  180. data/lib/superhosting/cli/cmd/admin_list.rb +11 -0
  181. data/lib/superhosting/cli/cmd/admin_passwd.rb +4 -0
  182. data/lib/superhosting/cli/cmd/container_admin_list.rb +4 -0
  183. data/lib/superhosting/cli/cmd/container_inspect.rb +11 -0
  184. data/lib/superhosting/cli/cmd/container_list.rb +18 -0
  185. data/lib/superhosting/cli/cmd/container_reconfigure.rb +11 -0
  186. data/lib/superhosting/cli/cmd/container_rename.rb +16 -0
  187. data/lib/superhosting/cli/cmd/model_list.rb +11 -0
  188. data/lib/superhosting/cli/cmd/{container_reconfig.rb → model_reconfigure.rb} +1 -1
  189. data/lib/superhosting/cli/cmd/model_tree.rb +30 -0
  190. data/lib/superhosting/cli/cmd/model_update.rb +11 -0
  191. data/lib/superhosting/cli/cmd/mux_reconfigure.rb +11 -0
  192. data/lib/superhosting/cli/cmd/repair.rb +8 -0
  193. data/lib/superhosting/cli/cmd/site_container.rb +15 -0
  194. data/lib/superhosting/cli/cmd/site_inspect.rb +11 -0
  195. data/lib/superhosting/cli/cmd/site_list.rb +35 -0
  196. data/lib/superhosting/cli/cmd/site_name.rb +15 -0
  197. data/lib/superhosting/cli/cmd/site_reconfigure.rb +11 -0
  198. data/lib/superhosting/cli/cmd/site_rename.rb +4 -0
  199. data/lib/superhosting/cli/cmd/user_add.rb +11 -5
  200. data/lib/superhosting/cli/cmd/user_change.rb +12 -6
  201. data/lib/superhosting/cli/cmd/user_list.rb +7 -0
  202. data/lib/superhosting/cli/cmd/user_passwd.rb +9 -0
  203. data/lib/superhosting/composite_mapper.rb +12 -0
  204. data/lib/superhosting/composite_mapper/base.rb +17 -0
  205. data/lib/superhosting/composite_mapper/container.rb +9 -0
  206. data/lib/superhosting/composite_mapper/site.rb +13 -0
  207. data/lib/superhosting/config/net_status.yml +122 -0
  208. data/lib/superhosting/config_executor.rb +12 -0
  209. data/lib/superhosting/{script_executor → config_executor}/base.rb +6 -5
  210. data/lib/superhosting/config_executor/container.rb +69 -0
  211. data/lib/superhosting/config_executor/site.rb +18 -0
  212. data/lib/superhosting/controller/admin.rb +84 -4
  213. data/lib/superhosting/controller/admin/container.rb +62 -2
  214. data/lib/superhosting/controller/base.rb +18 -0
  215. data/lib/superhosting/controller/container.rb +185 -122
  216. data/lib/superhosting/controller/container/admin.rb +25 -3
  217. data/lib/superhosting/controller/container/states.rb +296 -0
  218. data/lib/superhosting/controller/model.rb +62 -0
  219. data/lib/superhosting/controller/mux.rb +88 -0
  220. data/lib/superhosting/controller/mysql.rb +2 -2
  221. data/lib/superhosting/controller/site.rb +217 -72
  222. data/lib/superhosting/controller/site/alias.rb +32 -6
  223. data/lib/superhosting/controller/site/states.rb +41 -0
  224. data/lib/superhosting/controller/user.rb +233 -4
  225. data/lib/superhosting/docker_api.rb +170 -6
  226. data/lib/superhosting/helper/cmd.rb +40 -0
  227. data/lib/superhosting/helper/config.rb +80 -0
  228. data/lib/superhosting/helper/file.rb +56 -0
  229. data/lib/superhosting/helper/i18n.rb +13 -0
  230. data/lib/superhosting/helper/logger.rb +136 -0
  231. data/lib/superhosting/helper/states.rb +69 -0
  232. data/lib/superhosting/helpers.rb +5 -21
  233. data/lib/superhosting/mapper_inheritance/base.rb +16 -0
  234. data/lib/superhosting/mapper_inheritance/model.rb +96 -0
  235. data/lib/superhosting/mapper_inheritance/mux.rb +49 -0
  236. data/lib/superhosting/patches/path_mapper/dir_node.rb +23 -0
  237. data/lib/superhosting/patches/path_mapper/file_node.rb +47 -0
  238. data/lib/superhosting/patches/path_mapper/null_node.rb +35 -0
  239. data/lib/superhosting/patches/string/punycode.rb +21 -0
  240. data/lib/superhosting/version.rb +1 -1
  241. data/provision/bootstrap.sh +11 -0
  242. data/provision/docker.sh +25 -0
  243. data/provision/pam_docker.sh +5 -0
  244. data/{bootstrap.sh → provision/vagrant.sh} +5 -8
  245. data/superhosting.gemspec +14 -3
  246. metadata +368 -12
  247. data/lib/superhosting/script_executor/container.rb +0 -36
  248. data/lib/superhosting/script_executor/site.rb +0 -13
@@ -0,0 +1,12 @@
1
+ module Superhosting
2
+ module ConfigExecutor
3
+ def self.new(**kwargs)
4
+ klass = if kwargs[:site].nil?
5
+ Container
6
+ else
7
+ Site
8
+ end
9
+ klass.new(kwargs)
10
+ end
11
+ end
12
+ end
@@ -1,12 +1,12 @@
1
1
  module Superhosting
2
- module ScriptExecutor
2
+ module ConfigExecutor
3
3
  class Base
4
4
  include Helpers
5
5
 
6
6
  attr_accessor :commands
7
- attr_accessor :model, :lib, :config
7
+ attr_accessor :model, :lib, :etc, :docker_api
8
8
 
9
- def initialize(model:, lib:, config:, **kwargs)
9
+ def initialize(model:, lib:, etc:, docker_api:, **kwargs)
10
10
  kwargs.each do |k, v|
11
11
  instance_variable_set("@#{k}", v)
12
12
  self.class.class_eval("attr_accessor :#{k}")
@@ -15,11 +15,12 @@ module Superhosting
15
15
  self.commands = []
16
16
  self.model = model
17
17
  self.lib = lib
18
- self.config = config
18
+ self.etc = etc
19
+ self.docker_api = docker_api
19
20
  end
20
21
 
21
22
  def execute(script)
22
- self.instance_eval(script)
23
+ self.instance_eval(script, script.path.to_s)
23
24
  end
24
25
  end
25
26
  end
@@ -0,0 +1,69 @@
1
+ module Superhosting
2
+ module ConfigExecutor
3
+ class Container < Base
4
+ attr_accessor :container, :mux, :mux_name, :registry_files
5
+
6
+ def initialize(container:, on_reconfig:, on_config:, mux: nil, **kwargs)
7
+ self.container = container
8
+ self.mux = mux
9
+ self.mux_name = mux.nil? ? mux : "mux-#{mux.name}"
10
+ self.registry_files = []
11
+ @on_config = on_config
12
+ @on_reconfig = on_reconfig
13
+ super(**kwargs)
14
+ end
15
+
16
+ def mkdir(path, **options)
17
+ if @on_config
18
+ PathMapper.new(path).create!
19
+ self.set_file_attributes(path, options)
20
+ self.registry_files << path.to_s
21
+ end
22
+ end
23
+
24
+ def config(save_to, script=nil, **options)
25
+ if @on_config
26
+ save_to_mapper = PathMapper.new(save_to)
27
+ script = options.delete(:source) || save_to_mapper.name if script.nil?
28
+ script = script.to_s.end_with?('.erb') ? script : "#{script}.erb"
29
+ raise NetStatus::Exception.new(error: :error, code: :can_not_pass_an_absolute_path, data: { path: script }) if Pathname.new(script).absolute?
30
+ script_mapper = self.config_mapper(options).config_templates.f(script)
31
+ raise NetStatus::Exception.new(error: :error, code: :file_does_not_exists, data: { path: script_mapper.path.to_s }) if script_mapper.nil?
32
+ save_to_mapper.put!(script_mapper)
33
+ self.set_file_attributes(save_to_mapper.path, options)
34
+ self.registry_files << save_to_mapper.path.to_s
35
+ end
36
+ end
37
+
38
+ def on_reconfig(cmd)
39
+ self.commands << cmd if @on_reconfig
40
+ end
41
+
42
+ def run_commands
43
+ self.commands.each do |cmd|
44
+ if cmd == :container_restart
45
+ self.container.lib.signature.delete!(logger: false)
46
+ else
47
+ self.command! cmd
48
+ end
49
+ end
50
+ end
51
+
52
+ protected
53
+
54
+ def set_file_attributes(path, user: nil, group: nil, mode: nil, **kwargs)
55
+ chown!(user, group, path) if user and group
56
+ chmod!(mode, path) if user and mode
57
+ end
58
+
59
+ def base_mapper
60
+ self.container
61
+ end
62
+
63
+ def config_mapper(options)
64
+ self.base_mapper.erb_options = instance_variables_to_hash(self).merge(options)
65
+ self.base_mapper
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,18 @@
1
+ module Superhosting
2
+ module ConfigExecutor
3
+ class Site < Container
4
+ attr_accessor :site
5
+
6
+ def initialize(site:, **kwargs)
7
+ self.site = site
8
+ super(**kwargs)
9
+ end
10
+
11
+ protected
12
+
13
+ def base_mapper
14
+ self.site
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,20 +1,100 @@
1
1
  module Superhosting
2
2
  module Controller
3
3
  class Admin < Base
4
- def add(name:)
4
+ def initialize(**kwargs)
5
+ super(**kwargs)
6
+ @admins_mapper = @config.admins
7
+ end
8
+
9
+ def list
10
+ admins = {}
11
+ @admins_mapper.grep_dirs.map do |dir_name|
12
+ admin_name = dir_name.name
13
+
14
+ container_admin_controller = self.get_controller(Admin::Container, name: admin_name)
15
+ if (resp = container_admin_controller.list).net_status_ok?
16
+ admins[admin_name] = resp[:data]
17
+ else
18
+ return resp
19
+ end
20
+ end
21
+
22
+ { data: admins }
23
+ end
5
24
 
25
+ def add(name:, generate: false)
26
+ if (resp = self.not_existing_validation(name: name)).net_status_ok?
27
+ admin_dir = @admins_mapper.f(name)
28
+ admin_dir.create!
29
+ admin_dir.passwd.put!(name)
30
+ self.reindex_admin(name: name)
31
+ self.command!("chmod 640 #{admin_dir.path}")
32
+ self.passwd(name: name, generate: generate)
33
+ else
34
+ resp
35
+ end
6
36
  end
7
37
 
8
38
  def delete(name:)
39
+ if (resp = self.existing_validation(name: name)).net_status_ok?
40
+ admin_container_controller = self.get_controller(Admin::Container, name: name)
41
+ if (resp = admin_container_controller._delete_all_users).net_status_ok?
42
+ admin_dir = @admins_mapper.f(name)
43
+ admin_dir.delete!
44
+ self.reindex_admin(name: name)
45
+ end
46
+ end
47
+ resp
48
+ end
49
+
50
+ def passwd(name:, generate: false)
51
+ if (resp = self.existing_validation(name: name)).net_status_ok?
52
+ user_controller = self.get_controller(User)
53
+ admin_dir = @admins_mapper.f(name)
54
+ passwords = user_controller._create_password(generate: generate)
55
+ admin_dir.passwd.put!("#{name}:#{passwords[:encrypted_password]}")
56
+
57
+ users = self.index[name]
58
+ users.each do |user_name|
59
+ user_controller._update_password(name: user_name, encrypted_password: passwords[:encrypted_password])
60
+ end
9
61
 
62
+ generate ? { data: passwords[:password] } : {}
63
+ else
64
+ resp
65
+ end
10
66
  end
11
67
 
12
- def passwd(name:, generate: nil)
68
+ def container(name:)
69
+ self.get_controller(Container, name: name)
70
+ end
71
+
72
+ def existing_validation(name:)
73
+ (@admins_mapper.f(name)).nil? ? { error: :logical_error, code: :admin_does_not_exists, data: { name: name } } : {}
74
+ end
75
+
76
+ def not_existing_validation(name:)
77
+ self.existing_validation(name: name).net_status_ok? ? { error: :logical_error, code: :admin_exists, data: { name: name } } : {}
78
+ end
79
+
80
+ def index
81
+ @@index ||= self.reindex
82
+ end
13
83
 
84
+ def reindex
85
+ @@index = {}
86
+ @admins_mapper.grep_dirs.each {|dir_name| self.reindex_admin(name: dir_name.name) }
87
+ @@index
14
88
  end
15
89
 
16
- def container(name:, logger: @logger)
17
- Container.new(name: name, logger: logger)
90
+ def reindex_admin(name:)
91
+ @@index ||= {}
92
+ if @admins_mapper.f(name).nil?
93
+ @@index.delete(name)
94
+ else
95
+ admin_container_controller = self.get_controller(Admin::Container, name: name)
96
+ @@index[name] = admin_container_controller._users_list.net_status_ok![:data] || []
97
+ end
18
98
  end
19
99
  end
20
100
  end
@@ -2,21 +2,81 @@ module Superhosting
2
2
  module Controller
3
3
  class Admin
4
4
  class Container < Base
5
- def initialize(name:, **kvargs)
5
+ def initialize(name:, **kwargs)
6
+ super(kwargs)
6
7
  @admin_name = name
7
- super(kvargs)
8
+ @user_controller = self.get_controller(User)
9
+ @admin_controller = self.get_controller(Admin)
10
+ @container_controller = self.get_controller(Controller::Container)
11
+ @admin_passwd = @config.admins.f(@admin_name).passwd
12
+
13
+ @admin_controller.existing_validation(name: @admin_name).net_status_ok!
8
14
  end
9
15
 
10
16
  def list
17
+ containers = @container_controller._list
18
+ container_users = containers.map do |container_name, data|
19
+ unless @user_controller._get(name: "#{container_name}_admin_#{@admin_name}").nil?
20
+ { container: container_name, user: "#{container_name}_admin_#{@admin_name}" }
21
+ end
22
+ end.compact
11
23
 
24
+ { data: container_users }
12
25
  end
13
26
 
14
27
  def add(name:)
28
+ admin_name = "admin_#{@admin_name}"
15
29
 
30
+ if (resp = @container_controller.available_validation(name: name)).net_status_ok? and
31
+ (resp = @user_controller.not_existing_validation(name: admin_name, container_name: name)).net_status_ok?
32
+ user, encrypted_password = @admin_passwd.split(':')
33
+ if (resp = @user_controller._add(name: admin_name, container_name: name, shell: '/bin/bash')).net_status_ok?
34
+ resp = encrypted_password.nil? ? {} : @user_controller._update_password(name: "#{name}_#{admin_name}", encrypted_password: encrypted_password)
35
+ end
36
+ end
37
+ resp
16
38
  end
17
39
 
18
40
  def delete(name:)
41
+ admin_name = "admin_#{@admin_name}"
42
+
43
+ if (resp = @container_controller.available_validation(name: name)).net_status_ok? and
44
+ (resp = @user_controller.existing_validation(name: admin_name, container_name: name)).net_status_ok?
45
+ resp = @user_controller.delete(name: admin_name, container_name: name)
46
+ end
47
+ resp
48
+ end
49
+
50
+ def _containers_list
51
+ if (resp = self.list).net_status_ok?
52
+ containers = resp[:data].map {|elm| elm[:container] }
53
+ { data: containers }
54
+ else
55
+ resp
56
+ end
57
+ end
58
+
59
+ def _users_list
60
+ if (resp = self.list).net_status_ok?
61
+ users = resp[:data].map {|elm| elm[:user] }
62
+ { data: users }
63
+ else
64
+ resp
65
+ end
66
+ end
19
67
 
68
+ def _delete_all_users
69
+ if (resp = self._containers_list).net_status_ok?
70
+ containers = resp[:data]
71
+ containers.each do |container_name|
72
+ unless (resp = self.delete(name: container_name)).net_status_ok?
73
+ return resp
74
+ end
75
+ end
76
+ {}
77
+ else
78
+ resp
79
+ end
20
80
  end
21
81
  end
22
82
  end
@@ -0,0 +1,18 @@
1
+ module Superhosting
2
+ module Controller
3
+ class Base < Base
4
+ def repair
5
+ container_controller = self.get_controller(Container)
6
+ container_controller.index.each do |container_name, hash_of_mappers|
7
+ if hash_of_mappers[:state_mapper].value != 'up'
8
+ container_controller.reconfigure(name: container_name).net_status_ok!
9
+ else
10
+ container_controller._each_site(name: container_name) do |controller, name, state|
11
+ controller.reconfigure(name: name).net_status_ok! if state != 'up'
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,173 +1,236 @@
1
1
  module Superhosting
2
2
  module Controller
3
3
  class Container < Base
4
- CONTAINER_NAME_FORMAT = /[a-zA-Z0-9][a-zA-Z0-9_.-]+/
4
+ CONTAINER_NAME_FORMAT = /^[a-zA-Z0-9][a-zA-Z0-9_.-]+$/
5
+
6
+ def initialize(**kwargs)
7
+ super
8
+ self.index
9
+ end
5
10
 
6
11
  def list
7
- docker = @docker_api.container_list.map {|c| c['Names'].first.slice(1..-1) }.to_set
8
- sx = @config.containers._grep_dirs.map {|n| n._name }.to_set
9
- containers = (docker & sx)
12
+ # TODO
13
+ # docker = @docker_api.container_list.map {|c| c['Names'].first.slice(1..-1) }.to_set
14
+ # sx = @config.containers.grep_dirs.map {|n| n.name }.compact.to_set
15
+ # containers = (docker & sx)
10
16
 
11
- { data: containers.to_a }
17
+ containers = self._list
18
+ { data: containers }
12
19
  end
13
20
 
14
- def add(name:, mail: 'model', admin_mail: nil, model: nil)
15
- return { error: :input_error, message: "Invalid container name '#{name}' - only '#{CONTAINER_NAME_FORMAT}' are allowed" } if name !~ CONTAINER_NAME_FORMAT
16
- return { error: :logical_error, message: 'Container already running.' } if @docker_api.container_info(name)
17
- return { error: :input_error, message: 'No model given.' } unless (model_ = model || @config.default_model(default: nil))
18
-
19
- # config
20
- config_path_ = "#{@config_path}/containers/#{name}"
21
- config_path_mapper = PathMapper.new(config_path_)
22
- FileUtils.mkdir_p config_path_
23
-
24
- # model
25
- create_conf("#{config_path_}/model", model) unless model.nil?
26
- model_mapper = @config.models.f(:"#{model_}")
27
-
28
- # image
29
- return { error: :input_error, message: "No docker_image specified in model '#{model_}.'" } unless (image = model_mapper.docker_image(default: nil))
30
-
31
- # mail
32
- unless mail != 'no'
33
- if mail == 'yes'
34
- create_conf("#{config_path_}/mail", mail)
35
- admin_mail_ = admin_mail
36
- create_conf("#{config_path_}/admin_mail", admin_mail_) unless admin_mail_.nil?
37
- return { error: :input_error, message: 'Admin mail required.' } if admin_mail_.nil?
38
- elsif mail == 'model'
39
- if model_mapper.default_mail == 'yes'
40
- admin_mail_ = admin_mail || model_mapper.default_admin_mail(default: nil)
41
- return { error: :input_error, message: 'Admin mail required.' } if admin_mail_.nil?
42
- end
43
- end
21
+ def _list
22
+ def data(name)
23
+ mapper = self.index[name][:mapper]
24
+ docker_options = mapper.docker.grep_files.map {|f| [f.name, f.value] }.to_h
25
+ configs = mapper.f('config.rb', overlay: false).reverse.map {|f| f.value }
26
+ { docker: docker_options, configs: configs }
44
27
  end
45
28
 
46
- # lib
47
- lib_path_ = "#{@lib_path}/containers/#{name}"
48
- lib_path_mapper = PathMapper.new(lib_path_)
49
- FileUtils.rm_rf "#{lib_path_}/configs"
50
- FileUtils.mkdir_p "#{lib_path_}/configs"
51
- FileUtils.mkdir_p "#{lib_path_}/web"
52
-
53
- # user/group
54
- self.command("groupadd #{name}")
55
- self.command("useradd #{name} -g #{name} -d #{lib_path_}/web/")
29
+ containers = {}
30
+ @config.containers.grep_dirs.map do |n|
31
+ name = n.name
32
+ user_controller = self.get_controller(User)
33
+ containers[name] = {
34
+ state: self.state(name: name).value,
35
+ users: user_controller._list(container_name: name),
36
+ admins: self.admin(name: name)._list
37
+ }.merge(data(name)) if self.index.key? name and self.index[name][:mapper].lib.state.file?
38
+ end
39
+ containers
40
+ end
56
41
 
57
- user = Etc.getpwnam(name)
42
+ def inspect(name:)
43
+ if (resp = self.existing_validation(name: name)).net_status_ok?
44
+ { data: self._list[name] }
45
+ else
46
+ resp
47
+ end
48
+ end
58
49
 
59
- write_if_not_exist("#{lib_path_}/configs/etc-group", "#{name}:x:#{user.gid}:")
60
- write_if_not_exist("#{lib_path_}/configs/etc-passwd", "#{name}:x:#{user.uid}:#{user.gid}::/web/:/usr/sbin/nologin")
50
+ def add(name:, mail: 'model', admin_mail: nil, model: nil)
51
+ resp = self._reconfigure(name: name, mail: mail, admin_mail: admin_mail, model: model) if (resp = self.not_existing_validation(name: name)).net_status_ok?
52
+ resp
53
+ end
61
54
 
62
- # system users
63
- users = [config_path_mapper.system_users, model_mapper.system_users].find {|f| f.is_a? PathMapper::FileNode }
64
- users.lines.each {|u| self.command("useradd #{name}_#{u.strip} -g #{name} -d #{lib_path_}/web/") } unless users.nil?
55
+ def delete(name:)
56
+ if (resp = self.existing_validation(name: name)).net_status_ok?
57
+ lib_mapper = @lib.containers.f(name)
58
+
59
+ states = {
60
+ up: { action: :stop, undo: :run, next: :configuration_applied },
61
+ configuration_applied: { action: :unconfigure_with_unapply, undo: :configure_with_apply, next: :mux_runned },
62
+ mux_runned: { action: :stop_mux, undo: :run_mux, next: :users_installed },
63
+ users_installed: { action: :uninstall_users, next: :data_installed },
64
+ data_installed: { action: :uninstall_data }
65
+ }
66
+
67
+ self.on_state(state_mapper: lib_mapper, states: states,
68
+ name: name)
69
+ end
70
+ resp
71
+ end
65
72
 
66
- # services
67
- cserv = @config.containers.f(name).services._grep(/.*\.erb/).map {|n| [n._name, n]}.to_h
68
- mserv = model_mapper.services._grep(/.*\.erb/).map {|n| [n._name, n]}.to_h
69
- services = mserv.merge!(cserv)
73
+ def change(name:, mail: 'model', admin_mail: nil, model: nil)
70
74
 
71
- supervisor_path = "#{lib_path_}/supervisor"
72
- FileUtils.mkdir_p supervisor_path
73
- services.each do |_name, node|
74
- text = erb(node, model: model_, container: config_path_mapper)
75
- create_conf("#{supervisor_path}/#{_name[/.*[^\.erb]/]}", text)
76
- end
75
+ end
77
76
 
78
- # container
79
- unless model_mapper.f('container.rb').nil?
80
- registry_path = lib_path_mapper.registry.f('container')._path
81
- ex = ScriptExecutor::Container.new(
82
- container: config_path_mapper, container_name: name, container_lib: lib_path_mapper, registry_path: registry_path,
83
- model: model_mapper, config: @config, lib: @lib
84
- )
85
- ex.execute(model_mapper.f('container.rb'))
86
- ex.commands.each {|c| self.command c }
77
+ def update(name:)
78
+ if (resp = self.existing_validation(name: name)).net_status_ok? and @docker_api.container_exists?(name)
79
+ mapper = self.index[name][:mapper]
80
+ image = mapper.lib.image.value
81
+ self._recreate_docker(name: name) unless @docker_api.container_image?(name, image)
87
82
  end
83
+ resp
84
+ end
88
85
 
89
- # docker
90
- write_if_not_exist('/etc/security/docker.conf', "@#{name} #{name}")
86
+ def rename(name:, new_name:)
87
+ if (resp = self.available_validation(name: name)).net_status_ok? and
88
+ (resp = self.adding_validation(name: new_name)).net_status_ok?
91
89
 
92
- # run container
93
- self.command "docker run --detach --name #{name} -v #{lib_path_}/configs/:/.configs:ro
94
- -v #{lib_path_}/web:/web #{image} /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf".split
90
+ mapper = self.index[name][:mapper]
91
+ new_etc_mapper = mapper.etc.parent.f(new_name)
92
+ model = nil if (model = mapper.f('model').value).nil? # TODO: mail:, admin_mail:
95
93
 
96
- { error: :error, message: 'Unable to run docker container.' } unless @docker_api.container_info(name)
97
- end
94
+ mapper.rename!(new_etc_mapper.path)
95
+ mapper.create!
98
96
 
99
- def delete(name:)
100
- config_path_mapper = @config.containers.f(name)
101
- lib_path_mapper = PathMapper.new("#{@lib_path}/containers/#{name}")
102
- model = config_path_mapper.model(default: @config.default_model)
103
- model_mapper = @config.models.f(:"#{model}")
104
-
105
- sites = config_path_mapper.sites._grep_dirs.map { |n| n._name }
106
- sites.each do |s|
107
97
  begin
108
- Site.new(instance_variables_to_hash(self)).delete(s)
109
- rescue NetStatus::Exception => e
110
- raise Error::Controller, e.net_status
98
+ self.stop(name: name).net_status_ok!
99
+ self.unconfigure_with_unapply(name: name).net_status_ok!
100
+ if (resp = self._reconfigure(name: new_name, model: model)).net_status_ok?
101
+ new_mapper = self.index[new_name][:mapper]
102
+ mapper.lib.web.rename!(new_mapper.lib.web.path)
103
+ mapper.lib.sites.rename!(new_mapper.lib.sites.path)
104
+ mapper.lib.registry.sites.rename!(new_mapper.lib.registry.sites.path)
105
+
106
+ site_controller = self.get_controller(Site)
107
+ site_controller.reindex_container_sites(container_name: new_name)
108
+ site_controller.reindex_container_sites(container_name: name)
109
+
110
+ self.reconfigure(name: new_name).net_status_ok!
111
+ self.delete(name: name).net_status_ok!
112
+ end
113
+ rescue Exception => e
114
+ resp = e.net_status
115
+ raise
116
+ ensure
117
+ unless resp.net_status_ok?
118
+ unless new_mapper.nil?
119
+ new_mapper.lib.web.rename!(mapper.lib.web.path)
120
+ new_mapper.lib.sites.rename!(mapper.lib.sites.path)
121
+ new_etc_mapper.rename!(mapper.path)
122
+ self.reconfigure(name: name)
123
+ end
124
+ self.delete(name: new_name)
125
+ end
111
126
  end
112
127
  end
128
+ resp
129
+ end
113
130
 
114
- unless (container = lib_path_mapper.registry.f('container')).nil?
115
- FileUtils.rm container.lines
116
- FileUtils.rm container._path
131
+ def reconfigure(name:)
132
+ if (resp = self.existing_validation(name: name)).net_status_ok?
133
+ self.set_state(name: name, state: :data_installed)
134
+ resp = self._reconfigure(name: name)
117
135
  end
136
+ resp
137
+ end
118
138
 
119
- unless model_mapper.f('container.rb').nil?
120
- registry_path = lib_path_mapper.registry.f('container')._path
121
- ex = ScriptExecutor::Container.new(
122
- container: config_path_mapper, container_name: name, container_lib: lib_path_mapper,
123
- registry_path: registry_path, on_reconfig_only: true,
124
- model: model_mapper, config: @config, lib: @lib
125
- )
126
- ex.execute(model_mapper.f('container.rb'))
127
- ex.commands.each {|c| self.command c }
128
- end
139
+ def _reconfigure(name:, **kwargs)
140
+ lib_mapper = @lib.containers.f(name)
129
141
 
130
- @docker_api.container_kill(name)
131
- @docker_api.container_rm(name)
132
- remove_line_from_file('/etc/security/docker.conf', "@#{name} #{name}")
142
+ states = {
143
+ none: { action: :install_data, undo: :uninstall_data, next: :data_installed },
144
+ data_installed: { action: :install_users, undo: :uninstall_users, next: :users_installed },
145
+ users_installed: { action: :run_mux, undo: :stop_mux, next: :mux_runned },
146
+ mux_runned: { action: :configure_with_apply, undo: :unconfigure_with_unapply, next: :configuration_applied },
147
+ configuration_applied: { action: :run, undo: :stop, next: :up }
148
+ }
133
149
 
134
- begin
135
- gid = Etc.getgrnam(name).gid
136
- Etc.passwd do |user|
137
- self.command("userdel #{user.name}") if user.gid == gid
138
- end
139
- self.command("groupdel #{name}")
140
- rescue ArgumentError => e
141
- # repeated command execution: group name already does not exist
142
- end
150
+ self.on_state(state_mapper: lib_mapper, states: states,
151
+ name: name, **kwargs)
152
+ end
143
153
 
144
- FileUtils.rm_rf "#{@lib_path}/containers/#{name}/configs"
154
+ def save(name:, to:)
145
155
 
146
- {}
147
156
  end
148
157
 
149
- def change(name:, mail: 'model', admin_mail: nil, model: nil)
158
+ def restore(name:, from:, mail: 'model', admin_mail: nil, model: nil)
150
159
 
151
160
  end
152
161
 
153
- def update(name:)
162
+ def admin(name:)
163
+ self.get_controller(Admin, name: name)
164
+ end
154
165
 
166
+ def base_validation(name:)
167
+ @docker_api.container_rm_inactive!(name)
168
+ (name !~ CONTAINER_NAME_FORMAT) ? { error: :input_error, code: :invalid_container_name, data: { name: name, regex: CONTAINER_NAME_FORMAT } } : {}
155
169
  end
156
170
 
157
- def reconfig(name:)
171
+ def adding_validation(name:)
172
+ if (resp = self.base_validation(name: name)).net_status_ok?
173
+ resp = self.not_running_validation(name: name)
174
+ end
175
+ resp
176
+ end
158
177
 
178
+ def running_validation(name:)
179
+ @docker_api.container_running?(name) ? {}: { error: :logical_error, code: :container_is_not_running, data: { name: name } }
159
180
  end
160
181
 
161
- def save(name:, to:)
182
+ def not_running_validation(name:)
183
+ @docker_api.container_not_running?(name) ? {} : { error: :logical_error, code: :container_is_running, data: { name: name } }
184
+ end
162
185
 
186
+ def existing_validation(name:)
187
+ self.index.include?(name) ? {} : { error: :logical_error, code: :container_does_not_exists, data: { name: name } }
163
188
  end
164
189
 
165
- def restore(name:, from:, mail: 'model', admin_mail: nil, model: nil)
190
+ def not_existing_validation(name:)
191
+ self.existing_validation(name: name).net_status_ok? ? { error: :logical_error, code: :container_exists, data: { name: name } } : {}
192
+ end
193
+
194
+ def available_validation(name:)
195
+ if (resp = self.existing_validation(name: name)).net_status_ok?
196
+ resp = (self.index[name][:mapper].lib.state.value == 'up') ? {} : { error: :logical_error, code: :container_is_not_available, data: { name: name } }
197
+ end
198
+ resp
199
+ end
166
200
 
201
+ def index
202
+ @@index ||= self.reindex
167
203
  end
168
204
 
169
- def admin(name:, logger: @logger)
170
- Admin.new(name: name, logger: logger)
205
+ def reindex
206
+ @config.containers.grep_dirs.each {|mapper| self.reindex_container(name: mapper.name) }
207
+ @@index ||= {}
208
+ end
209
+
210
+ def reindex_container(name:)
211
+ @@index ||= {}
212
+ etc_mapper = @config.containers.f(name)
213
+ web_mapper = PathMapper.new('/web').f(name)
214
+ lib_mapper = @lib.containers.f(name)
215
+ state_mapper = lib_mapper.state
216
+
217
+ if etc_mapper.nil?
218
+ @@index.delete(name)
219
+ return
220
+ end
221
+
222
+ model_name = etc_mapper.f('model', default: @config.default_model)
223
+ model_mapper = @config.models.f(model_name)
224
+ etc_mapper = MapperInheritance::Model.new(model_mapper).set_inheritors(etc_mapper)
225
+
226
+ mapper = CompositeMapper.new(etc_mapper: etc_mapper, lib_mapper: lib_mapper, web_mapper: web_mapper)
227
+
228
+ etc_mapper.erb_options = { container: mapper }
229
+ mux_mapper = if (mux_file_mapper = etc_mapper.mux).file?
230
+ MapperInheritance::Mux.new(@config.muxs.f(mux_file_mapper)).set_inheritors
231
+ end
232
+
233
+ @@index[name] = { mapper: mapper, mux_mapper: mux_mapper, state_mapper: state_mapper }
171
234
  end
172
235
  end
173
236
  end