smartmachine 0.8.0 → 1.0.0
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.
- checksums.yaml +4 -4
- data/LICENSE.txt +661 -0
- data/README.md +147 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/smartmachine +3 -0
- data/lib/smart_machine/apps/app.rb +165 -181
- data/lib/smart_machine/apps/container.rb +120 -0
- data/lib/smart_machine/apps/manager.rb +182 -0
- data/lib/smart_machine/base.rb +24 -6
- data/lib/smart_machine/buildpackers/buildpacker.rb +95 -0
- data/lib/smart_machine/{engine/buildpacks → buildpackers}/rails/Dockerfile +3 -3
- data/lib/smart_machine/buildpackers/rails.rb +221 -0
- data/lib/smart_machine/commands/app.rb +112 -0
- data/lib/smart_machine/commands/buildpacker.rb +53 -0
- data/lib/smart_machine/commands/credentials.rb +17 -0
- data/lib/smart_machine/commands/docker.rb +23 -0
- data/lib/smart_machine/commands/engine.rb +27 -0
- data/lib/smart_machine/commands/grid.rb +33 -0
- data/lib/smart_machine/commands/grid_commands/elasticsearch.rb +68 -0
- data/lib/smart_machine/commands/grid_commands/minio.rb +65 -0
- data/lib/smart_machine/commands/grid_commands/mysql.rb +71 -0
- data/lib/smart_machine/commands/grid_commands/nginx.rb +53 -0
- data/lib/smart_machine/commands/grid_commands/prereceiver.rb +96 -0
- data/lib/smart_machine/commands/grid_commands/redis.rb +65 -0
- data/lib/smart_machine/commands/grid_commands/scheduler.rb +15 -0
- data/lib/smart_machine/commands/grid_commands/sub_thor.rb +15 -0
- data/lib/smart_machine/commands/machine.rb +24 -0
- data/lib/smart_machine/commands/syncer.rb +23 -0
- data/lib/smart_machine/commands/utilities.rb +37 -0
- data/lib/smart_machine/commands.rb +66 -0
- data/lib/smart_machine/configuration.rb +79 -0
- data/lib/smart_machine/credentials.rb +93 -95
- data/lib/smart_machine/docker.rb +144 -143
- data/lib/smart_machine/engine/Dockerfile +7 -5
- data/lib/smart_machine/engine.rb +104 -79
- data/lib/smart_machine/grids/elasticsearch.rb +70 -89
- data/lib/smart_machine/grids/minio.rb +79 -68
- data/lib/smart_machine/grids/mysql.rb +207 -202
- data/lib/smart_machine/grids/nginx.rb +176 -135
- data/lib/smart_machine/grids/prereceiver/Dockerfile +2 -2
- data/lib/smart_machine/grids/prereceiver/pre-receive +17 -0
- data/lib/smart_machine/grids/prereceiver.rb +169 -169
- data/lib/smart_machine/grids/redis.rb +75 -57
- data/lib/smart_machine/grids/scheduler/Dockerfile +1 -1
- data/lib/smart_machine/logger.rb +26 -26
- data/lib/smart_machine/machine.rb +128 -194
- data/lib/smart_machine/scp.rb +15 -0
- data/lib/smart_machine/ssh.rb +69 -40
- data/lib/smart_machine/syncer.rb +133 -0
- data/lib/smart_machine/templates/dotsmartmachine/Gemfile +7 -0
- data/lib/smart_machine/templates/dotsmartmachine/config/elasticsearch.yml +5 -0
- data/lib/smart_machine/templates/dotsmartmachine/config/environment.rb +0 -9
- data/lib/smart_machine/templates/dotsmartmachine/config/minio.yml +13 -0
- data/lib/smart_machine/templates/dotsmartmachine/config/mysql/schedule.rb +3 -3
- data/lib/smart_machine/templates/dotsmartmachine/config/mysql.yml +13 -0
- data/lib/smart_machine/templates/dotsmartmachine/config/prereceiver.yml +7 -0
- data/lib/smart_machine/templates/dotsmartmachine/config/redis.yml +15 -0
- data/lib/smart_machine/templates/dotsmartmachine/config/users.yml +1 -1
- data/lib/smart_machine/templates/dotsmartmachine/gitignore-template +47 -0
- data/lib/smart_machine/templates/dotsmartmachine/{grids/elasticsearch/data → vendor}/.keep +0 -0
- data/lib/smart_machine/version.rb +30 -6
- data/lib/smart_machine.rb +42 -16
- metadata +97 -47
- data/CHANGELOG.rdoc +0 -0
- data/MIT-LICENSE +0 -21
- data/README.rdoc +0 -87
- data/bin/buildpacker +0 -8
- data/bin/prereceiver +0 -8
- data/bin/scheduler +0 -18
- data/bin/smartmachine +0 -81
- data/bin/smartrunner +0 -33
- data/lib/smart_machine/apps/rails.rb +0 -250
- data/lib/smart_machine/apps.rb +0 -14
- data/lib/smart_machine/boot.rb +0 -32
- data/lib/smart_machine/buildpacker.rb +0 -106
- data/lib/smart_machine/gem_version.rb +0 -17
- data/lib/smart_machine/grids.rb +0 -18
- data/lib/smart_machine/sync.rb +0 -120
- data/lib/smart_machine/templates/dotsmartmachine/grids/elasticsearch/logs/.keep +0 -0
- data/lib/smart_machine/templates/dotsmartmachine/grids/minio/data/.keep +0 -0
- data/lib/smart_machine/templates/dotsmartmachine/grids/mysql/backups/.keep +0 -0
- data/lib/smart_machine/templates/dotsmartmachine/grids/mysql/data/.keep +0 -0
- data/lib/smart_machine/templates/dotsmartmachine/grids/prereceiver/pre-receive +0 -17
- data/lib/smart_machine/templates/dotsmartmachine/grids/redis/data/.keep +0 -0
- data/lib/smart_machine/user.rb +0 -38
@@ -0,0 +1,182 @@
|
|
1
|
+
module SmartMachine
|
2
|
+
module Apps
|
3
|
+
class Manager < SmartMachine::Base
|
4
|
+
attr_accessor :appname, :appversion
|
5
|
+
|
6
|
+
def initialize(appname:, appversion: nil)
|
7
|
+
@appname = appname
|
8
|
+
@appversion = appversion
|
9
|
+
|
10
|
+
@home_dir = File.expand_path('~')
|
11
|
+
@container_path = "#{@home_dir}/machine/apps/containers/#{@appname}"
|
12
|
+
|
13
|
+
# Checking if given appname exists
|
14
|
+
repository_path = "#{@home_dir}/machine/apps/repositories/#{@appname}.git"
|
15
|
+
raise "App with name '#{@appname}' does not exist. Please provide a valid appname." unless Dir.exist?(repository_path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def deploy
|
19
|
+
logger.formatter = proc do |severity, datetime, progname, message|
|
20
|
+
severity_text = { "DEBUG" => "\u{1f527} #{severity}:", "INFO" => " \u{276f}", "WARN" => "\u{2757} #{severity}:",
|
21
|
+
"ERROR" => "\u{274c} #{severity}:", "FATAL" => "\u{2b55} #{severity}:", "UNKNOWN" => "\u{2753} #{severity}:"
|
22
|
+
}
|
23
|
+
"\t\t\t\t#{severity_text[severity]} #{message}\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
Dir.chdir("#{@container_path}/releases") do
|
27
|
+
# Setting app version to latest if not set.
|
28
|
+
unless @appversion
|
29
|
+
versions = Dir.glob('*').select { |f| File.directory? f }.sort
|
30
|
+
@appversion = versions.last
|
31
|
+
end
|
32
|
+
|
33
|
+
buildpacker = SmartMachine::Buildpackers::Rails.new(appname: @appname, appversion: @appversion)
|
34
|
+
if buildpacker.package
|
35
|
+
if release
|
36
|
+
sleep 7
|
37
|
+
clean
|
38
|
+
logger.info "Launched Application ... Success."
|
39
|
+
exit 10
|
40
|
+
else
|
41
|
+
raise "Error: Could not release the application."
|
42
|
+
end
|
43
|
+
else
|
44
|
+
raise "Error: Could not package the application."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
logger.formatter = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def ps_scaler(formation:)
|
52
|
+
Dir.chdir("#{@container_path}/releases") do
|
53
|
+
# Setting app version to latest if not set.
|
54
|
+
unless @appversion
|
55
|
+
versions = Dir.glob('*').select { |f| File.directory? f }.sort
|
56
|
+
@appversion = versions.last
|
57
|
+
end
|
58
|
+
|
59
|
+
formation.each do |proc_name, final_count|
|
60
|
+
config = processes.dig(proc_name.to_sym)
|
61
|
+
raise "no config found for the #{proc_name} process." unless config.present?
|
62
|
+
|
63
|
+
current_count = `docker ps -aq --filter name="#{@appname}-#{@appversion}-#{proc_name}-" | wc -l`
|
64
|
+
|
65
|
+
final_count = final_count.to_i
|
66
|
+
current_count = current_count.to_i
|
67
|
+
|
68
|
+
if final_count > current_count
|
69
|
+
((current_count + 1)..final_count).each do |index|
|
70
|
+
containerize_process!(name: "#{@appname}-#{@appversion}-#{proc_name}-#{index}", config: config)
|
71
|
+
end
|
72
|
+
elsif final_count < current_count
|
73
|
+
((final_count + 1)..current_count).each do |index|
|
74
|
+
container = SmartMachine::Apps::Container.new(name: "#{@appname}-#{@appversion}-#{proc_name}-#{index}", appname: @appname, appversion: @appversion)
|
75
|
+
container.stop!
|
76
|
+
end
|
77
|
+
else
|
78
|
+
# No Operation. Don't do anything.
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def env_vars
|
85
|
+
@env_vars ||= load_env_vars
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def release
|
91
|
+
logger.info "Releasing Application ..."
|
92
|
+
|
93
|
+
if processes.present?
|
94
|
+
processes.each do |name, config|
|
95
|
+
containerize_process!(name: "#{@appname}-#{@appversion}-#{name}-1", config: config)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
logger.fatal "No smartmachine.yml file found. Proceeding with default settings."
|
99
|
+
return false
|
100
|
+
|
101
|
+
# Use the below code when you want to provide a default when smartmachine.yml is not present.
|
102
|
+
# containerize_process!(name: "#{@appname}-#{@appversion}-web-1", config: { command: "bundle exec puma --config config/puma.rb", networks: "nginx-network" })
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def containerize_process!(name:, config:)
|
107
|
+
container = SmartMachine::Apps::Container.new(name: name, appname: @appname, appversion: @appversion)
|
108
|
+
if container.create!(using_command: config.dig(:command))
|
109
|
+
networks = config.dig(:networks)&.split(" ")
|
110
|
+
networks.each do |network|
|
111
|
+
container.connect_to_network!(network_name: network)
|
112
|
+
end
|
113
|
+
|
114
|
+
unless container.start!
|
115
|
+
container.stop!
|
116
|
+
end
|
117
|
+
else
|
118
|
+
container.stop!
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def clean
|
123
|
+
return unless env_vars.present?
|
124
|
+
|
125
|
+
logger.info "Cleaning up ..."
|
126
|
+
|
127
|
+
# Clean up very old versions
|
128
|
+
Dir.chdir("#{@container_path}/releases") do
|
129
|
+
versions = Dir.glob('*').select { |f| File.directory? f }.sort
|
130
|
+
destroy_count = versions.count - env_vars['KEEP_RELEASES'].to_i
|
131
|
+
if destroy_count > 0
|
132
|
+
logger.debug "Deleting older application releases ..."
|
133
|
+
destroy_count.times do
|
134
|
+
version = versions.shift
|
135
|
+
FileUtils.rm_r(File.join(Dir.pwd, version))
|
136
|
+
|
137
|
+
# Remove corresponding docker containers & images, if they exist.
|
138
|
+
system("docker ps -aq --filter ancestor=smartmachine/apps/#{@appname}:#{version} | xargs --no-run-if-empty docker stop | xargs --no-run-if-empty docker rm", out: File::NULL)
|
139
|
+
system("docker image ls -aq --filter reference=smartmachine/apps/#{@appname}:#{version} | xargs --no-run-if-empty docker image rm", out: File::NULL)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
versions = Dir.glob('*').select { |f| File.directory? f }.sort
|
144
|
+
versions_count = versions.count
|
145
|
+
if versions_count > 0
|
146
|
+
versions_count.times do
|
147
|
+
version = versions.shift
|
148
|
+
unless version == @appversion
|
149
|
+
system("docker ps -aq --filter ancestor=smartmachine/apps/#{@appname}:#{version} | xargs --no-run-if-empty docker stop", out: File::NULL)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def load_env_vars
|
157
|
+
unless File.exist? "#{@container_path}/env"
|
158
|
+
logger.fatal "Environment could not be loaded ... Failed."
|
159
|
+
return false
|
160
|
+
end
|
161
|
+
|
162
|
+
env_vars = {}
|
163
|
+
File.open("#{@container_path}/env").each_line do |line|
|
164
|
+
line.chomp!
|
165
|
+
next if line.empty? || line.start_with?('#')
|
166
|
+
key, value = line.split "="
|
167
|
+
env_vars[key] = value
|
168
|
+
end
|
169
|
+
|
170
|
+
env_vars
|
171
|
+
end
|
172
|
+
|
173
|
+
def processes
|
174
|
+
@processes ||= deserialize(IO.binread("#{@appversion}/smartmachine.yml")).deep_symbolize_keys
|
175
|
+
end
|
176
|
+
|
177
|
+
def deserialize(config)
|
178
|
+
YAML.load(ERB.new(config).result).presence || {}
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
data/lib/smart_machine/base.rb
CHANGED
@@ -2,10 +2,28 @@ require 'smart_machine/logger'
|
|
2
2
|
require "active_support/inflector"
|
3
3
|
|
4
4
|
module SmartMachine
|
5
|
-
|
6
|
-
|
5
|
+
class Base
|
6
|
+
include SmartMachine::Logger
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def initialize
|
9
|
+
end
|
10
|
+
|
11
|
+
def platform_on_machine?(os:, distro_name: nil)
|
12
|
+
case os
|
13
|
+
when "linux"
|
14
|
+
command = "(uname | grep -q 'Linux')"
|
15
|
+
command += " && (cat /etc/os-release | grep -q 'NAME=\"Debian GNU/Linux\"')" if distro_name == "debian"
|
16
|
+
when "mac"
|
17
|
+
command = "(uname | grep -q 'Darwin')"
|
18
|
+
end
|
19
|
+
|
20
|
+
machine = SmartMachine::Machine.new
|
21
|
+
command ? machine.run_on_machine(commands: command) : false
|
22
|
+
end
|
23
|
+
|
24
|
+
def machine_has_engine_installed?
|
25
|
+
machine = SmartMachine::Machine.new
|
26
|
+
machine.run_on_machine(commands: ["which smartengine | grep -q '/smartengine'"])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module SmartMachine
|
2
|
+
module Buildpackers
|
3
|
+
class Buildpacker < SmartMachine::Base
|
4
|
+
def initialize(packname:)
|
5
|
+
@packname = packname
|
6
|
+
end
|
7
|
+
|
8
|
+
def installer
|
9
|
+
if @packname == "rails"
|
10
|
+
unless system("docker image inspect #{rails_image_name}", [:out, :err] => File::NULL)
|
11
|
+
print "-----> Creating image #{rails_image_name} ... "
|
12
|
+
command = [
|
13
|
+
"docker image build -t #{rails_image_name}",
|
14
|
+
"--build-arg SMARTMACHINE_VERSION=#{SmartMachine.version}",
|
15
|
+
"--build-arg USER_UID=`id -u`",
|
16
|
+
"--build-arg USER_NAME=`id -un`",
|
17
|
+
"#{SmartMachine.config.gem_dir}/lib/smart_machine/buildpackers/rails"
|
18
|
+
]
|
19
|
+
if system(command.join(" "), out: File::NULL)
|
20
|
+
puts "done"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
raise "Error: Pack with name #{name} not supported."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def uninstaller
|
29
|
+
if @packname == "rails"
|
30
|
+
if system("docker image inspect #{rails_image_name}", [:out, :err] => File::NULL)
|
31
|
+
print "-----> Removing image #{rails_image_name} ... "
|
32
|
+
if system("docker image rm #{rails_image_name}", out: File::NULL)
|
33
|
+
puts "done"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raise "Error: Pack with name #{name} not supported."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def packer
|
42
|
+
if @packname == "rails" && File.exist?("bin/rails")
|
43
|
+
rails = SmartMachine::Buildpackers::Rails.new(appname: nil, appversion: nil)
|
44
|
+
rails.packer
|
45
|
+
else
|
46
|
+
raise "Error: Pack with name #{@packname} not supported."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def rails_image_name
|
53
|
+
"smartmachine/buildpackers/rails:#{SmartMachine.version}"
|
54
|
+
end
|
55
|
+
|
56
|
+
# These swapfile methods can be used (after required modification), when you need to make swapfile for more memory.
|
57
|
+
# def self.create_swapfile
|
58
|
+
# # Creating swapfile for bundler to work properly
|
59
|
+
# unless system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
|
60
|
+
# print "-----> Creating swap swapfile ... "
|
61
|
+
# system("sudo install -o root -g root -m 0600 /dev/null /swapfile", out: File::NULL)
|
62
|
+
# system("sudo dd if=/dev/zero of=/swapfile bs=1k count=2048k", [:out, :err] => File::NULL)
|
63
|
+
# system("sudo mkswap /swapfile", out: File::NULL)
|
64
|
+
# system("sudo sh -c 'echo \"/swapfile none swap sw 0 0\" >> /etc/fstab'", out: File::NULL)
|
65
|
+
# system("echo 10 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
|
66
|
+
# system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
|
67
|
+
# system("echo vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf", out: File::NULL)
|
68
|
+
# puts "done"
|
69
|
+
#
|
70
|
+
# print "-----> Starting swap swapfile ... "
|
71
|
+
# if system("sudo swapon /swapfile", out: File::NULL)
|
72
|
+
# puts "done"
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# def self.destroy_swapfile
|
78
|
+
# if system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
|
79
|
+
# print "-----> Stopping swap swapfile ... "
|
80
|
+
# if system("sudo swapoff /swapfile", out: File::NULL)
|
81
|
+
# system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
|
82
|
+
# system("echo 60 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
|
83
|
+
# puts "done"
|
84
|
+
#
|
85
|
+
# print "-----> Removing swap swapfile ... "
|
86
|
+
# system("sudo sed -i '/^\\/swapfile/d' /etc/fstab", out: File::NULL)
|
87
|
+
# if system("sudo rm /swapfile", out: File::NULL)
|
88
|
+
# puts "done"
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
ARG SMARTMACHINE_VERSION
|
2
2
|
|
3
|
-
FROM smartmachine:$SMARTMACHINE_VERSION
|
4
|
-
LABEL maintainer="
|
3
|
+
FROM smartmachine/smartengine:$SMARTMACHINE_VERSION
|
4
|
+
LABEL maintainer="plainsource <plainsource@humanmind.me>"
|
5
5
|
|
6
6
|
# Ruby on Rails Essentials
|
7
7
|
RUN apk add --update build-base && \
|
@@ -18,4 +18,4 @@ RUN apk add --update build-base && \
|
|
18
18
|
# Gems
|
19
19
|
RUN gem install bundler -v 2.1.4
|
20
20
|
|
21
|
-
CMD ["buildpacker", "
|
21
|
+
CMD ["smartmachine", "buildpacker", "packer", "rails"]
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module SmartMachine
|
4
|
+
module Buildpackers
|
5
|
+
class Rails < SmartMachine::Base
|
6
|
+
def initialize(appname:, appversion:)
|
7
|
+
@home_dir = File.expand_path('~')
|
8
|
+
@appname = appname
|
9
|
+
@appversion = appversion
|
10
|
+
@container_path = "#{@home_dir}/machine/apps/containers/#{@appname}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def package
|
14
|
+
return unless File.exist? "#{@container_path}/releases/#{@appversion}/bin/rails"
|
15
|
+
|
16
|
+
logger.formatter = proc do |severity, datetime, progname, message|
|
17
|
+
severity_text = { "DEBUG" => "\u{1f527} #{severity}:", "INFO" => " \u{276f}", "WARN" => "\u{2757} #{severity}:",
|
18
|
+
"ERROR" => "\u{274c} #{severity}:", "FATAL" => "\u{2b55} #{severity}:", "UNKNOWN" => "\u{2753} #{severity}:"
|
19
|
+
}
|
20
|
+
"\t\t\t\t#{severity_text[severity]} #{message}\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
logger.info "Ruby on Rails application detected."
|
24
|
+
logger.info "Packaging Application ..."
|
25
|
+
|
26
|
+
# Setup rails env
|
27
|
+
env_path = "#{@container_path}/env"
|
28
|
+
system("grep -q '^## Rails' #{env_path} || echo '## Rails' >> #{env_path}")
|
29
|
+
system("grep -q '^MALLOC_ARENA_MAX=' #{env_path} || echo '# MALLOC_ARENA_MAX=2' >> #{env_path}")
|
30
|
+
system("grep -q '^RAILS_ENV=' #{env_path} || echo 'RAILS_ENV=production' >> #{env_path}")
|
31
|
+
system("grep -q '^RACK_ENV=' #{env_path} || echo 'RACK_ENV=production' >> #{env_path}")
|
32
|
+
system("grep -q '^RAILS_LOG_TO_STDOUT=' #{env_path} || echo 'RAILS_LOG_TO_STDOUT=enabled' >> #{env_path}")
|
33
|
+
system("grep -q '^RAILS_SERVE_STATIC_FILES=' #{env_path} || echo 'RAILS_SERVE_STATIC_FILES=enabled' >> #{env_path}")
|
34
|
+
system("grep -q '^LANG=' #{env_path} || echo 'LANG=en_US.UTF-8' >> #{env_path}")
|
35
|
+
system("grep -q '^RAILS_MASTER_KEY=' #{env_path} || echo 'RAILS_MASTER_KEY=yourmasterkey' >> #{env_path}")
|
36
|
+
logger.warn "Please set your RAILS_MASTER_KEY env var for this rails app." if system("grep -q '^RAILS_MASTER_KEY=yourmasterkey' #{env_path}")
|
37
|
+
|
38
|
+
# Setup app folders needed for volumes. If this is not created then docker will create it while running the container,
|
39
|
+
# but the folder will have root user assigned instead of the current user.
|
40
|
+
FileUtils.mkdir_p("#{@container_path}/app/vendor/bundle")
|
41
|
+
FileUtils.mkdir_p("#{@container_path}/app/public/assets")
|
42
|
+
FileUtils.mkdir_p("#{@container_path}/app/public/packs")
|
43
|
+
FileUtils.mkdir_p("#{@container_path}/app/node_modules")
|
44
|
+
FileUtils.mkdir_p("#{@container_path}/app/storage")
|
45
|
+
FileUtils.mkdir_p("#{@container_path}/releases/#{@appversion}/vendor/bundle")
|
46
|
+
FileUtils.mkdir_p("#{@container_path}/releases/#{@appversion}/public/assets")
|
47
|
+
FileUtils.mkdir_p("#{@container_path}/releases/#{@appversion}/public/packs")
|
48
|
+
FileUtils.mkdir_p("#{@container_path}/releases/#{@appversion}/node_modules")
|
49
|
+
FileUtils.mkdir_p("#{@container_path}/releases/#{@appversion}/storage")
|
50
|
+
|
51
|
+
# Creating a valid docker app image.
|
52
|
+
container = SmartMachine::Apps::Container.new(name: "#{@appname}-#{@appversion}-packed", appname: @appname, appversion: @appversion)
|
53
|
+
if container.commit_app_image!
|
54
|
+
logger.formatter = nil
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
|
58
|
+
logger.formatter = nil
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
def packer
|
63
|
+
set_logger_formatter_arrow
|
64
|
+
|
65
|
+
if File.exist? "tmp/smartmachine/packed"
|
66
|
+
begin
|
67
|
+
pid = File.read('tmp/smartmachine/packed').to_i
|
68
|
+
Process.kill('QUIT', pid)
|
69
|
+
rescue Errno::ESRCH # No such process
|
70
|
+
end
|
71
|
+
exec "bundle", "exec", "puma", "--config", "config/puma.rb"
|
72
|
+
else
|
73
|
+
if initial_setup? && bundle_install? && precompile_assets? && db_migrate? && test_web_server?
|
74
|
+
logger.formatter = nil
|
75
|
+
|
76
|
+
exit 0
|
77
|
+
else
|
78
|
+
logger.error "Could not continue ... Launch Failed."
|
79
|
+
logger.formatter = nil
|
80
|
+
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Perform initial_setup
|
89
|
+
def initial_setup?
|
90
|
+
logger.info "Performing initial setup ..."
|
91
|
+
|
92
|
+
exit_status = nil
|
93
|
+
|
94
|
+
# Fix for mysql2 gem to support sha256_password, until it is fixed in main mysql2 gem.
|
95
|
+
# https://github.com/brianmario/mysql2/issues/1023
|
96
|
+
exit_status = system("mkdir -p ./lib/mariadb && ln -s /usr/lib/mariadb/plugin ./lib/mariadb/plugin")
|
97
|
+
|
98
|
+
if exit_status
|
99
|
+
return true
|
100
|
+
else
|
101
|
+
logger.error "Could not complete initial setup."
|
102
|
+
return false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Perform bundle install
|
107
|
+
def bundle_install?
|
108
|
+
logger.info "Performing bundle install ..."
|
109
|
+
|
110
|
+
set_logger_formatter_tabs
|
111
|
+
|
112
|
+
unless system("bundle config set deployment 'true' && bundle config set clean 'true'")
|
113
|
+
logger.error "Could not complete bundle config setting."
|
114
|
+
return false
|
115
|
+
end
|
116
|
+
|
117
|
+
exit_status = nil
|
118
|
+
Open3.popen2e("bundle", "install") do |stdin, stdout_and_stderr, wait_thr|
|
119
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
120
|
+
exit_status = wait_thr.value.success?
|
121
|
+
end
|
122
|
+
set_logger_formatter_arrow
|
123
|
+
|
124
|
+
if exit_status
|
125
|
+
return true
|
126
|
+
else
|
127
|
+
logger.error "Could not complete bundle install."
|
128
|
+
return false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Perform pre-compiling of assets
|
133
|
+
def precompile_assets?
|
134
|
+
logger.info "Installing Javascript dependencies & pre-compiling assets ..."
|
135
|
+
|
136
|
+
set_logger_formatter_tabs
|
137
|
+
exit_status = nil
|
138
|
+
Open3.popen2e("bundle", "exec", "rails", "assets:precompile") do |stdin, stdout_and_stderr, wait_thr|
|
139
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
140
|
+
exit_status = wait_thr.value.success?
|
141
|
+
end
|
142
|
+
set_logger_formatter_arrow
|
143
|
+
|
144
|
+
if exit_status
|
145
|
+
return true
|
146
|
+
else
|
147
|
+
logger.error "Could not install Javascript dependencies or pre-compile assets."
|
148
|
+
return false
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Perform db_migrate
|
153
|
+
def db_migrate?
|
154
|
+
return true # remove this line when you want to start using db_migrate?
|
155
|
+
|
156
|
+
logger.info "Performing database migrations ..."
|
157
|
+
|
158
|
+
set_logger_formatter_tabs
|
159
|
+
exit_status = nil
|
160
|
+
Open3.popen2e("bundle", "exec", "rails", "db:migrate") do |stdin, stdout_and_stderr, wait_thr|
|
161
|
+
stdout_and_stderr.each { |line| logger.info "#{line}" }
|
162
|
+
exit_status = wait_thr.value.success?
|
163
|
+
end
|
164
|
+
set_logger_formatter_arrow
|
165
|
+
|
166
|
+
if exit_status
|
167
|
+
return true
|
168
|
+
else
|
169
|
+
logger.error "Could not complete database migrations."
|
170
|
+
return false
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Perform testing of web server
|
175
|
+
def test_web_server?
|
176
|
+
logger.info "Setting up Web Server ..."
|
177
|
+
|
178
|
+
# tmp folders
|
179
|
+
FileUtils.mkdir_p("tmp/pids")
|
180
|
+
FileUtils.mkdir_p("tmp/smartmachine")
|
181
|
+
FileUtils.rm_f("tmp/smartmachine/packed")
|
182
|
+
|
183
|
+
# Spawn Process
|
184
|
+
pid = Process.spawn("bundle", "exec", "puma", "--config", "config/puma.rb", out: File::NULL)
|
185
|
+
Process.detach(pid)
|
186
|
+
|
187
|
+
# Sleep
|
188
|
+
sleep 5
|
189
|
+
|
190
|
+
# Check PID running
|
191
|
+
status = nil
|
192
|
+
begin
|
193
|
+
Process.kill(0, pid)
|
194
|
+
system("echo '#{pid}' > tmp/smartmachine/packed")
|
195
|
+
status = true
|
196
|
+
rescue Errno::ESRCH # No such process
|
197
|
+
logger.info "Web Server could not start"
|
198
|
+
status = false
|
199
|
+
end
|
200
|
+
|
201
|
+
# Return status
|
202
|
+
return status
|
203
|
+
end
|
204
|
+
|
205
|
+
def set_logger_formatter_arrow
|
206
|
+
logger.formatter = proc do |severity, datetime, progname, message|
|
207
|
+
severity_text = { "DEBUG" => "\u{1f527} #{severity}:", "INFO" => " \u{276f}", "WARN" => "\u{2757} #{severity}:",
|
208
|
+
"ERROR" => "\u{274c} #{severity}:", "FATAL" => "\u{2b55} #{severity}:", "UNKNOWN" => "\u{2753} #{severity}:"
|
209
|
+
}
|
210
|
+
"\t\t\t\t#{severity_text[severity]} #{message}\n"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def set_logger_formatter_tabs
|
215
|
+
logger.formatter = proc do |severity, datetime, progname, message|
|
216
|
+
"\t\t\t\t #{message}"
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module SmartMachine
|
2
|
+
module Commands
|
3
|
+
class App < Thor
|
4
|
+
include Utilities
|
5
|
+
|
6
|
+
desc "create [APPNAME] [APPDOMAIN] [USERNAME]", "Create an App"
|
7
|
+
def create(appname, appdomain, username)
|
8
|
+
inside_machine_dir do
|
9
|
+
with_docker_running do
|
10
|
+
machine = SmartMachine::Machine.new
|
11
|
+
machine.run_on_machine commands: "smartengine app creater #{appname} #{appdomain} #{username}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "destroy [APPNAME]", "Destroy an App"
|
17
|
+
def destroy(appname)
|
18
|
+
inside_machine_dir do
|
19
|
+
with_docker_running do
|
20
|
+
machine = SmartMachine::Machine.new
|
21
|
+
machine.run_on_machine commands: "smartengine app destroyer #{appname}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "ps:scale [APPNAME]", "Scale the app processes"
|
27
|
+
map "ps:scale" => "ps_scale"
|
28
|
+
option :formation, type: :hash, required: true
|
29
|
+
option :version, type: :numeric, default: nil
|
30
|
+
def ps_scale(appname)
|
31
|
+
inside_machine_dir do
|
32
|
+
with_docker_running do
|
33
|
+
machine = SmartMachine::Machine.new
|
34
|
+
command = [
|
35
|
+
"smartengine app ps:scaler #{appname}"
|
36
|
+
]
|
37
|
+
formation = options[:formation].map { |proctype, count| "#{proctype}:#{count}" }.join(' ')
|
38
|
+
command.push("--formation=#{formation}") if options[:formation]
|
39
|
+
command.push("--version=#{options[:version]}") if options[:version]
|
40
|
+
machine.run_on_machine commands: command.join(" ")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "up [APPNAME]", "Take UP the app"
|
46
|
+
option :version, type: :numeric, default: 0
|
47
|
+
def up(appname)
|
48
|
+
inside_machine_dir do
|
49
|
+
with_docker_running do
|
50
|
+
machine = SmartMachine::Machine.new
|
51
|
+
machine.run_on_machine commands: "smartengine app uper #{appname} --version=#{options[:version]}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "down [APPNAME]", "Take DOWN the app"
|
57
|
+
def down(appname)
|
58
|
+
inside_machine_dir do
|
59
|
+
with_docker_running do
|
60
|
+
machine = SmartMachine::Machine.new
|
61
|
+
machine.run_on_machine commands: "smartengine app downer #{appname}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "creater", "App creator", hide: true
|
67
|
+
def creater(appname, appdomain, username)
|
68
|
+
inside_engine_machine_dir do
|
69
|
+
app = SmartMachine::Apps::App.new(appname: appname, username: username)
|
70
|
+
prereceiver_name, prereceiver_config = SmartMachine.config.grids.prereceiver.first
|
71
|
+
app.creater(appdomain: appdomain, prereceiver_name: prereceiver_name)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "destroyer", "App destroyer", hide: true
|
76
|
+
def destroyer(appname)
|
77
|
+
inside_engine_machine_dir do
|
78
|
+
app = SmartMachine::Apps::App.new(appname: appname)
|
79
|
+
app.destroyer
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "ps:scaler [APPNAME]", "Scale the app processes", hide: true
|
84
|
+
map "ps:scaler" => "ps_scaler"
|
85
|
+
option :formation, type: :hash, required: true
|
86
|
+
option :version, type: :numeric, default: nil
|
87
|
+
def ps_scaler(appname)
|
88
|
+
inside_engine_machine_dir do
|
89
|
+
manager = SmartMachine::Apps::Manager.new(appname: appname, appversion: options[:version])
|
90
|
+
manager.ps_scaler(formation: options[:formation])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "uper [APPNAME]", "App uper", hide: true
|
95
|
+
option :version, type: :numeric, default: 0
|
96
|
+
def uper(appname)
|
97
|
+
inside_engine_machine_dir do
|
98
|
+
app = SmartMachine::Apps::App.new(appname: appname)
|
99
|
+
app.uper(version: options[:version])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
desc "downer [APPNAME]", "App downer", hide: true
|
104
|
+
def downer(appname)
|
105
|
+
inside_engine_machine_dir do
|
106
|
+
app = SmartMachine::Apps::App.new(appname: appname)
|
107
|
+
app.downer
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|