Finish create site feature.Add server manager.

This commit is contained in:
BoHung Chiu 2020-04-24 22:38:28 +08:00
parent f2860dee59
commit 3d8167d5e4
15 changed files with 491 additions and 13 deletions

View File

@ -7,18 +7,100 @@ class Admin::SitePanelController < OrbitAdminController
def index def index
@site_construct = SiteConstruct.new @site_construct = SiteConstruct.new
@module_app = ModuleApp.where(:title=>@app_title).first
end
def server_manager
@module_app = ModuleApp.where(:title=>@app_title).first
@categories = @module_app.categories
@tags = []
@filter_fields = filter_fields(@categories,@tags)
@site_servers = SiteServer.all.with_categories(filters("category")).with_status(filters("status"))
@site_servers = search_data(@site_servers,[:server_name,:ip]).page(params[:page].to_i).per(10)
if request.xhr?
render :partial => "server_manager_index"
end
end
def edit_server_info
@module_app = ModuleApp.where(:title=>@app_title).first
if params[:type] == 'update'
@site_server = SiteServer.find(params[:id]) rescue nil
if @site_server.present?
@site_server.update_attributes(site_server_params)
else
@site_server = SiteServer.create(site_server_params)
end
redirect_to admin_site_panel_server_manager_path
elsif params[:type] == 'create'
@site_server = SiteServer.new
elsif params[:type] == 'delete'
SiteServer.find(params[:id]).destroy
redirect_to admin_site_panel_server_manager_path
else
@site_server = SiteServer.find(params[:id])
end
end end
def create def create
site_construct = SiteConstruct.new(site_construct_params) site_construct = SiteConstruct.new(site_construct_params)
site_construct.user_id = current_user.id.to_s site_construct.user_id = current_user.id.to_s
site_construct.status = "creating"
site_construct.save site_construct.save
redirect_to admin_site_panel_path("msg" => "success") git_user = "chiu"
git_password = "orbit_is_great_1"
git_url = "http://gitlab.tp.rulingcom.com/orbit_chiu1/orbit4-5.git"
site_server = SiteServer.where(:server_name=>site_construct.server_type).first
ip = site_server.ip
user = site_server.account
password = site_server.password
site_name = site_construct.site_name
domain_name = site_construct.domain_name
port = site_construct.port
db_name = site_construct.db_name
path = site_construct.path
site_construct_id = site_construct.id.to_s
Thread.new do
system("rake create_site:create_site[#{git_user},#{git_password},#{git_url},#{ip},#{user},#{password},#{site_name},#{domain_name},#{port},#{db_name},#{path},#{site_construct_id}]")
end
redirect_to "#{admin_site_panel_sites_list_path}?id=#{site_construct_id}"
end
def create_site
site_construct = SiteConstruct.find(params[:id])
site_construct.user_id = current_user.id.to_s
git_user = "chiu"
git_password = "orbit_is_great_1"
git_url = "http://gitlab.tp.rulingcom.com/orbit_chiu1/orbit4-5.git"
site_server = SiteServer.where(:server_name=>site_construct.server_type).first
ip = site_server.ip
user = site_server.account
password = site_server.password
site_name = site_construct.site_name
domain_name = site_construct.domain_name
port = site_construct.port
db_name = site_construct.db_name
path = site_construct.path
site_construct_id = params[:id]
Thread.new do
puts site_construct_id
system("rake create_site:create_site['#{git_user}','#{git_password}','#{git_url}','#{ip}','#{user}','#{password}','#{site_name}','#{domain_name}','#{port}','#{db_name}','#{path}','#{site_construct_id}']")
end
render :json =>{"success"=>true}
end
def sites_list
@sites = SiteConstruct.all.desc(:id)
end
def site_infos
site_construct = SiteConstruct.where(:id=>params[:id]).first
if site_construct.nil?
render :json => {:status=>"creating",:infos=>[]}
else
render :json => {:status=>site_construct.status,:infos=>site_construct.infos}
end
end end
private private
def site_construct_params def site_construct_params
params.require(:site_construct).permit! params.require(:site_construct).permit!
end end
def site_server_params
params.require(:site_server).permit!
end
end end

View File

@ -2,18 +2,19 @@ class SiteConstruct
include Mongoid::Document include Mongoid::Document
include Mongoid::Timestamps include Mongoid::Timestamps
SERVER_TYPES = ["Pending","Store"] SERVER_TYPES = SiteServer.all.map{|s| s.server_name}
SITE_TYPES = ["School","Gravity"] SITE_TYPES = ["School","Gravity"]
field :server_type field :server_type
field :site_name field :site_name
field :domain_name field :domain_name
field :db_name field :db_name
field :port field :port, type: String, :default => "80"
field :path field :path
field :site_type field :site_type
field :school_name field :school_name
field :user_id field :user_id
field :constructed, type: Boolean, :default => false field :constructed, type: Boolean, :default => false
field :status, type: String, :default => ""
field :infos, type: Array, :default => []
end end

View File

@ -10,7 +10,7 @@ class SiteRequest
field :maintenance_years, type: Integer field :maintenance_years, type: Integer
field :optional_modules, type: Array, default: [] field :optional_modules, type: Array, default: []
field :custom_module, type: Boolean, default: false field :custom_module, type: Boolean, default: false
field :custom_module_details field :custom_module_details, type: String, default: ''
field :template_number field :template_number
field :custom_template, type: Boolean, default: false field :custom_template, type: Boolean, default: false
field :custom_template_details field :custom_template_details

13
app/models/site_server.rb Normal file
View File

@ -0,0 +1,13 @@
class SiteServer
include Mongoid::Document
include Mongoid::Timestamps
include OrbitCategory::Categorizable
include OrbitTag::Taggable
include OrbitModel::Status
field :server_name , type: String ,default: ''
field :domain_name , type: String ,default: ''
field :ip , type: String ,default: ''
field :account , type: String ,default: ''
field :password , type: String ,default: ''
field :active , type: Boolean ,default: true
end

View File

@ -87,6 +87,11 @@
</div> </div>
</fieldset> </fieldset>
<script type="text/javascript"> <script type="text/javascript">
var domain_name_relations = {};
<% SiteServer.all.each do |server_server| %>
domain_name_relations['<%= server_server.server_name %>'] = '<%= server_server.domain_name %>';
<% end %>
console.log(domain_name_relations);
$("#school_name").on("blur",function(){ $("#school_name").on("blur",function(){
var school = $(this).val().toLowerCase(); var school = $(this).val().toLowerCase();
if($("#site_name").val() == ""){ if($("#site_name").val() == ""){
@ -109,11 +114,17 @@
$("#path").val("/home/rulingcom/" + type); $("#path").val("/home/rulingcom/" + type);
} }
}) })
$('#site_construct_server_type').click(function(){
var domain_name = domain_name_relations[$(this).val()];
$('#domain_name').siblings('.hint').html('schoolname-deptname.'+domain_name+' eg: nctu-eed.'+domain_name);
})
$("#site_name").on("blur",function(){ $("#site_name").on("blur",function(){
var val = $(this).val(), var val = $(this).val(),
type = $("#site_construct_site_type").val(), type = $("#site_construct_site_type").val(),
school = $("#school_name").val(); school = $("#school_name").val(),
$("#domain_name").val(val.replace("_","-") + ".pending.rulingcom.com"); domain_name = domain_name_relations[$('#site_construct_server_type').val()];
$('#domain_name').siblings('.hint').html('schoolname-deptname.'+domain_name+' eg: nctu-eed.'+domain_name);
$("#domain_name").val(val.replace("_","-") + "."+domain_name);
$("#db_name").val(val); $("#db_name").val(val);
type = (type == "School" ? "school_sites" : "orbit_sites" ); type = (type == "School" ? "school_sites" : "orbit_sites" );
if(school != ""){ if(school != ""){

View File

@ -0,0 +1,25 @@
<table class="table main-list default footable-loaded">
<thead>
<tr>
<th>Server name</th>
<th>IP</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<% @site_servers.each do |site_server|%>
<tr>
<td><%=site_server.server_name%></td>
<td><%=site_server.ip%></td>
<td>
<a class="btn btn-primary" href = "<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}" %>"><%=t(:edit)%></a>
<a class="btn btn-primary" href = "#" onclick="if(window.confirm('Do you really want to delete <%=site_server.server_name%>?')) { window.location.href = '<%= admin_site_panel_edit_server_info_path+"?id=#{site_server.id.to_s}&type=delete" %>';}"><%=t(:remove)%></a>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="bottomnav clearfix">
<div class="pagination pagination-centered"><%=paginate(@site_servers)%></div>
<a class="btn btn-primary pull-right" href="<%=admin_site_panel_edit_server_info_path+"?type=create"%>"><%=t(:add)%></a>
</div>

View File

@ -0,0 +1,74 @@
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<% end %>
<%= form_for @site_server ,:url=>{:action=>"edit_server_info",:type=>'update'},:method=>:post, :html => {:class=>"form-horizontal main-forms"} do |f|%>
<fieldset>
<input type='hidden' name='id' value='<%=@site_server.id.to_s%>'/>
<!-- Input Area -->
<div class="input-area">
<!-- Module Tabs -->
<div class="nav-name"><strong><%= t(:module) %></strong></div>
<ul class="nav nav-pills module-nav">
<li class="active">
<a href="#basic" data-toggle="tab"><%= t(:basic) %></a>
</li>
</ul>
<!-- Module -->
<div class="tab-content module-area">
<!-- Basic Module -->
<div class="tab-pane fade in active" id="basic">
<!-- Category -->
<div class="control-group">
<label class="control-label muted"><%= t(:category) %></label>
<div class="controls">
<%= select_category(f, @module_app) %>
</div>
</div>
<!-- Tag Module -->
<div class="control-group">
<label class="control-label muted"><%= t(:tags) %></label>
<%= select_tags(f, @module_app) %>
</div>
<div class="control-group">
<label class="control-label muted" for="server_name">Server name:</label>
<div class="controls">
<% if @site_server.new_record? %>
<%= f.text_field :server_name,{:id=>'server_name'} %>
<% else %>
<span style=" display: inline-block; vertical-align: -webkit-baseline-middle; font-size: 1.5em;"><%= @site_server.server_name %></span>
<% f.hidden_field :server_name,{:id=>'server_name'} %>
<% end%>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="domain_name">Domain name:</label>
<div class="controls">
<%= f.text_field :domain_name,{:id=>'domain_name'} %>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="ip">IP:</label>
<div class="controls">
<%= f.text_field :ip,{:id=>'ip'} %>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="account">Account:</label>
<div class="controls">
<%= f.text_field :account,{:id=>'account'} %>
</div>
</div>
<div class="control-group">
<label class="control-label muted" for="password">Password:</label>
<div class="controls">
<%= f.text_field :password,{:id=>'password'} %>
</div>
</div>
</div>
</div>
</div>
<div class="form-actions">
<%= f.submit t('submit'), class: 'btn btn-primary' %>
</div>
</fieldset>
<% end %>

View File

@ -0,0 +1,12 @@
<% content_for :page_specific_javascript do %>
<%= javascript_include_tag "lib/module-area" %>
<% end %>
<% content_for :page_specific_css do %>
<%= stylesheet_link_tag "lib/main-forms" %>
<%= stylesheet_link_tag "lib/main-list" %>
<%= stylesheet_link_tag "lib/pageslide" %>
<% end %>
<%= render_filter @filter_fields, "index_table" %>
<span id="index_table">
<%= render :partial => "server_manager_index" %>
</span>

View File

@ -0,0 +1,133 @@
<% if !params[:id].blank? %>
<div id='dialog-confirm' title='site infos'>
<div style='clear:both;'></div>
<div id='info_texts'></div>
</div>
<% end %>
<table class="table main-list default footable-loaded">
<thead>
<tr>
<th>Server name</th>
<th>Domain name</th>
<th>Port</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<% status_relation = {"creating"=>"<span style=\"color: skyblue;\">creating</span>".html_safe,"error"=>"<span style=\"color: red;\">error</span>".html_safe,"finish"=>"<span style=\"color: darkseagreen;\">finish</span>".html_safe}%>
<% @sites.each do |site|%>
<tr>
<td><%=site.server_type%></td>
<td><a href="http://<%=site.domain_name%>" title="open http://<%=site.domain_name%> to new window" target="_blank"><%=site.domain_name%></a></td>
<td><%=site.port%></td>
<td class="site_status"><%= (site.status.blank? ? "not yet create" : status_relation[site.status]) %></td>
<td>
<a href="#" title="see infos for <%=site.domain_name%>" class="btn btn-primary see_infos" data-id="<%=site.id.to_s%>">See infos</a>
<% if site.status.blank? %>
<a href="#" title="create <%=site.domain_name%>" class="btn btn-primary create_site" data-id="<%=site.id.to_s%>">Create site</a>
<% elsif site.status == "error" || site.status == "finish" %>
<a href="#" title="recreate <%=site.domain_name%>" class="btn btn-primary create_site" data-id="<%=site.id.to_s%>">Recreate site</a>
<% end%>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="bottomnav clearfix">
<a class="btn btn-primary pull-right" href="<%=admin_site_panel_path%>" title="Create new web"><%=t(:add)%></a>
</div>
<script type="text/javascript">
$(document).ready(function(){
var close_info = false;
var timeout_id;
var status_relation = {"creating":"<span style=\"color: skyblue;\">creating</span>","error":"<span style=\"color: red;\">error</span>","finish": "<span style=\"color: darkseagreen;\">finish</span>"};
function see_infos(id){
if(!close_info){
var request = $.post("<%=admin_site_panel_site_infos_path%>",{"id":id});
request.done(function(data){
var infos = request.responseJSON.infos;
var status = request.responseJSON.status;
if($("#info_texts").length == 0)
return infos.join("<br>")
else{
$("#info_texts").html(infos.join("<br>"));
if(status == "")
var status_text = "not yet create";
else
var status_text = status_relation[status];
$(".see_infos[data-id="+id+"]").parent().siblings(".site_status").html(status_text);
if(status == "creating" || status == "error" ){
console.log(request.responseJSON);
timeout_id = window.setTimeout(see_infos(id),1000);
}else{
close_info = true;
window.clearTimeout(timeout_id);
console.log(request.responseJSON);
}
}
})
}else{
window.clearTimeout(timeout_id);
}
};
$('.see_infos').click(function(){
close_info = true;
window.clearTimeout(timeout_id);
close_info = false;
var id = $(this).attr("data-id");
if($("#dialog-confirm").length == 0){
$("#main-wrap").before("<div id='dialog-confirm' title='site infos'>"+
"<div style='clear:both;'></div><div id='info_texts'>"+see_infos(id)+"</div>"+
"</div>");
}else{
see_infos(id);
};
$( "#dialog-confirm" ).dialog({
resizable: true,
minHeight: 100,
maxHeight: 400,
modal: true,
buttons: {
"<%= t('client_management.confirm') %>": function(){$( this ).dialog( "close" );close_info = true;}
}
});
});
$('.create_site').click(function(){
close_info = true;
window.clearTimeout(timeout_id);
close_info = false;
var id = $(this).attr("data-id");
$.post("<%= admin_site_panel_create_site_path %>",{'id': id}).done(function(){
if($("#dialog-confirm").length == 0){
$("#main-wrap").before("<div id='dialog-confirm' title='site infos'>"+
"<div style='clear:both;'></div><div id='info_texts'>"+see_infos(id)+"</div>"+
"</div>");
}else{
see_infos(id);
};
$( "#dialog-confirm" ).dialog({
resizable: true,
minHeight: 100,
maxHeight: 400,
modal: true,
buttons: {
"<%= t('client_management.confirm') %>": function(){$( this ).dialog( "close" );close_info = true;}
}
});
})
});
<% if !params[:id].blank? %>
see_infos("<%=params[:id]%>");
$( "#dialog-confirm" ).dialog({
resizable: true,
minHeight: 100,
maxHeight: 400,
modal: true,
buttons: {
"<%= t('client_management.confirm') %>": function(){$( this ).dialog( "close" );close_info = true;}
}
});
<% end %>
})
</script>

View File

@ -13,7 +13,7 @@ Gem::Specification.new do |s|
s.summary = "ClientManagement tool for store." s.summary = "ClientManagement tool for store."
s.description = "ClientManagement tool for store." s.description = "ClientManagement tool for store."
s.license = "MIT" s.license = "MIT"
s.add_dependency "net-ssh"
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]
s.test_files = Dir["test/**/*"] s.test_files = Dir["test/**/*"]
end end

View File

@ -54,3 +54,6 @@ en:
receipt_status: Receipt Status receipt_status: Receipt Status
loading_purchases: Loading Purchases loading_purchases: Loading Purchases
create_site: Create Site create_site: Create Site
sites_list: Site list
server_manager: Server Manager
confirm: Confirm

View File

@ -54,3 +54,6 @@ zh_tw:
receipt_status: Receipt Status receipt_status: Receipt Status
loading_purchases: Loading Purchases loading_purchases: Loading Purchases
create_site: Create Site create_site: Create Site
sites_list: Site list
server_manager: Server Manager
confirm: Confirm

View File

@ -36,8 +36,14 @@ Rails.application.routes.draw do
get "contracts" get "contracts"
end end
end end
get "site_panel/site_infos" => "site_panel#site_infos"
post "site_panel/site_infos" => "site_panel#site_infos"
post "site_panel/create_site" => "site_panel#create_site"
get "site_panel" => "site_panel#index" get "site_panel" => "site_panel#index"
get "site_panel/sites_list" => "site_panel#sites_list"
get "site_panel/server_manager" => "site_panel#server_manager"
get "site_panel/edit_server_info" => "site_panel#edit_server_info"
post "site_panel/edit_server_info" => "site_panel#edit_server_info"
resources :site_panel resources :site_panel
end end

View File

@ -6,6 +6,7 @@ module ClientManagement
base_url File.expand_path File.dirname(__FILE__) base_url File.expand_path File.dirname(__FILE__)
categorizable categorizable
authorizable authorizable
taggable "SiteServer"
# frontend_enabled # frontend_enabled
# data_count 1..30 # data_count 1..30
set_keyword_contstraints ["/cpanel/"] set_keyword_contstraints ["/cpanel/"]
@ -39,6 +40,17 @@ module ClientManagement
:active_for_action=>{'admin/site_panel'=>"index"}, :active_for_action=>{'admin/site_panel'=>"index"},
:available_for => 'users' :available_for => 'users'
context_link 'client_management.sites_list',
:link_path=>"admin_site_panel_sites_list_path" ,
:priority=>1,
:active_for_action=>{'admin/site_panel'=>"sites_list"},
:available_for => 'users'
context_link 'client_management.server_manager',
:link_path=>"admin_site_panel_server_manager_path" ,
:priority=>1,
:active_for_action=>{'admin/site_panel'=>"server_manager"},
:available_for => 'users'
end end
end end
end end

103
lib/tasks/create_site.rake Normal file
View File

@ -0,0 +1,103 @@
require 'net/ssh'
require 'pathname'
namespace :create_site do
desc "Create Site Script"
task :create_site,[:git_user,:git_password,:git_url,:ip,:user,:password,:site_name,:domain_name,:port,:db_name,:path,:site_construct_id] => :environment do |task,args|
@password = args.password
puts args
if args.site_construct_id.blank?
@site_construct = SiteConstruct.new
@site_construct.server_type = (SiteServer.where(:ip=>args.ip).first.server_name rescue args.ip)
@site_construct.site_name = args.site_name
@site_construct.domain_name = args.domain_name
@site_construct.db_name = args.db_name
@site_construct.port = args.port
@site_construct.path = args.path
@site_construct.school_name = args.site_name.split(/[-_]/)
@site_construct.user_id = User.first.id.to_s
@site_construct.save
else
@site_construct = SiteConstruct.find(args.site_construct_id)
end
begin
@site_construct.update(:status=>"creating")
Net::SSH.start(args.ip , args.user , password: args.password) do |ssh|
update_infos("setting nginx for #{args.site_name}")
nginx_setting_texts = ('upstream '+args.site_name+'_sock {\n'+
' server unix:'+args.path+'/'+args.site_name+'/tmp/unicorn.sock;\n'+
'}\n'+
'server {\n'+
' listen '+args.port+';\n\n'+
' root '+args.path+'/'+args.site_name+'/public;\n\n'+
'server_name '+args.domain_name+';\n\n'+
' client_max_body_size 500m;\n\n'+
' location / {\n'+
' try_files \$uri \$uri/index.html \$uri.html @app;\n'+
' }\n\n'+
' location @app {\n'+
' proxy_redirect off;\n'+
' proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;\n'+
' proxy_set_header Host \$http_host;\n'+
' proxy_connect_timeout 360;\n'+
'proxy_pass http://'+args.site_name+'_sock;\n'+
' }\n'+
'}')
exec_ssh_command_by_sudo(ssh,"touch /etc/nginx/orbit_sites/#{args.site_name}")
exec_ssh_command_by_sudo(ssh,"sh -c \"echo '#{nginx_setting_texts}' > /etc/nginx/orbit_sites/#{args.site_name}\"")
update_infos("restarting nginx")
exec_ssh_command_by_sudo(ssh,"service nginx restart")
update_infos("finish restarting nginx")
dir = Pathname.new(args.path)
while dir.to_s != '/' do
exec_ssh_command_by_sudo(ssh,"mkdir #{dir}")
dir = dir.dirname
end
update_infos("cloning orbit4-5 from #{args.git_url} to #{args.path}/#{args.site_name}")
exec_ssh_command_by_sudo(ssh,"git clone #{args.git_url.gsub("http://","http://#{args.git_user+':'+args.git_password+'@'}").gsub("https://","https://#{args.git_user+':'+args.git_password+'@'}")} #{args.path}/#{args.site_name}")
exec_ssh_command_by_sudo(ssh,"chown #{args.user}:#{args.user} -R #{args.path}/#{args.site_name}")
exec_ssh_command_by_sudo(ssh,"chmod 777 #{args.path}/#{args.site_name} -R")
db_setting_text = ssh.exec!("cat #{args.path}/#{args.site_name}/config/mongoid.yml")
update_infos("setting dbname to #{args.db_name}")
exec_ssh_command_by_sudo(ssh,"echo '#{db_setting_text.gsub("orbit_4_5",args.db_name)}' > #{args.path}/#{args.site_name}/config/mongoid.yml")
gemdir = ssh.exec!("/home/rulingcom/.rvm/bin/rvm gemdir").to_s
if gemdir.include?("No such file or directory")
ls = ssh.exec!("echo `ls /home`").to_s.split
ls.each do |d|
gemdir = ssh.exec!("/home/#{d}/.rvm/bin/rvm gemdir").to_s
break if !gemdir.to_s.include?("No such file or directory")
end
end
if gemdir.include?("No such file or directory")
update_infos("please connect your admin to install rvm on #{args.ip}")
@site_construct.update(:status =>"error")
else
bundle_dir = gemdir.gsub("\n","") + '/bin/bundle'
update_infos("execing bundle install...")
exec_ssh_command_by_sudo(ssh,"bash -l -c 'cd #{args.path}/#{args.site_name}\n#{bundle_dir} install'")
exec_ssh_command_by_sudo(ssh,"bash -l -c 'cd #{args.path}/#{args.site_name}\n#{bundle_dir} install'")
update_infos("finish execing bundle install")
update_infos("starting #{args.site_name} web server to development")
exec_ssh_command_by_sudo(ssh,"bash -l -c 'cd #{args.path}/#{args.site_name}\n#{bundle_dir} exec unicorn_rails -c config/unicorn.rb -D -E development\n'")
update_infos("finish creating #{args.site_name}")
@site_construct.update(:status =>"finish")
puts "finish creating #{args.site_name} on #{args.ip}"
end
end
rescue =>e
@site_construct.update(:status =>"error",:infos=>@site_construct.infos.push("#{e}"))
end
end
def exec_ssh_command_by_sudo(session,command)
output = session.exec!("echo '#{@password}' | sudo -S #{command}")
# output = session.exec!("echo '#{@password}' | sudo -S -s #{command}")
if output.include?("sudo:") && output.include?("command not found")
output = session.exec!(command)
end
return output
end
def update_infos(info)
@site_construct.infos = @site_construct.infos.push(info)
@site_construct.save!
return @site_construct.infos
end
end