central-cli 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.dockerignore +3 -0
- data/.gitignore +15 -0
- data/.rspec +6 -0
- data/.rubocop.yml +5 -0
- data/Dockerfile +15 -0
- data/Gemfile +10 -0
- data/LICENSE +191 -0
- data/README.md +39 -0
- data/Rakefile +9 -0
- data/VERSION +1 -0
- data/bin/cm +85 -0
- data/central-cli.gemspec +35 -0
- data/central-docker.sh +6 -0
- data/lib/central/cli/app_command.rb +29 -0
- data/lib/central/cli/apps/build_command.rb +24 -0
- data/lib/central/cli/apps/central_yml_generator.rb +88 -0
- data/lib/central/cli/apps/common.rb +166 -0
- data/lib/central/cli/apps/deploy_command.rb +191 -0
- data/lib/central/cli/apps/docker_compose_generator.rb +48 -0
- data/lib/central/cli/apps/docker_helper.rb +85 -0
- data/lib/central/cli/apps/dockerfile_generator.rb +15 -0
- data/lib/central/cli/apps/init_command.rb +91 -0
- data/lib/central/cli/apps/list_command.rb +68 -0
- data/lib/central/cli/apps/logs_command.rb +76 -0
- data/lib/central/cli/apps/monitor_command.rb +93 -0
- data/lib/central/cli/apps/remove_command.rb +80 -0
- data/lib/central/cli/apps/restart_command.rb +38 -0
- data/lib/central/cli/apps/scale_command.rb +31 -0
- data/lib/central/cli/apps/show_command.rb +23 -0
- data/lib/central/cli/apps/start_command.rb +39 -0
- data/lib/central/cli/apps/stop_command.rb +39 -0
- data/lib/central/cli/auth/aws/create_command.rb +34 -0
- data/lib/central/cli/auth/aws_command.rb +7 -0
- data/lib/central/cli/auth/list_command.rb +28 -0
- data/lib/central/cli/auth_command.rb +9 -0
- data/lib/central/cli/bytes_helper.rb +38 -0
- data/lib/central/cli/common.rb +148 -0
- data/lib/central/cli/container_command.rb +10 -0
- data/lib/central/cli/containers/exec_command.rb +21 -0
- data/lib/central/cli/containers/inspect_command.rb +22 -0
- data/lib/central/cli/etcd/common.rb +7 -0
- data/lib/central/cli/etcd/get_command.rb +26 -0
- data/lib/central/cli/etcd/list_command.rb +31 -0
- data/lib/central/cli/etcd/mkdir_command.rb +21 -0
- data/lib/central/cli/etcd/remove_command.rb +25 -0
- data/lib/central/cli/etcd/set_command.rb +22 -0
- data/lib/central/cli/etcd_command.rb +16 -0
- data/lib/central/cli/external_registries/add_command.rb +21 -0
- data/lib/central/cli/external_registries/delete_command.rb +15 -0
- data/lib/central/cli/external_registries/list_command.rb +27 -0
- data/lib/central/cli/external_registries/remove_command.rb +13 -0
- data/lib/central/cli/external_registry_command.rb +14 -0
- data/lib/central/cli/login_command.rb +121 -0
- data/lib/central/cli/logout_command.rb +7 -0
- data/lib/central/cli/master/aws/create_command.rb +41 -0
- data/lib/central/cli/master/aws_command.rb +7 -0
- data/lib/central/cli/master/azure/create_command.rb +39 -0
- data/lib/central/cli/master/azure_command.rb +11 -0
- data/lib/central/cli/master/digital_ocean/create_command.rb +35 -0
- data/lib/central/cli/master/digital_ocean_command.rb +11 -0
- data/lib/central/cli/master/list_command.rb +28 -0
- data/lib/central/cli/master/use_command.rb +34 -0
- data/lib/central/cli/master/users/add_role_command.rb +26 -0
- data/lib/central/cli/master/users/invite_command.rb +24 -0
- data/lib/central/cli/master/users/list_command.rb +18 -0
- data/lib/central/cli/master/users/remove_command.rb +22 -0
- data/lib/central/cli/master/users/remove_role_command.rb +25 -0
- data/lib/central/cli/master/users_command.rb +15 -0
- data/lib/central/cli/master/vagrant/create_command.rb +25 -0
- data/lib/central/cli/master/vagrant/restart_command.rb +20 -0
- data/lib/central/cli/master/vagrant/ssh_command.rb +15 -0
- data/lib/central/cli/master/vagrant/start_command.rb +20 -0
- data/lib/central/cli/master/vagrant/stop_command.rb +20 -0
- data/lib/central/cli/master/vagrant/terminate_command.rb +13 -0
- data/lib/central/cli/master/vagrant_command.rb +21 -0
- data/lib/central/cli/master_command.rb +19 -0
- data/lib/central/cli/node_command.rb +30 -0
- data/lib/central/cli/nodes/add_label_command.rb +19 -0
- data/lib/central/cli/nodes/aws/create_command.rb +40 -0
- data/lib/central/cli/nodes/aws/restart_command.rb +29 -0
- data/lib/central/cli/nodes/aws/terminate_command.rb +21 -0
- data/lib/central/cli/nodes/aws_command.rb +14 -0
- data/lib/central/cli/nodes/azure/create_command.rb +40 -0
- data/lib/central/cli/nodes/azure/restart_command.rb +31 -0
- data/lib/central/cli/nodes/azure/terminate_command.rb +21 -0
- data/lib/central/cli/nodes/azure_command.rb +14 -0
- data/lib/central/cli/nodes/digital_ocean/create_command.rb +32 -0
- data/lib/central/cli/nodes/digital_ocean/restart_command.rb +27 -0
- data/lib/central/cli/nodes/digital_ocean/terminate_command.rb +19 -0
- data/lib/central/cli/nodes/digital_ocean_command.rb +14 -0
- data/lib/central/cli/nodes/label_command.rb +12 -0
- data/lib/central/cli/nodes/labels/add_command.rb +19 -0
- data/lib/central/cli/nodes/labels/remove_command.rb +23 -0
- data/lib/central/cli/nodes/list_command.rb +62 -0
- data/lib/central/cli/nodes/remove_command.rb +16 -0
- data/lib/central/cli/nodes/remove_label_command.rb +23 -0
- data/lib/central/cli/nodes/show_command.rb +49 -0
- data/lib/central/cli/nodes/ssh_command.rb +31 -0
- data/lib/central/cli/nodes/update_command.rb +20 -0
- data/lib/central/cli/nodes/vagrant/create_command.rb +27 -0
- data/lib/central/cli/nodes/vagrant/restart_command.rb +26 -0
- data/lib/central/cli/nodes/vagrant/ssh_command.rb +21 -0
- data/lib/central/cli/nodes/vagrant/start_command.rb +26 -0
- data/lib/central/cli/nodes/vagrant/stop_command.rb +26 -0
- data/lib/central/cli/nodes/vagrant/terminate_command.rb +17 -0
- data/lib/central/cli/nodes/vagrant_command.rb +20 -0
- data/lib/central/cli/register_command.rb +21 -0
- data/lib/central/cli/registry/create_command.rb +144 -0
- data/lib/central/cli/registry/delete_command.rb +22 -0
- data/lib/central/cli/registry/remove_command.rb +19 -0
- data/lib/central/cli/registry_command.rb +11 -0
- data/lib/central/cli/service_command.rb +49 -0
- data/lib/central/cli/services/add_env_command.rb +19 -0
- data/lib/central/cli/services/add_secret_command.rb +24 -0
- data/lib/central/cli/services/container_command.rb +8 -0
- data/lib/central/cli/services/containers_command.rb +32 -0
- data/lib/central/cli/services/create_command.rb +90 -0
- data/lib/central/cli/services/delete_command.rb +19 -0
- data/lib/central/cli/services/deploy_command.rb +21 -0
- data/lib/central/cli/services/env_command.rb +11 -0
- data/lib/central/cli/services/envs/add_command.rb +19 -0
- data/lib/central/cli/services/envs/list_command.rb +20 -0
- data/lib/central/cli/services/envs/remove_command.rb +18 -0
- data/lib/central/cli/services/envs_command.rb +20 -0
- data/lib/central/cli/services/link_command.rb +26 -0
- data/lib/central/cli/services/list_command.rb +42 -0
- data/lib/central/cli/services/logs_command.rb +57 -0
- data/lib/central/cli/services/monitor_command.rb +58 -0
- data/lib/central/cli/services/remove_command.rb +17 -0
- data/lib/central/cli/services/remove_env_command.rb +18 -0
- data/lib/central/cli/services/remove_secret_command.rb +28 -0
- data/lib/central/cli/services/restart_command.rb +17 -0
- data/lib/central/cli/services/scale_command.rb +17 -0
- data/lib/central/cli/services/secret_command.rb +9 -0
- data/lib/central/cli/services/secrets/link_command.rb +24 -0
- data/lib/central/cli/services/secrets/unlink_command.rb +28 -0
- data/lib/central/cli/services/services_helper.rb +360 -0
- data/lib/central/cli/services/show_command.rb +18 -0
- data/lib/central/cli/services/start_command.rb +17 -0
- data/lib/central/cli/services/stats_command.rb +74 -0
- data/lib/central/cli/services/stop_command.rb +17 -0
- data/lib/central/cli/services/unlink_command.rb +25 -0
- data/lib/central/cli/services/update_command.rb +78 -0
- data/lib/central/cli/stack_command.rb +32 -0
- data/lib/central/cli/stack_options.rb +11 -0
- data/lib/central/cli/stacks/add_user_command.rb +18 -0
- data/lib/central/cli/stacks/audit_log_command.rb +21 -0
- data/lib/central/cli/stacks/cloud_config_command.rb +41 -0
- data/lib/central/cli/stacks/common.rb +95 -0
- data/lib/central/cli/stacks/create_command.rb +26 -0
- data/lib/central/cli/stacks/current_command.rb +25 -0
- data/lib/central/cli/stacks/env_command.rb +32 -0
- data/lib/central/cli/stacks/list_command.rb +35 -0
- data/lib/central/cli/stacks/list_users_command.rb +26 -0
- data/lib/central/cli/stacks/logs_command.rb +81 -0
- data/lib/central/cli/stacks/remove_command.rb +26 -0
- data/lib/central/cli/stacks/remove_user_command.rb +17 -0
- data/lib/central/cli/stacks/show_command.rb +19 -0
- data/lib/central/cli/stacks/trusted_subnets/add_command.rb +16 -0
- data/lib/central/cli/stacks/trusted_subnets/list_command.rb +17 -0
- data/lib/central/cli/stacks/trusted_subnets/remove_command.rb +20 -0
- data/lib/central/cli/stacks/update_command.rb +27 -0
- data/lib/central/cli/stacks/use_command.rb +21 -0
- data/lib/central/cli/stacks/user_command.rb +11 -0
- data/lib/central/cli/stacks/users/add_command.rb +18 -0
- data/lib/central/cli/stacks/users/list_command.rb +18 -0
- data/lib/central/cli/stacks/users/remove_command.rb +17 -0
- data/lib/central/cli/user/forgot_password_command.rb +16 -0
- data/lib/central/cli/user/reset_password_command.rb +21 -0
- data/lib/central/cli/user/verify_command.rb +22 -0
- data/lib/central/cli/user_command.rb +12 -0
- data/lib/central/cli/vault/list_command.rb +25 -0
- data/lib/central/cli/vault/read_command.rb +17 -0
- data/lib/central/cli/vault/remove_command.rb +14 -0
- data/lib/central/cli/vault/update_command.rb +18 -0
- data/lib/central/cli/vault/write_command.rb +22 -0
- data/lib/central/cli/vault_command.rb +16 -0
- data/lib/central/cli/version.rb +5 -0
- data/lib/central/cli/version_command.rb +22 -0
- data/lib/central/cli/vpn/config_command.rb +25 -0
- data/lib/central/cli/vpn/create_command.rb +71 -0
- data/lib/central/cli/vpn/delete_command.rb +21 -0
- data/lib/central/cli/vpn/remove_command.rb +19 -0
- data/lib/central/cli/vpn_command.rb +13 -0
- data/lib/central/cli/whoami_command.rb +20 -0
- data/lib/central/client.rb +208 -0
- data/lib/central/errors.rb +10 -0
- data/lib/central/machine/aws.rb +14 -0
- data/lib/central/machine/aws/auth_provisioner.rb +161 -0
- data/lib/central/machine/aws/cloudinit.yml +71 -0
- data/lib/central/machine/aws/cloudinit_master.yml +118 -0
- data/lib/central/machine/aws/cloudinit_oauth.yml +76 -0
- data/lib/central/machine/aws/common.rb +31 -0
- data/lib/central/machine/aws/master_provisioner.rb +171 -0
- data/lib/central/machine/aws/node_destroyer.rb +46 -0
- data/lib/central/machine/aws/node_provisioner.rb +214 -0
- data/lib/central/machine/azure.rb +13 -0
- data/lib/central/machine/azure/cloudinit.yml +64 -0
- data/lib/central/machine/azure/cloudinit_master.yml +106 -0
- data/lib/central/machine/azure/logger.rb +26 -0
- data/lib/central/machine/azure/master_provisioner.rb +125 -0
- data/lib/central/machine/azure/node_destroyer.rb +52 -0
- data/lib/central/machine/azure/node_provisioner.rb +126 -0
- data/lib/central/machine/cert_helper.rb +39 -0
- data/lib/central/machine/cloud_config/cloudinit.yml +70 -0
- data/lib/central/machine/cloud_config/node_generator.rb +27 -0
- data/lib/central/machine/common.rb +16 -0
- data/lib/central/machine/digital_ocean.rb +13 -0
- data/lib/central/machine/digital_ocean/cloudinit.yml +64 -0
- data/lib/central/machine/digital_ocean/cloudinit_master.yml +118 -0
- data/lib/central/machine/digital_ocean/master_provisioner.rb +99 -0
- data/lib/central/machine/digital_ocean/node_destroyer.rb +40 -0
- data/lib/central/machine/digital_ocean/node_provisioner.rb +81 -0
- data/lib/central/machine/random_name.rb +39 -0
- data/lib/central/machine/vagrant.rb +12 -0
- data/lib/central/machine/vagrant/Vagrantfile.master.rb.erb +116 -0
- data/lib/central/machine/vagrant/Vagrantfile.node.rb.erb +32 -0
- data/lib/central/machine/vagrant/cloudinit.yml +73 -0
- data/lib/central/machine/vagrant/master_destroyer.rb +34 -0
- data/lib/central/machine/vagrant/master_provisioner.rb +79 -0
- data/lib/central/machine/vagrant/node_destroyer.rb +38 -0
- data/lib/central/machine/vagrant/node_provisioner.rb +68 -0
- data/lib/central/scripts/completer +157 -0
- data/lib/central/scripts/init +11 -0
- data/spec/central/cli/app/common_spec.rb +150 -0
- data/spec/central/cli/app/deploy_command_spec.rb +598 -0
- data/spec/central/cli/app/docker_helper_spec.rb +102 -0
- data/spec/central/cli/app/scale_spec.rb +49 -0
- data/spec/central/cli/common_spec.rb +117 -0
- data/spec/central/cli/login_command_spec.rb +31 -0
- data/spec/central/cli/master/current_command_spec.rb +55 -0
- data/spec/central/cli/master/use_command_spec.rb +37 -0
- data/spec/central/cli/master/users/invite_command_spec.rb +34 -0
- data/spec/central/cli/master/users/remove_command_spec.rb +26 -0
- data/spec/central/cli/master/users/roles/add_command_spec.rb +34 -0
- data/spec/central/cli/master/users/roles/remove_command_spec.rb +34 -0
- data/spec/central/cli/register_command_spec.rb +56 -0
- data/spec/central/cli/services/containers_command_spec.rb +40 -0
- data/spec/central/cli/services/link_command_spec.rb +38 -0
- data/spec/central/cli/services/restart_command_spec.rb +27 -0
- data/spec/central/cli/services/secrets/link_command_spec.rb +59 -0
- data/spec/central/cli/services/secrets/unlink_command_spec.rb +48 -0
- data/spec/central/cli/services/services_helper_spec.rb +170 -0
- data/spec/central/cli/services/unlink_command_spec.rb +38 -0
- data/spec/central/cli/stacks/trusted_subnets/add_command_spec.rb +37 -0
- data/spec/central/cli/stacks/trusted_subnets/list_command_spec.rb +30 -0
- data/spec/central/cli/stacks/trusted_subnets/remove_command_spec.rb +37 -0
- data/spec/central/cli/version_command_spec.rb +16 -0
- data/spec/fixtures/central.yml +17 -0
- data/spec/fixtures/docker-compose.yml +8 -0
- data/spec/fixtures/mysql.yml +3 -0
- data/spec/fixtures/wordpress-scaled.yml +3 -0
- data/spec/fixtures/wordpress.yml +2 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/client_helpers.rb +30 -0
- data/spec/support/fixtures_helpers.rb +7 -0
- data/tasks/rspec.rake +5 -0
- 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
|