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,110 @@
|
|
1
|
+
module Kontena
|
2
|
+
autoload :StacksClient, 'kontena/stacks_client'
|
3
|
+
|
4
|
+
class StacksCache
|
5
|
+
class CachedStack
|
6
|
+
|
7
|
+
attr_reader :stack_name
|
8
|
+
|
9
|
+
def initialize(stack_name)
|
10
|
+
@stack_name = stack_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def read
|
14
|
+
File.read(path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def load
|
18
|
+
::YAML.safe_load(read, [], [], true, path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def write(content)
|
22
|
+
raise ArgumentError, "Stack name and version required" unless stack_name.stack_name && stack_name.version
|
23
|
+
unless File.directory?(File.dirname(path))
|
24
|
+
require 'fileutils'
|
25
|
+
FileUtils.mkdir_p(File.dirname(path))
|
26
|
+
end
|
27
|
+
File.write(path, content)
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete
|
31
|
+
File.unlink(path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def cached?
|
35
|
+
return false unless stack_name.version
|
36
|
+
File.exist?(path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def path
|
40
|
+
path = File.expand_path(File.join(base_path, "#{stack_name.stack_name}-#{stack_name.version}.yml"))
|
41
|
+
raise "Path traversal attempted" unless path.start_with?(base_path)
|
42
|
+
path
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def base_path
|
48
|
+
Kontena::StacksCache.base_path
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class RegistryClientFactory
|
53
|
+
require 'kontena/cli/common'
|
54
|
+
require 'kontena/cli/stacks/common'
|
55
|
+
include Kontena::Cli::Common
|
56
|
+
include Kontena::Cli::Stacks::Common
|
57
|
+
end
|
58
|
+
|
59
|
+
class << self
|
60
|
+
def pull(stack_name)
|
61
|
+
cache(stack_name).read
|
62
|
+
end
|
63
|
+
|
64
|
+
def dputs(msg)
|
65
|
+
Kontena.logger.debug { msg }
|
66
|
+
end
|
67
|
+
|
68
|
+
def cache(stack_name)
|
69
|
+
stack = CachedStack.new(stack_name)
|
70
|
+
if stack.cached?
|
71
|
+
dputs "Reading from cache: #{stack.path}"
|
72
|
+
else
|
73
|
+
dputs "Retrieving #{stack.stack_name} from registry"
|
74
|
+
content = client.pull(stack_name)
|
75
|
+
yaml = ::YAML.safe_load(content, [], [], true, stack.stack_name.to_s)
|
76
|
+
new_stack_name = Kontena::Cli::Stacks::StackName.new(yaml['stack'], yaml['version'])
|
77
|
+
new_stack = CachedStack.new(new_stack_name)
|
78
|
+
if new_stack.cached?
|
79
|
+
dputs "Already cached"
|
80
|
+
stack = new_stack
|
81
|
+
else
|
82
|
+
dputs "Writing #{stack.path}"
|
83
|
+
new_stack.write(content)
|
84
|
+
dputs "#{new_stack.stack_name} cached to #{new_stack.path}"
|
85
|
+
stack = new_stack
|
86
|
+
end
|
87
|
+
end
|
88
|
+
stack
|
89
|
+
end
|
90
|
+
|
91
|
+
def registry_url(stack_name)
|
92
|
+
client.full_uri(stack_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def client
|
96
|
+
@client ||= RegistryClientFactory.new.stacks_client
|
97
|
+
end
|
98
|
+
|
99
|
+
def base_path
|
100
|
+
return @base_path if @base_path
|
101
|
+
@base_path = File.join(Dir.home, '.kontena/cache/stacks')
|
102
|
+
unless File.directory?(@base_path)
|
103
|
+
require 'fileutils'
|
104
|
+
FileUtils.mkdir_p(@base_path)
|
105
|
+
end
|
106
|
+
@base_path
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'kontena/client'
|
2
|
+
|
3
|
+
module Kontena
|
4
|
+
class StacksClient < Client
|
5
|
+
|
6
|
+
ACCEPT_JSON = { 'Accept' => 'application/json' }
|
7
|
+
ACCEPT_YAML = { 'Accept' => 'application/yaml' }
|
8
|
+
ACCEPT_JSONAPI = { 'Accept' => 'application/vnd.api+json' }
|
9
|
+
CT_YAML = { 'Content-Type' => 'application/yaml' }
|
10
|
+
CT_JSONAPI = { 'Content-Type' => 'application/vnd.api+json' }
|
11
|
+
|
12
|
+
def raise_unless_token
|
13
|
+
unless token && token['access_token']
|
14
|
+
raise Kontena::Errors::StandardError.new(401, "Stack registry write operations require authentication")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def raise_unless_read_token
|
19
|
+
return false unless options[:read_requires_token]
|
20
|
+
unless token && token['access_token']
|
21
|
+
raise Kontena::Errors::StandardError.new(401, "Stack registry requires authentication")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def full_uri(stack_name)
|
26
|
+
URI.join(api_url, path_to_version(stack_name)).to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def path_to_version(stack_name)
|
30
|
+
path_to_stack(stack_name) + "/stack-versions/%s" % (stack_name.version || 'latest')
|
31
|
+
end
|
32
|
+
|
33
|
+
def path_to_stack(stack_name)
|
34
|
+
"/v2/organizations/%s/stacks/%s" % [stack_name.user, stack_name.stack]
|
35
|
+
end
|
36
|
+
|
37
|
+
def push(stack_name, data)
|
38
|
+
raise_unless_token
|
39
|
+
post(
|
40
|
+
'/v2/stack-files',
|
41
|
+
{
|
42
|
+
'data' => {
|
43
|
+
'type' => 'stack-files',
|
44
|
+
'attributes' => { 'content' => data }
|
45
|
+
}
|
46
|
+
},
|
47
|
+
{},
|
48
|
+
CT_JSONAPI,
|
49
|
+
true
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
def show(stack_name, include_prerelease: true)
|
54
|
+
raise_unless_read_token
|
55
|
+
result = get("#{path_to_stack(stack_name)}", { 'include' => 'latest-version', 'include-prerelease' => include_prerelease }, ACCEPT_JSONAPI)
|
56
|
+
if result['included']
|
57
|
+
latest = result['included'].find { |i| i['type'] == 'stack-versions' }
|
58
|
+
return result unless latest
|
59
|
+
result['data']['attributes']['latest-version'] = {}
|
60
|
+
result['data']['attributes']['latest-version']['version'] = latest['attributes']['version']
|
61
|
+
result['data']['attributes']['latest-version']['description'] = latest['attributes']['description']
|
62
|
+
result['data']['attributes']['latest-version']['meta'] = latest['meta']
|
63
|
+
end
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
def versions(stack_name, include_prerelease: true, include_deleted: false)
|
68
|
+
raise_unless_read_token
|
69
|
+
get("#{path_to_stack(stack_name)}/stack-versions", { 'include-prerelease' => include_prerelease, 'include-deleted' => include_deleted}, ACCEPT_JSONAPI).dig('data')
|
70
|
+
end
|
71
|
+
|
72
|
+
def pull(stack_name)
|
73
|
+
raise_unless_read_token
|
74
|
+
get(path_to_version(stack_name) + '/yaml', nil, ACCEPT_YAML)
|
75
|
+
rescue StandardError => ex
|
76
|
+
ex.message << " : #{path_to_version(stack_name)}"
|
77
|
+
raise ex, ex.message
|
78
|
+
end
|
79
|
+
|
80
|
+
def search(query, tags: [], include_prerelease: true, include_private: true, include_versionless: true)
|
81
|
+
raise_unless_read_token
|
82
|
+
if tags.empty?
|
83
|
+
result = get('/v2/stacks', { 'query' => query, 'include' => 'latest-version', 'include-prerelease' => include_prerelease, 'include-private' => include_private, 'include-versionless' => include_versionless }, ACCEPT_JSONAPI)
|
84
|
+
else
|
85
|
+
result = get('/v2/tags/%s/stacks' % tags.join(','), { 'query' => query, 'include' => 'latest-version', 'include-prerelease' => include_prerelease, 'include-private' => include_private }, ACCEPT_JSONAPI)
|
86
|
+
end
|
87
|
+
|
88
|
+
data = result.dig('data')
|
89
|
+
included = result.dig('included')
|
90
|
+
if included
|
91
|
+
data.each do |row|
|
92
|
+
name = '%s/%s' % [row.fetch('attributes', {}).fetch('organization-id'), row.fetch('attributes', {}).fetch('name')]
|
93
|
+
next if name.nil?
|
94
|
+
included_version = included.find { |i| i.fetch('attributes', {}).fetch('name') == name }
|
95
|
+
if included_version
|
96
|
+
row['attributes']['latest-version'] = {}
|
97
|
+
row['attributes']['latest-version']['version'] = included_version['attributes']['version']
|
98
|
+
row['attributes']['latest-version']['description'] = included_version['attributes']['description']
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
data
|
103
|
+
end
|
104
|
+
|
105
|
+
def destroy(stack_name)
|
106
|
+
raise_unless_token
|
107
|
+
if stack_name.version
|
108
|
+
id = stack_version_id(stack_name)
|
109
|
+
if id.nil?
|
110
|
+
raise Kontena::Errors::StandardError.new(404, 'Not found')
|
111
|
+
end
|
112
|
+
delete('/v2/stack-versions/%s' % id, nil, {}, ACCEPT_JSONAPI)
|
113
|
+
else
|
114
|
+
id = stack_id(stack_name)
|
115
|
+
if id.nil?
|
116
|
+
raise Kontena::Errors::StandardError.new(404, 'Not found')
|
117
|
+
end
|
118
|
+
delete('/v2/stacks/%s' % id, nil, {}, ACCEPT_JSONAPI)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def make_private(stack_name)
|
123
|
+
change_visibility(stack_name, is_private: true)
|
124
|
+
end
|
125
|
+
|
126
|
+
def make_public(stack_name)
|
127
|
+
change_visibility(stack_name, is_private: false)
|
128
|
+
end
|
129
|
+
|
130
|
+
def create(stack_name, is_private: true)
|
131
|
+
post(
|
132
|
+
'/v2/stacks',
|
133
|
+
stack_data(stack_name, is_private: is_private),
|
134
|
+
{},
|
135
|
+
CT_JSONAPI.merge(ACCEPT_JSONAPI)
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def stack_id(stack_name)
|
142
|
+
show(stack_name).dig('data', 'id')
|
143
|
+
end
|
144
|
+
|
145
|
+
def stack_version_id(stack_name)
|
146
|
+
version = versions(stack_name, include_prerelease: true).find { |v| v.dig('attributes', 'version') == stack_name.version }
|
147
|
+
if version
|
148
|
+
version['id']
|
149
|
+
else
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def change_visibility(stack_name, is_private: true)
|
155
|
+
raise_unless_token
|
156
|
+
put(
|
157
|
+
'/v2/stacks/%s' % stack_id(stack_name),
|
158
|
+
stack_data(stack_name, is_private: is_private),
|
159
|
+
{},
|
160
|
+
CT_JSONAPI.merge(ACCEPT_JSONAPI)
|
161
|
+
)
|
162
|
+
end
|
163
|
+
|
164
|
+
def stack_data(stack_name, is_private: true)
|
165
|
+
{
|
166
|
+
data: {
|
167
|
+
type: 'stacks',
|
168
|
+
attributes: {
|
169
|
+
'name' => stack_name.stack,
|
170
|
+
'organization-id' => stack_name.user,
|
171
|
+
'is-private' => is_private
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/lib/kontena/util.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
module Kontena
|
2
|
+
module Util
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
def symbolize_keys(obj)
|
8
|
+
case obj
|
9
|
+
when Hash
|
10
|
+
obj.map { |k,v| [k.to_sym, symbolize_keys(v)] }.to_h
|
11
|
+
when Array
|
12
|
+
obj.map { |v| symbolize_keys(v) }
|
13
|
+
else
|
14
|
+
obj
|
15
|
+
end
|
16
|
+
end
|
17
|
+
module_function :symbolize_keys
|
18
|
+
|
19
|
+
def symbolize_keys!(obj)
|
20
|
+
case obj
|
21
|
+
when Hash
|
22
|
+
obj.keys.each { |k| obj[k.to_sym] = symbolize_keys!(obj.delete(k)) }
|
23
|
+
when Array
|
24
|
+
obj.map! { |v| symbolize_keys!(v) }
|
25
|
+
else
|
26
|
+
end
|
27
|
+
obj
|
28
|
+
end
|
29
|
+
module_function :symbolize_keys!
|
30
|
+
|
31
|
+
def stringify_keys(obj)
|
32
|
+
case obj
|
33
|
+
when Hash
|
34
|
+
obj.map { |k,v| [k.to_s, stringify_keys(v)] }.to_h
|
35
|
+
when Array
|
36
|
+
obj.map { |v| stringify_keys(v) }
|
37
|
+
else
|
38
|
+
obj
|
39
|
+
end
|
40
|
+
end
|
41
|
+
module_function :stringify_keys
|
42
|
+
|
43
|
+
def stringify_keys!(obj)
|
44
|
+
case obj
|
45
|
+
when Hash
|
46
|
+
obj.keys.each { |k| obj[k.to_s] = stringify_keys!(obj.delete(k)) }
|
47
|
+
when Array
|
48
|
+
obj.map! { |v| stringify_keys!(v) }
|
49
|
+
else
|
50
|
+
end
|
51
|
+
obj
|
52
|
+
end
|
53
|
+
module_function :stringify_keys!
|
54
|
+
|
55
|
+
# @param [String] cmd
|
56
|
+
def which(cmd)
|
57
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
58
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
59
|
+
exts.each { |ext|
|
60
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
61
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
62
|
+
}
|
63
|
+
end
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
# Compatibility between ruby_dig and Ruby 2.3. Ruby_dig returns
|
68
|
+
# nil when trying to dig into a string, Ruby 2.3 dig raises
|
69
|
+
# TypeError.
|
70
|
+
#
|
71
|
+
# @param [Hash] source_hash
|
72
|
+
# @param [*keys] list_of_keys
|
73
|
+
def safe_dig(hash, *keys)
|
74
|
+
hash.dig(*keys)
|
75
|
+
rescue TypeError
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def time_ago(time)
|
80
|
+
now = Time.now.to_i
|
81
|
+
time = time.kind_of?(Integer) ? time : DateTime.parse(time).to_time.to_i
|
82
|
+
diff = now - time
|
83
|
+
seconds_to_human(diff) + ' ago'
|
84
|
+
end
|
85
|
+
|
86
|
+
def time_until(seconds)
|
87
|
+
'in ' + seconds_to_human(seconds)
|
88
|
+
end
|
89
|
+
|
90
|
+
def seconds_to_human(seconds)
|
91
|
+
if seconds > 60 * 60 * 24
|
92
|
+
result = "#{seconds / 60 / 60 / 24} days"
|
93
|
+
elsif seconds > 60 * 60
|
94
|
+
result = "#{seconds / 60 / 60} hours"
|
95
|
+
elsif seconds > 60
|
96
|
+
result = "#{seconds / 60} minutes"
|
97
|
+
else
|
98
|
+
result = "#{seconds} seconds"
|
99
|
+
end
|
100
|
+
result.start_with?('1 ') ? result[0..-2] : result
|
101
|
+
end
|
102
|
+
|
103
|
+
def longest_string_in_array(array)
|
104
|
+
array.max_by(&:length).length
|
105
|
+
end
|
106
|
+
|
107
|
+
module_function(:which)
|
108
|
+
|
109
|
+
module ClassMethods
|
110
|
+
def experimental?
|
111
|
+
ENV.has_key?('KONTENA_EXPERIMENTAL')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
data/lib/kontena_cli.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'kontena/autoload_core'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
$KONTENA_START_TIME = Time.now.to_f
|
5
|
+
at_exit do
|
6
|
+
Kontena.logger.debug { "Execution took #{(Time.now.to_f - $KONTENA_START_TIME).round(3)} seconds" }
|
7
|
+
Kontena.logger.debug { "#{$!.class.name}" + ($!.respond_to?(:status) ? " status #{$!.status}" : "") } if $!
|
8
|
+
end
|
9
|
+
|
10
|
+
module Kontena
|
11
|
+
module Cli
|
12
|
+
autoload :Config, 'kontena/cli/config'
|
13
|
+
autoload :ShellSpinner, 'kontena/cli/spinner'
|
14
|
+
autoload :Spinner, 'kontena/cli/spinner'
|
15
|
+
autoload :Common, 'kontena/cli/common'
|
16
|
+
autoload :TableGenerator, 'kontena/cli/table_generator'
|
17
|
+
end
|
18
|
+
|
19
|
+
autoload :Command, 'kontena/command'
|
20
|
+
autoload :Client, 'kontena/client'
|
21
|
+
autoload :StacksCache, 'kontena/stacks_cache'
|
22
|
+
autoload :PluginManager, 'kontena/plugin_manager'
|
23
|
+
autoload :MainCommand, 'kontena/main_command'
|
24
|
+
autoload :Errors, 'kontena/errors'
|
25
|
+
autoload :Util, 'kontena/util'
|
26
|
+
|
27
|
+
# Run a kontena command like it was launched from the command line. Re-raises any exceptions,
|
28
|
+
# except a SystemExit with status 0, which is considered a success.
|
29
|
+
#
|
30
|
+
# @param [String,Array<String>] command_line
|
31
|
+
# @return command result or nil
|
32
|
+
def self.run!(*cmdline)
|
33
|
+
if cmdline.first.kind_of?(Array)
|
34
|
+
command = cmdline.first
|
35
|
+
elsif cmdline.size == 1 && cmdline.first.include?(' ')
|
36
|
+
command = cmdline.first.shellsplit
|
37
|
+
else
|
38
|
+
command = cmdline
|
39
|
+
end
|
40
|
+
logger.debug { "Running Kontena.run(#{command.inspect})" }
|
41
|
+
result = Kontena::MainCommand.new(File.basename(__FILE__)).run(command)
|
42
|
+
logger.debug { "Command completed, result: #{result.inspect} status: 0" }
|
43
|
+
result
|
44
|
+
rescue SystemExit => ex
|
45
|
+
logger.debug { "Command caused SystemExit, status: #{ex.status}" }
|
46
|
+
return true if ex.status.zero?
|
47
|
+
raise ex
|
48
|
+
rescue => ex
|
49
|
+
logger.error { "Command #{cmdline.inspect} exception" }
|
50
|
+
logger.error { ex }
|
51
|
+
raise ex
|
52
|
+
end
|
53
|
+
|
54
|
+
# Run a kontena command and return true if the command did not raise or exit with a non-zero exit code. Raises nothing.
|
55
|
+
# @param [String,Array<String>] command_line
|
56
|
+
# @return [TrueClass,FalseClass] success
|
57
|
+
def self.run(*cmdline)
|
58
|
+
result = run!(*cmdline)
|
59
|
+
result.nil? ? true : result
|
60
|
+
rescue SystemExit => ex
|
61
|
+
ex.status.zero?
|
62
|
+
rescue
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.log_target
|
67
|
+
return @log_target if @log_target
|
68
|
+
|
69
|
+
@log_target = ENV['LOG_TARGET']
|
70
|
+
|
71
|
+
if debug?
|
72
|
+
@log_target ||= $stderr
|
73
|
+
elsif @log_target.nil?
|
74
|
+
@log_target = File.join(home, 'krates.log')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.reset_logger
|
79
|
+
@log_target, @logger = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.home
|
83
|
+
return @home if @home
|
84
|
+
@home = File.join(Dir.home, '.krates')
|
85
|
+
Dir.mkdir(@home, 0700) unless File.directory?(@home)
|
86
|
+
@home
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String] x.y
|
90
|
+
def self.minor_version
|
91
|
+
Kontena::Cli::VERSION.split('.')[0..1].join('.')
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.version
|
95
|
+
"krates/#{Kontena::Cli::VERSION}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.on_windows?
|
99
|
+
ENV['OS'] == 'Windows_NT' && RUBY_PLATFORM !~ /cygwin/
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.browserless?
|
103
|
+
!!(RUBY_PLATFORM =~ /linux|(?:free|net|open)bsd|solaris|aix|hpux/ && ENV['DISPLAY'].to_s.empty?)
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.simple_terminal?
|
107
|
+
ENV['KONTENA_SIMPLE_TERM'] || !$stdout.tty?
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.pastel
|
111
|
+
return @pastel if @pastel
|
112
|
+
require 'pastel'
|
113
|
+
@pastel = Pastel.new(enabled: !simple_terminal?)
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.prompt
|
117
|
+
return @prompt if @prompt
|
118
|
+
if simple_terminal?
|
119
|
+
require_relative 'kontena/light_prompt'
|
120
|
+
klass = Kontena::LightPrompt
|
121
|
+
else
|
122
|
+
require 'tty-prompt'
|
123
|
+
klass = TTY::Prompt
|
124
|
+
end
|
125
|
+
|
126
|
+
@prompt = klass.new(
|
127
|
+
active_color: :cyan,
|
128
|
+
help_color: :white,
|
129
|
+
error_color: :red,
|
130
|
+
interrupt: :exit,
|
131
|
+
prefix: pastel.green('> ')
|
132
|
+
)
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.reset_prompt
|
136
|
+
@prompt = nil
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.root
|
140
|
+
File.dirname(__dir__)
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.cli_root(*joinables)
|
144
|
+
if joinables.empty?
|
145
|
+
File.join(Kontena.root, 'lib/kontena/cli')
|
146
|
+
else
|
147
|
+
File.join(Kontena.root, 'lib/kontena/cli', *joinables)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.logger
|
152
|
+
return @logger if @logger
|
153
|
+
if log_target.respond_to?(:tty?) && log_target.tty?
|
154
|
+
logger = Logger.new(log_target)
|
155
|
+
require 'kontena/cli/log_formatters/compact'
|
156
|
+
logger.formatter = Kontena::Cli::LogFormatter::Compact.new
|
157
|
+
else
|
158
|
+
logger = Logger.new(log_target, 1, 1_048_576)
|
159
|
+
require 'kontena/cli/log_formatters/strip_color'
|
160
|
+
logger.formatter = Kontena::Cli::LogFormatter::StripColor.new
|
161
|
+
end
|
162
|
+
logger.level = debug? ? Logger::DEBUG : Logger::INFO
|
163
|
+
logger.progname = 'CLI'
|
164
|
+
@logger = logger
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.debug?
|
168
|
+
!['', 'false'].include?(ENV['DEBUG'].to_s)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Monkeypatching string to mimick 'colorize' gem
|
173
|
+
class String
|
174
|
+
def colorize(color_sym)
|
175
|
+
::Kontena.pastel.send(color_sym, self)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
require 'retriable'
|
181
|
+
Retriable.configure do |c|
|
182
|
+
c.on_retry = Proc.new do |exception, try, elapsed_time, next_interval|
|
183
|
+
Kontena.logger.debug { "Retriable retry: #{try} - Exception: #{exception.class.name} - #{exception.message}. Elapsed: #{elapsed_time} Next interval: #{next_interval}" }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
require 'ruby_dig'
|
188
|
+
require 'shellwords'
|
189
|
+
require 'kontena/cli/version'
|
190
|
+
Kontena.logger.debug { "Krates #{Kontena::Cli::VERSION} (ruby-#{RUBY_VERSION}+#{RUBY_PLATFORM})" }
|