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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +661 -0
  3. data/README.md +147 -0
  4. data/bin/console +14 -0
  5. data/bin/setup +8 -0
  6. data/exe/smartmachine +3 -0
  7. data/lib/smart_machine/apps/app.rb +165 -181
  8. data/lib/smart_machine/apps/container.rb +120 -0
  9. data/lib/smart_machine/apps/manager.rb +182 -0
  10. data/lib/smart_machine/base.rb +24 -6
  11. data/lib/smart_machine/buildpackers/buildpacker.rb +95 -0
  12. data/lib/smart_machine/{engine/buildpacks → buildpackers}/rails/Dockerfile +3 -3
  13. data/lib/smart_machine/buildpackers/rails.rb +221 -0
  14. data/lib/smart_machine/commands/app.rb +112 -0
  15. data/lib/smart_machine/commands/buildpacker.rb +53 -0
  16. data/lib/smart_machine/commands/credentials.rb +17 -0
  17. data/lib/smart_machine/commands/docker.rb +23 -0
  18. data/lib/smart_machine/commands/engine.rb +27 -0
  19. data/lib/smart_machine/commands/grid.rb +33 -0
  20. data/lib/smart_machine/commands/grid_commands/elasticsearch.rb +68 -0
  21. data/lib/smart_machine/commands/grid_commands/minio.rb +65 -0
  22. data/lib/smart_machine/commands/grid_commands/mysql.rb +71 -0
  23. data/lib/smart_machine/commands/grid_commands/nginx.rb +53 -0
  24. data/lib/smart_machine/commands/grid_commands/prereceiver.rb +96 -0
  25. data/lib/smart_machine/commands/grid_commands/redis.rb +65 -0
  26. data/lib/smart_machine/commands/grid_commands/scheduler.rb +15 -0
  27. data/lib/smart_machine/commands/grid_commands/sub_thor.rb +15 -0
  28. data/lib/smart_machine/commands/machine.rb +24 -0
  29. data/lib/smart_machine/commands/syncer.rb +23 -0
  30. data/lib/smart_machine/commands/utilities.rb +37 -0
  31. data/lib/smart_machine/commands.rb +66 -0
  32. data/lib/smart_machine/configuration.rb +79 -0
  33. data/lib/smart_machine/credentials.rb +93 -95
  34. data/lib/smart_machine/docker.rb +144 -143
  35. data/lib/smart_machine/engine/Dockerfile +7 -5
  36. data/lib/smart_machine/engine.rb +104 -79
  37. data/lib/smart_machine/grids/elasticsearch.rb +70 -89
  38. data/lib/smart_machine/grids/minio.rb +79 -68
  39. data/lib/smart_machine/grids/mysql.rb +207 -202
  40. data/lib/smart_machine/grids/nginx.rb +176 -135
  41. data/lib/smart_machine/grids/prereceiver/Dockerfile +2 -2
  42. data/lib/smart_machine/grids/prereceiver/pre-receive +17 -0
  43. data/lib/smart_machine/grids/prereceiver.rb +169 -169
  44. data/lib/smart_machine/grids/redis.rb +75 -57
  45. data/lib/smart_machine/grids/scheduler/Dockerfile +1 -1
  46. data/lib/smart_machine/logger.rb +26 -26
  47. data/lib/smart_machine/machine.rb +128 -194
  48. data/lib/smart_machine/scp.rb +15 -0
  49. data/lib/smart_machine/ssh.rb +69 -40
  50. data/lib/smart_machine/syncer.rb +133 -0
  51. data/lib/smart_machine/templates/dotsmartmachine/Gemfile +7 -0
  52. data/lib/smart_machine/templates/dotsmartmachine/config/elasticsearch.yml +5 -0
  53. data/lib/smart_machine/templates/dotsmartmachine/config/environment.rb +0 -9
  54. data/lib/smart_machine/templates/dotsmartmachine/config/minio.yml +13 -0
  55. data/lib/smart_machine/templates/dotsmartmachine/config/mysql/schedule.rb +3 -3
  56. data/lib/smart_machine/templates/dotsmartmachine/config/mysql.yml +13 -0
  57. data/lib/smart_machine/templates/dotsmartmachine/config/prereceiver.yml +7 -0
  58. data/lib/smart_machine/templates/dotsmartmachine/config/redis.yml +15 -0
  59. data/lib/smart_machine/templates/dotsmartmachine/config/users.yml +1 -1
  60. data/lib/smart_machine/templates/dotsmartmachine/gitignore-template +47 -0
  61. data/lib/smart_machine/templates/dotsmartmachine/{grids/elasticsearch/data → vendor}/.keep +0 -0
  62. data/lib/smart_machine/version.rb +30 -6
  63. data/lib/smart_machine.rb +42 -16
  64. metadata +97 -47
  65. data/CHANGELOG.rdoc +0 -0
  66. data/MIT-LICENSE +0 -21
  67. data/README.rdoc +0 -87
  68. data/bin/buildpacker +0 -8
  69. data/bin/prereceiver +0 -8
  70. data/bin/scheduler +0 -18
  71. data/bin/smartmachine +0 -81
  72. data/bin/smartrunner +0 -33
  73. data/lib/smart_machine/apps/rails.rb +0 -250
  74. data/lib/smart_machine/apps.rb +0 -14
  75. data/lib/smart_machine/boot.rb +0 -32
  76. data/lib/smart_machine/buildpacker.rb +0 -106
  77. data/lib/smart_machine/gem_version.rb +0 -17
  78. data/lib/smart_machine/grids.rb +0 -18
  79. data/lib/smart_machine/sync.rb +0 -120
  80. data/lib/smart_machine/templates/dotsmartmachine/grids/elasticsearch/logs/.keep +0 -0
  81. data/lib/smart_machine/templates/dotsmartmachine/grids/minio/data/.keep +0 -0
  82. data/lib/smart_machine/templates/dotsmartmachine/grids/mysql/backups/.keep +0 -0
  83. data/lib/smart_machine/templates/dotsmartmachine/grids/mysql/data/.keep +0 -0
  84. data/lib/smart_machine/templates/dotsmartmachine/grids/prereceiver/pre-receive +0 -17
  85. data/lib/smart_machine/templates/dotsmartmachine/grids/redis/data/.keep +0 -0
  86. 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
@@ -2,10 +2,28 @@ require 'smart_machine/logger'
2
2
  require "active_support/inflector"
3
3
 
4
4
  module SmartMachine
5
- class Base
6
- include SmartMachine::Logger
5
+ class Base
6
+ include SmartMachine::Logger
7
7
 
8
- def initialize
9
- end
10
- end
11
- end
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="Timeboard <hello@timeboard.me>"
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", "pack"]
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