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.
Files changed (293) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +212 -0
  3. data/LOGO +10 -0
  4. data/VERSION +1 -0
  5. data/bin/krates +23 -0
  6. data/lib/kontena/autoload_core.rb +19 -0
  7. data/lib/kontena/callback.rb +60 -0
  8. data/lib/kontena/callbacks/.gitkeep +0 -0
  9. data/lib/kontena/callbacks/auth/01_list_and_select_grid_after_master_auth.rb +26 -0
  10. data/lib/kontena/callbacks/master/01_clear_current_master_after_terminate.rb +19 -0
  11. data/lib/kontena/callbacks/master/deploy/01_show_logo_before_deploy.rb +14 -0
  12. data/lib/kontena/callbacks/master/deploy/04_default_master_version.rb +18 -0
  13. data/lib/kontena/callbacks/master/deploy/05_before_deploy_configuration_wizard.rb +105 -0
  14. data/lib/kontena/callbacks/master/deploy/40_install_ssl_certificate_after_deploy.rb +32 -0
  15. data/lib/kontena/callbacks/master/deploy/50_authenticate_after_deploy.rb +66 -0
  16. data/lib/kontena/callbacks/master/deploy/55_create_initial_grid_after_deploy.rb +21 -0
  17. data/lib/kontena/callbacks/master/deploy/56_set_server_provider_after_deploy.rb +24 -0
  18. data/lib/kontena/callbacks/master/deploy/60_configure_auth_provider_after_deploy.rb +31 -0
  19. data/lib/kontena/callbacks/master/deploy/70_invite_self_after_deploy.rb +95 -0
  20. data/lib/kontena/callbacks/master/deploy/90_proptip_after_deploy.rb +33 -0
  21. data/lib/kontena/cli/browser_launcher.rb +61 -0
  22. data/lib/kontena/cli/bytes_helper.rb +40 -0
  23. data/lib/kontena/cli/certificate/authorize_command.rb +107 -0
  24. data/lib/kontena/cli/certificate/common.rb +16 -0
  25. data/lib/kontena/cli/certificate/domain_authorization/list_command.rb +24 -0
  26. data/lib/kontena/cli/certificate/domain_authorization/remove_authorization_command.rb +25 -0
  27. data/lib/kontena/cli/certificate/domain_authorize_command.rb +7 -0
  28. data/lib/kontena/cli/certificate/export_command.rb +28 -0
  29. data/lib/kontena/cli/certificate/get_command.rb +33 -0
  30. data/lib/kontena/cli/certificate/import_command.rb +61 -0
  31. data/lib/kontena/cli/certificate/list_command.rb +75 -0
  32. data/lib/kontena/cli/certificate/register_command.rb +30 -0
  33. data/lib/kontena/cli/certificate/remove_command.rb +23 -0
  34. data/lib/kontena/cli/certificate/request_command.rb +20 -0
  35. data/lib/kontena/cli/certificate/show_command.rb +22 -0
  36. data/lib/kontena/cli/certificate_command.rb +18 -0
  37. data/lib/kontena/cli/cloud/login_command.rb +186 -0
  38. data/lib/kontena/cli/cloud/logout_command.rb +14 -0
  39. data/lib/kontena/cli/cloud/master/add_command.rb +156 -0
  40. data/lib/kontena/cli/cloud/master/list_command.rb +35 -0
  41. data/lib/kontena/cli/cloud/master/remove_command.rb +68 -0
  42. data/lib/kontena/cli/cloud/master/show_command.rb +21 -0
  43. data/lib/kontena/cli/cloud/master/update_command.rb +52 -0
  44. data/lib/kontena/cli/cloud/master_command.rb +14 -0
  45. data/lib/kontena/cli/cloud_command.rb +13 -0
  46. data/lib/kontena/cli/common.rb +360 -0
  47. data/lib/kontena/cli/config.rb +662 -0
  48. data/lib/kontena/cli/container_command.rb +10 -0
  49. data/lib/kontena/cli/containers/exec_command.rb +31 -0
  50. data/lib/kontena/cli/containers/inspect_command.rb +16 -0
  51. data/lib/kontena/cli/containers/list_command.rb +51 -0
  52. data/lib/kontena/cli/containers/logs_command.rb +19 -0
  53. data/lib/kontena/cli/etcd/common.rb +8 -0
  54. data/lib/kontena/cli/etcd/get_command.rb +26 -0
  55. data/lib/kontena/cli/etcd/health_command.rb +53 -0
  56. data/lib/kontena/cli/etcd/list_command.rb +36 -0
  57. data/lib/kontena/cli/etcd/mkdir_command.rb +23 -0
  58. data/lib/kontena/cli/etcd/remove_command.rb +29 -0
  59. data/lib/kontena/cli/etcd/set_command.rb +24 -0
  60. data/lib/kontena/cli/etcd_command.rb +12 -0
  61. data/lib/kontena/cli/external_registries/add_command.rb +25 -0
  62. data/lib/kontena/cli/external_registries/list_command.rb +23 -0
  63. data/lib/kontena/cli/external_registries/remove_command.rb +17 -0
  64. data/lib/kontena/cli/external_registry_command.rb +9 -0
  65. data/lib/kontena/cli/grid_command.rb +21 -0
  66. data/lib/kontena/cli/grid_options.rb +12 -0
  67. data/lib/kontena/cli/grids/audit_log_command.rb +22 -0
  68. data/lib/kontena/cli/grids/cloud_config_command.rb +53 -0
  69. data/lib/kontena/cli/grids/common.rb +182 -0
  70. data/lib/kontena/cli/grids/create_command.rb +48 -0
  71. data/lib/kontena/cli/grids/current_command.rb +25 -0
  72. data/lib/kontena/cli/grids/env_command.rb +32 -0
  73. data/lib/kontena/cli/grids/events_command.rb +50 -0
  74. data/lib/kontena/cli/grids/health_command.rb +69 -0
  75. data/lib/kontena/cli/grids/list_command.rb +59 -0
  76. data/lib/kontena/cli/grids/logs_command.rb +35 -0
  77. data/lib/kontena/cli/grids/remove_command.rb +31 -0
  78. data/lib/kontena/cli/grids/show_command.rb +25 -0
  79. data/lib/kontena/cli/grids/trusted_subnet_command.rb +10 -0
  80. data/lib/kontena/cli/grids/trusted_subnets/add_command.rb +18 -0
  81. data/lib/kontena/cli/grids/trusted_subnets/list_command.rb +18 -0
  82. data/lib/kontena/cli/grids/trusted_subnets/remove_command.rb +26 -0
  83. data/lib/kontena/cli/grids/update_command.rb +35 -0
  84. data/lib/kontena/cli/grids/use_command.rb +26 -0
  85. data/lib/kontena/cli/grids/user_command.rb +9 -0
  86. data/lib/kontena/cli/grids/users/add_command.rb +18 -0
  87. data/lib/kontena/cli/grids/users/list_command.rb +20 -0
  88. data/lib/kontena/cli/grids/users/remove_command.rb +20 -0
  89. data/lib/kontena/cli/helpers/exec_helper.rb +209 -0
  90. data/lib/kontena/cli/helpers/health_helper.rb +65 -0
  91. data/lib/kontena/cli/helpers/log_helper.rb +113 -0
  92. data/lib/kontena/cli/helpers/time_helper.rb +29 -0
  93. data/lib/kontena/cli/localhost_web_server.rb +113 -0
  94. data/lib/kontena/cli/log_formatters/compact.rb +65 -0
  95. data/lib/kontena/cli/log_formatters/strip_color.rb +13 -0
  96. data/lib/kontena/cli/logout_command.rb +10 -0
  97. data/lib/kontena/cli/master/audit_log_command.rb +19 -0
  98. data/lib/kontena/cli/master/config/export_command.rb +46 -0
  99. data/lib/kontena/cli/master/config/get_command.rb +26 -0
  100. data/lib/kontena/cli/master/config/import_command.rb +67 -0
  101. data/lib/kontena/cli/master/config/set_command.rb +19 -0
  102. data/lib/kontena/cli/master/config/unset_command.rb +20 -0
  103. data/lib/kontena/cli/master/config_command.rb +17 -0
  104. data/lib/kontena/cli/master/create_command.rb +74 -0
  105. data/lib/kontena/cli/master/current_command.rb +25 -0
  106. data/lib/kontena/cli/master/init_cloud_command.rb +45 -0
  107. data/lib/kontena/cli/master/join_command.rb +22 -0
  108. data/lib/kontena/cli/master/list_command.rb +24 -0
  109. data/lib/kontena/cli/master/login_command.rb +331 -0
  110. data/lib/kontena/cli/master/logout_command.rb +25 -0
  111. data/lib/kontena/cli/master/remove_command.rb +55 -0
  112. data/lib/kontena/cli/master/ssh_command.rb +72 -0
  113. data/lib/kontena/cli/master/token/common.rb +29 -0
  114. data/lib/kontena/cli/master/token/create_command.rb +50 -0
  115. data/lib/kontena/cli/master/token/current_command.rb +45 -0
  116. data/lib/kontena/cli/master/token/list_command.rb +39 -0
  117. data/lib/kontena/cli/master/token/remove_command.rb +19 -0
  118. data/lib/kontena/cli/master/token/show_command.rb +34 -0
  119. data/lib/kontena/cli/master/token_command.rb +13 -0
  120. data/lib/kontena/cli/master/use_command.rb +31 -0
  121. data/lib/kontena/cli/master/user/invite_command.rb +51 -0
  122. data/lib/kontena/cli/master/user/list_command.rb +29 -0
  123. data/lib/kontena/cli/master/user/remove_command.rb +24 -0
  124. data/lib/kontena/cli/master/user/role/add_command.rb +29 -0
  125. data/lib/kontena/cli/master/user/role/remove_command.rb +27 -0
  126. data/lib/kontena/cli/master/user/role_command.rb +6 -0
  127. data/lib/kontena/cli/master/user_command.rb +9 -0
  128. data/lib/kontena/cli/master_command.rb +21 -0
  129. data/lib/kontena/cli/node_command.rb +17 -0
  130. data/lib/kontena/cli/nodes/create_command.rb +25 -0
  131. data/lib/kontena/cli/nodes/env_command.rb +37 -0
  132. data/lib/kontena/cli/nodes/health_command.rb +47 -0
  133. data/lib/kontena/cli/nodes/label_command.rb +10 -0
  134. data/lib/kontena/cli/nodes/labels/add_command.rb +18 -0
  135. data/lib/kontena/cli/nodes/labels/list_command.rb +19 -0
  136. data/lib/kontena/cli/nodes/labels/remove_command.rb +32 -0
  137. data/lib/kontena/cli/nodes/list_command.rb +97 -0
  138. data/lib/kontena/cli/nodes/remove_command.rb +34 -0
  139. data/lib/kontena/cli/nodes/reset_token_command.rb +34 -0
  140. data/lib/kontena/cli/nodes/show_command.rb +56 -0
  141. data/lib/kontena/cli/nodes/ssh_command.rb +63 -0
  142. data/lib/kontena/cli/nodes/update_command.rb +31 -0
  143. data/lib/kontena/cli/plugin_command.rb +12 -0
  144. data/lib/kontena/cli/plugins/common.rb +8 -0
  145. data/lib/kontena/cli/plugins/install_command.rb +42 -0
  146. data/lib/kontena/cli/plugins/list_command.rb +31 -0
  147. data/lib/kontena/cli/plugins/search_command.rb +25 -0
  148. data/lib/kontena/cli/plugins/show_command.rb +17 -0
  149. data/lib/kontena/cli/plugins/uninstall_command.rb +31 -0
  150. data/lib/kontena/cli/plugins/upgrade_command.rb +60 -0
  151. data/lib/kontena/cli/registry/create_command.rb +151 -0
  152. data/lib/kontena/cli/registry/remove_command.rb +21 -0
  153. data/lib/kontena/cli/registry_command.rb +8 -0
  154. data/lib/kontena/cli/service_command.rb +28 -0
  155. data/lib/kontena/cli/services/container_command.rb +8 -0
  156. data/lib/kontena/cli/services/containers_command.rb +39 -0
  157. data/lib/kontena/cli/services/create_command.rb +105 -0
  158. data/lib/kontena/cli/services/deploy_command.rb +25 -0
  159. data/lib/kontena/cli/services/env_command.rb +9 -0
  160. data/lib/kontena/cli/services/envs/add_command.rb +21 -0
  161. data/lib/kontena/cli/services/envs/list_command.rb +22 -0
  162. data/lib/kontena/cli/services/envs/remove_command.rb +22 -0
  163. data/lib/kontena/cli/services/events_command.rb +36 -0
  164. data/lib/kontena/cli/services/exec_command.rb +107 -0
  165. data/lib/kontena/cli/services/link_command.rb +35 -0
  166. data/lib/kontena/cli/services/list_command.rb +66 -0
  167. data/lib/kontena/cli/services/logs_command.rb +33 -0
  168. data/lib/kontena/cli/services/monitor_command.rb +58 -0
  169. data/lib/kontena/cli/services/remove_command.rb +60 -0
  170. data/lib/kontena/cli/services/restart_command.rb +19 -0
  171. data/lib/kontena/cli/services/scale_command.rb +21 -0
  172. data/lib/kontena/cli/services/secret_command.rb +8 -0
  173. data/lib/kontena/cli/services/secrets/link_command.rb +26 -0
  174. data/lib/kontena/cli/services/secrets/unlink_command.rb +28 -0
  175. data/lib/kontena/cli/services/services_helper.rb +579 -0
  176. data/lib/kontena/cli/services/show_command.rb +26 -0
  177. data/lib/kontena/cli/services/start_command.rb +21 -0
  178. data/lib/kontena/cli/services/stats_command.rb +87 -0
  179. data/lib/kontena/cli/services/stop_command.rb +21 -0
  180. data/lib/kontena/cli/services/unlink_command.rb +30 -0
  181. data/lib/kontena/cli/services/update_command.rb +94 -0
  182. data/lib/kontena/cli/spinner.rb +205 -0
  183. data/lib/kontena/cli/stack_command.rb +21 -0
  184. data/lib/kontena/cli/stacks/build_command.rb +125 -0
  185. data/lib/kontena/cli/stacks/common.rb +209 -0
  186. data/lib/kontena/cli/stacks/deploy_command.rb +37 -0
  187. data/lib/kontena/cli/stacks/events_command.rb +33 -0
  188. data/lib/kontena/cli/stacks/inspect_command.rb +17 -0
  189. data/lib/kontena/cli/stacks/install_command.rb +95 -0
  190. data/lib/kontena/cli/stacks/label_command.rb +10 -0
  191. data/lib/kontena/cli/stacks/labels/add_command.rb +21 -0
  192. data/lib/kontena/cli/stacks/labels/common.rb +19 -0
  193. data/lib/kontena/cli/stacks/labels/list_command.rb +21 -0
  194. data/lib/kontena/cli/stacks/labels/remove_command.rb +21 -0
  195. data/lib/kontena/cli/stacks/list_command.rb +154 -0
  196. data/lib/kontena/cli/stacks/logs_command.rb +35 -0
  197. data/lib/kontena/cli/stacks/monitor_command.rb +93 -0
  198. data/lib/kontena/cli/stacks/registry/create_command.rb +24 -0
  199. data/lib/kontena/cli/stacks/registry/make_private_command.rb +24 -0
  200. data/lib/kontena/cli/stacks/registry/make_public_command.rb +24 -0
  201. data/lib/kontena/cli/stacks/registry/pull_command.rb +28 -0
  202. data/lib/kontena/cli/stacks/registry/push_command.rb +40 -0
  203. data/lib/kontena/cli/stacks/registry/remove_command.rb +30 -0
  204. data/lib/kontena/cli/stacks/registry/search_command.rb +42 -0
  205. data/lib/kontena/cli/stacks/registry/show_command.rb +65 -0
  206. data/lib/kontena/cli/stacks/registry_command.rb +12 -0
  207. data/lib/kontena/cli/stacks/remove_command.rb +80 -0
  208. data/lib/kontena/cli/stacks/restart_command.rb +24 -0
  209. data/lib/kontena/cli/stacks/service_generator.rb +131 -0
  210. data/lib/kontena/cli/stacks/service_generator_v2.rb +27 -0
  211. data/lib/kontena/cli/stacks/show_command.rb +168 -0
  212. data/lib/kontena/cli/stacks/stack_name.rb +71 -0
  213. data/lib/kontena/cli/stacks/stacks_helper.rb +83 -0
  214. data/lib/kontena/cli/stacks/stop_command.rb +24 -0
  215. data/lib/kontena/cli/stacks/upgrade_command.rb +264 -0
  216. data/lib/kontena/cli/stacks/validate_command.rb +75 -0
  217. data/lib/kontena/cli/stacks/yaml/custom_validators/affinities_validator.rb +19 -0
  218. data/lib/kontena/cli/stacks/yaml/custom_validators/build_validator.rb +22 -0
  219. data/lib/kontena/cli/stacks/yaml/custom_validators/certificates_validator.rb +22 -0
  220. data/lib/kontena/cli/stacks/yaml/custom_validators/extends_validator.rb +22 -0
  221. data/lib/kontena/cli/stacks/yaml/custom_validators/hooks_validator.rb +102 -0
  222. data/lib/kontena/cli/stacks/yaml/custom_validators/secrets_validator.rb +22 -0
  223. data/lib/kontena/cli/stacks/yaml/opto/certificates_resolver.rb +37 -0
  224. data/lib/kontena/cli/stacks/yaml/opto/prompt_resolver.rb +78 -0
  225. data/lib/kontena/cli/stacks/yaml/opto/service_instances_resolver.rb +25 -0
  226. data/lib/kontena/cli/stacks/yaml/opto/service_link_resolver.rb +80 -0
  227. data/lib/kontena/cli/stacks/yaml/opto/vault_cert_prompt_resolver.rb +39 -0
  228. data/lib/kontena/cli/stacks/yaml/opto/vault_resolver.rb +13 -0
  229. data/lib/kontena/cli/stacks/yaml/opto/vault_setter.rb +12 -0
  230. data/lib/kontena/cli/stacks/yaml/opto.rb +16 -0
  231. data/lib/kontena/cli/stacks/yaml/reader.rb +525 -0
  232. data/lib/kontena/cli/stacks/yaml/service_extender.rb +65 -0
  233. data/lib/kontena/cli/stacks/yaml/stack_file_loader/file_loader.rb +41 -0
  234. data/lib/kontena/cli/stacks/yaml/stack_file_loader/registry_loader.rb +24 -0
  235. data/lib/kontena/cli/stacks/yaml/stack_file_loader/uri_loader.rb +23 -0
  236. data/lib/kontena/cli/stacks/yaml/stack_file_loader.rb +152 -0
  237. data/lib/kontena/cli/stacks/yaml/validations.rb +119 -0
  238. data/lib/kontena/cli/stacks/yaml/validator_v3.rb +164 -0
  239. data/lib/kontena/cli/subcommand_loader.rb +83 -0
  240. data/lib/kontena/cli/table_generator.rb +128 -0
  241. data/lib/kontena/cli/vault/export_command.rb +24 -0
  242. data/lib/kontena/cli/vault/import_command.rb +75 -0
  243. data/lib/kontena/cli/vault/list_command.rb +37 -0
  244. data/lib/kontena/cli/vault/read_command.rb +27 -0
  245. data/lib/kontena/cli/vault/remove_command.rb +23 -0
  246. data/lib/kontena/cli/vault/update_command.rb +24 -0
  247. data/lib/kontena/cli/vault/write_command.rb +23 -0
  248. data/lib/kontena/cli/vault_command.rb +13 -0
  249. data/lib/kontena/cli/version.rb +10 -0
  250. data/lib/kontena/cli/version_command.rb +20 -0
  251. data/lib/kontena/cli/volume_command.rb +9 -0
  252. data/lib/kontena/cli/volumes/create_command.rb +42 -0
  253. data/lib/kontena/cli/volumes/list_command.rb +29 -0
  254. data/lib/kontena/cli/volumes/remove_command.rb +29 -0
  255. data/lib/kontena/cli/volumes/show_command.rb +38 -0
  256. data/lib/kontena/cli/vpn/config_command.rb +27 -0
  257. data/lib/kontena/cli/vpn/create_command.rb +99 -0
  258. data/lib/kontena/cli/vpn/remove_command.rb +22 -0
  259. data/lib/kontena/cli/vpn_command.rb +9 -0
  260. data/lib/kontena/cli/whoami_command.rb +38 -0
  261. data/lib/kontena/client.rb +574 -0
  262. data/lib/kontena/command.rb +251 -0
  263. data/lib/kontena/debug_instrumentor.rb +80 -0
  264. data/lib/kontena/errors.rb +50 -0
  265. data/lib/kontena/light_prompt.rb +103 -0
  266. data/lib/kontena/machine/cert_helper.rb +43 -0
  267. data/lib/kontena/machine/cloud_config/cloudinit.yml +82 -0
  268. data/lib/kontena/machine/cloud_config/node_generator.rb +28 -0
  269. data/lib/kontena/machine/common.rb +17 -0
  270. data/lib/kontena/machine/random_name.rb +42 -0
  271. data/lib/kontena/main_command.rb +66 -0
  272. data/lib/kontena/plugin_manager/cleaner.rb +33 -0
  273. data/lib/kontena/plugin_manager/common.rb +89 -0
  274. data/lib/kontena/plugin_manager/installer.rb +78 -0
  275. data/lib/kontena/plugin_manager/loader.rb +93 -0
  276. data/lib/kontena/plugin_manager/rubygems_client.rb +59 -0
  277. data/lib/kontena/plugin_manager/uninstaller.rb +34 -0
  278. data/lib/kontena/plugin_manager.rb +26 -0
  279. data/lib/kontena/presets/github_auth_provider.yml +11 -0
  280. data/lib/kontena/presets/kontena_auth_provider.yml +11 -0
  281. data/lib/kontena/scripts/completer +9 -0
  282. data/lib/kontena/scripts/completer.rb +334 -0
  283. data/lib/kontena/scripts/init +18 -0
  284. data/lib/kontena/scripts/kontena.zsh +11 -0
  285. data/lib/kontena/scripts/krates.bash +8 -0
  286. data/lib/kontena/stacks/change_resolver.rb +118 -0
  287. data/lib/kontena/stacks/stack_data.rb +58 -0
  288. data/lib/kontena/stacks/stack_data_set.rb +51 -0
  289. data/lib/kontena/stacks_cache.rb +110 -0
  290. data/lib/kontena/stacks_client.rb +177 -0
  291. data/lib/kontena/util.rb +116 -0
  292. data/lib/kontena_cli.rb +190 -0
  293. 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
@@ -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
@@ -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})" }