krates 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +212 -0
- data/LOGO +10 -0
- data/VERSION +1 -0
- data/bin/krates +23 -0
- data/lib/kontena/autoload_core.rb +19 -0
- data/lib/kontena/callback.rb +60 -0
- data/lib/kontena/callbacks/.gitkeep +0 -0
- data/lib/kontena/callbacks/auth/01_list_and_select_grid_after_master_auth.rb +26 -0
- data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +19 -0
- data/lib/kontena/callbacks/master/deploy/01_show_logo_before_deploy.rb +14 -0
- data/lib/kontena/callbacks/master/deploy/04_default_master_version.rb +18 -0
- data/lib/kontena/callbacks/master/deploy/05_before_deploy_configuration_wizard.rb +105 -0
- data/lib/kontena/callbacks/master/deploy/40_install_ssl_certificate_after_deploy.rb +32 -0
- data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +66 -0
- data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +21 -0
- data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +24 -0
- data/lib/kontena/callbacks/master/deploy/60_configure_auth_provider_after_deploy.rb +31 -0
- data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +95 -0
- data/lib/kontena/callbacks/master/deploy/90_proptip_after_deploy.rb +33 -0
- data/lib/kontena/cli/browser_launcher.rb +61 -0
- data/lib/kontena/cli/bytes_helper.rb +40 -0
- data/lib/kontena/cli/certificate/authorize_command.rb +107 -0
- data/lib/kontena/cli/certificate/common.rb +16 -0
- data/lib/kontena/cli/certificate/domain_authorization/list_command.rb +24 -0
- data/lib/kontena/cli/certificate/domain_authorization/remove_authorization_command.rb +25 -0
- data/lib/kontena/cli/certificate/domain_authorize_command.rb +7 -0
- data/lib/kontena/cli/certificate/export_command.rb +28 -0
- data/lib/kontena/cli/certificate/get_command.rb +33 -0
- data/lib/kontena/cli/certificate/import_command.rb +61 -0
- data/lib/kontena/cli/certificate/list_command.rb +75 -0
- data/lib/kontena/cli/certificate/register_command.rb +30 -0
- data/lib/kontena/cli/certificate/remove_command.rb +23 -0
- data/lib/kontena/cli/certificate/request_command.rb +20 -0
- data/lib/kontena/cli/certificate/show_command.rb +22 -0
- data/lib/kontena/cli/certificate_command.rb +18 -0
- data/lib/kontena/cli/cloud/login_command.rb +186 -0
- data/lib/kontena/cli/cloud/logout_command.rb +14 -0
- data/lib/kontena/cli/cloud/master/add_command.rb +156 -0
- data/lib/kontena/cli/cloud/master/list_command.rb +35 -0
- data/lib/kontena/cli/cloud/master/remove_command.rb +68 -0
- data/lib/kontena/cli/cloud/master/show_command.rb +21 -0
- data/lib/kontena/cli/cloud/master/update_command.rb +52 -0
- data/lib/kontena/cli/cloud/master_command.rb +14 -0
- data/lib/kontena/cli/cloud_command.rb +13 -0
- data/lib/kontena/cli/common.rb +360 -0
- data/lib/kontena/cli/config.rb +662 -0
- data/lib/kontena/cli/container_command.rb +10 -0
- data/lib/kontena/cli/containers/exec_command.rb +31 -0
- data/lib/kontena/cli/containers/inspect_command.rb +16 -0
- data/lib/kontena/cli/containers/list_command.rb +51 -0
- data/lib/kontena/cli/containers/logs_command.rb +19 -0
- data/lib/kontena/cli/etcd/common.rb +8 -0
- data/lib/kontena/cli/etcd/get_command.rb +26 -0
- data/lib/kontena/cli/etcd/health_command.rb +53 -0
- data/lib/kontena/cli/etcd/list_command.rb +36 -0
- data/lib/kontena/cli/etcd/mkdir_command.rb +23 -0
- data/lib/kontena/cli/etcd/remove_command.rb +29 -0
- data/lib/kontena/cli/etcd/set_command.rb +24 -0
- data/lib/kontena/cli/etcd_command.rb +12 -0
- data/lib/kontena/cli/external_registries/add_command.rb +25 -0
- data/lib/kontena/cli/external_registries/list_command.rb +23 -0
- data/lib/kontena/cli/external_registries/remove_command.rb +17 -0
- data/lib/kontena/cli/external_registry_command.rb +9 -0
- data/lib/kontena/cli/grid_command.rb +21 -0
- data/lib/kontena/cli/grid_options.rb +12 -0
- data/lib/kontena/cli/grids/audit_log_command.rb +22 -0
- data/lib/kontena/cli/grids/cloud_config_command.rb +53 -0
- data/lib/kontena/cli/grids/common.rb +182 -0
- data/lib/kontena/cli/grids/create_command.rb +48 -0
- data/lib/kontena/cli/grids/current_command.rb +25 -0
- data/lib/kontena/cli/grids/env_command.rb +32 -0
- data/lib/kontena/cli/grids/events_command.rb +50 -0
- data/lib/kontena/cli/grids/health_command.rb +69 -0
- data/lib/kontena/cli/grids/list_command.rb +59 -0
- data/lib/kontena/cli/grids/logs_command.rb +35 -0
- data/lib/kontena/cli/grids/remove_command.rb +31 -0
- data/lib/kontena/cli/grids/show_command.rb +25 -0
- data/lib/kontena/cli/grids/trusted_subnet_command.rb +10 -0
- data/lib/kontena/cli/grids/trusted_subnets/add_command.rb +18 -0
- data/lib/kontena/cli/grids/trusted_subnets/list_command.rb +18 -0
- data/lib/kontena/cli/grids/trusted_subnets/remove_command.rb +26 -0
- data/lib/kontena/cli/grids/update_command.rb +35 -0
- data/lib/kontena/cli/grids/use_command.rb +26 -0
- data/lib/kontena/cli/grids/user_command.rb +9 -0
- data/lib/kontena/cli/grids/users/add_command.rb +18 -0
- data/lib/kontena/cli/grids/users/list_command.rb +20 -0
- data/lib/kontena/cli/grids/users/remove_command.rb +20 -0
- data/lib/kontena/cli/helpers/exec_helper.rb +209 -0
- data/lib/kontena/cli/helpers/health_helper.rb +65 -0
- data/lib/kontena/cli/helpers/log_helper.rb +113 -0
- data/lib/kontena/cli/helpers/time_helper.rb +29 -0
- data/lib/kontena/cli/localhost_web_server.rb +113 -0
- data/lib/kontena/cli/log_formatters/compact.rb +65 -0
- data/lib/kontena/cli/log_formatters/strip_color.rb +13 -0
- data/lib/kontena/cli/logout_command.rb +10 -0
- data/lib/kontena/cli/master/audit_log_command.rb +19 -0
- data/lib/kontena/cli/master/config/export_command.rb +46 -0
- data/lib/kontena/cli/master/config/get_command.rb +26 -0
- data/lib/kontena/cli/master/config/import_command.rb +67 -0
- data/lib/kontena/cli/master/config/set_command.rb +19 -0
- data/lib/kontena/cli/master/config/unset_command.rb +20 -0
- data/lib/kontena/cli/master/config_command.rb +17 -0
- data/lib/kontena/cli/master/create_command.rb +74 -0
- data/lib/kontena/cli/master/current_command.rb +25 -0
- data/lib/kontena/cli/master/init_cloud_command.rb +45 -0
- data/lib/kontena/cli/master/join_command.rb +22 -0
- data/lib/kontena/cli/master/list_command.rb +24 -0
- data/lib/kontena/cli/master/login_command.rb +331 -0
- data/lib/kontena/cli/master/logout_command.rb +25 -0
- data/lib/kontena/cli/master/remove_command.rb +55 -0
- data/lib/kontena/cli/master/ssh_command.rb +72 -0
- data/lib/kontena/cli/master/token/common.rb +29 -0
- data/lib/kontena/cli/master/token/create_command.rb +50 -0
- data/lib/kontena/cli/master/token/current_command.rb +45 -0
- data/lib/kontena/cli/master/token/list_command.rb +39 -0
- data/lib/kontena/cli/master/token/remove_command.rb +19 -0
- data/lib/kontena/cli/master/token/show_command.rb +34 -0
- data/lib/kontena/cli/master/token_command.rb +13 -0
- data/lib/kontena/cli/master/use_command.rb +31 -0
- data/lib/kontena/cli/master/user/invite_command.rb +51 -0
- data/lib/kontena/cli/master/user/list_command.rb +29 -0
- data/lib/kontena/cli/master/user/remove_command.rb +24 -0
- data/lib/kontena/cli/master/user/role/add_command.rb +29 -0
- data/lib/kontena/cli/master/user/role/remove_command.rb +27 -0
- data/lib/kontena/cli/master/user/role_command.rb +6 -0
- data/lib/kontena/cli/master/user_command.rb +9 -0
- data/lib/kontena/cli/master_command.rb +21 -0
- data/lib/kontena/cli/node_command.rb +17 -0
- data/lib/kontena/cli/nodes/create_command.rb +25 -0
- data/lib/kontena/cli/nodes/env_command.rb +37 -0
- data/lib/kontena/cli/nodes/health_command.rb +47 -0
- data/lib/kontena/cli/nodes/label_command.rb +10 -0
- data/lib/kontena/cli/nodes/labels/add_command.rb +18 -0
- data/lib/kontena/cli/nodes/labels/list_command.rb +19 -0
- data/lib/kontena/cli/nodes/labels/remove_command.rb +32 -0
- data/lib/kontena/cli/nodes/list_command.rb +97 -0
- data/lib/kontena/cli/nodes/remove_command.rb +34 -0
- data/lib/kontena/cli/nodes/reset_token_command.rb +34 -0
- data/lib/kontena/cli/nodes/show_command.rb +56 -0
- data/lib/kontena/cli/nodes/ssh_command.rb +63 -0
- data/lib/kontena/cli/nodes/update_command.rb +31 -0
- data/lib/kontena/cli/plugin_command.rb +12 -0
- data/lib/kontena/cli/plugins/common.rb +8 -0
- data/lib/kontena/cli/plugins/install_command.rb +42 -0
- data/lib/kontena/cli/plugins/list_command.rb +31 -0
- data/lib/kontena/cli/plugins/search_command.rb +25 -0
- data/lib/kontena/cli/plugins/show_command.rb +17 -0
- data/lib/kontena/cli/plugins/uninstall_command.rb +31 -0
- data/lib/kontena/cli/plugins/upgrade_command.rb +60 -0
- data/lib/kontena/cli/registry/create_command.rb +151 -0
- data/lib/kontena/cli/registry/remove_command.rb +21 -0
- data/lib/kontena/cli/registry_command.rb +8 -0
- data/lib/kontena/cli/service_command.rb +28 -0
- data/lib/kontena/cli/services/container_command.rb +8 -0
- data/lib/kontena/cli/services/containers_command.rb +39 -0
- data/lib/kontena/cli/services/create_command.rb +105 -0
- data/lib/kontena/cli/services/deploy_command.rb +25 -0
- data/lib/kontena/cli/services/env_command.rb +9 -0
- data/lib/kontena/cli/services/envs/add_command.rb +21 -0
- data/lib/kontena/cli/services/envs/list_command.rb +22 -0
- data/lib/kontena/cli/services/envs/remove_command.rb +22 -0
- data/lib/kontena/cli/services/events_command.rb +36 -0
- data/lib/kontena/cli/services/exec_command.rb +107 -0
- data/lib/kontena/cli/services/link_command.rb +35 -0
- data/lib/kontena/cli/services/list_command.rb +66 -0
- data/lib/kontena/cli/services/logs_command.rb +33 -0
- data/lib/kontena/cli/services/monitor_command.rb +58 -0
- data/lib/kontena/cli/services/remove_command.rb +60 -0
- data/lib/kontena/cli/services/restart_command.rb +19 -0
- data/lib/kontena/cli/services/scale_command.rb +21 -0
- data/lib/kontena/cli/services/secret_command.rb +8 -0
- data/lib/kontena/cli/services/secrets/link_command.rb +26 -0
- data/lib/kontena/cli/services/secrets/unlink_command.rb +28 -0
- data/lib/kontena/cli/services/services_helper.rb +579 -0
- data/lib/kontena/cli/services/show_command.rb +26 -0
- data/lib/kontena/cli/services/start_command.rb +21 -0
- data/lib/kontena/cli/services/stats_command.rb +87 -0
- data/lib/kontena/cli/services/stop_command.rb +21 -0
- data/lib/kontena/cli/services/unlink_command.rb +30 -0
- data/lib/kontena/cli/services/update_command.rb +94 -0
- data/lib/kontena/cli/spinner.rb +205 -0
- data/lib/kontena/cli/stack_command.rb +21 -0
- data/lib/kontena/cli/stacks/build_command.rb +125 -0
- data/lib/kontena/cli/stacks/common.rb +209 -0
- data/lib/kontena/cli/stacks/deploy_command.rb +37 -0
- data/lib/kontena/cli/stacks/events_command.rb +33 -0
- data/lib/kontena/cli/stacks/inspect_command.rb +17 -0
- data/lib/kontena/cli/stacks/install_command.rb +95 -0
- data/lib/kontena/cli/stacks/label_command.rb +10 -0
- data/lib/kontena/cli/stacks/labels/add_command.rb +21 -0
- data/lib/kontena/cli/stacks/labels/common.rb +19 -0
- data/lib/kontena/cli/stacks/labels/list_command.rb +21 -0
- data/lib/kontena/cli/stacks/labels/remove_command.rb +21 -0
- data/lib/kontena/cli/stacks/list_command.rb +154 -0
- data/lib/kontena/cli/stacks/logs_command.rb +35 -0
- data/lib/kontena/cli/stacks/monitor_command.rb +93 -0
- data/lib/kontena/cli/stacks/registry/create_command.rb +24 -0
- data/lib/kontena/cli/stacks/registry/make_private_command.rb +24 -0
- data/lib/kontena/cli/stacks/registry/make_public_command.rb +24 -0
- data/lib/kontena/cli/stacks/registry/pull_command.rb +28 -0
- data/lib/kontena/cli/stacks/registry/push_command.rb +40 -0
- data/lib/kontena/cli/stacks/registry/remove_command.rb +30 -0
- data/lib/kontena/cli/stacks/registry/search_command.rb +42 -0
- data/lib/kontena/cli/stacks/registry/show_command.rb +65 -0
- data/lib/kontena/cli/stacks/registry_command.rb +12 -0
- data/lib/kontena/cli/stacks/remove_command.rb +80 -0
- data/lib/kontena/cli/stacks/restart_command.rb +24 -0
- data/lib/kontena/cli/stacks/service_generator.rb +131 -0
- data/lib/kontena/cli/stacks/service_generator_v2.rb +27 -0
- data/lib/kontena/cli/stacks/show_command.rb +168 -0
- data/lib/kontena/cli/stacks/stack_name.rb +71 -0
- data/lib/kontena/cli/stacks/stacks_helper.rb +83 -0
- data/lib/kontena/cli/stacks/stop_command.rb +24 -0
- data/lib/kontena/cli/stacks/upgrade_command.rb +264 -0
- data/lib/kontena/cli/stacks/validate_command.rb +75 -0
- data/lib/kontena/cli/stacks/yaml/custom_validators/affinities_validator.rb +19 -0
- data/lib/kontena/cli/stacks/yaml/custom_validators/build_validator.rb +22 -0
- data/lib/kontena/cli/stacks/yaml/custom_validators/certificates_validator.rb +22 -0
- data/lib/kontena/cli/stacks/yaml/custom_validators/extends_validator.rb +22 -0
- data/lib/kontena/cli/stacks/yaml/custom_validators/hooks_validator.rb +102 -0
- data/lib/kontena/cli/stacks/yaml/custom_validators/secrets_validator.rb +22 -0
- data/lib/kontena/cli/stacks/yaml/opto/certificates_resolver.rb +37 -0
- data/lib/kontena/cli/stacks/yaml/opto/prompt_resolver.rb +78 -0
- data/lib/kontena/cli/stacks/yaml/opto/service_instances_resolver.rb +25 -0
- data/lib/kontena/cli/stacks/yaml/opto/service_link_resolver.rb +80 -0
- data/lib/kontena/cli/stacks/yaml/opto/vault_cert_prompt_resolver.rb +39 -0
- data/lib/kontena/cli/stacks/yaml/opto/vault_resolver.rb +13 -0
- data/lib/kontena/cli/stacks/yaml/opto/vault_setter.rb +12 -0
- data/lib/kontena/cli/stacks/yaml/opto.rb +16 -0
- data/lib/kontena/cli/stacks/yaml/reader.rb +525 -0
- data/lib/kontena/cli/stacks/yaml/service_extender.rb +65 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/file_loader.rb +41 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/registry_loader.rb +24 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader/uri_loader.rb +23 -0
- data/lib/kontena/cli/stacks/yaml/stack_file_loader.rb +152 -0
- data/lib/kontena/cli/stacks/yaml/validations.rb +119 -0
- data/lib/kontena/cli/stacks/yaml/validator_v3.rb +164 -0
- data/lib/kontena/cli/subcommand_loader.rb +83 -0
- data/lib/kontena/cli/table_generator.rb +128 -0
- data/lib/kontena/cli/vault/export_command.rb +24 -0
- data/lib/kontena/cli/vault/import_command.rb +75 -0
- data/lib/kontena/cli/vault/list_command.rb +37 -0
- data/lib/kontena/cli/vault/read_command.rb +27 -0
- data/lib/kontena/cli/vault/remove_command.rb +23 -0
- data/lib/kontena/cli/vault/update_command.rb +24 -0
- data/lib/kontena/cli/vault/write_command.rb +23 -0
- data/lib/kontena/cli/vault_command.rb +13 -0
- data/lib/kontena/cli/version.rb +10 -0
- data/lib/kontena/cli/version_command.rb +20 -0
- data/lib/kontena/cli/volume_command.rb +9 -0
- data/lib/kontena/cli/volumes/create_command.rb +42 -0
- data/lib/kontena/cli/volumes/list_command.rb +29 -0
- data/lib/kontena/cli/volumes/remove_command.rb +29 -0
- data/lib/kontena/cli/volumes/show_command.rb +38 -0
- data/lib/kontena/cli/vpn/config_command.rb +27 -0
- data/lib/kontena/cli/vpn/create_command.rb +99 -0
- data/lib/kontena/cli/vpn/remove_command.rb +22 -0
- data/lib/kontena/cli/vpn_command.rb +9 -0
- data/lib/kontena/cli/whoami_command.rb +38 -0
- data/lib/kontena/client.rb +574 -0
- data/lib/kontena/command.rb +251 -0
- data/lib/kontena/debug_instrumentor.rb +80 -0
- data/lib/kontena/errors.rb +50 -0
- data/lib/kontena/light_prompt.rb +103 -0
- data/lib/kontena/machine/cert_helper.rb +43 -0
- data/lib/kontena/machine/cloud_config/cloudinit.yml +82 -0
- data/lib/kontena/machine/cloud_config/node_generator.rb +28 -0
- data/lib/kontena/machine/common.rb +17 -0
- data/lib/kontena/machine/random_name.rb +42 -0
- data/lib/kontena/main_command.rb +66 -0
- data/lib/kontena/plugin_manager/cleaner.rb +33 -0
- data/lib/kontena/plugin_manager/common.rb +89 -0
- data/lib/kontena/plugin_manager/installer.rb +78 -0
- data/lib/kontena/plugin_manager/loader.rb +93 -0
- data/lib/kontena/plugin_manager/rubygems_client.rb +59 -0
- data/lib/kontena/plugin_manager/uninstaller.rb +34 -0
- data/lib/kontena/plugin_manager.rb +26 -0
- data/lib/kontena/presets/github_auth_provider.yml +11 -0
- data/lib/kontena/presets/kontena_auth_provider.yml +11 -0
- data/lib/kontena/scripts/completer +9 -0
- data/lib/kontena/scripts/completer.rb +334 -0
- data/lib/kontena/scripts/init +18 -0
- data/lib/kontena/scripts/kontena.zsh +11 -0
- data/lib/kontena/scripts/krates.bash +8 -0
- data/lib/kontena/stacks/change_resolver.rb +118 -0
- data/lib/kontena/stacks/stack_data.rb +58 -0
- data/lib/kontena/stacks/stack_data_set.rb +51 -0
- data/lib/kontena/stacks_cache.rb +110 -0
- data/lib/kontena/stacks_client.rb +177 -0
- data/lib/kontena/util.rb +116 -0
- data/lib/kontena_cli.rb +190 -0
- metadata +518 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Grids
|
4
|
+
class UseCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Common
|
7
|
+
|
8
|
+
requires_current_master
|
9
|
+
|
10
|
+
parameter "NAME", "Grid name to use"
|
11
|
+
|
12
|
+
option ['--silent'], :flag, 'Reduce output verbosity'
|
13
|
+
|
14
|
+
def execute
|
15
|
+
grid = find_grid_by_name(name)
|
16
|
+
unless grid
|
17
|
+
exit_with_error pastel.red("Could not resolve grid by name [#{name}]. For a list of existing grids please run: kontena grid list")
|
18
|
+
end
|
19
|
+
config.current_master.grid = grid['name']
|
20
|
+
config.write
|
21
|
+
unless self.silent?
|
22
|
+
puts "Using grid: #{pastel.cyan(grid['name'])}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Kontena::Cli::Grids
|
2
|
+
|
3
|
+
|
4
|
+
class UserCommand < Kontena::Command
|
5
|
+
subcommand ["list", "ls"], "List grid users", load_subcommand('grids/users/list_command')
|
6
|
+
subcommand "add", "Add user to grid", load_subcommand('grids/users/add_command')
|
7
|
+
subcommand ["remove", "rm"], "Remove user from grid", load_subcommand('grids/users/remove_command')
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Grids::Users
|
4
|
+
class AddCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Cli::Grids::Common
|
8
|
+
|
9
|
+
parameter "EMAIL", "Email address"
|
10
|
+
|
11
|
+
def execute
|
12
|
+
require_api_url
|
13
|
+
token = require_token
|
14
|
+
data = { email: email }
|
15
|
+
client(token).post("grids/#{current_grid}/users", data)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Grids::Users
|
4
|
+
class ListCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::Grids::Common
|
7
|
+
include Kontena::Cli::TableGenerator::Helper
|
8
|
+
include Kontena::Cli::GridOptions
|
9
|
+
|
10
|
+
requires_current_master
|
11
|
+
|
12
|
+
def fields
|
13
|
+
quiet? ? %w(email) : %w(email name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute
|
17
|
+
print_table(client.get("grids/#{current_grid}/users")['users'])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative '../common'
|
2
|
+
|
3
|
+
module Kontena::Cli::Grids::Users
|
4
|
+
class RemoveCommand < Kontena::Command
|
5
|
+
include Kontena::Cli::Common
|
6
|
+
include Kontena::Cli::GridOptions
|
7
|
+
include Kontena::Cli::Grids::Common
|
8
|
+
|
9
|
+
parameter "EMAIL", "Email address"
|
10
|
+
option "--force", :flag, "Force remove", default: false, attribute_name: :forced
|
11
|
+
|
12
|
+
def execute
|
13
|
+
require_api_url
|
14
|
+
token = require_token
|
15
|
+
confirm_command(email) unless forced?
|
16
|
+
|
17
|
+
result = client(token).delete("grids/#{current_grid}/users/#{email}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
require 'tty-screen'
|
3
|
+
require 'kontena-websocket-client'
|
4
|
+
|
5
|
+
module Kontena::Cli::Helpers
|
6
|
+
module ExecHelper
|
7
|
+
|
8
|
+
websocket_log_level = if ENV["DEBUG"] == 'websocket'
|
9
|
+
Logger::DEBUG
|
10
|
+
elsif Kontena.debug?
|
11
|
+
Logger::INFO
|
12
|
+
else
|
13
|
+
Logger::WARN
|
14
|
+
end
|
15
|
+
|
16
|
+
Kontena::Websocket::Logging.initialize_logger(STDERR, websocket_log_level)
|
17
|
+
|
18
|
+
WEBSOCKET_CLIENT_OPTIONS = {
|
19
|
+
connect_timeout: ENV["EXCON_CONNECT_TIMEOUT"] ? ENV["EXCON_CONNECT_TIMEOUT"].to_f : 10.0,
|
20
|
+
open_timeout: ENV["EXCON_CONNECT_TIMEOUT"] ? ENV["EXCON_CONNECT_TIMEOUT"].to_f : 10.0,
|
21
|
+
ping_interval: ENV["EXCON_READ_TIMEOUT"] ? ENV["EXCON_READ_TIMEOUT"].to_f : 30.0,
|
22
|
+
ping_timeout: ENV["EXCON_CONNECT_TIMEOUT"] ? ENV["EXCON_CONNECT_TIMEOUT"].to_f : 10.0,
|
23
|
+
close_timeout: ENV["EXCON_CONNECT_TIMEOUT"] ? ENV["EXCON_CONNECT_TIMEOUT"].to_f : 10.0,
|
24
|
+
write_timeout: ENV["EXCON_WRITE_TIMEOUT"] ? ENV["EXCON_WRITE_TIMEOUT"].to_f : 10.0,
|
25
|
+
}
|
26
|
+
|
27
|
+
# @param ws [Kontena::Websocket::Client]
|
28
|
+
# @param tty [Boolean] read stdin in raw mode, sending tty escapes for remote pty
|
29
|
+
# @raise [ArgumentError] not a tty
|
30
|
+
# @yield [data]
|
31
|
+
# @yieldparam data [String] unicode data from stdin
|
32
|
+
# @raise [ArgumentError] not a tty
|
33
|
+
# @return EOF on stdin (!tty)
|
34
|
+
def read_stdin(tty: nil)
|
35
|
+
if tty
|
36
|
+
# NOTE: This check has been disabled since tests in Jenkins are run without TTY allocation
|
37
|
+
# raise ArgumentError, "the input device is not a TTY" unless STDIN.tty?
|
38
|
+
|
39
|
+
STDIN.raw { |io|
|
40
|
+
# we do not expect EOF on a TTY, ^D sends a tty escape to close the pty instead
|
41
|
+
loop do
|
42
|
+
# raises EOFError, SyscallError or IOError
|
43
|
+
chunk = io.readpartial(1024)
|
44
|
+
|
45
|
+
# STDIN.raw does not use the ruby external_encoding, it returns binary strings (ASCII-8BIT encoding)
|
46
|
+
# however, we use websocket text frames with JSON, which expects unicode strings encodable as UTF-8, and does not handle arbitrary binary data
|
47
|
+
# assume all stdin input is using ruby's external_encoding... the JSON.dump will fail if not.
|
48
|
+
chunk.force_encoding(Encoding.default_external)
|
49
|
+
|
50
|
+
yield chunk
|
51
|
+
end
|
52
|
+
}
|
53
|
+
else
|
54
|
+
# line-buffered, using the default external_encoding (probably UTF-8)
|
55
|
+
while line = STDIN.gets
|
56
|
+
yield line
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [String]
|
62
|
+
def websocket_url(path, query = nil)
|
63
|
+
url = URI.parse(require_current_master.url)
|
64
|
+
url.scheme = url.scheme.sub('http', 'ws')
|
65
|
+
url.path = '/v1/' + path
|
66
|
+
url.query = (query && !query.empty?) ? URI.encode_www_form(query) : nil
|
67
|
+
url.to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param ws [Kontena::Websocket::Client]
|
71
|
+
# @raise [RuntimeError] exec error
|
72
|
+
# @return [Integer] exit code
|
73
|
+
def websocket_exec_read(ws)
|
74
|
+
ws.read do |msg|
|
75
|
+
msg = JSON.parse(msg)
|
76
|
+
|
77
|
+
logger.debug "websocket exec read: #{msg.inspect}"
|
78
|
+
|
79
|
+
if msg.has_key?('error')
|
80
|
+
raise msg['error']
|
81
|
+
elsif msg.has_key?('exit')
|
82
|
+
# breaks the read loop
|
83
|
+
return msg['exit'].to_i
|
84
|
+
elsif msg.has_key?('stream')
|
85
|
+
if msg['stream'] == 'stdout'
|
86
|
+
$stdout << msg['chunk']
|
87
|
+
else
|
88
|
+
$stderr << msg['chunk']
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param ws [Kontena::Websocket::Client]
|
95
|
+
# @param msg [Hash]
|
96
|
+
def websocket_exec_write(ws, msg)
|
97
|
+
logger.debug "websocket exec write: #{msg.inspect}"
|
98
|
+
|
99
|
+
ws.send(JSON.dump(msg))
|
100
|
+
end
|
101
|
+
|
102
|
+
# Start thread to read from stdin, and write to websocket.
|
103
|
+
# Closes websocket on stdin read errors.
|
104
|
+
#
|
105
|
+
# @param ws [Kontena::Websocket::Client]
|
106
|
+
# @param tty [Boolean]
|
107
|
+
# @return [Thread]
|
108
|
+
def websocket_exec_write_thread(ws, tty: nil)
|
109
|
+
Thread.new do
|
110
|
+
begin
|
111
|
+
if tty
|
112
|
+
console_height, console_width = TTY::Screen.size
|
113
|
+
websocket_exec_write(ws, 'tty_size' => {
|
114
|
+
width: console_width, height: console_height
|
115
|
+
})
|
116
|
+
end
|
117
|
+
read_stdin(tty: tty) do |stdin|
|
118
|
+
logger.debug "websocket exec stdin with encoding=#{stdin.encoding}: #{stdin.inspect}"
|
119
|
+
websocket_exec_write(ws, 'stdin' => stdin)
|
120
|
+
end
|
121
|
+
websocket_exec_write(ws, 'stdin' => nil) # EOF
|
122
|
+
rescue => exc
|
123
|
+
logger.error exc
|
124
|
+
ws.close(1001, "stdin read #{exc.class}: #{exc}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Connect to server websocket, send from stdin, and write out messages
|
130
|
+
#
|
131
|
+
# @param paths [String]
|
132
|
+
# @param options [Hash] @see Kontena::Websocket::Client
|
133
|
+
# @param cmd [Array<String>] command to execute
|
134
|
+
# @param interactive [Boolean] Interactive TTY on/off
|
135
|
+
# @param shell [Boolean] Shell on/of
|
136
|
+
# @param tty [Boolean] TTY on/of
|
137
|
+
# @return [Integer] exit code
|
138
|
+
def websocket_exec(path, cmd, interactive: false, shell: false, tty: false)
|
139
|
+
exit_status = nil
|
140
|
+
write_thread = nil
|
141
|
+
|
142
|
+
query = {}
|
143
|
+
query[:interactive] = interactive if interactive
|
144
|
+
query[:shell] = shell if shell
|
145
|
+
query[:tty] = tty if tty
|
146
|
+
|
147
|
+
server = require_current_master
|
148
|
+
url = websocket_url(path, query)
|
149
|
+
token = require_token
|
150
|
+
options = WEBSOCKET_CLIENT_OPTIONS.dup
|
151
|
+
options[:headers] = {
|
152
|
+
'Authorization' => "Bearer #{token.access_token}"
|
153
|
+
}
|
154
|
+
options[:ssl_params] = {
|
155
|
+
verify_mode: ENV['SSL_IGNORE_ERRORS'].to_s == 'true' ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER,
|
156
|
+
ca_file: server.ssl_cert_path,
|
157
|
+
}
|
158
|
+
options[:ssl_hostname] = server.ssl_subject_cn
|
159
|
+
|
160
|
+
logger.debug { "websocket exec connect... #{url}" }
|
161
|
+
|
162
|
+
# we do not expect CloseError, because the server will send an 'exit' message first,
|
163
|
+
# and we return before seeing the close frame
|
164
|
+
# TODO: handle HTTP 404 errors
|
165
|
+
Kontena::Websocket::Client.connect(url, **options) do |ws|
|
166
|
+
logger.debug { "websocket exec open" }
|
167
|
+
|
168
|
+
# first frame contains exec command
|
169
|
+
websocket_exec_write(ws, 'cmd' => cmd)
|
170
|
+
|
171
|
+
if interactive
|
172
|
+
# start new thread to write from stdin to websocket
|
173
|
+
write_thread = websocket_exec_write_thread(ws, tty: tty)
|
174
|
+
end
|
175
|
+
|
176
|
+
# blocks reading from websocket, returns with exec exit code
|
177
|
+
exit_status = websocket_exec_read(ws)
|
178
|
+
|
179
|
+
fail ws.close_reason unless exit_status
|
180
|
+
end
|
181
|
+
|
182
|
+
rescue Kontena::Websocket::Error => exc
|
183
|
+
exit_with_error(exc)
|
184
|
+
|
185
|
+
rescue => exc
|
186
|
+
logger.error { "websocket exec error: #{exc}" }
|
187
|
+
raise
|
188
|
+
|
189
|
+
else
|
190
|
+
logger.debug { "websocket exec exit: #{exit_status}"}
|
191
|
+
return exit_status
|
192
|
+
|
193
|
+
ensure
|
194
|
+
if write_thread
|
195
|
+
write_thread.kill
|
196
|
+
write_thread.join
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Execute command on container using websocket API.
|
201
|
+
#
|
202
|
+
# @param id [String] Container ID (grid/host/name)
|
203
|
+
# @param cmd [Array<String>] command to execute
|
204
|
+
# @return [Integer] exit code
|
205
|
+
def container_exec(id, cmd, **exec_options)
|
206
|
+
websocket_exec("containers/#{id}/exec", cmd, **exec_options)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Kontena::Cli::Helpers
|
2
|
+
module HealthHelper
|
3
|
+
def health_icon(health)
|
4
|
+
case health
|
5
|
+
when nil
|
6
|
+
" "
|
7
|
+
when :ok
|
8
|
+
pastel.green('⊛')
|
9
|
+
when :warning
|
10
|
+
pastel.yellow('⊙')
|
11
|
+
when :error
|
12
|
+
pastel.red('⊗')
|
13
|
+
when :offline
|
14
|
+
pastel.dark('⊝')
|
15
|
+
else
|
16
|
+
fail "Invalid health=#{health}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Validate grid nodes configuration and status
|
21
|
+
#
|
22
|
+
# @param grid [Hash] get(/grids/:grid) => { ... }
|
23
|
+
# @param nodes [Array<Hash>] get(/grids/:grid/nodes)[nodes] => [ { ... } ]
|
24
|
+
# @return [Symbol] health
|
25
|
+
def grid_health(grid, nodes)
|
26
|
+
initial = grid['initial_size']
|
27
|
+
minimum = grid['initial_size'] / 2 + 1 # a majority is required for etcd quorum
|
28
|
+
|
29
|
+
online = nodes.select{|node| node['initial_member'] && node['connected']}
|
30
|
+
|
31
|
+
if online.length < minimum
|
32
|
+
return :error
|
33
|
+
elsif online.length < initial
|
34
|
+
return :warning
|
35
|
+
else
|
36
|
+
return :ok
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Validate grid node status based on the grid health
|
41
|
+
#
|
42
|
+
# @param node [Hash] GET /nodes/:grid/:node
|
43
|
+
# @param grid_health [Symbol] @see #grid_health
|
44
|
+
# @return [Symbol] health
|
45
|
+
def node_health(node, grid_health)
|
46
|
+
if node['initial_member']
|
47
|
+
return node['connected'] ? grid_health : :offline
|
48
|
+
else
|
49
|
+
return node['connected'] ? :ok : :offline
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param node_etcd_health [Hash{health: String, error: String}]
|
54
|
+
# @return [Symbol, String]
|
55
|
+
def node_etcd_health(node_etcd_health)
|
56
|
+
if node_etcd_health['health']
|
57
|
+
return :ok, "healthy"
|
58
|
+
elsif node_etcd_health['error']
|
59
|
+
return :error, "unhealthy: #{node_etcd_health['error']}"
|
60
|
+
else
|
61
|
+
return :error, "unhealthy"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Kontena::Cli::Helpers
|
2
|
+
module LogHelper
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
if base.respond_to?(:option)
|
6
|
+
base.option ["-f", "--follow"], :flag, "Follow log output", :attribute_name => :tail, default: false
|
7
|
+
base.option ['--tail', '--lines'], "LINES", "Number of lines to show from the end of the logs", :attribute_name => :lines, default: 100 do |s|
|
8
|
+
Integer(s)
|
9
|
+
end
|
10
|
+
base.option "--since", "SINCE", "Show logs since given timestamp"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String]
|
15
|
+
def token
|
16
|
+
@token ||= require_token
|
17
|
+
end
|
18
|
+
|
19
|
+
def show_logs(url, query_params = { }, &block)
|
20
|
+
if tail?
|
21
|
+
stream_logs(url, query_params, &block)
|
22
|
+
else
|
23
|
+
get_logs(url, query_params, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_logs(url, query_params)
|
28
|
+
query_params[:limit] = lines if lines
|
29
|
+
query_params[:since] = since if since
|
30
|
+
|
31
|
+
result = client(token).get(url, query_params)
|
32
|
+
result['logs'].each do |log|
|
33
|
+
yield log
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [String] url
|
38
|
+
# @param [Hash] query_params
|
39
|
+
def stream_logs(url, query_params)
|
40
|
+
query_params[:limit] = lines if lines
|
41
|
+
query_params[:since] = since if since
|
42
|
+
query_params[:follow] = 1
|
43
|
+
|
44
|
+
last_seen = nil
|
45
|
+
streamer = lambda do |chunk, remaining_bytes, total_bytes|
|
46
|
+
log = buffered_log_json(chunk)
|
47
|
+
if log
|
48
|
+
yield log
|
49
|
+
last_seen = log['id']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
query_params[:from] = last_seen if last_seen
|
55
|
+
client(token).get_stream(url, streamer, query_params)
|
56
|
+
rescue => exc
|
57
|
+
retry if exc.cause.is_a?(EOFError) # Excon wraps the EOFerror into SocketError
|
58
|
+
raise
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [String] chunk
|
63
|
+
# @return [Hash,NilClass]
|
64
|
+
def buffered_log_json(chunk)
|
65
|
+
@buffer = '' if @buffer.nil?
|
66
|
+
return if @buffer.empty? && chunk.strip.empty?
|
67
|
+
begin
|
68
|
+
orig_chunk = chunk
|
69
|
+
unless @buffer.empty?
|
70
|
+
chunk = @buffer + chunk
|
71
|
+
end
|
72
|
+
unless chunk.empty?
|
73
|
+
log = JSON.parse(chunk)
|
74
|
+
end
|
75
|
+
@buffer = ''
|
76
|
+
log
|
77
|
+
rescue
|
78
|
+
@buffer << orig_chunk
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def show_log(log)
|
84
|
+
color = color_for_container(log['name'])
|
85
|
+
prefix = "#{log['created_at']} #{log['name']}:"
|
86
|
+
|
87
|
+
puts "#{pastel.send(color, prefix)} #{log['data']}"
|
88
|
+
end
|
89
|
+
|
90
|
+
# @param [String] container_id
|
91
|
+
# @return [Symbol]
|
92
|
+
def color_for_container(container_id)
|
93
|
+
color_maps[container_id] = colors.shift unless color_maps[container_id]
|
94
|
+
color_maps[container_id].to_sym
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [Hash]
|
98
|
+
def color_maps
|
99
|
+
@color_maps ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [Array<Symbol>]
|
103
|
+
def colors
|
104
|
+
if(@colors.nil? || @colors.size == 0)
|
105
|
+
@colors = %i(
|
106
|
+
red green yellow blue magenta cyan bright_red bright_green
|
107
|
+
bright_yellow bright_blue bright_magenta bright_cyan
|
108
|
+
)
|
109
|
+
end
|
110
|
+
@colors
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Kontena::Cli::Helpers
|
2
|
+
module TimeHelper
|
3
|
+
# Return an approximation of how long ago the given time was.
|
4
|
+
# @param time [String]
|
5
|
+
# @param terse [Boolean] very terse output (2-3 chars wide)
|
6
|
+
def time_since(time, terse: false)
|
7
|
+
return '' if time.nil? || time.empty?
|
8
|
+
|
9
|
+
dt = Time.now - Time.parse(time)
|
10
|
+
|
11
|
+
dt_s = dt.to_i
|
12
|
+
dt_m, dt_s = dt_s / 60, dt_s % 60
|
13
|
+
dt_h, dt_m = dt_m / 60, dt_m % 60
|
14
|
+
dt_d, dt_h = dt_h / 60, dt_h % 60
|
15
|
+
|
16
|
+
parts = []
|
17
|
+
parts << "%dd" % dt_d if dt_d > 0
|
18
|
+
parts << "%dh" % dt_h if dt_h > 0
|
19
|
+
parts << "%dm" % dt_m if dt_m > 0
|
20
|
+
parts << "%ds" % dt_s
|
21
|
+
|
22
|
+
if terse
|
23
|
+
return parts.first
|
24
|
+
else
|
25
|
+
return parts.join('')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Kontena
|
5
|
+
class LocalhostWebServer
|
6
|
+
# Serves one request to http://localhost:<random_port>/cb
|
7
|
+
#
|
8
|
+
# Used for local webserver browser authentication flow.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# server = LocalhostWebServer.new
|
12
|
+
# server.url
|
13
|
+
# => "http://localhost:1234/cb"
|
14
|
+
# response = server.serve_one
|
15
|
+
# # <visit server.url?foo=bar&bar=123 on browser>
|
16
|
+
# => { "foo" => "bar", "bar" => 123 } # (it converts integers!)
|
17
|
+
attr_accessor :server, :success_response, :error_response, :port
|
18
|
+
|
19
|
+
DEFAULT_ERROR_MESSAGE = "Bad request"
|
20
|
+
SUCCESS_URL = "https://cloud.kontena.io/terminal-success"
|
21
|
+
|
22
|
+
# Get new server instance
|
23
|
+
#
|
24
|
+
# @param [String] success_response Returned for successful callback
|
25
|
+
# @param [String] error_response Returned for unsuccessful callback
|
26
|
+
def initialize(success_response: nil, error_response: nil, port: nil)
|
27
|
+
@success_response = success_response
|
28
|
+
@error_response = error_response || DEFAULT_ERROR_MESSAGE
|
29
|
+
@server = TCPServer.new('localhost', port || 0)
|
30
|
+
@port = @server.addr[1]
|
31
|
+
end
|
32
|
+
|
33
|
+
# The url to this service, send this as redirect_uri to auth provider.
|
34
|
+
def url
|
35
|
+
"http://localhost:#{port}/cb"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Serve one request and return query params.
|
39
|
+
#
|
40
|
+
# @return [Hash] query_params
|
41
|
+
def serve_one
|
42
|
+
Kontena.logger.debug("LHWS") { "Waiting for connection on port #{port}.." }
|
43
|
+
socket = server.accept
|
44
|
+
|
45
|
+
content = socket.recvfrom(2048).first.split(/(?:\r)?\n/)
|
46
|
+
|
47
|
+
request = content.shift
|
48
|
+
|
49
|
+
headers = {}
|
50
|
+
while line = content.shift
|
51
|
+
break if line.nil?
|
52
|
+
break if line == ''
|
53
|
+
header, value = line.chomp.split(/:\s{0,}/, 2)
|
54
|
+
headers[header] = value
|
55
|
+
end
|
56
|
+
|
57
|
+
body = content.join("\n")
|
58
|
+
|
59
|
+
Kontena.logger.debug("LHWS") { "Got request: \"#{request.inspect}\n Headers: #{headers.inspect}\n Body: #{body}\"" }
|
60
|
+
|
61
|
+
get_request = request[/GET (\/cb.+?) HTTP/, 1]
|
62
|
+
if get_request
|
63
|
+
if success_response
|
64
|
+
socket.print [
|
65
|
+
'HTTP/1.1 200 OK',
|
66
|
+
'Content-Type: text/html',
|
67
|
+
"Content-Length: #{success_response.bytesize}",
|
68
|
+
"Connection: close",
|
69
|
+
'',
|
70
|
+
success_response
|
71
|
+
].join("\r\n")
|
72
|
+
else
|
73
|
+
socket.print [
|
74
|
+
'HTTP/1.1 302 Found',
|
75
|
+
"Location: #{SUCCESS_URL}",
|
76
|
+
"Referrer-Policy: no-referrer",
|
77
|
+
"Connection: close",
|
78
|
+
''
|
79
|
+
].join("\r\n")
|
80
|
+
end
|
81
|
+
|
82
|
+
socket.close
|
83
|
+
server.close
|
84
|
+
uri = URI.parse("http://localhost#{get_request}")
|
85
|
+
Kontena.logger.debug("LHWS") { " * Parsing params: \"#{uri.query}\"" }
|
86
|
+
params = {}
|
87
|
+
URI.decode_www_form(uri.query).each do |key, value|
|
88
|
+
if value.to_s == ''
|
89
|
+
next
|
90
|
+
elsif value.to_s =~ /\A\d+\z/
|
91
|
+
params[key] = value.to_i
|
92
|
+
else
|
93
|
+
params[key] = value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
params
|
97
|
+
else
|
98
|
+
# Unless it's a query to /cb, send an error message and keep listening,
|
99
|
+
# it might have been something funny like fetching favicon.ico
|
100
|
+
socket.print [
|
101
|
+
'HTTP/1.1 400 Bad request',
|
102
|
+
'Content-Type: text/plain',
|
103
|
+
"Content-Length: #{error_response.bytesize}",
|
104
|
+
'Connection: close',
|
105
|
+
'',
|
106
|
+
error_response
|
107
|
+
].join("\r\n")
|
108
|
+
socket.close
|
109
|
+
serve_one # serve more, this one was not proper.
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Kontena
|
4
|
+
module Cli
|
5
|
+
module LogFormatter
|
6
|
+
class Compact < Logger::Formatter
|
7
|
+
def self.ms_since_first
|
8
|
+
Time.now.to_f - @first_log
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.ms_since_last
|
12
|
+
((Time.now.to_f - @last_log) * 1000).to_i
|
13
|
+
ensure
|
14
|
+
@last_log = Time.now.to_f
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.__init_timers__
|
18
|
+
@first_log = $KONTENA_START_TIME || Time.now.to_f
|
19
|
+
@last_log = @first_log
|
20
|
+
end
|
21
|
+
|
22
|
+
__init_timers__
|
23
|
+
|
24
|
+
DEBUG_INDICATOR = Kontena.pastel.inverse.bright_blue('DEBUG').freeze
|
25
|
+
WARN_INDICATOR = Kontena.pastel.inverse.yellow('WARN ').freeze
|
26
|
+
INFO_INDICATOR = Kontena.pastel.inverse.cyan('INFO ').freeze
|
27
|
+
ERROR_INDICATOR = Kontena.pastel.inverse.red('ERROR').freeze
|
28
|
+
|
29
|
+
def colorize_severity(severity)
|
30
|
+
case severity[0..0]
|
31
|
+
when 'D' then DEBUG_INDICATOR
|
32
|
+
when 'W' then WARN_INDICATOR
|
33
|
+
when 'I' then INFO_INDICATOR
|
34
|
+
when 'E', 'F' then ERROR_INDICATOR
|
35
|
+
else severity[0..0]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
TS_FORMAT = '%4d'.freeze
|
40
|
+
|
41
|
+
def colorized_time
|
42
|
+
elapsed = self.class.ms_since_last
|
43
|
+
ts = TS_FORMAT % [elapsed]
|
44
|
+
if elapsed > 300
|
45
|
+
Kontena.pastel.red(ts)
|
46
|
+
elsif elapsed > 100
|
47
|
+
Kontena.pastel.yellow(ts)
|
48
|
+
else
|
49
|
+
ts
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if ENV['DEBUG_PERF']
|
54
|
+
define_method :call do |severity, time, progname, msg|
|
55
|
+
"#{colorize_severity(severity)} #{colorized_time} #{msg2str(msg)}\n"
|
56
|
+
end
|
57
|
+
else
|
58
|
+
define_method :call do |severity, time, progname, msg|
|
59
|
+
"#{colorize_severity(severity)} #{msg2str(msg)}\n"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|