central-cli 0.6.3

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 (259) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +3 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +6 -0
  5. data/.rubocop.yml +5 -0
  6. data/Dockerfile +15 -0
  7. data/Gemfile +10 -0
  8. data/LICENSE +191 -0
  9. data/README.md +39 -0
  10. data/Rakefile +9 -0
  11. data/VERSION +1 -0
  12. data/bin/cm +85 -0
  13. data/central-cli.gemspec +35 -0
  14. data/central-docker.sh +6 -0
  15. data/lib/central/cli/app_command.rb +29 -0
  16. data/lib/central/cli/apps/build_command.rb +24 -0
  17. data/lib/central/cli/apps/central_yml_generator.rb +88 -0
  18. data/lib/central/cli/apps/common.rb +166 -0
  19. data/lib/central/cli/apps/deploy_command.rb +191 -0
  20. data/lib/central/cli/apps/docker_compose_generator.rb +48 -0
  21. data/lib/central/cli/apps/docker_helper.rb +85 -0
  22. data/lib/central/cli/apps/dockerfile_generator.rb +15 -0
  23. data/lib/central/cli/apps/init_command.rb +91 -0
  24. data/lib/central/cli/apps/list_command.rb +68 -0
  25. data/lib/central/cli/apps/logs_command.rb +76 -0
  26. data/lib/central/cli/apps/monitor_command.rb +93 -0
  27. data/lib/central/cli/apps/remove_command.rb +80 -0
  28. data/lib/central/cli/apps/restart_command.rb +38 -0
  29. data/lib/central/cli/apps/scale_command.rb +31 -0
  30. data/lib/central/cli/apps/show_command.rb +23 -0
  31. data/lib/central/cli/apps/start_command.rb +39 -0
  32. data/lib/central/cli/apps/stop_command.rb +39 -0
  33. data/lib/central/cli/auth/aws/create_command.rb +34 -0
  34. data/lib/central/cli/auth/aws_command.rb +7 -0
  35. data/lib/central/cli/auth/list_command.rb +28 -0
  36. data/lib/central/cli/auth_command.rb +9 -0
  37. data/lib/central/cli/bytes_helper.rb +38 -0
  38. data/lib/central/cli/common.rb +148 -0
  39. data/lib/central/cli/container_command.rb +10 -0
  40. data/lib/central/cli/containers/exec_command.rb +21 -0
  41. data/lib/central/cli/containers/inspect_command.rb +22 -0
  42. data/lib/central/cli/etcd/common.rb +7 -0
  43. data/lib/central/cli/etcd/get_command.rb +26 -0
  44. data/lib/central/cli/etcd/list_command.rb +31 -0
  45. data/lib/central/cli/etcd/mkdir_command.rb +21 -0
  46. data/lib/central/cli/etcd/remove_command.rb +25 -0
  47. data/lib/central/cli/etcd/set_command.rb +22 -0
  48. data/lib/central/cli/etcd_command.rb +16 -0
  49. data/lib/central/cli/external_registries/add_command.rb +21 -0
  50. data/lib/central/cli/external_registries/delete_command.rb +15 -0
  51. data/lib/central/cli/external_registries/list_command.rb +27 -0
  52. data/lib/central/cli/external_registries/remove_command.rb +13 -0
  53. data/lib/central/cli/external_registry_command.rb +14 -0
  54. data/lib/central/cli/login_command.rb +121 -0
  55. data/lib/central/cli/logout_command.rb +7 -0
  56. data/lib/central/cli/master/aws/create_command.rb +41 -0
  57. data/lib/central/cli/master/aws_command.rb +7 -0
  58. data/lib/central/cli/master/azure/create_command.rb +39 -0
  59. data/lib/central/cli/master/azure_command.rb +11 -0
  60. data/lib/central/cli/master/digital_ocean/create_command.rb +35 -0
  61. data/lib/central/cli/master/digital_ocean_command.rb +11 -0
  62. data/lib/central/cli/master/list_command.rb +28 -0
  63. data/lib/central/cli/master/use_command.rb +34 -0
  64. data/lib/central/cli/master/users/add_role_command.rb +26 -0
  65. data/lib/central/cli/master/users/invite_command.rb +24 -0
  66. data/lib/central/cli/master/users/list_command.rb +18 -0
  67. data/lib/central/cli/master/users/remove_command.rb +22 -0
  68. data/lib/central/cli/master/users/remove_role_command.rb +25 -0
  69. data/lib/central/cli/master/users_command.rb +15 -0
  70. data/lib/central/cli/master/vagrant/create_command.rb +25 -0
  71. data/lib/central/cli/master/vagrant/restart_command.rb +20 -0
  72. data/lib/central/cli/master/vagrant/ssh_command.rb +15 -0
  73. data/lib/central/cli/master/vagrant/start_command.rb +20 -0
  74. data/lib/central/cli/master/vagrant/stop_command.rb +20 -0
  75. data/lib/central/cli/master/vagrant/terminate_command.rb +13 -0
  76. data/lib/central/cli/master/vagrant_command.rb +21 -0
  77. data/lib/central/cli/master_command.rb +19 -0
  78. data/lib/central/cli/node_command.rb +30 -0
  79. data/lib/central/cli/nodes/add_label_command.rb +19 -0
  80. data/lib/central/cli/nodes/aws/create_command.rb +40 -0
  81. data/lib/central/cli/nodes/aws/restart_command.rb +29 -0
  82. data/lib/central/cli/nodes/aws/terminate_command.rb +21 -0
  83. data/lib/central/cli/nodes/aws_command.rb +14 -0
  84. data/lib/central/cli/nodes/azure/create_command.rb +40 -0
  85. data/lib/central/cli/nodes/azure/restart_command.rb +31 -0
  86. data/lib/central/cli/nodes/azure/terminate_command.rb +21 -0
  87. data/lib/central/cli/nodes/azure_command.rb +14 -0
  88. data/lib/central/cli/nodes/digital_ocean/create_command.rb +32 -0
  89. data/lib/central/cli/nodes/digital_ocean/restart_command.rb +27 -0
  90. data/lib/central/cli/nodes/digital_ocean/terminate_command.rb +19 -0
  91. data/lib/central/cli/nodes/digital_ocean_command.rb +14 -0
  92. data/lib/central/cli/nodes/label_command.rb +12 -0
  93. data/lib/central/cli/nodes/labels/add_command.rb +19 -0
  94. data/lib/central/cli/nodes/labels/remove_command.rb +23 -0
  95. data/lib/central/cli/nodes/list_command.rb +62 -0
  96. data/lib/central/cli/nodes/remove_command.rb +16 -0
  97. data/lib/central/cli/nodes/remove_label_command.rb +23 -0
  98. data/lib/central/cli/nodes/show_command.rb +49 -0
  99. data/lib/central/cli/nodes/ssh_command.rb +31 -0
  100. data/lib/central/cli/nodes/update_command.rb +20 -0
  101. data/lib/central/cli/nodes/vagrant/create_command.rb +27 -0
  102. data/lib/central/cli/nodes/vagrant/restart_command.rb +26 -0
  103. data/lib/central/cli/nodes/vagrant/ssh_command.rb +21 -0
  104. data/lib/central/cli/nodes/vagrant/start_command.rb +26 -0
  105. data/lib/central/cli/nodes/vagrant/stop_command.rb +26 -0
  106. data/lib/central/cli/nodes/vagrant/terminate_command.rb +17 -0
  107. data/lib/central/cli/nodes/vagrant_command.rb +20 -0
  108. data/lib/central/cli/register_command.rb +21 -0
  109. data/lib/central/cli/registry/create_command.rb +144 -0
  110. data/lib/central/cli/registry/delete_command.rb +22 -0
  111. data/lib/central/cli/registry/remove_command.rb +19 -0
  112. data/lib/central/cli/registry_command.rb +11 -0
  113. data/lib/central/cli/service_command.rb +49 -0
  114. data/lib/central/cli/services/add_env_command.rb +19 -0
  115. data/lib/central/cli/services/add_secret_command.rb +24 -0
  116. data/lib/central/cli/services/container_command.rb +8 -0
  117. data/lib/central/cli/services/containers_command.rb +32 -0
  118. data/lib/central/cli/services/create_command.rb +90 -0
  119. data/lib/central/cli/services/delete_command.rb +19 -0
  120. data/lib/central/cli/services/deploy_command.rb +21 -0
  121. data/lib/central/cli/services/env_command.rb +11 -0
  122. data/lib/central/cli/services/envs/add_command.rb +19 -0
  123. data/lib/central/cli/services/envs/list_command.rb +20 -0
  124. data/lib/central/cli/services/envs/remove_command.rb +18 -0
  125. data/lib/central/cli/services/envs_command.rb +20 -0
  126. data/lib/central/cli/services/link_command.rb +26 -0
  127. data/lib/central/cli/services/list_command.rb +42 -0
  128. data/lib/central/cli/services/logs_command.rb +57 -0
  129. data/lib/central/cli/services/monitor_command.rb +58 -0
  130. data/lib/central/cli/services/remove_command.rb +17 -0
  131. data/lib/central/cli/services/remove_env_command.rb +18 -0
  132. data/lib/central/cli/services/remove_secret_command.rb +28 -0
  133. data/lib/central/cli/services/restart_command.rb +17 -0
  134. data/lib/central/cli/services/scale_command.rb +17 -0
  135. data/lib/central/cli/services/secret_command.rb +9 -0
  136. data/lib/central/cli/services/secrets/link_command.rb +24 -0
  137. data/lib/central/cli/services/secrets/unlink_command.rb +28 -0
  138. data/lib/central/cli/services/services_helper.rb +360 -0
  139. data/lib/central/cli/services/show_command.rb +18 -0
  140. data/lib/central/cli/services/start_command.rb +17 -0
  141. data/lib/central/cli/services/stats_command.rb +74 -0
  142. data/lib/central/cli/services/stop_command.rb +17 -0
  143. data/lib/central/cli/services/unlink_command.rb +25 -0
  144. data/lib/central/cli/services/update_command.rb +78 -0
  145. data/lib/central/cli/stack_command.rb +32 -0
  146. data/lib/central/cli/stack_options.rb +11 -0
  147. data/lib/central/cli/stacks/add_user_command.rb +18 -0
  148. data/lib/central/cli/stacks/audit_log_command.rb +21 -0
  149. data/lib/central/cli/stacks/cloud_config_command.rb +41 -0
  150. data/lib/central/cli/stacks/common.rb +95 -0
  151. data/lib/central/cli/stacks/create_command.rb +26 -0
  152. data/lib/central/cli/stacks/current_command.rb +25 -0
  153. data/lib/central/cli/stacks/env_command.rb +32 -0
  154. data/lib/central/cli/stacks/list_command.rb +35 -0
  155. data/lib/central/cli/stacks/list_users_command.rb +26 -0
  156. data/lib/central/cli/stacks/logs_command.rb +81 -0
  157. data/lib/central/cli/stacks/remove_command.rb +26 -0
  158. data/lib/central/cli/stacks/remove_user_command.rb +17 -0
  159. data/lib/central/cli/stacks/show_command.rb +19 -0
  160. data/lib/central/cli/stacks/trusted_subnets/add_command.rb +16 -0
  161. data/lib/central/cli/stacks/trusted_subnets/list_command.rb +17 -0
  162. data/lib/central/cli/stacks/trusted_subnets/remove_command.rb +20 -0
  163. data/lib/central/cli/stacks/update_command.rb +27 -0
  164. data/lib/central/cli/stacks/use_command.rb +21 -0
  165. data/lib/central/cli/stacks/user_command.rb +11 -0
  166. data/lib/central/cli/stacks/users/add_command.rb +18 -0
  167. data/lib/central/cli/stacks/users/list_command.rb +18 -0
  168. data/lib/central/cli/stacks/users/remove_command.rb +17 -0
  169. data/lib/central/cli/user/forgot_password_command.rb +16 -0
  170. data/lib/central/cli/user/reset_password_command.rb +21 -0
  171. data/lib/central/cli/user/verify_command.rb +22 -0
  172. data/lib/central/cli/user_command.rb +12 -0
  173. data/lib/central/cli/vault/list_command.rb +25 -0
  174. data/lib/central/cli/vault/read_command.rb +17 -0
  175. data/lib/central/cli/vault/remove_command.rb +14 -0
  176. data/lib/central/cli/vault/update_command.rb +18 -0
  177. data/lib/central/cli/vault/write_command.rb +22 -0
  178. data/lib/central/cli/vault_command.rb +16 -0
  179. data/lib/central/cli/version.rb +5 -0
  180. data/lib/central/cli/version_command.rb +22 -0
  181. data/lib/central/cli/vpn/config_command.rb +25 -0
  182. data/lib/central/cli/vpn/create_command.rb +71 -0
  183. data/lib/central/cli/vpn/delete_command.rb +21 -0
  184. data/lib/central/cli/vpn/remove_command.rb +19 -0
  185. data/lib/central/cli/vpn_command.rb +13 -0
  186. data/lib/central/cli/whoami_command.rb +20 -0
  187. data/lib/central/client.rb +208 -0
  188. data/lib/central/errors.rb +10 -0
  189. data/lib/central/machine/aws.rb +14 -0
  190. data/lib/central/machine/aws/auth_provisioner.rb +161 -0
  191. data/lib/central/machine/aws/cloudinit.yml +71 -0
  192. data/lib/central/machine/aws/cloudinit_master.yml +118 -0
  193. data/lib/central/machine/aws/cloudinit_oauth.yml +76 -0
  194. data/lib/central/machine/aws/common.rb +31 -0
  195. data/lib/central/machine/aws/master_provisioner.rb +171 -0
  196. data/lib/central/machine/aws/node_destroyer.rb +46 -0
  197. data/lib/central/machine/aws/node_provisioner.rb +214 -0
  198. data/lib/central/machine/azure.rb +13 -0
  199. data/lib/central/machine/azure/cloudinit.yml +64 -0
  200. data/lib/central/machine/azure/cloudinit_master.yml +106 -0
  201. data/lib/central/machine/azure/logger.rb +26 -0
  202. data/lib/central/machine/azure/master_provisioner.rb +125 -0
  203. data/lib/central/machine/azure/node_destroyer.rb +52 -0
  204. data/lib/central/machine/azure/node_provisioner.rb +126 -0
  205. data/lib/central/machine/cert_helper.rb +39 -0
  206. data/lib/central/machine/cloud_config/cloudinit.yml +70 -0
  207. data/lib/central/machine/cloud_config/node_generator.rb +27 -0
  208. data/lib/central/machine/common.rb +16 -0
  209. data/lib/central/machine/digital_ocean.rb +13 -0
  210. data/lib/central/machine/digital_ocean/cloudinit.yml +64 -0
  211. data/lib/central/machine/digital_ocean/cloudinit_master.yml +118 -0
  212. data/lib/central/machine/digital_ocean/master_provisioner.rb +99 -0
  213. data/lib/central/machine/digital_ocean/node_destroyer.rb +40 -0
  214. data/lib/central/machine/digital_ocean/node_provisioner.rb +81 -0
  215. data/lib/central/machine/random_name.rb +39 -0
  216. data/lib/central/machine/vagrant.rb +12 -0
  217. data/lib/central/machine/vagrant/Vagrantfile.master.rb.erb +116 -0
  218. data/lib/central/machine/vagrant/Vagrantfile.node.rb.erb +32 -0
  219. data/lib/central/machine/vagrant/cloudinit.yml +73 -0
  220. data/lib/central/machine/vagrant/master_destroyer.rb +34 -0
  221. data/lib/central/machine/vagrant/master_provisioner.rb +79 -0
  222. data/lib/central/machine/vagrant/node_destroyer.rb +38 -0
  223. data/lib/central/machine/vagrant/node_provisioner.rb +68 -0
  224. data/lib/central/scripts/completer +157 -0
  225. data/lib/central/scripts/init +11 -0
  226. data/spec/central/cli/app/common_spec.rb +150 -0
  227. data/spec/central/cli/app/deploy_command_spec.rb +598 -0
  228. data/spec/central/cli/app/docker_helper_spec.rb +102 -0
  229. data/spec/central/cli/app/scale_spec.rb +49 -0
  230. data/spec/central/cli/common_spec.rb +117 -0
  231. data/spec/central/cli/login_command_spec.rb +31 -0
  232. data/spec/central/cli/master/current_command_spec.rb +55 -0
  233. data/spec/central/cli/master/use_command_spec.rb +37 -0
  234. data/spec/central/cli/master/users/invite_command_spec.rb +34 -0
  235. data/spec/central/cli/master/users/remove_command_spec.rb +26 -0
  236. data/spec/central/cli/master/users/roles/add_command_spec.rb +34 -0
  237. data/spec/central/cli/master/users/roles/remove_command_spec.rb +34 -0
  238. data/spec/central/cli/register_command_spec.rb +56 -0
  239. data/spec/central/cli/services/containers_command_spec.rb +40 -0
  240. data/spec/central/cli/services/link_command_spec.rb +38 -0
  241. data/spec/central/cli/services/restart_command_spec.rb +27 -0
  242. data/spec/central/cli/services/secrets/link_command_spec.rb +59 -0
  243. data/spec/central/cli/services/secrets/unlink_command_spec.rb +48 -0
  244. data/spec/central/cli/services/services_helper_spec.rb +170 -0
  245. data/spec/central/cli/services/unlink_command_spec.rb +38 -0
  246. data/spec/central/cli/stacks/trusted_subnets/add_command_spec.rb +37 -0
  247. data/spec/central/cli/stacks/trusted_subnets/list_command_spec.rb +30 -0
  248. data/spec/central/cli/stacks/trusted_subnets/remove_command_spec.rb +37 -0
  249. data/spec/central/cli/version_command_spec.rb +16 -0
  250. data/spec/fixtures/central.yml +17 -0
  251. data/spec/fixtures/docker-compose.yml +8 -0
  252. data/spec/fixtures/mysql.yml +3 -0
  253. data/spec/fixtures/wordpress-scaled.yml +3 -0
  254. data/spec/fixtures/wordpress.yml +2 -0
  255. data/spec/spec_helper.rb +27 -0
  256. data/spec/support/client_helpers.rb +30 -0
  257. data/spec/support/fixtures_helpers.rb +7 -0
  258. data/tasks/rspec.rake +5 -0
  259. metadata +463 -0
@@ -0,0 +1,48 @@
1
+ require 'yaml'
2
+ require_relative 'common'
3
+
4
+ module Central::Cli::Apps
5
+ class DockerComposeGenerator
6
+ include Common
7
+
8
+ attr_reader :docker_compose_file
9
+
10
+ def initialize(filename)
11
+ @docker_compose_file = filename
12
+ end
13
+
14
+ def generate(procfile, addons, env_file)
15
+ if procfile.keys.size > 0
16
+ # generate services found in Procfile
17
+ docker_compose = {}
18
+ procfile.keys.each do |service|
19
+ docker_compose[service] = { 'build' => '.' }
20
+ if app_json && service == 'web' # Heroku generates PORT env variable so should we do too
21
+ docker_compose[service]['environment'] = ['PORT=5000']
22
+ docker_compose[service]['ports'] = ['5000:5000']
23
+ end
24
+ docker_compose[service]['command'] = "/start #{service}" if service != 'web'
25
+ docker_compose[service]['env_file'] = env_file if env_file
26
+
27
+ # generate addon services
28
+ addons.each do |addon|
29
+ addon_service = addon.split(':')[0]
30
+ addon_service.slice!('heroku-')
31
+ next unless valid_addons.key?(addon_service)
32
+ docker_compose[service]['links'] = [] unless docker_compose[service]['links']
33
+ docker_compose[service]['links'] << "#{addon_service}:#{addon_service}"
34
+ docker_compose[service]['environment'] = [] unless docker_compose[service]['environment']
35
+ docker_compose[service]['environment'] += valid_addons[addon_service]['environment']
36
+ docker_compose[addon_service] = { 'image' => valid_addons[addon_service]['image'] }
37
+ end
38
+ end
39
+ else
40
+ # no Procfile found, create dummy web service
41
+ docker_compose = { 'web' => { 'build' => '.' } }
42
+ docker_compose['web']['env_file'] = env_file if env_file
43
+ end
44
+ # create docker-compose.yml file
45
+ create_yml(docker_compose, docker_compose_file)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,85 @@
1
+ module Central::Cli::Apps
2
+ module DockerHelper
3
+ # @param [Hash] services
4
+ # @param [Boolean] force_build
5
+ # @param [Boolean] no_cache
6
+ def process_docker_images(services, force_build = false, no_cache = false)
7
+ if services.none? { |_name, service| service['build'] }
8
+ puts 'Not found any service with build option'
9
+ return
10
+ end
11
+
12
+ services.each do |_name, service|
13
+ next unless service['build'] && (!image_exist?(service['image']) || force_build)
14
+ dockerfile = service['dockerfile'] || 'Dockerfile'
15
+ unless validate_image_name(service['image'])
16
+ abort("'#{service['image']}' is not valid Docker image name")
17
+ end
18
+ unless dockerfile_exist?(service['build'], dockerfile)
19
+ abort("'#{service['build']}' does not have #{dockerfile}")
20
+ end
21
+ if service['hooks'] && service['hooks']['pre_build']
22
+ puts 'Running pre_build hook'.colorize(:cyan)
23
+ run_pre_build_hook(service['hooks']['pre_build'])
24
+ end
25
+ puts "Building image #{service['image'].colorize(:cyan)}"
26
+ build_docker_image(service['image'], service['build'], dockerfile, no_cache)
27
+ puts "Pushing image #{service['image'].colorize(:cyan)} to registry"
28
+ push_docker_image(service['image'])
29
+ end
30
+ end
31
+
32
+ # @param [String] name
33
+ # @return [Boolean]
34
+ def validate_image_name(name)
35
+ !(/^[\w.\/\-:]+:?+[\w+.]+$/ =~ name).nil?
36
+ end
37
+
38
+ # @param [String] name
39
+ # @param [String] path
40
+ # @param [String] dockerfile
41
+ # @param [Boolean] no_cache
42
+ # @return [Integer]
43
+ def build_docker_image(name, path, dockerfile, no_cache = false)
44
+ cmd = ["docker build -t #{name}"]
45
+ if dockerfile != 'Dockerfile'
46
+ cmd << "-f #{File.join(File.expand_path(path), dockerfile)}"
47
+ end
48
+ cmd << '--no-cache' if no_cache
49
+ cmd << path
50
+ ret = system(cmd.join(' '))
51
+ abort("Failed to build image #{name.colorize(:cyan)}") unless ret
52
+ ret
53
+ end
54
+
55
+ # @param [String] image
56
+ # @return [Integer]
57
+ def push_docker_image(image)
58
+ ret = system("docker push #{image}")
59
+ abort("Failed to push image #{image.colorize(:cyan)}") unless ret
60
+ ret
61
+ end
62
+
63
+ # @param [String] image
64
+ # @return [Boolean]
65
+ def image_exist?(image)
66
+ `docker history #{image} 2>&1`; $CHILD_STATUS.success?
67
+ end
68
+
69
+ # @param [String] path
70
+ # @param [String] dockerfile
71
+ # @return [Boolean]
72
+ def dockerfile_exist?(path, dockerfile)
73
+ file = File.join(File.expand_path(path), dockerfile)
74
+ File.exist?(file)
75
+ end
76
+
77
+ # @param [Hash] hook
78
+ def run_pre_build_hook(hook)
79
+ hook.each do |h|
80
+ ret = system(h['cmd'])
81
+ abort("Failed to run pre_build hook: #{h['name']}!".colorize(:red)) unless ret
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,15 @@
1
+ require 'yaml'
2
+ require_relative 'common'
3
+
4
+ module Central::Cli::Apps
5
+ class DockerfileGenerator
6
+ include Common
7
+
8
+ def generate(base_image)
9
+ dockerfile = File.new('Dockerfile', 'w')
10
+ dockerfile.puts "FROM #{base_image}"
11
+ dockerfile.puts 'CMD ["/start", "web"]'
12
+ dockerfile.close
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,91 @@
1
+ require 'securerandom'
2
+ require_relative 'common'
3
+ require_relative 'dockerfile_generator'
4
+ require_relative 'docker_compose_generator'
5
+ require_relative 'central_yml_generator'
6
+
7
+ module Central::Cli::Apps
8
+ class InitCommand < Clamp::Command
9
+ include Central::Cli::Common
10
+ include Common
11
+
12
+ option ['-f', '--file'], 'FILE', 'Specify a docker-compose file', attribute_name: :docker_compose_file, default: 'docker-compose.yml'
13
+ option ['-i', '--image-name'], 'IMAGE_NAME', 'Specify a docker image name'
14
+ option ['-b', '--base-image'], 'BASE_IMAGE_NAME', 'Specify a docker base image name', default: 'central/buildstep'
15
+ option ['-p', '--project-name'], 'NAME', 'Specify an alternate project name (default: directory name)'
16
+
17
+ attr_reader :service_prefix
18
+
19
+ def execute
20
+ require 'highline/import'
21
+
22
+ @service_prefix = project_name || File.basename(Dir.getwd)
23
+
24
+ if File.exist?('Dockerfile')
25
+ puts 'Found Dockerfile'
26
+ elsif create_dockerfile?
27
+ puts "Creating #{'Dockerfile'.colorize(:cyan)}"
28
+ DockerfileGenerator.new.generate(base_image)
29
+ end
30
+
31
+ procfile = if File.exist?('Procfile')
32
+ YAML.load(File.read('Procfile'))
33
+ else
34
+ {}
35
+ end
36
+
37
+ app_env = create_env_file(app_json)
38
+ addons = app_json['addons'] || []
39
+
40
+ if File.exist?(docker_compose_file)
41
+ puts "Found #{docker_compose_file}."
42
+ elsif create_docker_compose_yml?
43
+ puts "Creating #{docker_compose_file.colorize(:cyan)}"
44
+ docker_compose_generator = DockerComposeGenerator.new(docker_compose_file)
45
+ docker_compose_generator.generate(procfile, addons, app_env)
46
+ end
47
+
48
+ if File.exist?('central.yml')
49
+ puts "Updating #{'central.yml'.colorize(:cyan)}"
50
+ else
51
+ puts "Creating #{'central.yml'.colorize(:cyan)}"
52
+ end
53
+
54
+ central_yml_generator = CentralYmlGenerator.new(image_name, service_prefix)
55
+ if File.exist?(docker_compose_file)
56
+ central_yml_generator.generate_from_compose_file(docker_compose_file)
57
+ else
58
+ central_yml_generator.generate(procfile, addons, app_env)
59
+ end
60
+
61
+ puts "Your app is ready! Deploy with 'cm app deploy'.".colorize(:green)
62
+ end
63
+
64
+ protected
65
+
66
+ def create_dockerfile?
67
+ ['', 'y', 'yes'].include? ask('Dockerfile not found. Do you want to create it? [Yn]: ').downcase
68
+ end
69
+
70
+ def create_env_file(app_json)
71
+ if app_json['env']
72
+ app_env = File.new('.env', 'w')
73
+ app_json['env'].each do |key, env|
74
+ value = if env['generator'] == 'secret'
75
+ SecureRandom.hex(64)
76
+ else
77
+ env['value']
78
+ end
79
+ app_env.puts "#{key}=#{value}"
80
+ end
81
+ app_env.close
82
+ return '.env'
83
+ end
84
+ nil
85
+ end
86
+
87
+ def create_docker_compose_yml?
88
+ ['', 'y', 'yes'].include? ask("#{docker_compose_file} not found. Do you want to create it? [Yn]: ").downcase
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,68 @@
1
+ require_relative 'common'
2
+ require 'tty'
3
+
4
+ module Central::Cli::Apps
5
+ class ListCommand < Clamp::Command
6
+ include Central::Cli::Common
7
+ include Central::Cli::StackOptions
8
+ include Common
9
+
10
+ option ['-f', '--file'], 'FILE', 'Specify an alternate Central compose file', attribute_name: :filename, default: 'central.yml'
11
+ option ['-p', '--project-name'], 'NAME', 'Specify an alternate project name (default: directory name)'
12
+
13
+ parameter '[SERVICE] ...', 'Services to start'
14
+
15
+ attr_reader :services, :service_prefix
16
+
17
+ def execute
18
+ require_config_file(filename)
19
+
20
+ @service_prefix = project_name || current_dir
21
+ @services = load_services(filename, service_list, service_prefix)
22
+ if services.size > 0
23
+ show_services(services)
24
+ elsif !service_list.empty?
25
+ puts "No such service: #{service_list.join(', ')}".colorize(:red)
26
+ end
27
+ end
28
+
29
+ def show_services(services)
30
+ header = %w(Name Images Instances Stateful State Ports)
31
+ rows = []
32
+
33
+ services.each do |service_name, _opts|
34
+ service = begin
35
+ get_service(token, prefixed_name(service_name))
36
+ rescue
37
+ false
38
+ end
39
+ if service
40
+ name = service['name'].sub("#{@service_prefix}-", '')
41
+ state = service['stateful'] ? 'yes' : 'no'
42
+ ports = service['ports'].map do|p|
43
+ "#{p['ip']}:#{p['node_port']}->#{p['container_port']}/#{p['protocol']}"
44
+ end.join(', ')
45
+ running = service['instances']['running']
46
+ desired = service['container_count']
47
+ instances = "#{running} / #{desired}"
48
+ rows << [
49
+ name,
50
+ service['image'],
51
+ instances,
52
+ state,
53
+ (service['state'] ? ' ✓ '.colorize(:green) : ' ✘ '.colorize(:red)),
54
+ ports
55
+ ]
56
+ else
57
+ rows << [service_name.colorize(:yellow), '-', '-', '-', '-', '-']
58
+ end
59
+ end
60
+
61
+ ttable = TTY::Table.new header: header, rows: Array.new(rows)
62
+ renderer = TTY::Table::Renderer::Unicode.new(ttable)
63
+ renderer.border.style = :cyan
64
+ renderer.padding = [0, 1, 0, 1]
65
+ puts renderer.render
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,76 @@
1
+ require_relative 'common'
2
+
3
+ module Central::Cli::Apps
4
+ class LogsCommand < Clamp::Command
5
+ include Central::Cli::Common
6
+ include Central::Cli::StackOptions
7
+ include Common
8
+
9
+ option ['-f', '--file'], 'FILE', 'Specify an alternate Central compose file', attribute_name: :filename, default: 'central.yml'
10
+ option ['-p', '--project-name'], 'NAME', 'Specify an alternate project name (default: directory name)'
11
+ option ['-l', '--lines'], 'LINES', 'How many lines to show', default: '100'
12
+ option '--since', 'SINCE', 'Show logs since given timestamp'
13
+ option ['-t', '--tail'], :flag, 'Tail (follow) logs', default: false
14
+ parameter '[SERVICE] ...', 'Show only specified service logs'
15
+
16
+ attr_reader :services, :service_prefix
17
+
18
+ def execute
19
+ require_config_file(filename)
20
+
21
+ @service_prefix = project_name || current_dir
22
+ @services = load_services(filename, service_list, service_prefix)
23
+ if services.size > 0
24
+ show_logs(services)
25
+ elsif !service_list.empty?
26
+ puts "No such service: #{service_list.join(', ')}".colorize(:red)
27
+ end
28
+ end
29
+
30
+ def show_logs(services)
31
+ last_id = nil
32
+ loop do
33
+ query_params = []
34
+ query_params << "from=#{last_id}" unless last_id.nil?
35
+ query_params << "limit=#{lines}"
36
+ query_params << "since=#{since}" if !since.nil? && last_id.nil?
37
+ logs = []
38
+ services.each do |service_name, _opts|
39
+ service = begin
40
+ get_service(token, prefixed_name(service_name))
41
+ rescue
42
+ false
43
+ end
44
+ result = client(token).get("services/#{service['id']}/container_logs?#{query_params.join('&')}") if service
45
+ logs += result['logs'] if result && result['logs']
46
+ end
47
+ logs.sort! { |x, y| DateTime.parse(x['created_at']) <=> DateTime.parse(y['created_at']) }
48
+ logs.each do |log|
49
+ color = color_for_container(log['name'])
50
+ prefix = "#{log['created_at']} #{log['name']}:".colorize(color)
51
+ puts "#{prefix} #{log['data']}"
52
+ last_id = log['id']
53
+ end
54
+ break unless tail?
55
+ sleep(2)
56
+ end
57
+ end
58
+
59
+ def color_for_container(container_id)
60
+ color_maps[container_id] = colors.shift unless color_maps[container_id]
61
+ color_maps[container_id].to_sym
62
+ end
63
+
64
+ def color_maps
65
+ @color_maps ||= {}
66
+ end
67
+
68
+ def colors
69
+ if @colors.nil? || @colors.size == 0
70
+ @colors = [:green, :magenta, :yellow, :cyan, :red,
71
+ :light_green, :light_yellow, :ligh_magenta, :light_cyan, :light_red]
72
+ end
73
+ @colors
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,93 @@
1
+ require_relative 'common'
2
+
3
+ module Central::Cli::Apps
4
+ class MonitorCommand < Clamp::Command
5
+ include Central::Cli::Common
6
+ include Central::Cli::StackOptions
7
+ include Common
8
+
9
+ option ['-f', '--file'], 'FILE', 'Specify an alternate Central compose file', attribute_name: :filename, default: 'central.yml'
10
+ option ['-p', '--project-name'], 'NAME', 'Specify an alternate project name (default: directory name)'
11
+
12
+ parameter '[SERVICE] ...', 'Services to start'
13
+
14
+ attr_reader :services, :service_prefix
15
+
16
+ def execute
17
+ require_config_file(filename)
18
+
19
+ @service_prefix = project_name || current_dir
20
+ @services = load_services(filename, service_list, service_prefix)
21
+ if services.size > 0
22
+ show_monitor(services)
23
+ elsif !service_list.empty?
24
+ puts "No such service: #{service_list.join(', ')}".colorize(:red)
25
+ end
26
+ end
27
+
28
+ def show_monitor(services)
29
+ require_api_url
30
+ token = require_token
31
+ loop do
32
+ nodes = {}
33
+ services.each do |name, _data|
34
+ service = prefixed_name(name)
35
+ result = begin
36
+ client(token).get("services/#{current_stack}/#{service}/containers")
37
+ rescue
38
+ nil
39
+ end
40
+ next unless result
41
+ services[name]['instances'] = result['containers'].size
42
+ result['containers'].each do |container|
43
+ container['service'] = name
44
+ nodes[container['node']['name']] ||= []
45
+ nodes[container['node']['name']] << container
46
+ end
47
+ end
48
+ clear_terminal
49
+ puts 'services:'
50
+ services.each do |name, data|
51
+ color = color_for_service(name)
52
+ puts " #{"■".colorize(color)} #{name} (#{data['instances']} instances)"
53
+ end
54
+ puts 'nodes:'
55
+ node_names = nodes.keys.sort
56
+ node_names.each do |name|
57
+ containers = nodes[name]
58
+ puts " #{name} (#{containers.size} instances)"
59
+ print ' '
60
+ containers.each do |container|
61
+ icon = "■"
62
+ icon = "□" if container['status'] != 'running'
63
+ color = color_for_service(container['service'])
64
+ print icon.colorize(color)
65
+ end
66
+ puts ''
67
+ end
68
+ sleep 1
69
+ end
70
+ end
71
+
72
+ def color_for_service(service)
73
+ color_maps[service] = colors.shift unless color_maps[service]
74
+ color_maps[service].to_sym
75
+ end
76
+
77
+ def color_maps
78
+ @color_maps ||= {}
79
+ end
80
+
81
+ def colors
82
+ if @colors.nil? || @colors.size == 0
83
+ @colors = [:green, :magenta, :yellow, :cyan, :red,
84
+ :light_green, :light_yellow, :ligh_magenta, :light_cyan, :light_red]
85
+ end
86
+ @colors
87
+ end
88
+
89
+ def clear_terminal
90
+ print "\e[H\e[2J"
91
+ end
92
+ end
93
+ end