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,662 @@
1
+ require 'ostruct'
2
+ require 'singleton'
3
+ require 'forwardable'
4
+ require 'logger'
5
+ autoload :JSON, 'json'
6
+
7
+ module Kontena
8
+ module Cli
9
+ # Helper to access and update the CLI configuration file.
10
+ #
11
+ # Also provides a "fake" config hash that behaves just like the file based
12
+ # config when ENV-variables are used instead of config file.
13
+ class Config < OpenStruct
14
+ include Singleton
15
+
16
+ module Fields
17
+ def keys
18
+ @table.keys
19
+ end
20
+
21
+ def values_at(*fields)
22
+ (fields.first.is_a?(Array) ? fields.first : fields).map { |field| self[field] }
23
+ end
24
+ end
25
+
26
+ include Fields
27
+
28
+ attr_accessor :logger
29
+ attr_accessor :current_server
30
+ attr_reader :current_account
31
+
32
+
33
+ def self.reset_instance
34
+ Singleton.send :__init__, self
35
+ self
36
+ end
37
+
38
+ TokenExpiredError = Class.new(StandardError)
39
+
40
+ def initialize
41
+ super
42
+ @logger = Kontena.logger
43
+
44
+ load_settings_from_config_file
45
+
46
+ override_master_settings_from_env
47
+ override_cloud_settings_from_env
48
+
49
+ debug { "Configuration loaded with #{servers.count} servers and #{accounts.count} accounts." }
50
+ debug { "Current master: #{current_server || '(not selected)'}" }
51
+ debug { "Current grid: #{current_grid || '(not selected)'}" }
52
+ debug { "Current account: #{current_account.nil? ? '(not selected)' : current_account.name}" }
53
+ end
54
+
55
+ def debug(&block)
56
+ Kontena.logger.add(Logger::DEBUG, nil, 'CONFIG', &block)
57
+ end
58
+
59
+ def override_master_settings_from_env
60
+ if ENV['KONTENA_URL']
61
+ server = find_server_by(url: ENV['KONTENA_URL'])
62
+ if server.nil?
63
+ debug { 'Using new master url from env KONTENA_URL' }
64
+ server = Server.new(
65
+ url: ENV['KONTENA_URL'],
66
+ name: ENV['KONTENA_MASTER'] || 'default'
67
+ )
68
+ servers << server
69
+ else
70
+ debug { "Using master #{server.name} in config found via url in env KONTENA_URL" }
71
+ end
72
+ elsif ENV['KONTENA_MASTER']
73
+ server = find_server_by(name: ENV['KONTENA_MASTER'])
74
+ if server
75
+ debug { "Using master #{ENV['KONTENA_MASTER']} set via env KONTENA_MASTER" }
76
+ end
77
+ elsif current_master
78
+ server = current_master
79
+ end
80
+
81
+ if server.nil?
82
+ debug { 'Could not determine a master through config or env' }
83
+ self.current_master = nil
84
+ return
85
+ else
86
+ self.current_master = server.name
87
+ end
88
+
89
+ if ENV['KONTENA_GRID']
90
+ debug { "Using grid #{ENV['KONTENA_GRID']} from env KONTENA_GRID" }
91
+ server.grid = ENV['KONTENA_GRID']
92
+ end
93
+
94
+ if ENV['KONTENA_TOKEN']
95
+ debug { 'Using master token from env KONTENA_TOKEN' }
96
+ server.token ||= Token.new(parent_type: :master, parent_name: server.name)
97
+ server.token.access_token = ENV['KONTENA_TOKEN']
98
+ server.token.refresh_token = nil
99
+ server.token.expires_at = nil
100
+ end
101
+ end
102
+
103
+ def override_cloud_settings_from_env
104
+ if ENV['KONTENA_CLOUD']
105
+ account = find_account(ENV['KONTENA_CLOUD'])
106
+ if account
107
+ debug { "Using cloud account #{ENV['KONTENA_CLOUD']} from config selected by env KONTENA_CLOUD" }
108
+ self.current_account = account.name
109
+ else
110
+ debug { "Using new cloud account #{ENV['KONTENA_CLOUD']} from env" }
111
+ account = Accout.new(kontena_account_data.merge(name: ENV['KONTENA_CLOUD']))
112
+ accounts << account
113
+ end
114
+ elsif current_account
115
+ account = current_account
116
+ end
117
+
118
+ if account.nil?
119
+ debug { 'No account data from config or env' }
120
+ self.current_account = nil
121
+ return
122
+ end
123
+
124
+ if ENV['KONTENA_CLOUD_TOKEN']
125
+ debug { 'Using cloud token from env KONTENA_CLOUD_TOKEN' }
126
+ account.token ||= Token.new(parent_type: :account, parent_name: account.name)
127
+ account.token.access_token = ENV['KONTENA_CLOUD_TOKEN']
128
+ account.token.refresh_token = nil
129
+ account.token.expires_at = nil
130
+ end
131
+ end
132
+
133
+ def extract_token!(hash={})
134
+ Token.new(
135
+ access_token: hash.delete('token'),
136
+ refresh_token: hash.delete('refresh_token'),
137
+ expires_at: hash.delete('token_expires_at').to_i
138
+ )
139
+ end
140
+
141
+ # Load configuration from default location ($HOME/.krates.json)
142
+ def load_settings_from_config_file
143
+ settings = config_file_available? ? parse_config_file : default_settings
144
+
145
+ Array(settings['servers']).each do |server_data|
146
+ if server_data['token']
147
+ token = extract_token!(server_data)
148
+ token.parent_type = :master
149
+ token.parent_name = server_data['name']
150
+ server = Server.new(server_data)
151
+ server.token = token
152
+ else
153
+ server = Server.new(server_data)
154
+ end
155
+ server.account ||= 'master'
156
+ if servers.find { |s| s['name'] == server.name}
157
+ server.name = "#{server.name}-2"
158
+ server.name.succ! until servers.find { |s| s['name'] == server.name }.nil?
159
+ debug { "Renamed server to #{server.name} because a duplicate was found in config" }
160
+ end
161
+ servers << server
162
+ end
163
+
164
+ self.current_server = settings['current_server']
165
+
166
+ Array(settings['accounts']).each do |account_data|
167
+ if account_data['token']
168
+ token = extract_token!(account_data)
169
+ token.parent_type = :account
170
+ token.parent_name = account_data['name']
171
+ account = Account.new(account_data)
172
+ account.token = token
173
+ else
174
+ account = Account.new(account_data)
175
+ end
176
+ accounts << account
177
+ end
178
+
179
+ ka = find_account('kontena')
180
+ if ka
181
+ kontena_account_data.each {|k,v| ka[k] = v}
182
+ else
183
+ accounts << Account.new(kontena_account_data)
184
+ end
185
+
186
+ master_index = find_account_index('master')
187
+ accounts.delete_at(master_index) if master_index
188
+ accounts << Account.new(master_account_data)
189
+
190
+ self.current_account = settings['current_account'] || 'kontena'
191
+ end
192
+
193
+ def kontena_account_data
194
+ {
195
+ name: 'kontena',
196
+ url: ENV['KONTENA_CLOUD_URL'] || 'https://cloud-api.kontena.io',
197
+ stacks_url: ENV['KONTENA_STACK_REGISTRY_URL'] || 'https://stacks.kontena.io',
198
+ token_endpoint: ENV['AUTH_TOKEN_ENDPOINT'] || 'https://cloud-api.kontena.io/oauth2/token',
199
+ authorization_endpoint: ENV['AUTH_AUTHORIZE_ENDPOINT'] || 'https://cloud.kontena.io/login/oauth/authorize',
200
+ userinfo_endpoint: ENV['AUTH_USERINFO_ENDPOINT'] || 'https://cloud-api.kontena.io/user',
201
+ token_post_content_type: ENV['AUTH_TOKEN_POST_CONTENT_TYPE'] || 'application/x-www-form-urlencoded',
202
+ code_requires_basic_auth: ENV['AUTH_CODE_REQUIRES_BASIC_AUTH'].to_s == true,
203
+ token_method: ENV['AUTH_TOKEN_METHOD'] || 'post',
204
+ scope: ENV['AUTH_USERINFO_SCOPE'] || 'user',
205
+ client_id: nil,
206
+ stacks_read_authentication: ENV['KONTENA_STACK_REGISTRY_READ_AUTHENTICATION'].to_s == 'true'
207
+ }
208
+ end
209
+
210
+ def master_account_data
211
+ {
212
+ name: 'master',
213
+ token_endpoint: '/oauth2/token',
214
+ authorization_endpoint: '/oauth2/authorize',
215
+ userinfo_endpoint: '/v1/user',
216
+ token_post_content_type: 'application/json',
217
+ token_method: 'post',
218
+ code_requires_basic_auth: false
219
+ }
220
+ end
221
+
222
+ # Verifies access to existing configuration file
223
+ #
224
+ # @return [Boolean]
225
+ def config_file_available?
226
+ File.exist?(config_filename) && File.readable?(config_filename)
227
+ end
228
+
229
+ # Default settings hash, used when configuration file does not exist.
230
+ #
231
+ # @return [Hash]
232
+ def default_settings
233
+ debug { 'Configuration file not found, using default settings.' }
234
+ {
235
+ 'current_server' => 'default',
236
+ 'servers' => []
237
+ }
238
+ end
239
+
240
+ # Converts old style settings hash into modern one
241
+ #
242
+ # @param [Hash] settings_hash
243
+ # @return [Hash] migrated_settings_hash
244
+ def migrate_legacy_settings(settings)
245
+ debug { "Migrating from legacy style configuration" }
246
+ {
247
+ 'current_server' => 'default',
248
+ 'servers' => [
249
+ settings['server'].merge(
250
+ 'name' => 'default',
251
+ 'account' => 'kontena'
252
+ )
253
+ ],
254
+ 'accounts' => [ kontena_account_data ]
255
+ }
256
+ end
257
+
258
+ # Read, parse and migrate the configuration file
259
+ #
260
+ # @return [Hash] config_data
261
+ def parse_config_file
262
+ debug { "Loading configuration from #{config_filename}" }
263
+ settings = JSON.load(File.read(config_filename))
264
+ if settings.has_key?('server')
265
+ settings = migrate_legacy_settings(settings)
266
+ else
267
+ settings
268
+ end
269
+ end
270
+
271
+ # Return the configuration file path. You can override the default
272
+ # by using KONTENA_CONFIG environment variable.
273
+ #
274
+ # @return [String] path
275
+ def config_filename
276
+ return @config_filename if @config_filename
277
+ if ENV['KONTENA_CONFIG']
278
+ debug { "Using #{ENV['KONTENA_CONFIG']} as config file set through env KONTENA_CONFIG"}
279
+ @config_filename = ENV['KONTENA_CONFIG']
280
+ else
281
+ @config_filename = default_config_filename
282
+ end
283
+ end
284
+
285
+ # Generate the default configuration filename
286
+ def default_config_filename
287
+ File.join(Dir.home, '.krates.json')
288
+ end
289
+
290
+ # List of configured servers
291
+ #
292
+ # @return [Array]
293
+ def servers
294
+ @servers ||= []
295
+ end
296
+
297
+ # List of configured accounts
298
+ #
299
+ # @return [Array]
300
+ def accounts
301
+ @accounts ||= []
302
+ end
303
+
304
+ # Add a new server to the configuration
305
+ #
306
+ # @param [Hash] server_data
307
+ def add_server(data)
308
+ token = Token.new(
309
+ access_token: data.delete('token'),
310
+ refresh_token: data.delete('refresh_token'),
311
+ expires_at: data.delete('token_expires_at'),
312
+ parent_type: :master,
313
+ parent_name: data['name'] || data[:name]
314
+ )
315
+ server = Server.new(data.merge(token: token))
316
+ if (existing_index = find_server_index(server.name))
317
+ servers[existing_index] = server
318
+ else
319
+ servers << server
320
+ end
321
+ write
322
+ end
323
+
324
+ # Search the server list for a server by field(s) and value(s).
325
+ # @example
326
+ # find_server_by(url: 'https://localhost', token: 'abcd')
327
+ # @param [Hash] search_criteria
328
+ # @return [Server, NilClass]
329
+ def find_server_by(criteria = {})
330
+ servers.find{|s| criteria.none? {|k,v| v != s[k]}}
331
+ end
332
+
333
+ # Search the server list for a server by field(s) and value(s)
334
+ # and return its index.
335
+ #
336
+ # @example
337
+ # find_server_index(url: 'https://localhost')
338
+ # @param [Hash] search_criteria
339
+ # @return [Fixnum, NilClass]
340
+ def find_server_index_by(criteria = {})
341
+ servers.find_index{|s| criteria.none? {|k,v| v != s[k]}}
342
+ end
343
+
344
+ # Shortcut to find_server_by(name: name)
345
+ #
346
+ # @param [String] server_name
347
+ # @return [Server, NilClass]
348
+ def find_server(name)
349
+ find_server_by(name: name)
350
+ end
351
+
352
+ # Shortcut to find_server_index_by(name: name)
353
+ #
354
+ # @param [String] server_name
355
+ # @return [Fixnum, NilClass]
356
+ def find_server_index(name)
357
+ find_server_index_by(name: name)
358
+ end
359
+
360
+ def find_account(name)
361
+ accounts.find{|a| a['name'] == name.to_s}
362
+ end
363
+
364
+ def find_account_index(name)
365
+ accounts.find_index{|a| a['name'] == name.to_s}
366
+ end
367
+
368
+ # Currently selected master's configuration data
369
+ #
370
+ # @return [Server]
371
+ def current_master
372
+ return servers[@current_master_index] if @current_master_index
373
+ return nil unless current_server
374
+ @current_master_index = find_server_index(current_server)
375
+ servers[@current_master_index] if @current_master_index
376
+ end
377
+
378
+ # Raises unless current master has token.
379
+ #
380
+ # @return [Token] current_master_token
381
+ # @raise [ArgumentError] if no token available
382
+ def require_current_master_token
383
+ require_current_master
384
+ token = current_master.token
385
+ if token && token.access_token
386
+ return token unless token.expired?
387
+ raise TokenExpiredError, "The access token has expired and needs to be refreshed."
388
+ end
389
+ raise ArgumentError, "You are not logged into a Kontena Master. Use: kontena master login"
390
+ end
391
+
392
+ # Raises unless current master is selected.
393
+ #
394
+ # @return [Server] current_master
395
+ # @raise [ArgumentError] if no account is selected
396
+ def require_current_master
397
+ return current_master if current_master
398
+ raise ArgumentError, "You are not logged into a Kontena Master. Use: kontena master login"
399
+ end
400
+
401
+ # Raises unless current account is selected.
402
+ #
403
+ # @return [Account] current_account
404
+ # @raise [ArgumentError] if no account is selected
405
+ def require_current_account
406
+ return @current_account if @current_account
407
+ raise ArgumentError, "You are not logged into an authorization provider. Use: kontena cloud login"
408
+ end
409
+
410
+ def require_current_account_token
411
+ account = require_current_account
412
+ if !account || account.token.nil? || account.token.access_token.nil?
413
+ raise ArgumentError, "You are not logged in to Kontena Cloud. Use: kontena cloud login"
414
+ elsif account.token.expired?
415
+ raise TokenExpiredError, "The cloud access token has expired and needs to be refreshed." unless cloud_client.refresh_token
416
+ end
417
+ end
418
+
419
+ # Set the current master.
420
+ #
421
+ # @param [String] server_name
422
+ # @raise [ArgumentError] if server by that name doesn't exist
423
+ def current_master=(name)
424
+ @current_master_index = nil
425
+ if name.nil?
426
+ self.current_server = nil
427
+ else
428
+ index = find_server_index(name.respond_to?(:name) ? name.name : name)
429
+ if index
430
+ self.current_server = servers[index].name
431
+ else
432
+ raise ArgumentError, "Server '#{name}' does not exist, can't add as current master."
433
+ end
434
+ end
435
+ end
436
+
437
+ # Raises unless current grid is selected.
438
+ #
439
+ # @return [String] current_grid_name
440
+ # @raise [ArgumentError] if no grid is selected
441
+ def require_current_grid
442
+ return current_grid if current_grid
443
+ raise ArgumentError, "You have not selected a grid. Use: kontena grid"
444
+ end
445
+
446
+ # Name of the currently selected grid. Can override using
447
+ # KONTENA_GRID environment variable.
448
+ #
449
+ # @return [String, NilClass]
450
+ def current_grid
451
+ return ENV['KONTENA_GRID'] unless ENV['KONTENA_GRID'].to_s.empty?
452
+ return nil unless current_master
453
+ current_master.grid
454
+ end
455
+
456
+ # Set the current grid name.
457
+ #
458
+ # @param [String] grid_name
459
+ # @raise [ArgumentError] if current master hasn't been selected
460
+ def current_grid=(name)
461
+ if current_master
462
+ current_master.grid = name
463
+ else
464
+ raise ArgumentError, "Current master not selected, can't set grid."
465
+ end
466
+ end
467
+
468
+ def current_account=(name)
469
+ if name.nil?
470
+ @current_account = nil
471
+ elsif name == 'master'
472
+ raise ArgumentError, "The master account can not be used as current account."
473
+ else
474
+ account = find_account(name.respond_to?(:name) ? name.name : name)
475
+ if account
476
+ @current_account = account
477
+ else
478
+ raise ArgumentError, "Account '#{name}' not found in configuration"
479
+ end
480
+ end
481
+ end
482
+
483
+ # Returns a cleaned up version of the kontena account data with only the token and name.
484
+ def kontena_account_hash
485
+ hash = { name: 'kontena' }
486
+ acc = find_account('kontena')
487
+ if acc && acc.token
488
+ hash[:username] = acc.username if acc.username
489
+ hash.merge!(acc.token.to_h)
490
+ end
491
+ hash
492
+ end
493
+
494
+ # Generate a hash from the current configuration.
495
+ #
496
+ # @return [Hash]
497
+ def to_hash
498
+ hash = {
499
+ current_server: (self.current_server && find_server(self.current_server)) ? self.current_server : nil,
500
+ current_account: self.current_account ? self.current_account.name : nil,
501
+ servers: servers.map(&:to_h),
502
+ accounts: accounts.reject{|a| a.name == 'master' || a.name == 'kontena'}.map(&:to_h) + [kontena_account_hash]
503
+ }
504
+ hash[:servers].each do |server|
505
+ server.delete(:account) if server[:account] == 'master'
506
+ end
507
+ hash
508
+ end
509
+
510
+ # Generate a JSON string from the current configuration
511
+ #
512
+ # @return [String]
513
+ def to_json
514
+ JSON.pretty_generate(to_hash)
515
+ end
516
+
517
+ # Write the current configuration to config file.
518
+ # Does nothing if using settings from environment variables.
519
+ def write
520
+ return nil if ENV['KONTENA_URL']
521
+ debug { "Writing configuration to #{config_filename}" }
522
+ File.write(config_filename, to_json)
523
+ end
524
+
525
+ class << self
526
+ extend Forwardable
527
+ def_delegators :instance, *Config.instance_methods(false)
528
+ end
529
+
530
+ module TokenSerializer
531
+ # Modified to_h to handle token data serialization
532
+ #
533
+ # @return [Hash]
534
+ def to_h
535
+ token = delete_field(:token) if respond_to?(:token)
536
+ result = super
537
+ if token
538
+ self.token = token
539
+ result.merge!(token.to_h)
540
+ end
541
+ result
542
+ end
543
+ end
544
+
545
+ module ConfigurationInstance
546
+ def config
547
+ Kontena::Cli::Config.instance
548
+ end
549
+ end
550
+
551
+ class Account < OpenStruct
552
+ include Fields
553
+ include TokenSerializer
554
+ include ConfigurationInstance
555
+
556
+ # Strip token info from master-account, the token is saved with the server.
557
+ def to_h
558
+ if self.name == 'master'
559
+ super.to_h.reject do |k,_|
560
+ [:url, :token, :refresh_token, :token_expires_at].include?(k)
561
+ end
562
+ else
563
+ super
564
+ end
565
+ end
566
+ end
567
+
568
+ class Server < OpenStruct
569
+ include Fields
570
+ include TokenSerializer
571
+ include ConfigurationInstance
572
+
573
+ def initialize(*args)
574
+ super
575
+ @table[:account] ||= 'master'
576
+ end
577
+
578
+ def uri
579
+ @uri ||= URI.parse(self.url)
580
+ end
581
+
582
+ # @return [String, nil] path to ~/.kontena/certs/*.pem
583
+ def ssl_cert_path
584
+ path = File.join(Dir.home, '.kontena', 'certs', "#{self.uri.host}.pem")
585
+
586
+ if File.exist?(path) && File.readable?(path)
587
+ return path
588
+ else
589
+ return nil
590
+ end
591
+ end
592
+
593
+ # @return [OpenSSL::X509::Certificate, nil]
594
+ def ssl_cert
595
+ if path = self.ssl_cert_path
596
+ return OpenSSL::X509::Certificate.new(File.read(path))
597
+ else
598
+ return nil
599
+ end
600
+ end
601
+
602
+ # @return [String, nil] ssl cert subject CN=
603
+ def ssl_subject_cn
604
+ if cert = self.ssl_cert
605
+ return cert.subject.to_a.select{|name, data, type| name == 'CN' }.map{|name, data, type| data }.first
606
+ else
607
+ nil
608
+ end
609
+ end
610
+ end
611
+
612
+ class Token < OpenStruct
613
+ include Fields
614
+ include ConfigurationInstance
615
+
616
+ # Hash representation of token data
617
+ #
618
+ # @return [Hash]
619
+ def to_h
620
+ {
621
+ token: self.access_token,
622
+ token_expires_at: self.expires_at,
623
+ refresh_token: self.refresh_token
624
+ }.merge(self.respond_to?(:username) ? {username: self.username} : {})
625
+ end
626
+
627
+ def expires?
628
+ expires_at.nil? ? false : expires_at.to_i > 0
629
+ end
630
+
631
+ def expired?
632
+ expires? && expires_at && expires_at.to_i < Time.now.utc.to_i
633
+ end
634
+
635
+ def account
636
+ return @account if @account
637
+ return config.find_account('master') unless parent
638
+ @account =
639
+ case parent_type
640
+ when :master then config.find_account(parent.account)
641
+ when :account then parent
642
+ else
643
+ nil
644
+ end
645
+ end
646
+
647
+ def parent
648
+ return nil unless parent_type
649
+ return nil unless parent_name
650
+ case parent_type
651
+ when :master
652
+ config.find_server(parent_name)
653
+ when :account
654
+ config.find_account(parent_name)
655
+ else
656
+ nil
657
+ end
658
+ end
659
+ end
660
+ end
661
+ end
662
+ end
@@ -0,0 +1,10 @@
1
+ class Kontena::Cli::ContainerCommand < Kontena::Command
2
+
3
+ subcommand ["list", "ls"], "List grid containers", load_subcommand('containers/list_command')
4
+ subcommand "exec", "Execute command inside a container", load_subcommand('containers/exec_command')
5
+ subcommand "inspect", "Inspect the container", load_subcommand('containers/inspect_command')
6
+ subcommand "logs", "Show container logs", load_subcommand('containers/logs_command')
7
+
8
+ def execute
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../helpers/exec_helper'
2
+
3
+ module Kontena::Cli::Containers
4
+ class ExecCommand < Kontena::Command
5
+ include Kontena::Cli::Common
6
+ include Kontena::Cli::GridOptions
7
+ include Kontena::Cli::Helpers::ExecHelper
8
+
9
+ usage "[OPTIONS] [CONTAINER_ID] -- [CMD] ..."
10
+
11
+ parameter "CONTAINER_ID", "Container id"
12
+ parameter "CMD ...", "Command"
13
+
14
+ option ["--shell"], :flag, "Execute as a shell command", default: false
15
+ option ["-i", "--interactive"], :flag, "Keep stdin open", default: false
16
+ option ["-t", "--tty"], :flag, "Allocate a pseudo-TTY", default: false
17
+
18
+ requires_current_master
19
+ requires_current_grid
20
+
21
+ def execute
22
+ exit_status = container_exec("#{current_grid}/#{self.container_id}", self.cmd_list,
23
+ interactive: interactive?,
24
+ shell: shell?,
25
+ tty: tty?,
26
+ )
27
+
28
+ exit exit_status unless exit_status.zero?
29
+ end
30
+ end
31
+ end