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,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
- class Credentials < SmartMachine::Base
7
+ class Credentials < SmartMachine::Base
9
8
 
10
- CIPHER = "aes-256-gcm"
9
+ CIPHER = "aes-256-gcm"
11
10
 
12
- def initialize
13
- end
11
+ def initialize
12
+ end
14
13
 
15
- def create
16
- write_key
17
- write credentials_template
18
- end
14
+ def create
15
+ write_key
16
+ write credentials_template
17
+ end
19
18
 
20
- def edit
21
- content_path = Pathname.new "config/credentials.yml.enc"
22
- tmp_file = "#{Process.pid}.#{content_path.basename.to_s.chomp('.enc')}"
23
- tmp_path = Pathname.new File.join(Dir.tmpdir, tmp_file)
24
- contents = read
25
- tmp_path.binwrite contents
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
- system("#{ENV['EDITOR']} #{tmp_path}")
26
+ system("#{ENV['EDITOR']} #{tmp_path}")
28
27
 
29
- updated_contents = tmp_path.binread
28
+ updated_contents = tmp_path.binread
30
29
 
31
- if updated_contents != contents
32
- write(updated_contents)
33
- puts "File encrypted and saved."
34
- else
35
- puts "File contents were not changed."
36
- end
37
- ensure
38
- FileUtils.rm(tmp_path) if tmp_path&.exist?
39
- end
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
- def read_key
42
- read_env_key || read_key_file || handle_missing_key
43
- end
40
+ def read_key
41
+ read_env_key || read_key_file || handle_missing_key
42
+ end
44
43
 
45
- def config
46
- @config ||= deserialize(read).deep_symbolize_keys
47
- end
44
+ def config
45
+ @config ||= deserialize(read).deep_symbolize_keys
46
+ end
48
47
 
49
- private
48
+ private
50
49
 
51
- def credentials_template
50
+ def credentials_template
52
51
  <<~YAML
53
52
  machine:
54
53
  name: #{SecureRandom.hex(8)}
55
- address: 122.122.122.122
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
- browser: on
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
- elasticsearch:
76
- port: 9200
67
+ redisone:
68
+ password: #{SecureRandom.hex(16)}
77
69
  YAML
78
- end
79
-
80
- def read
81
- decrypt IO.binread "config/credentials.yml.enc"
82
- end
83
-
84
- def write(contents)
85
- IO.binwrite "config/credentials.yml.enc.tmp", encrypt(contents)
86
- FileUtils.mv "config/credentials.yml.enc.tmp", "config/credentials.yml.enc"
87
- end
88
-
89
- def encrypt(contents)
90
- encryptor.encrypt_and_sign contents
91
- end
92
-
93
- def decrypt(contents)
94
- encryptor.decrypt_and_verify contents
95
- end
96
-
97
- def encryptor
98
- @encryptor ||= ActiveSupport::MessageEncryptor.new([ read_key ].pack("H*"), cipher: CIPHER)
99
- end
100
-
101
- def create_key
102
- SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
103
- end
104
-
105
- def write_key
106
- IO.binwrite "config/master.key.tmp", create_key
107
- FileUtils.mv "config/master.key.tmp", "config/master.key"
108
- end
109
-
110
- def read_env_key
111
- ENV['SMARTMACHINE_MASTER_KEY']
112
- end
113
-
114
- def read_key_file
115
- IO.binread("config/master.key").strip if File.file?("config/master.key")
116
- end
117
-
118
- def handle_missing_key
119
- raise "Missing SMARTMACHINE_MASTER_KEY. Please add SMARTMACHINE_MASTER_KEY to your environment."
120
- end
121
-
122
- def deserialize(config)
123
- YAML.load(config).presence || {}
124
- end
125
- end
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