smartmachine 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,37 @@
|
|
1
|
+
module SmartMachine
|
2
|
+
module Commands
|
3
|
+
module Utilities
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def in_machine_dir?
|
8
|
+
File.file?("./config/master.key")
|
9
|
+
end
|
10
|
+
|
11
|
+
def inside_machine_dir
|
12
|
+
if in_machine_dir?
|
13
|
+
yield
|
14
|
+
else
|
15
|
+
puts "Are you in the correct directory to run this command?"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def inside_engine_machine_dir
|
20
|
+
if ENV["INSIDE_ENGINE"] == "yes" && File.file?('./bin/smartengine')
|
21
|
+
yield
|
22
|
+
else
|
23
|
+
raise "Not inside the engine machine dir to run this command"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_docker_running
|
28
|
+
machine = SmartMachine::Machine.new
|
29
|
+
if machine.run_on_machine(commands: "docker info &>/dev/null")
|
30
|
+
yield
|
31
|
+
else
|
32
|
+
puts "Error: Docker daemon is not running. Have you installed docker? Please ensure docker daemon is running and try again."
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'smart_machine'
|
3
|
+
|
4
|
+
require 'smart_machine/commands/utilities'
|
5
|
+
|
6
|
+
require 'smart_machine/commands/app'
|
7
|
+
require 'smart_machine/commands/buildpacker'
|
8
|
+
require 'smart_machine/commands/credentials'
|
9
|
+
require 'smart_machine/commands/docker'
|
10
|
+
require 'smart_machine/commands/engine'
|
11
|
+
require 'smart_machine/commands/grid'
|
12
|
+
require 'smart_machine/commands/machine'
|
13
|
+
require 'smart_machine/commands/syncer'
|
14
|
+
|
15
|
+
module SmartMachine
|
16
|
+
module Commands
|
17
|
+
class CLI < Thor
|
18
|
+
include Utilities
|
19
|
+
|
20
|
+
def self.exit_on_failure?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "new [NAME]", "Creates a new machine using the given name"
|
25
|
+
option :dev, type: :boolean, default: false
|
26
|
+
def new(name)
|
27
|
+
raise "Can't create a machine inside a machine. Please come out of the machine directory to create another machine." if in_machine_dir?
|
28
|
+
|
29
|
+
machine = SmartMachine::Machine.new
|
30
|
+
machine.create(name: name, dev: options[:dev])
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "--version", "Shows the current SmartMachine version"
|
34
|
+
map ["--version", "-v"] => :version
|
35
|
+
def version
|
36
|
+
puts "SmartMachine #{SmartMachine.version}"
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "app", "Run app commands"
|
40
|
+
subcommand "app", App
|
41
|
+
|
42
|
+
desc "buildpacker", "Run buildpacker commands"
|
43
|
+
subcommand "buildpacker", Buildpacker
|
44
|
+
|
45
|
+
desc "credentials:edit", "Allows editing the credentials"
|
46
|
+
subcommand "credentials:edit", Credentials
|
47
|
+
|
48
|
+
desc "docker", "Run docker commands"
|
49
|
+
subcommand "docker", Docker
|
50
|
+
|
51
|
+
desc "engine", "Run engine commands"
|
52
|
+
subcommand "engine", Engine
|
53
|
+
|
54
|
+
desc "grid", "Run grid commands"
|
55
|
+
subcommand "grid", Grid
|
56
|
+
|
57
|
+
desc "machine", "Run machine commands"
|
58
|
+
subcommand "machine", Machine
|
59
|
+
|
60
|
+
desc "syncer", "Run syncer commands"
|
61
|
+
subcommand "syncer", Syncer
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
SmartMachine::Commands::CLI.start(ARGV)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "active_support/core_ext/hash/keys"
|
2
|
+
require "erb"
|
3
|
+
|
4
|
+
module SmartMachine
|
5
|
+
class Configuration < SmartMachine::Base
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
end
|
9
|
+
|
10
|
+
def config
|
11
|
+
@config ||= OpenStruct.new(grids: grids)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def grids
|
17
|
+
@grids ||= OpenStruct.new(elasticsearch: elasticsearch, minio: minio, mysql: mysql, prereceiver: prereceiver, redis: redis)
|
18
|
+
end
|
19
|
+
|
20
|
+
def elasticsearch
|
21
|
+
# Once the SmartMachine.config assignments in smart_machine.rb file has been removed, then this file exist condition can be removed to ensure that config/elasticsearch.yml always exists
|
22
|
+
if File.exist? "config/elasticsearch.yml"
|
23
|
+
deserialize(IO.binread("config/elasticsearch.yml")).deep_symbolize_keys
|
24
|
+
elsif File.exist? "#{File.expand_path('~')}/machine/config/elasticsearch.yml"
|
25
|
+
deserialize(IO.binread("#{File.expand_path('~')}/machine/config/elasticsearch.yml")).deep_symbolize_keys
|
26
|
+
else
|
27
|
+
{}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def minio
|
32
|
+
# Once the SmartMachine.config assignments in smart_machine.rb file has been removed, then this file exist condition can be removed to ensure that config/minio.yml always exists
|
33
|
+
if File.exist? "config/minio.yml"
|
34
|
+
deserialize(IO.binread("config/minio.yml")).deep_symbolize_keys
|
35
|
+
elsif File.exist? "#{File.expand_path('~')}/machine/config/minio.yml"
|
36
|
+
deserialize(IO.binread("#{File.expand_path('~')}/machine/config/minio.yml")).deep_symbolize_keys
|
37
|
+
else
|
38
|
+
{}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def mysql
|
43
|
+
# Once the SmartMachine.config assignments in smart_machine.rb file has been removed, then this file exist condition can be removed to ensure that config/mysql.yml always exists
|
44
|
+
if File.exist? "config/mysql.yml"
|
45
|
+
deserialize(IO.binread("config/mysql.yml")).deep_symbolize_keys
|
46
|
+
elsif File.exist? "#{File.expand_path('~')}/machine/config/mysql.yml"
|
47
|
+
deserialize(IO.binread("#{File.expand_path('~')}/machine/config/mysql.yml")).deep_symbolize_keys
|
48
|
+
else
|
49
|
+
{}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def prereceiver
|
54
|
+
# Once the SmartMachine.config assignments in smart_machine.rb file has been removed, then this file exist condition can be removed to ensure that config/prereceiver.yml always exists
|
55
|
+
if File.exist? "config/prereceiver.yml"
|
56
|
+
deserialize(IO.binread("config/prereceiver.yml")).deep_symbolize_keys
|
57
|
+
elsif File.exist? "#{File.expand_path('~')}/machine/config/prereceiver.yml" # To ensure file exists when inside the pre-receive hook of prereceiver.
|
58
|
+
deserialize(IO.binread("#{File.expand_path('~')}/machine/config/prereceiver.yml")).deep_symbolize_keys
|
59
|
+
else
|
60
|
+
{}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def redis
|
65
|
+
# Once the SmartMachine.config assignments in smart_machine.rb file has been removed, then this file exist condition can be removed to ensure that config/redis.yml always exists
|
66
|
+
if File.exist? "config/redis.yml"
|
67
|
+
deserialize(IO.binread("config/redis.yml")).deep_symbolize_keys
|
68
|
+
elsif File.exist? "#{File.expand_path('~')}/machine/config/redis.yml"
|
69
|
+
deserialize(IO.binread("#{File.expand_path('~')}/machine/config/redis.yml")).deep_symbolize_keys
|
70
|
+
else
|
71
|
+
{}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def deserialize(config)
|
76
|
+
YAML.load(ERB.new(config).result).presence || {}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -3,124 +3,122 @@ require "tmpdir"
|
|
3
3
|
require "active_support/message_encryptor"
|
4
4
|
require "active_support/core_ext/hash/keys"
|
5
5
|
|
6
|
-
# The main SmartMachine Credentials driver
|
7
6
|
module SmartMachine
|
8
|
-
|
7
|
+
class Credentials < SmartMachine::Base
|
9
8
|
|
10
|
-
|
9
|
+
CIPHER = "aes-256-gcm"
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
def initialize
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def create
|
15
|
+
write_key
|
16
|
+
write credentials_template
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
def edit
|
20
|
+
content_path = Pathname.new "config/credentials.yml.enc"
|
21
|
+
tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
|
22
|
+
tmp_path = Pathname.new File.join(Dir.tmpdir, tmp_file)
|
23
|
+
contents = read
|
24
|
+
tmp_path.binwrite contents
|
26
25
|
|
27
|
-
|
26
|
+
system("#{ENV['EDITOR']} #{tmp_path}")
|
28
27
|
|
29
|
-
|
28
|
+
updated_contents = tmp_path.binread
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
if updated_contents != contents
|
31
|
+
write(updated_contents)
|
32
|
+
puts "File encrypted and saved."
|
33
|
+
else
|
34
|
+
puts "File contents were not changed."
|
35
|
+
end
|
36
|
+
ensure
|
37
|
+
FileUtils.rm(tmp_path) if tmp_path&.exist?
|
38
|
+
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
def read_key
|
41
|
+
read_env_key || read_key_file || handle_missing_key
|
42
|
+
end
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
def config
|
45
|
+
@config ||= deserialize(read).deep_symbolize_keys
|
46
|
+
end
|
48
47
|
|
49
|
-
|
48
|
+
private
|
50
49
|
|
51
|
-
|
50
|
+
def credentials_template
|
52
51
|
<<~YAML
|
53
52
|
machine:
|
54
53
|
name: #{SecureRandom.hex(8)}
|
55
|
-
address:
|
54
|
+
address: 127.0.0.1
|
56
55
|
port: 22
|
57
56
|
root_password: #{SecureRandom.hex(16)}
|
58
57
|
username: #{SecureRandom.hex(8)}
|
59
58
|
password: #{SecureRandom.hex(16)}
|
60
|
-
|
61
|
-
minio:
|
62
|
-
name: #{SecureRandom.hex(8)}
|
59
|
+
minioone:
|
63
60
|
access_key: #{SecureRandom.hex(8)}
|
64
61
|
secret_key: #{SecureRandom.hex(16)}
|
65
|
-
|
66
|
-
worm: off
|
67
|
-
|
68
|
-
mysql:
|
69
|
-
port: 3306
|
62
|
+
mysqlone:
|
70
63
|
root_password: #{SecureRandom.hex(16)}
|
71
64
|
username: #{SecureRandom.hex(8)}
|
72
65
|
password: #{SecureRandom.hex(16)}
|
73
66
|
database_name: #{SecureRandom.hex(8)}
|
74
|
-
|
75
|
-
|
76
|
-
port: 9200
|
67
|
+
redisone:
|
68
|
+
password: #{SecureRandom.hex(16)}
|
77
69
|
YAML
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def read
|
73
|
+
if File.exist? "config/credentials.yml.enc"
|
74
|
+
decrypt IO.binread "config/credentials.yml.enc"
|
75
|
+
elsif File.exist? "#{File.expand_path('~')}/machine/config/credentials.yml.enc"
|
76
|
+
decrypt IO.binread "#{File.expand_path('~')}/machine/config/credentials.yml.enc"
|
77
|
+
else
|
78
|
+
raise "Could not find credentials file."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def write(contents)
|
83
|
+
IO.binwrite "config/credentials.yml.enc.tmp", encrypt(contents)
|
84
|
+
FileUtils.mv "config/credentials.yml.enc.tmp", "config/credentials.yml.enc"
|
85
|
+
end
|
86
|
+
|
87
|
+
def encrypt(contents)
|
88
|
+
encryptor.encrypt_and_sign contents
|
89
|
+
end
|
90
|
+
|
91
|
+
def decrypt(contents)
|
92
|
+
encryptor.decrypt_and_verify contents
|
93
|
+
end
|
94
|
+
|
95
|
+
def encryptor
|
96
|
+
@encryptor ||= ActiveSupport::MessageEncryptor.new([ read_key ].pack("H*"), cipher: CIPHER)
|
97
|
+
end
|
98
|
+
|
99
|
+
def create_key
|
100
|
+
SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
|
101
|
+
end
|
102
|
+
|
103
|
+
def write_key
|
104
|
+
IO.binwrite "config/master.key.tmp", create_key
|
105
|
+
FileUtils.mv "config/master.key.tmp", "config/master.key"
|
106
|
+
end
|
107
|
+
|
108
|
+
def read_env_key
|
109
|
+
ENV['SMARTMACHINE_MASTER_KEY']
|
110
|
+
end
|
111
|
+
|
112
|
+
def read_key_file
|
113
|
+
IO.binread("config/master.key").strip if File.file?("config/master.key")
|
114
|
+
end
|
115
|
+
|
116
|
+
def handle_missing_key
|
117
|
+
raise "Missing SMARTMACHINE_MASTER_KEY. Please add SMARTMACHINE_MASTER_KEY to your environment."
|
118
|
+
end
|
119
|
+
|
120
|
+
def deserialize(config)
|
121
|
+
YAML.load(config).presence || {}
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|