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.
- 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,29 @@
|
|
|
1
|
+
require_relative 'apps/init_command'
|
|
2
|
+
require_relative 'apps/build_command'
|
|
3
|
+
require_relative 'apps/deploy_command'
|
|
4
|
+
require_relative 'apps/start_command'
|
|
5
|
+
require_relative 'apps/stop_command'
|
|
6
|
+
require_relative 'apps/restart_command'
|
|
7
|
+
require_relative 'apps/remove_command'
|
|
8
|
+
require_relative 'apps/list_command'
|
|
9
|
+
require_relative 'apps/logs_command'
|
|
10
|
+
require_relative 'apps/monitor_command'
|
|
11
|
+
require_relative 'apps/show_command'
|
|
12
|
+
require_relative 'apps/scale_command'
|
|
13
|
+
|
|
14
|
+
class Central::Cli::AppCommand < Clamp::Command
|
|
15
|
+
subcommand 'init', 'Init Central application', Central::Cli::Apps::InitCommand
|
|
16
|
+
subcommand 'build', 'Build Central services', Central::Cli::Apps::BuildCommand
|
|
17
|
+
subcommand 'deploy', 'Deploy Central services', Central::Cli::Apps::DeployCommand
|
|
18
|
+
subcommand 'scale', 'Scale services', Central::Cli::Apps::ScaleCommand
|
|
19
|
+
subcommand 'start', 'Start services', Central::Cli::Apps::StartCommand
|
|
20
|
+
subcommand 'stop', 'Stop services', Central::Cli::Apps::StopCommand
|
|
21
|
+
subcommand 'restart', 'Restart services', Central::Cli::Apps::RestartCommand
|
|
22
|
+
subcommand 'show', 'Show service details', Central::Cli::Apps::ShowCommand
|
|
23
|
+
subcommand %w(ps list ls), 'List services', Central::Cli::Apps::ListCommand
|
|
24
|
+
subcommand ['logs'], 'Show service logs', Central::Cli::Apps::LogsCommand
|
|
25
|
+
subcommand 'monitor', 'Monitor services', Central::Cli::Apps::MonitorCommand
|
|
26
|
+
subcommand %w(remove rm), 'Remove services', Central::Cli::Apps::RemoveCommand
|
|
27
|
+
def execute
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require_relative 'common'
|
|
2
|
+
require_relative 'docker_helper'
|
|
3
|
+
|
|
4
|
+
module Central::Cli::Apps
|
|
5
|
+
class BuildCommand < Clamp::Command
|
|
6
|
+
include Central::Cli::Common
|
|
7
|
+
include Common
|
|
8
|
+
include DockerHelper
|
|
9
|
+
|
|
10
|
+
option ['-p', '--project-name'], 'NAME', 'Specify an alternate project name (default: directory name)'
|
|
11
|
+
option ['-f', '--file'], 'FILE', 'Specify an alternate Central compose file', attribute_name: :filename, default: 'central.yml'
|
|
12
|
+
option ['--no-cache'], :flag, 'Do not use cache when building the image', default: false
|
|
13
|
+
parameter '[SERVICE] ...', 'Services to build'
|
|
14
|
+
|
|
15
|
+
attr_reader :services, :service_prefix
|
|
16
|
+
|
|
17
|
+
def execute
|
|
18
|
+
require_config_file(filename)
|
|
19
|
+
@service_prefix = project_name || current_dir
|
|
20
|
+
@services = load_services(filename, service_list, service_prefix)
|
|
21
|
+
process_docker_images(services, true, no_cache?)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require_relative 'common'
|
|
3
|
+
|
|
4
|
+
module Central::Cli::Apps
|
|
5
|
+
class CentralYmlGenerator
|
|
6
|
+
include Common
|
|
7
|
+
|
|
8
|
+
attr_reader :image_name, :service_prefix
|
|
9
|
+
|
|
10
|
+
def initialize(image_name, service_prefix)
|
|
11
|
+
@image_name = image_name
|
|
12
|
+
@service_prefix = service_prefix
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def generate_from_compose_file(docker_compose_file)
|
|
16
|
+
services = {}
|
|
17
|
+
# extend services from docker-compose.yml
|
|
18
|
+
file = File.read(docker_compose_file)
|
|
19
|
+
compose_services = YAML.load(file)
|
|
20
|
+
compose_services.each do |name, options|
|
|
21
|
+
services[name] = { 'extends' => { 'file' => 'docker-compose.yml', 'service' => name } }
|
|
22
|
+
if options.key?('build')
|
|
23
|
+
image = image_name || "registry.central.local/#{File.basename(Dir.getwd)}:latest"
|
|
24
|
+
services[name]['image'] = image
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# set Heroku addon service as stateful by default
|
|
28
|
+
services[name]['stateful'] = true if valid_addons.key?(name)
|
|
29
|
+
|
|
30
|
+
# we have to generate Central urls to env vars for Heroku addons
|
|
31
|
+
# redis://openredis:6379 -> redis://project-name-openredis:6379
|
|
32
|
+
next unless options['links']
|
|
33
|
+
options['links'].each do |link|
|
|
34
|
+
service_link = link.split(':').first
|
|
35
|
+
if valid_addons.key?(service_link)
|
|
36
|
+
services[name]['environment'] ||= []
|
|
37
|
+
services[name]['environment'] += valid_addons(service_prefix)[service_link]['environment']
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
create_yml(services, 'central.yml')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def generate(procfile, addons, env_file)
|
|
45
|
+
image = image_name || "registry.central.local/#{File.basename(Dir.getwd)}:latest"
|
|
46
|
+
if procfile.keys.size > 0
|
|
47
|
+
# generate services found in Procfile
|
|
48
|
+
services = {}
|
|
49
|
+
procfile.keys.each do |name|
|
|
50
|
+
services[name] = { 'image' => image }
|
|
51
|
+
services[name]['environment'] = ['PORT=5000'] if app_json && name == 'web' # Heroku generates PORT env variable so should we do too
|
|
52
|
+
services[name]['command'] = "/start #{name}" if name != 'web'
|
|
53
|
+
services[name]['env_file'] = env_file if env_file
|
|
54
|
+
|
|
55
|
+
# generate addon services
|
|
56
|
+
addons.each do |addon|
|
|
57
|
+
addon_service = addon.split(':')[0]
|
|
58
|
+
addon_service.slice!('heroku-')
|
|
59
|
+
next unless valid_addons.key?(addon_service)
|
|
60
|
+
services[name]['links'] ||= []
|
|
61
|
+
services[name]['links'] << "#{addon_service}:#{addon_service}"
|
|
62
|
+
services[name]['environment'] ||= []
|
|
63
|
+
services[name]['environment'] += valid_addons(service_prefix)[addon_service]['environment']
|
|
64
|
+
services[addon_service] = { 'image' => valid_addons[addon_service]['image'], 'stateful' => true }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
else
|
|
68
|
+
# no Procfile found, create dummy web service
|
|
69
|
+
services = { 'web' => { 'image' => image } }
|
|
70
|
+
services['web']['env_file'] = env_file if env_file
|
|
71
|
+
end
|
|
72
|
+
# create central.yml file
|
|
73
|
+
create_yml(services, 'central.yml')
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def create_yml(services, filename)
|
|
77
|
+
if File.exist?(filename)
|
|
78
|
+
central_services = YAML.load(File.read(filename))
|
|
79
|
+
services.each do |name, _options|
|
|
80
|
+
if central_services[name]
|
|
81
|
+
services[name].merge!(central_services[name])
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
super(services, filename)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require_relative '../services/services_helper'
|
|
3
|
+
|
|
4
|
+
module Central::Cli::Apps
|
|
5
|
+
module Common
|
|
6
|
+
include Central::Cli::Services::ServicesHelper
|
|
7
|
+
|
|
8
|
+
def require_config_file(filename)
|
|
9
|
+
abort("File #{filename} does not exist") unless File.exist?(filename)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @param [String] filename
|
|
13
|
+
# @param [Array<String>] service_list
|
|
14
|
+
# @param [String] prefix
|
|
15
|
+
# @return [Hash]
|
|
16
|
+
def load_services(filename, service_list, prefix)
|
|
17
|
+
services = parse_services(filename, nil, prefix)
|
|
18
|
+
services.delete_if { |name, _service| !service_list.include?(name) } unless service_list.empty?
|
|
19
|
+
services
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @return [String]
|
|
23
|
+
def token
|
|
24
|
+
@token ||= require_token
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param [String] name
|
|
28
|
+
# @return [String]
|
|
29
|
+
def prefixed_name(name)
|
|
30
|
+
return name if service_prefix.strip == ''
|
|
31
|
+
|
|
32
|
+
"#{service_prefix}-#{name}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [String]
|
|
36
|
+
def current_dir
|
|
37
|
+
File.basename(Dir.getwd)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param [String] name
|
|
41
|
+
# @return [Boolean]
|
|
42
|
+
def service_exists?(name)
|
|
43
|
+
get_service(token, prefixed_name(name))
|
|
44
|
+
rescue
|
|
45
|
+
false
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param [String] file
|
|
49
|
+
# @param [String,NilClass] name
|
|
50
|
+
# @param [String] prefix
|
|
51
|
+
# @return [Hash]
|
|
52
|
+
def parse_services(file, name = nil, prefix = '')
|
|
53
|
+
services = YAML.load(File.read(File.expand_path(file)) % { project: prefix, stack: current_stack })
|
|
54
|
+
Dir.chdir(File.dirname(File.expand_path(file))) do
|
|
55
|
+
services.each do |name, options|
|
|
56
|
+
normalize_env_vars(options)
|
|
57
|
+
next unless options.key?('extends')
|
|
58
|
+
extension_file = options['extends']['file']
|
|
59
|
+
service_name = options['extends']['service']
|
|
60
|
+
options.delete('extends')
|
|
61
|
+
services[name] = extend_options(options, extension_file, service_name, prefix)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
if name.nil?
|
|
65
|
+
services
|
|
66
|
+
else
|
|
67
|
+
abort("Service #{name} not found in #{file}") unless services.key?(name)
|
|
68
|
+
services[name]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @param [Hash] options
|
|
73
|
+
# @param [String] file
|
|
74
|
+
# @param [String] service_name
|
|
75
|
+
# @param [String] prefix
|
|
76
|
+
# @return [Hash]
|
|
77
|
+
def extend_options(options, file, service_name, prefix)
|
|
78
|
+
parent_options = parse_services(file, service_name, prefix)
|
|
79
|
+
options['environment'] = extend_env_vars(parent_options['environment'], options['environment'])
|
|
80
|
+
options['secrets'] = extend_secrets(parent_options['secrets'], options['secrets'])
|
|
81
|
+
parent_options.merge(options)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# @param [Hash] options
|
|
85
|
+
def normalize_env_vars(options)
|
|
86
|
+
if options['environment'].is_a?(Hash)
|
|
87
|
+
options['environment'] = options['environment'].map { |k, v| "#{k}=#{v}" }
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# @param [Array] from
|
|
92
|
+
# @param [Array] to
|
|
93
|
+
# @return [Array]
|
|
94
|
+
def extend_env_vars(from, to)
|
|
95
|
+
env_vars = to || []
|
|
96
|
+
if from
|
|
97
|
+
from.each do |env|
|
|
98
|
+
env_vars << env unless to && to.find { |key| key.split('=').first == env.split('=').first }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
env_vars
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @param [Array] from
|
|
105
|
+
# @param [Array] to
|
|
106
|
+
# @return [Array]
|
|
107
|
+
def extend_secrets(from, to)
|
|
108
|
+
secrets = to || []
|
|
109
|
+
if from
|
|
110
|
+
from.each do |from_secret|
|
|
111
|
+
secrets << from_secret unless to && to.any? { |to_secret| to_secret['secret'] == from_secret['secret'] }
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
secrets
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @param [Hash] services
|
|
118
|
+
# @param [String] file
|
|
119
|
+
def create_yml(services, file = 'central.yml')
|
|
120
|
+
yml = File.new(file, 'w')
|
|
121
|
+
yml.puts services.to_yaml
|
|
122
|
+
yml.close
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# @return [Hash]
|
|
126
|
+
def app_json
|
|
127
|
+
@app_json = if !@app_json && File.exist?('app.json')
|
|
128
|
+
JSON.parse(File.read('app.json'))
|
|
129
|
+
else
|
|
130
|
+
{}
|
|
131
|
+
end
|
|
132
|
+
@app_json
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def valid_addons(prefix = nil)
|
|
136
|
+
prefix = "#{prefix}-" if prefix
|
|
137
|
+
|
|
138
|
+
{
|
|
139
|
+
'openredis' => {
|
|
140
|
+
'image' => 'redis:latest',
|
|
141
|
+
'environment' => ["REDIS_URL=redis://#{prefix}openredis:6379"]
|
|
142
|
+
},
|
|
143
|
+
'redis' => {
|
|
144
|
+
'image' => 'redis:latest',
|
|
145
|
+
'environment' => ["REDIS_URL=redis://#{prefix}redis:6379"]
|
|
146
|
+
},
|
|
147
|
+
'rediscloud' => {
|
|
148
|
+
'image' => 'redis:latest',
|
|
149
|
+
'environment' => ["REDISCLOUD_URL=redis://#{prefix}rediscloud:6379"]
|
|
150
|
+
},
|
|
151
|
+
'postgresql' => {
|
|
152
|
+
'image' => 'postgres:latest',
|
|
153
|
+
'environment' => ["DATABASE_URL=postgres://#{prefix}postgres:@postgresql:5432/postgres"]
|
|
154
|
+
},
|
|
155
|
+
'mongolab' => {
|
|
156
|
+
'image' => 'mongo:latest',
|
|
157
|
+
'environment' => ["MONGOLAB_URI=#{prefix}mongolab:27017"]
|
|
158
|
+
},
|
|
159
|
+
'memcachedcloud' => {
|
|
160
|
+
'image' => 'memcached:latest',
|
|
161
|
+
'environment' => ["MEMCACHEDCLOUD_SERVERS=#{prefix}memcachedcloud:11211"]
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require_relative 'common'
|
|
3
|
+
require_relative 'docker_helper'
|
|
4
|
+
|
|
5
|
+
module Central::Cli::Apps
|
|
6
|
+
class DeployCommand < Clamp::Command
|
|
7
|
+
include Central::Cli::Common
|
|
8
|
+
include Central::Cli::StackOptions
|
|
9
|
+
include Common
|
|
10
|
+
include DockerHelper
|
|
11
|
+
|
|
12
|
+
option ['-f', '--file'], 'FILE', 'Specify an alternate Central compose file', attribute_name: :filename, default: 'central.yml'
|
|
13
|
+
option ['--no-build'], :flag, 'Don\'t build an image, even if it\'s missing', default: false
|
|
14
|
+
option ['-p', '--project-name'], 'NAME', 'Specify an alternate project name (default: directory name)'
|
|
15
|
+
option '--async', :flag, 'Run deploys async/parallel'
|
|
16
|
+
option '--force-deploy', :flag, 'Force deploy even if service does not have any changes'
|
|
17
|
+
|
|
18
|
+
parameter '[SERVICE] ...', 'Services to start'
|
|
19
|
+
|
|
20
|
+
attr_reader :services, :service_prefix, :deploy_queue
|
|
21
|
+
|
|
22
|
+
def execute
|
|
23
|
+
require_api_url
|
|
24
|
+
require_token
|
|
25
|
+
require_config_file(filename)
|
|
26
|
+
@deploy_queue = []
|
|
27
|
+
@service_prefix = project_name || current_dir
|
|
28
|
+
@services = load_services(filename, service_list, service_prefix)
|
|
29
|
+
process_docker_images(services) unless no_build?
|
|
30
|
+
create_or_update_services(services)
|
|
31
|
+
deploy_services(deploy_queue)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# @param [Hash] services
|
|
37
|
+
def create_or_update_services(services)
|
|
38
|
+
services.each do |name, config|
|
|
39
|
+
create_or_update_service(name, config)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @param [Array] queue
|
|
44
|
+
def deploy_services(queue)
|
|
45
|
+
queue.each do |service|
|
|
46
|
+
name = service['id'].split('/').last
|
|
47
|
+
options = {}
|
|
48
|
+
options[:force] = true if force_deploy?
|
|
49
|
+
deploy_service(token, name, options)
|
|
50
|
+
print "deploying #{name.sub("#{service_prefix}-", '').colorize(:cyan)}"
|
|
51
|
+
unless async?
|
|
52
|
+
wait_for_deploy_to_finish(token, service['id'])
|
|
53
|
+
else
|
|
54
|
+
puts ''
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param [String] name
|
|
60
|
+
# @param [Hash] options
|
|
61
|
+
def create_or_update_service(name, options)
|
|
62
|
+
# skip if service is already processed or it's not present
|
|
63
|
+
return nil if in_deploy_queue?(name) || !services.keys.include?(name)
|
|
64
|
+
|
|
65
|
+
# create/update linked services recursively before continuing
|
|
66
|
+
unless options['links'].nil?
|
|
67
|
+
parse_links(options['links']).each_with_index do |linked_service, index|
|
|
68
|
+
# change prefixed service name also to links options
|
|
69
|
+
options['links'][index] = "#{prefixed_name(linked_service[:name])}:#{linked_service[:alias]}"
|
|
70
|
+
create_or_update_service(linked_service[:name], services[linked_service[:name]]) unless in_deploy_queue?(linked_service[:name])
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
merge_external_links(options)
|
|
75
|
+
merge_env_vars(options)
|
|
76
|
+
|
|
77
|
+
service = if service_exists?(name)
|
|
78
|
+
update(name, options)
|
|
79
|
+
else
|
|
80
|
+
create(name, options)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
deploy_queue.push service
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @param [String] name
|
|
87
|
+
def find_service_by_name(name)
|
|
88
|
+
get_service(token, prefixed_name(name))
|
|
89
|
+
rescue
|
|
90
|
+
nil
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @param [String] name
|
|
94
|
+
# @param [Hash] options
|
|
95
|
+
def create(name, options)
|
|
96
|
+
puts "creating #{name.colorize(:cyan)}"
|
|
97
|
+
name = prefixed_name(name)
|
|
98
|
+
data = { name: name }
|
|
99
|
+
data.merge!(parse_data(options))
|
|
100
|
+
create_service(token, current_stack, data)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @param [String] id
|
|
104
|
+
# @param [Hash] options
|
|
105
|
+
def update(id, options)
|
|
106
|
+
puts "updating #{id.colorize(:cyan)}"
|
|
107
|
+
id = prefixed_name(id)
|
|
108
|
+
data = parse_data(options)
|
|
109
|
+
update_service(token, id, data)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# @param [String] name
|
|
113
|
+
def in_deploy_queue?(name)
|
|
114
|
+
deploy_queue.find { |service| service['name'] == prefixed_name(name) } != nil
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# @param [Hash] options
|
|
118
|
+
def merge_env_vars(options)
|
|
119
|
+
return unless options['env_file']
|
|
120
|
+
|
|
121
|
+
options['env_file'] = [options['env_file']] if options['env_file'].is_a?(String)
|
|
122
|
+
options['environment'] = [] unless options['environment']
|
|
123
|
+
|
|
124
|
+
options['env_file'].each do |env_file|
|
|
125
|
+
options['environment'].concat(read_env_file(env_file))
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
options['environment'].uniq! { |s| s.split('=').first }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# @param [Hash] options
|
|
132
|
+
def merge_external_links(options)
|
|
133
|
+
if options['external_links']
|
|
134
|
+
options['links'] ||= []
|
|
135
|
+
options['links'] = options['links'] + options['external_links']
|
|
136
|
+
options.delete('external_links')
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# @param [String] path
|
|
141
|
+
def read_env_file(path)
|
|
142
|
+
File.readlines(path).delete_if { |line| line.start_with?('#') || line.empty? }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
##
|
|
146
|
+
# @param [Hash] options
|
|
147
|
+
def parse_data(options)
|
|
148
|
+
data = {}
|
|
149
|
+
data[:image] = parse_image(options['image'])
|
|
150
|
+
data[:env] = options['environment']
|
|
151
|
+
data[:container_count] = options['instances']
|
|
152
|
+
data[:links] = parse_links(options['links'] || [])
|
|
153
|
+
data[:ports] = parse_ports(options['ports'] || [])
|
|
154
|
+
data[:memory] = parse_memory(options['mem_limit'].to_s) if options['mem_limit']
|
|
155
|
+
data[:memory_swap] = parse_memory(options['memswap_limit'].to_s) if options['memswap_limit']
|
|
156
|
+
data[:cpu_shares] = options['cpu_shares'] if options['cpu_shares']
|
|
157
|
+
data[:volumes] = options['volumes'] || []
|
|
158
|
+
data[:volumes_from] = options['volumes_from'] || []
|
|
159
|
+
data[:cmd] = options['command'].split(' ') if options['command']
|
|
160
|
+
data[:affinity] = options['affinity'] || []
|
|
161
|
+
data[:user] = options['user'] if options['user']
|
|
162
|
+
data[:stateful] = options['stateful'] == true
|
|
163
|
+
data[:privileged] = options['privileged'] unless options['privileged'].nil?
|
|
164
|
+
data[:cap_add] = options['cap_add'] if options['cap_add']
|
|
165
|
+
data[:cap_drop] = options['cap_drop'] if options['cap_drop']
|
|
166
|
+
data[:net] = options['net'] if options['net']
|
|
167
|
+
data[:pid] = options['pid'] if options['pid']
|
|
168
|
+
data[:log_driver] = options['log_driver'] if options['log_driver']
|
|
169
|
+
data[:log_opts] = options['log_opt'] if options['log_opt'] && !options['log_opt'].empty?
|
|
170
|
+
|
|
171
|
+
deploy_opts = options['deploy'] || {}
|
|
172
|
+
data[:strategy] = deploy_opts['strategy'] if deploy_opts['strategy']
|
|
173
|
+
deploy = {}
|
|
174
|
+
if deploy_opts.key?('wait_for_port')
|
|
175
|
+
deploy[:wait_for_port] = deploy_opts['wait_for_port']
|
|
176
|
+
end
|
|
177
|
+
if deploy_opts.key?('min_health')
|
|
178
|
+
deploy[:min_health] = deploy_opts['min_health']
|
|
179
|
+
end
|
|
180
|
+
if deploy_opts.key?('interval')
|
|
181
|
+
deploy[:interval] = parse_relative_time(deploy_opts['interval'])
|
|
182
|
+
end
|
|
183
|
+
data[:deploy_opts] = deploy unless deploy.empty?
|
|
184
|
+
|
|
185
|
+
data[:hooks] = options['hooks'] || {}
|
|
186
|
+
data[:secrets] = options['secrets'] if options['secrets']
|
|
187
|
+
|
|
188
|
+
data
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|