class Superhosting::Controller::Container
Constants
- CONTAINER_NAME_FORMAT
Public Class Methods
new(**kwargs)
click to toggle source
Calls superclass method
Superhosting::Base::new
# File lib/superhosting/controller/container.rb, line 6 def initialize(**kwargs) super self.index end
Public Instance Methods
_collect_docker_options(mapper:, model_or_mux: nil)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 273 def _collect_docker_options(mapper:, model_or_mux: nil) model_or_mux ||= mapper.f('model', default: @config.default_model) return { error: :input_error, code: :no_docker_image_specified_in_model_or_mux, data: { name: model_or_mux } } if (image = mapper.docker.image).nil? all_options = mapper.docker.grep_files.map {|n| [n.name[/(.*(?=\.erb))|(.*)/].to_sym, n.value] }.to_h return { error: :logical_error, code: :docker_command_not_found } if (command = all_options[:command]).nil? command_options = @docker_api.grab_container_options(all_options) volume_opts = [] mapper.docker.f('volume', overlay: false).each {|v| volume_opts += v.lines unless v.nil? } volume_opts.each {|val| command_options << "--volume #{val}" } { data: [command_options, image, command] } end
_config_options(name:, on_reconfig:, on_config:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 212 def _config_options(name:, on_reconfig:, on_config:) mapper = self.index[name][:mapper] model = mapper.model(default: @config.default_model) model_mapper = @config.models.f(:"#{model}") registry_mapper = mapper.lib.registry.f('container') mux_mapper = self.index[name][:mux_mapper] { container: mapper, mux: mux_mapper, model: model_mapper, registry_mapper: registry_mapper, on_reconfig: on_reconfig, on_config: on_config, etc: @config, lib: @lib, docker_api: @docker_api } end
_delete_docker(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 232 def _delete_docker(name:) if @docker_api.container_exists?(name) @docker_api.container_unpause!(name) if @docker_api.container_paused?(name) @docker_api.container_kill!(name) @docker_api.container_rm!(name) end end
_each_site(name:) { |site_controller, site_name, data| ... }
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 288 def _each_site(name:) site_controller = self.get_controller(Superhosting::Controller::Site) site_controller._list(container_name: name).each do |site_name, data| yield site_controller, site_name, data[:state] end end
_list()
click to toggle source
# File lib/superhosting/controller/container.rb, line 21 def _list def data(name) mapper = self.index[name][:mapper] docker_options = mapper.docker.grep_files.map {|f| [f.name, f.value] }.to_h configs = mapper.f('config.rb', overlay: false).reverse.map {|f| f.value } { docker: docker_options, configs: configs } end containers = {} @config.containers.grep_dirs.map do |n| name = n.name user_controller = self.get_controller(User) containers[name] = { state: self.state(name: name).value, users: user_controller._list(container_name: name), admins: self.admin(name: name)._list }.merge(data(name)) if self.index.key? name and self.index[name][:mapper].lib.state.file? end containers end
_reconfigure(name:, **kwargs)
click to toggle source
# File lib/superhosting/controller/container.rb, line 139 def _reconfigure(name:, **kwargs) lib_mapper = @lib.containers.f(name) states = { none: { action: :install_data, undo: :uninstall_data, next: :data_installed }, data_installed: { action: :install_users, undo: :uninstall_users, next: :users_installed }, users_installed: { action: :run_mux, undo: :stop_mux, next: :mux_runned }, mux_runned: { action: :configure_with_apply, undo: :unconfigure_with_unapply, next: :configuration_applied }, configuration_applied: { action: :run, undo: :stop, next: :up } } self.on_state(state_mapper: lib_mapper, states: states, name: name, **kwargs) end
_recreate_docker(*docker_options, name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 240 def _recreate_docker(*docker_options, name:) docker_options ||= self._collect_docker_options(mapper: self.index[name][:mapper]).net_status_ok! self._delete_docker(name: name) self._run_docker(*docker_options, name: name) end
_run_docker(*docker_options, name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 246 def _run_docker(*docker_options, name:) docker_options = self._collect_docker_options(mapper: self.index[name][:mapper]).net_status_ok![:data] if docker_options.empty? @docker_api.container_run(name, *docker_options) end
_safe_run_docker(*docker_options, name:, restart: false)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 251 def _safe_run_docker(*docker_options, name:, restart: false) if restart self._recreate_docker(*docker_options, name: name) elsif @docker_api.container_exists?(name) if @docker_api.container_dead?(name) self._recreate_docker(*docker_options, name: name) elsif @docker_api.container_exited?(name) @docker_api.container_start!(name) elsif @docker_api.container_paused?(name) @docker_api.container_unpause!(name) elsif @docker_api.container_restarting?(name) Polling.start 10 do break unless @docker_api.container_restarting?(name) sleep 2 end end else self._run_docker(*docker_options, name: name) end self.running_validation(name: name) end
add(name:, mail: 'model', admin_mail: nil, model: nil)
click to toggle source
# File lib/superhosting/controller/container.rb, line 50 def add(name:, mail: 'model', admin_mail: nil, model: nil) resp = self._reconfigure(name: name, mail: mail, admin_mail: admin_mail, model: model) if (resp = self.not_existing_validation(name: name)).net_status_ok? resp end
adding_validation(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 171 def adding_validation(name:) if (resp = self.base_validation(name: name)).net_status_ok? resp = self.not_running_validation(name: name) end resp end
admin(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 162 def admin(name:) self.get_controller(Admin, name: name) end
apply(name:)
click to toggle source
Calls superclass method
# File lib/superhosting/controller/container/states.rb, line 147 def apply(name:) self._each_site(name: name) do |controller, sname, state| controller.apply(name: sname).net_status_ok! end super end
available_validation(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 194 def available_validation(name:) if (resp = self.existing_validation(name: name)).net_status_ok? resp = (self.index[name][:mapper].lib.state.value == 'up') ? {} : { error: :logical_error, code: :container_is_not_available, data: { name: name } } end resp end
base_validation(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 166 def base_validation(name:) @docker_api.container_rm_inactive!(name) (name !~ CONTAINER_NAME_FORMAT) ? { error: :input_error, code: :invalid_container_name, data: { name: name, regex: CONTAINER_NAME_FORMAT } } : {} end
change(name:, mail: 'model', admin_mail: nil, model: nil)
click to toggle source
# File lib/superhosting/controller/container.rb, line 73 def change(name:, mail: 'model', admin_mail: nil, model: nil) end
configure(name:)
click to toggle source
Calls superclass method
# File lib/superhosting/controller/container/states.rb, line 133 def configure(name:) self._each_site(name: name) do |controller, sname, state| controller.configure(name: sname).net_status_ok! end super end
configure_with_apply(name:)
click to toggle source
Calls superclass method
# File lib/superhosting/controller/container/states.rb, line 154 def configure_with_apply(name:) self._each_site(name: name) do |controller, sname, state| controller.reconfigure(name: sname).net_status_ok! end super end
data(name)
click to toggle source
# File lib/superhosting/controller/container.rb, line 22 def data(name) mapper = self.index[name][:mapper] docker_options = mapper.docker.grep_files.map {|f| [f.name, f.value] }.to_h configs = mapper.f('config.rb', overlay: false).reverse.map {|f| f.value } { docker: docker_options, configs: configs } end
delete(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 55 def delete(name:) if (resp = self.existing_validation(name: name)).net_status_ok? lib_mapper = @lib.containers.f(name) states = { up: { action: :stop, undo: :run, next: :configuration_applied }, configuration_applied: { action: :unconfigure_with_unapply, undo: :configure_with_apply, next: :mux_runned }, mux_runned: { action: :stop_mux, undo: :run_mux, next: :users_installed }, users_installed: { action: :uninstall_users, next: :data_installed }, data_installed: { action: :uninstall_data } } self.on_state(state_mapper: lib_mapper, states: states, name: name) end resp end
existing_validation(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 186 def existing_validation(name:) self.index.include?(name) ? {} : { error: :logical_error, code: :container_does_not_exists, data: { name: name } } end
index()
click to toggle source
# File lib/superhosting/controller/container.rb, line 201 def index @@index ||= self.reindex end
inspect(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 42 def inspect(name:) if (resp = self.existing_validation(name: name)).net_status_ok? { data: self._list[name] } else resp end end
install_data(name:, mail: 'model', admin_mail: nil, model: nil)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 6 def install_data(name:, mail: 'model', admin_mail: nil, model: nil) if !(resp = self.adding_validation(name: name)).net_status_ok? return resp elsif (model_ = model || @config.containers.f(name).f('model', default: @config.default_model)).nil? return { error: :input_error, code: :no_model_given } end # model model_mapper = @config.models.f(model_) return { error: :input_error, code: :model_does_not_exists, data: { name: model_ } } unless @config.models.f(model_).dir? etc_mapper = @config.containers.f(name).create! etc_mapper.model.put!(model) unless model.nil? # config self.reindex_container(name: name) mapper = self.index[name][:mapper] # mail unless mail != 'no' if mail == 'yes' mapper.mail.put!(mail) unless (admin_mail_ = admin_mail).nil? mapper.admin_mail.put!(admin_mail_) end elsif mail == 'model' if model_mapper.default_mail == 'yes' admin_mail_ = admin_mail || model_mapper.default_admin_mail end end return { error: :input_error, code: :option_admin_mail_required } if defined? admin_mail_ and admin_mail_.nil? end # lib mapper.lib.config.delete! mapper.lib.config.create! mapper.lib.web.create! # web PathMapper.new('/web').create! safe_link!(mapper.lib.web.path, mapper.web.path) {} end
install_users(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 69 def install_users(name:) mapper = self.index[name][:mapper] # user / group user_controller = self.get_controller(User) user_controller._group_pretty_add(name: name) unless (resp = user_controller._pretty_add_custom(name: name, group: name)).net_status_ok? return resp end user = user_controller._get(name: name) self.with_dry_run do |dry_run| user_gid = if dry_run 'XXXX' if user.nil? else user.gid end mapper.lib.config.f('etc-group').append_line!("#{name}:x:#{user_gid}:") unless user_gid.nil? end # system users current_system_users = user_controller._group_get_system_users(name: name) add_users = mapper.system_users.lines - current_system_users del_users = current_system_users - mapper.system_users.lines add_users.each do |u| unless (resp = user_controller._add_system_user(name: u.strip, container_name: name)).net_status_ok? return resp end end del_users.each do |u| user_name = "#{name}_#{u.strip}" user = user_controller._get(name: user_name) unless (resp = user_controller._del(name: user_name)).net_status_ok? return resp end mapper.lib.config.f('etc-passwd').remove_line!(/^#{user_name}:.*/) end # docker PathMapper.new('/etc/security/docker.conf').append_line!("@#{name} #{name}") # chown chown_r!(name, name, mapper.lib.web.path) {} end
list()
click to toggle source
# File lib/superhosting/controller/container.rb, line 11 def list # TODO # docker = @docker_api.container_list.map {|c| c['Names'].first.slice(1..-1) }.to_set # sx = @config.containers.grep_dirs.map {|n| n.name }.compact.to_set # containers = (docker & sx) containers = self._list { data: containers } end
not_existing_validation(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 190 def not_existing_validation(name:) self.existing_validation(name: name).net_status_ok? ? { error: :logical_error, code: :container_exists, data: { name: name } } : {} end
not_running_validation(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 182 def not_running_validation(name:) @docker_api.container_not_running?(name) ? {} : { error: :logical_error, code: :container_is_running, data: { name: name } } end
reconfigure(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 131 def reconfigure(name:) if (resp = self.existing_validation(name: name)).net_status_ok? self.set_state(name: name, state: :data_installed) resp = self._reconfigure(name: name) end resp end
reindex()
click to toggle source
# File lib/superhosting/controller/container.rb, line 205 def reindex @config.containers.grep_dirs.each {|mapper| self.reindex_container(name: mapper.name) } @@index ||= {} end
reindex_container(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 210 def reindex_container(name:) @@index ||= {} etc_mapper = @config.containers.f(name) web_mapper = PathMapper.new('/web').f(name) lib_mapper = @lib.containers.f(name) state_mapper = lib_mapper.state if etc_mapper.nil? @@index.delete(name) return end model_name = etc_mapper.f('model', default: @config.default_model) model_mapper = @config.models.f(model_name) etc_mapper = MapperInheritance::Model.new(model_mapper).set_inheritors(etc_mapper) mapper = CompositeMapper.new(etc_mapper: etc_mapper, lib_mapper: lib_mapper, web_mapper: web_mapper) etc_mapper.erb_options = { container: mapper } mux_mapper = if (mux_file_mapper = etc_mapper.mux).file? MapperInheritance::Mux.new(@config.muxs.f(mux_file_mapper)).set_inheritors end @@index[name] = { mapper: mapper, mux_mapper: mux_mapper, state_mapper: state_mapper } end
rename(name:, new_name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 86 def rename(name:, new_name:) if (resp = self.available_validation(name: name)).net_status_ok? and (resp = self.adding_validation(name: new_name)).net_status_ok? mapper = self.index[name][:mapper] new_etc_mapper = mapper.etc.parent.f(new_name) model = nil if (model = mapper.f('model').value).nil? # TODO: mail:, admin_mail: mapper.rename!(new_etc_mapper.path) mapper.create! begin self.stop(name: name).net_status_ok! self.unconfigure_with_unapply(name: name).net_status_ok! if (resp = self._reconfigure(name: new_name, model: model)).net_status_ok? new_mapper = self.index[new_name][:mapper] mapper.lib.web.rename!(new_mapper.lib.web.path) mapper.lib.sites.rename!(new_mapper.lib.sites.path) mapper.lib.registry.sites.rename!(new_mapper.lib.registry.sites.path) site_controller = self.get_controller(Site) site_controller.reindex_container_sites(container_name: new_name) site_controller.reindex_container_sites(container_name: name) self.reconfigure(name: new_name).net_status_ok! self.delete(name: name).net_status_ok! end rescue Exception => e resp = e.net_status raise ensure unless resp.net_status_ok? unless new_mapper.nil? new_mapper.lib.web.rename!(mapper.lib.web.path) new_mapper.lib.sites.rename!(mapper.lib.sites.path) new_etc_mapper.rename!(mapper.path) self.reconfigure(name: name) end self.delete(name: new_name) end end end resp end
restore(name:, from:, mail: 'model', admin_mail: nil, model: nil)
click to toggle source
# File lib/superhosting/controller/container.rb, line 158 def restore(name:, from:, mail: 'model', admin_mail: nil, model: nil) end
run(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 161 def run(name:) mapper = self.index[name][:mapper] if (resp = self._collect_docker_options(mapper: mapper)).net_status_ok? command_options, image, command = resp[:data] dump_command_option = (command_options + [command]).join("\n") dummy_signature_md5 = Digest::MD5.new.digest(dump_command_option) restart = (!image.compare_with(mapper.lib.image) or (dummy_signature_md5 != mapper.lib.signature.md5)) if (resp = self._safe_run_docker(command_options, image, command, name: name, restart: restart)).net_status_ok? mapper.lib.image.put!(image, logger: false) mapper.lib.signature.put!(dump_command_option, logger: false) end end resp end
run_mux(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 179 def run_mux(name:) resp = {} mapper = self.index[name][:mapper] if (mux_mapper = mapper.mux).file? mux_name = "mux-#{mux_mapper.value}" mux_controller = self.get_controller(Mux) resp = mux_controller.add(name: mux_name) if mux_controller.not_running_validation(name: mux_name).net_status_ok? mux_controller.index_push(mux_name, name) end resp end
running_validation(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 178 def running_validation(name:) @docker_api.container_running?(name) ? {}: { error: :logical_error, code: :container_is_not_running, data: { name: name } } end
save(name:, to:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 154 def save(name:, to:) end
stop(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 206 def stop(name:) self._delete_docker(name: name) self.get_controller(Mux).reindex {} end
stop_mux(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 193 def stop_mux(name:) mapper = self.index[name][:mapper] if (mux_mapper = mapper.mux).file? mux_name = "mux-#{mux_mapper.value}" mux_controller = self.get_controller(Mux) mux_controller.index_pop(mux_name, name) self._delete_docker(name: mux_name) unless mux_controller.index.include?(mux_name) end {} end
unconfigure(name:)
click to toggle source
Calls superclass method
# File lib/superhosting/controller/container/states.rb, line 140 def unconfigure(name:) self._each_site(name: name) do |controller, sname, state| controller.unconfigure(name: sname).net_status_ok! # TODO: unchanged site status end super end
uninstall_data(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 49 def uninstall_data(name:) if self.index.include? name mapper = self.index[name][:mapper] # lib safe_unlink!(mapper.web.path) mapper.lib = mapper.lib mapper.lib.web.delete! mapper.lib.config.delete! mapper.lib.delete! # config mapper.delete! self.reindex_container(name: name) end {} end
uninstall_users(name:)
click to toggle source
# File lib/superhosting/controller/container/states.rb, line 116 def uninstall_users(name:) mapper = self.index[name][:mapper] user_controller = self.get_controller(User) if (user = user_controller._get(name: name)) mapper.lib.config.f('etc-group').remove_line!("#{name}:x:#{user.gid}:") end user_controller._group_del_users(name: name) user_controller._group_pretty_del(name: name) # docker PathMapper.new('/etc/security/docker.conf').remove_line!("@#{name} #{name}") {} end
update(name:)
click to toggle source
# File lib/superhosting/controller/container.rb, line 77 def update(name:) if (resp = self.existing_validation(name: name)).net_status_ok? and @docker_api.container_exists?(name) mapper = self.index[name][:mapper] image = mapper.lib.image.value self._recreate_docker(name: name) unless @docker_api.container_image?(name, image) end resp end