bcome 1.3.6 → 1.4.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 (165) hide show
  1. checksums.yaml +4 -4
  2. data/bin/bcome +13 -8
  3. data/lib/bcome.rb +7 -11
  4. data/lib/objects/bcome/version.rb +19 -1
  5. data/lib/objects/bootup.rb +13 -5
  6. data/lib/objects/command/local.rb +2 -0
  7. data/lib/objects/config_factory.rb +3 -0
  8. data/lib/objects/driver/base.rb +36 -4
  9. data/lib/objects/driver/bucket.rb +6 -4
  10. data/lib/objects/driver/ec2.rb +35 -4
  11. data/lib/objects/driver/gcp.rb +124 -0
  12. data/lib/objects/driver/gcp/authentication/api_key.rb +6 -0
  13. data/lib/objects/driver/gcp/authentication/oauth.rb +101 -0
  14. data/lib/objects/driver/gcp/authentication/service_account.rb +7 -0
  15. data/lib/objects/driver/static.rb +2 -0
  16. data/lib/objects/encryptor.rb +26 -24
  17. data/lib/objects/exception/argument_error_invoking_method_from_command_line.rb +8 -4
  18. data/lib/objects/exception/base.rb +14 -10
  19. data/lib/objects/exception/can_only_subselect_on_inventory.rb +8 -4
  20. data/lib/objects/exception/cannot_authenticate_to_gcp.rb +11 -0
  21. data/lib/objects/exception/cannot_find_internal_registry_klass.rb +8 -4
  22. data/lib/objects/exception/cannot_find_inventory.rb +11 -0
  23. data/lib/objects/exception/cannot_find_subselection_parent.rb +8 -4
  24. data/lib/objects/exception/cant_find_key_in_cloud_tags.rb +8 -4
  25. data/lib/objects/exception/cant_find_key_in_metadata.rb +8 -4
  26. data/lib/objects/exception/cant_find_proxy_host_by_identifier.rb +8 -4
  27. data/lib/objects/exception/cant_find_proxy_host_by_namespace.rb +8 -4
  28. data/lib/objects/exception/could_not_initiate_ssh_connection.rb +8 -4
  29. data/lib/objects/exception/could_not_initiate_ssh_connection_through_backend_proxy.rb +8 -4
  30. data/lib/objects/exception/could_not_retrieve_terraform_output.rb +11 -0
  31. data/lib/objects/exception/deprecation_warning.rb +9 -7
  32. data/lib/objects/exception/duplicate_command_line_argument_key.rb +8 -4
  33. data/lib/objects/exception/ec2_driver_missing_provisioning_region.rb +8 -4
  34. data/lib/objects/exception/failed_to_run_local_command.rb +8 -4
  35. data/lib/objects/exception/generic.rb +11 -0
  36. data/lib/objects/exception/interactive_session_halt.rb +6 -2
  37. data/lib/objects/exception/invalid_bcome_breadcrumb.rb +8 -4
  38. data/lib/objects/exception/invalid_breadcrumb.rb +8 -4
  39. data/lib/objects/exception/invalid_context_command.rb +8 -4
  40. data/lib/objects/exception/invalid_gcp_authentication_scheme.rb +11 -0
  41. data/lib/objects/exception/invalid_identifier.rb +8 -4
  42. data/lib/objects/exception/invalid_machines_cache_config.rb +8 -4
  43. data/lib/objects/exception/invalid_matcher_query.rb +8 -4
  44. data/lib/objects/exception/invalid_meta_data_config.rb +8 -4
  45. data/lib/objects/exception/invalid_metadata_encryption_key.rb +8 -4
  46. data/lib/objects/exception/invalid_network_config.rb +8 -4
  47. data/lib/objects/exception/invalid_network_driver_type.rb +8 -4
  48. data/lib/objects/exception/invalid_port_forward_request.rb +11 -0
  49. data/lib/objects/exception/invalid_proxy_config.rb +8 -4
  50. data/lib/objects/exception/invalid_regexp_matcher_in_registry.rb +8 -4
  51. data/lib/objects/exception/invalid_registry_arguments_type.rb +8 -4
  52. data/lib/objects/exception/invalid_registry_command_name_length.rb +8 -4
  53. data/lib/objects/exception/invalid_registry_data_config.rb +8 -4
  54. data/lib/objects/exception/invalid_restriction_key_in_registry.rb +8 -4
  55. data/lib/objects/exception/invalid_ssh_config.rb +8 -4
  56. data/lib/objects/exception/inventories_cannot_have_subviews.rb +8 -4
  57. data/lib/objects/exception/malformed_command_line_arguments.rb +8 -4
  58. data/lib/objects/exception/method_invocation_requires_parameter.rb +8 -4
  59. data/lib/objects/exception/method_name_conflict_in_registry.rb +8 -4
  60. data/lib/objects/exception/missing_argument_for_registry_command.rb +8 -4
  61. data/lib/objects/exception/missing_description_on_view.rb +8 -4
  62. data/lib/objects/exception/missing_execute_on_registry_object.rb +8 -4
  63. data/lib/objects/exception/missing_gcp_authentication_scheme.rb +11 -0
  64. data/lib/objects/exception/missing_gcp_service_scopes.rb +11 -0
  65. data/lib/objects/exception/missing_identifier_on_view.rb +8 -4
  66. data/lib/objects/exception/missing_inventory_contributors.rb +11 -0
  67. data/lib/objects/exception/missing_ip_address_on_server.rb +8 -4
  68. data/lib/objects/exception/missing_network_config.rb +8 -4
  69. data/lib/objects/exception/missing_or_invalid_client_secrets.rb +11 -0
  70. data/lib/objects/exception/missing_params_for_rsync.rb +8 -4
  71. data/lib/objects/exception/missing_params_for_scp.rb +8 -4
  72. data/lib/objects/exception/missing_subselection_key.rb +8 -4
  73. data/lib/objects/exception/missing_type_on_view.rb +8 -4
  74. data/lib/objects/exception/no_node_found_for_breadcrumb.rb +8 -4
  75. data/lib/objects/exception/no_node_named_by_identifier.rb +8 -4
  76. data/lib/objects/exception/node_identifiers_must_be_unique.rb +8 -4
  77. data/lib/objects/exception/orchestration_script_does_not_exist.rb +8 -4
  78. data/lib/objects/exception/proxy_host_node_does_not_have_public_ip_address.rb +8 -4
  79. data/lib/objects/exception/unknown_dynamic_server_type.rb +11 -0
  80. data/lib/objects/exception/unknown_method_for_namespace.rb +8 -4
  81. data/lib/objects/interactive/session.rb +4 -1
  82. data/lib/objects/interactive/session_item/base.rb +2 -0
  83. data/lib/objects/interactive/session_item/capture_input.rb +2 -0
  84. data/lib/objects/interactive/session_item/transparent_ssh.rb +29 -23
  85. data/lib/objects/loading_bar/handler.rb +80 -0
  86. data/lib/objects/loading_bar/indicator/base.rb +64 -0
  87. data/lib/objects/loading_bar/indicator/basic.rb +34 -0
  88. data/lib/objects/loading_bar/indicator/progress.rb +26 -0
  89. data/lib/objects/loading_bar/pid_bucket.rb +27 -0
  90. data/lib/objects/modules/context.rb +13 -9
  91. data/lib/objects/modules/registry_management.rb +16 -10
  92. data/lib/objects/modules/ui_output.rb +10 -6
  93. data/lib/objects/modules/workspace_commands.rb +159 -155
  94. data/lib/objects/modules/workspace_menu.rb +129 -130
  95. data/lib/objects/node/attributes.rb +13 -21
  96. data/lib/objects/node/base.rb +113 -71
  97. data/lib/objects/node/cache_handler.rb +2 -0
  98. data/lib/objects/node/collection.rb +10 -9
  99. data/lib/objects/node/factory.rb +35 -28
  100. data/lib/objects/node/inventory/base.rb +100 -100
  101. data/lib/objects/node/inventory/defined.rb +110 -89
  102. data/lib/objects/node/inventory/merge.rb +43 -0
  103. data/lib/objects/node/inventory/subselect.rb +64 -46
  104. data/lib/objects/node/kube/base.rb +51 -0
  105. data/lib/objects/node/kube/container.rb +9 -0
  106. data/lib/objects/node/kube/estate.rb +19 -0
  107. data/lib/objects/node/kube/namespace.rb +24 -0
  108. data/lib/objects/node/kube/pod.rb +24 -0
  109. data/lib/objects/node/kube_wrap.rb +26 -0
  110. data/lib/objects/node/meta/base.rb +8 -1
  111. data/lib/objects/node/meta/cloud.rb +2 -0
  112. data/lib/objects/node/meta/local.rb +2 -0
  113. data/lib/objects/node/meta_data_factory.rb +3 -1
  114. data/lib/objects/node/meta_data_loader.rb +27 -28
  115. data/lib/objects/node/resources/base.rb +5 -1
  116. data/lib/objects/node/resources/inventory.rb +7 -5
  117. data/lib/objects/node/resources/merged.rb +38 -0
  118. data/lib/objects/node/resources/sub_inventory.rb +7 -4
  119. data/lib/objects/node/server/base.rb +88 -66
  120. data/lib/objects/node/server/dynamic/base.rb +23 -0
  121. data/lib/objects/node/server/{dynamic.rb → dynamic/ec2.rb} +14 -13
  122. data/lib/objects/node/server/dynamic/gcp.rb +47 -0
  123. data/lib/objects/node/server/static.rb +13 -2
  124. data/lib/objects/orchestration/base.rb +10 -0
  125. data/lib/objects/orchestration/interactive_terraform.rb +62 -27
  126. data/lib/objects/orchestrator.rb +22 -0
  127. data/lib/objects/parser/bread_crumb.rb +3 -1
  128. data/lib/objects/registry/arguments/base.rb +3 -1
  129. data/lib/objects/registry/arguments/command_line.rb +6 -1
  130. data/lib/objects/registry/arguments/console.rb +4 -1
  131. data/lib/objects/registry/command/base.rb +3 -0
  132. data/lib/objects/registry/command/external.rb +4 -2
  133. data/lib/objects/registry/command/group.rb +6 -3
  134. data/lib/objects/registry/command/internal.rb +3 -1
  135. data/lib/objects/registry/command/shortcut.rb +17 -9
  136. data/lib/objects/registry/command_list.rb +2 -0
  137. data/lib/objects/registry/loader.rb +10 -10
  138. data/lib/objects/ssh/bootstrap.rb +3 -1
  139. data/lib/objects/ssh/command.rb +10 -5
  140. data/lib/objects/ssh/command_exec.rb +13 -9
  141. data/lib/objects/ssh/connection_wrangler.rb +105 -0
  142. data/lib/objects/ssh/connector.rb +100 -0
  143. data/lib/objects/ssh/driver.rb +27 -230
  144. data/lib/objects/ssh/driver_concerns/command_strings.rb +17 -0
  145. data/lib/objects/ssh/driver_concerns/connection.rb +78 -0
  146. data/lib/objects/ssh/driver_concerns/functions.rb +89 -0
  147. data/lib/objects/ssh/driver_concerns/user.rb +32 -0
  148. data/lib/objects/ssh/{proxy_data.rb → proxy_hop.rb} +52 -7
  149. data/lib/objects/ssh/script_exec.rb +4 -1
  150. data/lib/objects/ssh/tunnel/local_port_forward.rb +5 -6
  151. data/lib/objects/ssh/tunnel_keeper.rb +21 -0
  152. data/lib/objects/ssh/window.rb +31 -0
  153. data/lib/objects/startup.rb +52 -0
  154. data/lib/objects/system/local.rb +3 -0
  155. data/lib/objects/terraform/output.rb +41 -0
  156. data/lib/objects/workspace.rb +3 -14
  157. data/patches/irb.rb +27 -3
  158. data/patches/string-encrypt.rb +20 -23
  159. data/patches/string.rb +5 -1
  160. data/patches/string_stylesheet.rb +2 -0
  161. metadata +95 -18
  162. data/lib/objects/progress_bar.rb +0 -30
  163. data/lib/objects/ssh/connection_handler.rb +0 -101
  164. data/lib/objects/terraform/parser.rb +0 -23
  165. data/lib/objects/terraform/state.rb +0 -40
@@ -1,140 +1,139 @@
1
- module Bcome::WorkspaceMenu
2
- def menu
3
- print "\n\n"
4
- puts "#{mode} menu".title + "\sfor #{self.class} #{namespace}".resource_value + "\n\n"
5
- enabled_menu_items.each_with_index do |menu_item, _index|
6
- item = menu_items[menu_item]
7
- next if !::Bcome::System::Local.instance.in_console_session? && item[:console_only]
8
- puts tab_spacing + menu_item.to_s.resource_key + item_spacing(menu_item) + (menu_items[menu_item][:description]).to_s.resource_value
9
- if item[:usage] || item[:terminal_usage]
10
- usage_string = ::Bcome::System::Local.instance.in_console_session? ? item[:usage] : "bcome #{keyed_namespace.empty? ? '' : "#{keyed_namespace}:"}#{item[:terminal_usage]}"
11
- puts tab_spacing + ("\s" * menu_item_spacing_length) + 'usage: '.instructional + usage_string
1
+ # frozen_string_literal: true
2
+
3
+ module Bcome
4
+ module WorkspaceMenu
5
+ def menu
6
+ print "\n\n"
7
+ puts "#{mode} menu".title + "\sfor #{self.class} #{namespace}".resource_value + "\n\n"
8
+ enabled_menu_items.each_with_index do |menu_item, _index|
9
+ item = menu_items[menu_item]
10
+ next if !::Bcome::System::Local.instance.in_console_session? && item[:console_only]
11
+
12
+ puts tab_spacing + menu_item.to_s.resource_key + item_spacing(menu_item) + (menu_items[menu_item][:description]).to_s.resource_value
13
+ if item[:usage] || item[:terminal_usage]
14
+ usage_string = ::Bcome::System::Local.instance.in_console_session? ? item[:usage] : "bcome #{keyed_namespace.empty? ? '' : "#{keyed_namespace}:"}#{item[:terminal_usage]}"
15
+ puts tab_spacing + ("\s" * menu_item_spacing_length) + 'usage: '.instructional + usage_string
16
+ end
17
+ puts "\n"
12
18
  end
13
- puts "\n"
14
- end
15
19
 
16
- nil
17
- end
20
+ nil
21
+ end
18
22
 
19
- def mode
20
- ::Bcome::System::Local.instance.in_console_session? ? 'Console' : 'Terminal'
21
- end
23
+ def mode
24
+ ::Bcome::System::Local.instance.in_console_session? ? 'Console' : 'Terminal'
25
+ end
22
26
 
23
- def item_spacing(item)
24
- "\s" * (menu_item_spacing_length - item.length)
25
- end
27
+ def item_spacing(item)
28
+ "\s" * (menu_item_spacing_length - item.length)
29
+ end
26
30
 
27
- def menu_item_spacing_length
28
- 16
29
- end
31
+ def menu_item_spacing_length
32
+ 16
33
+ end
30
34
 
31
- def tab_spacing
32
- "\s" * 3
33
- end
35
+ def tab_spacing
36
+ "\s" * 3
37
+ end
34
38
 
35
- def menu_items
36
- {
37
- ls: {
38
- description: 'list all available resources',
39
- console_only: false
40
- },
41
- lsa: {
42
- description: 'list all active resources',
43
- console_only: true
44
- },
45
- workon: {
46
- description: 'work on specific resources only, inactivating all others from this selection',
47
- usage: 'workon identifier1, identifier2 ...',
48
- console_only: true
49
- },
50
- disable: {
51
- description: 'remove a resource from this selection',
52
- usage: 'disable identifier1, identifier2 ...',
53
- console_only: true
54
- },
55
- enable: {
56
- description: 're-enable a resource within this selection',
57
- usage: 'enable identifier1, identifier2 ...',
58
- console_only: true
59
- },
60
- enable!: {
61
- description: 'enable all resources within this selection',
62
- console_only: true
63
- },
64
- disable!: {
65
- description: 'disable all resources within this selection',
66
- console_only: true
67
- },
68
- run: {
69
- description: 'execute a command to be run over ssh against all active resources',
70
- usage: "run 'command1', 'command2', ...",
71
- console_only: false,
72
- terminal_usage: "run 'command1' 'command2' ..."
73
- },
74
- interactive: {
75
- description: 'enter an interactive command session for all active resources',
76
- console_only: false
77
- },
78
- tree: {
79
- description: 'print a tree view for all resources and their sub-resources',
80
- console_only: false
81
- },
82
- ping: {
83
- description: 'ping all resources to test connectivity',
84
- console_only: false
85
- },
86
- put: {
87
- description: 'upload a file or directory using scp',
88
- usage: "put 'local/path','remote/path'",
89
- console_only: false,
90
- terminal_usage: "put 'local/path' 'remote/path'"
91
- },
92
- put_str: {
93
- description: 'Write a file /to/remote/path from a string',
94
- usage: 'put_str',
95
- console_only: false,
96
- terminal_usage: "put_str '<file contents>', 'remote/path'"
97
- },
98
- rsync: {
99
- description: 'upload a file or directory using rsync (faster)',
100
- usage: "rsync 'local/path','remote/path'",
101
- console_only: false,
102
- terminal_usage: "rsync 'local/path' 'remote/path'"
103
- },
104
- get: {
105
- description: 'download a file',
106
- usage: "get 'remote/path', 'local/path'",
107
- console_only: false,
108
- terminal_usage: "get 'remote/path' 'local/path"
109
- },
110
- cd: {
111
- description: 'enter the namespace for a resource from this selection',
112
- usage: 'cd identifier',
113
- console_only: true
114
- },
115
- save: {
116
- description: 'Save the current tree state',
117
- console_only: true
118
- },
119
- meta: {
120
- description: 'Print out all metadata related to this node'
121
- },
122
- pack_metadata: {
123
- description: 'Encrypt your metadata files',
124
- },
125
- unpack_metadata: {
126
- description: 'Decrypt and expose your encrypted metadata files',
127
- },
128
- registry: {
129
- description: 'List all user defined commands present in your registry, and available to this namespace',
130
- console_only: false
131
- },
132
- execute_script: {
133
- description: 'execute a bash script',
134
- console_only: false,
135
- usage: 'execute_script "script_name"',
136
- terminal_usage: 'execute_script script_name'
39
+ def menu_items
40
+ {
41
+ ls: {
42
+ description: 'list all available resources',
43
+ console_only: false
44
+ },
45
+ lsa: {
46
+ description: 'list all active resources',
47
+ console_only: true
48
+ },
49
+ workon: {
50
+ description: 'work on specific resources only, inactivating all others from this selection',
51
+ usage: 'workon identifier1, identifier2 ...',
52
+ console_only: true
53
+ },
54
+ disable: {
55
+ description: 'remove a resource from this selection',
56
+ usage: 'disable identifier1, identifier2 ...',
57
+ console_only: true
58
+ },
59
+ enable: {
60
+ description: 're-enable a resource within this selection',
61
+ usage: 'enable identifier1, identifier2 ...',
62
+ console_only: true
63
+ },
64
+ enable!: {
65
+ description: 'enable all resources within this selection',
66
+ console_only: true
67
+ },
68
+ disable!: {
69
+ description: 'disable all resources within this selection',
70
+ console_only: true
71
+ },
72
+ run: {
73
+ description: 'execute a command to be run over ssh against all active resources',
74
+ usage: "run 'command1', 'command2', ...",
75
+ console_only: false,
76
+ terminal_usage: "run 'command1' 'command2' ..."
77
+ },
78
+ interactive: {
79
+ description: 'enter an interactive command session for all active resources',
80
+ console_only: false
81
+ },
82
+ tree: {
83
+ description: 'print a tree view for all resources and their sub-resources',
84
+ console_only: false
85
+ },
86
+ ping: {
87
+ description: 'ping all resources to test connectivity',
88
+ console_only: false
89
+ },
90
+ put: {
91
+ description: 'upload a file or directory using scp',
92
+ usage: "put 'local/path','remote/path'",
93
+ console_only: false,
94
+ terminal_usage: "put 'local/path' 'remote/path'"
95
+ },
96
+ put_str: {
97
+ description: 'Write a file /to/remote/path from a string',
98
+ usage: 'put_str "string" "remote/path"',
99
+ console_only: false,
100
+ terminal_usage: "put_str '<file contents>', 'remote/path'"
101
+ },
102
+ rsync: {
103
+ description: 'upload a file or directory using rsync (faster)',
104
+ usage: "rsync 'local/path','remote/path'",
105
+ console_only: false,
106
+ terminal_usage: "rsync 'local/path' 'remote/path'"
107
+ },
108
+ get: {
109
+ description: 'download a file',
110
+ usage: "get 'remote/path', 'local/path'",
111
+ console_only: false,
112
+ terminal_usage: "get 'remote/path' 'local/path"
113
+ },
114
+ cd: {
115
+ description: 'enter the namespace for a resource from this selection',
116
+ usage: 'cd identifier',
117
+ console_only: true
118
+ },
119
+ save: {
120
+ description: 'Save the current tree state',
121
+ console_only: true
122
+ },
123
+ meta: {
124
+ description: 'Print out all metadata related to this node'
125
+ },
126
+ registry: {
127
+ description: 'List all user defined commands present in your registry, and available to this namespace',
128
+ console_only: false
129
+ },
130
+ execute_script: {
131
+ description: 'execute a bash script',
132
+ console_only: false,
133
+ usage: 'execute_script "script_name"',
134
+ terminal_usage: 'execute_script script_name'
135
+ }
137
136
  }
138
- }
137
+ end
139
138
  end
140
139
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Node::Attributes
2
4
  ## -- Attributes --
3
5
 
@@ -5,41 +7,31 @@ module Bcome::Node::Attributes
5
7
  @identifier
6
8
  end
7
9
 
8
- def description
9
- @description
10
- end
11
-
12
- def type
13
- @type
14
- end
15
-
16
10
  def ssh_driver
17
11
  @ssh_driver ||= ::Bcome::Ssh::Driver.new(ssh_data, self)
18
12
  end
19
13
 
20
14
  def ssh_data
21
- instance_var_name = '@ssh_settings'
22
- recurse_hash_data_for_instance_var(instance_var_name, :ssh_data)
15
+ recurse_hash_data_for_instance_key(:ssh_settings, :ssh_data)
23
16
  end
24
17
 
25
- def network_driver
26
- return nil if !network_data || (network_data.is_a?(Hash) && network_data.empty?)
27
- @network_driver ||= ::Bcome::Driver::Bucket.instance.driver_for_network_data(network_data)
28
- @network_driver
18
+ def network_data
19
+ recurse_hash_data_for_instance_key(:network, :network_data)
29
20
  end
30
21
 
31
22
  def filters
32
- instance_var_name = '@ec2_filters'
33
- recurse_hash_data_for_instance_var(instance_var_name, :filters)
23
+ recurse_hash_data_for_instance_key(:ec2_filters, :filters)
34
24
  end
35
25
 
36
- def network_data
37
- instance_var_name = '@network'
38
- recurse_hash_data_for_instance_var(instance_var_name, :network_data)
26
+ def network_driver
27
+ return nil if !network_data || (network_data.is_a?(Hash) && network_data.empty?)
28
+
29
+ @network_driver ||= ::Bcome::Driver::Bucket.instance.driver_for_network_data(network_data, self)
30
+ @network_driver
39
31
  end
40
32
 
41
- def recurse_hash_data_for_instance_var(instance_var_name, parent_key)
42
- instance_data = instance_variable_defined?(instance_var_name) ? instance_variable_get(instance_var_name) : {}
33
+ def recurse_hash_data_for_instance_key(instance_key, parent_key)
34
+ instance_data = respond_to?(instance_key) ? send(instance_key) : {}
43
35
  instance_data ||= {}
44
36
  instance_data = parent.send(parent_key).deep_merge(instance_data) if has_parent?
45
37
  instance_data
@@ -1,24 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Node
2
4
  class Base
3
-
4
5
  include Bcome::Context
5
6
  include Bcome::WorkspaceCommands
6
7
  include Bcome::Node::Attributes
7
8
  include Bcome::WorkspaceMenu
8
9
  include Bcome::Node::LocalMetaDataFactory
9
10
  include Bcome::Node::RegistryManagement
10
-
11
- DEFAULT_IDENTIFIER = "bcome"
11
+
12
+ def inspect
13
+ "<##{self.class}: #{namespace} @network_driver=#{network_driver}>"
14
+ end
12
15
 
13
16
  def self.const_missing(constant)
14
17
  ## Hook for direct access to node level resources by constant name where
15
18
  ## cd ServerName should yield the same outcome as cd "ServerName"
16
- set_context = ::IRB.CurrentContext.workspace.main
17
- return (set_context.resource_for_identifier(constant.to_s)) ? constant.to_s : super
19
+ set_context = ::IRB.CurrentContext.workspace.main
20
+ set_context.resource_for_identifier(constant.to_s) ? constant.to_s : super
18
21
  end
19
22
 
20
23
  attr_reader :params
21
24
 
25
+ DEFAULT_IDENTIFIER = 'bcome'
26
+
27
+ include Bcome::LoadingBar::Handler
28
+
22
29
  def initialize(params)
23
30
  @params = params
24
31
  @identifier = nil
@@ -30,11 +37,28 @@ module Bcome::Node
30
37
 
31
38
  set_view_attributes if @views
32
39
  validate_attributes
40
+
33
41
  ::Bcome::Registry::Loader.instance.set_command_group_for_node(self)
34
42
  end
35
43
 
36
- def bootstrap?
37
- false
44
+ attr_reader :parent
45
+
46
+ attr_reader :views
47
+
48
+ def method_missing(method_sym, *arguments)
49
+ raise Bcome::Exception::Generic, "undefined method '#{method_sym}' for #{self.class}" unless method_is_available_on_node?(method_sym)
50
+
51
+ if resource_identifiers.include?(method_sym.to_s)
52
+ method_sym.to_s
53
+ elsif command = user_command_wrapper.command_for_console_command_name(method_sym)
54
+ command.execute(self, arguments)
55
+ else
56
+ raise NameError, "Missing method #{method_sym} for #{self.class}"
57
+ end
58
+ end
59
+
60
+ def ssh_connect(params = {})
61
+ ::Bcome::Ssh::Connector.connect(self, params)
38
62
  end
39
63
 
40
64
  def collection?
@@ -50,48 +74,53 @@ module Bcome::Node
50
74
  end
51
75
 
52
76
  def enabled_menu_items
53
- [:ls, :lsa, :workon, :enable, :disable, :enable!, :disable!, :run, :tree, :ping, :put, :put_str, :rsync, :cd, :meta, :pack_metadata, :unpack_metadata, :registry, :interactive, :execute_script]
77
+ %i[ls lsa workon enable disable enable! disable! run tree ping put put_str rsync cd meta registry interactive execute_script]
54
78
  end
55
79
 
56
80
  def has_proxy?
57
81
  ssh_driver.has_proxy?
58
82
  end
59
83
 
60
- def identifier=(new_identifier)
61
- @identifier = new_identifier
62
- end
84
+ attr_writer :identifier
63
85
 
64
86
  def proxy
65
87
  ssh_driver.proxy
66
88
  end
67
-
68
- # TODO - why not do these in parallel?
89
+
90
+ def scoped_resources
91
+ # Active & not hidden
92
+ resources.active.reject(&:hide?)
93
+ end
94
+
69
95
  def scp(local_path, remote_path)
70
- resources.active.each do |resource|
96
+ scoped_resources.each do |resource|
71
97
  resource.put(local_path, remote_path)
72
98
  end
73
- return
99
+ nil
74
100
  end
75
101
 
76
102
  def rsync(local_path, remote_path)
77
- resources.active.each do |resource|
103
+ scoped_resources.each do |resource|
78
104
  resource.rsync(local_path, remote_path)
79
- end
80
- return
105
+ end
106
+ nil
81
107
  end
82
108
 
83
- def put(local_path, remote_path)
84
- resources.active.each do |resource|
85
- resource.put(local_path, remote_path)
109
+ def put(local_path, remote_path, connect = true)
110
+ ssh_connect if connect # Initiate connect at highest namespace level
111
+
112
+ scoped_resources.each do |resource|
113
+ resource.put(local_path, remote_path, false)
86
114
  end
87
- return
115
+ nil
88
116
  end
89
117
 
90
- def put_str(string, remote_path)
91
- resources.active.each do |resource|
92
- resource.put_str(string, remote_path)
118
+ def put_str(string, remote_path, connect = true)
119
+ ssh_connect if connect # Initiate connect at highest namespace level
120
+ scoped_resources.each do |resource|
121
+ resource.put_str(string, remote_path, false)
93
122
  end
94
- return
123
+ nil
95
124
  end
96
125
 
97
126
  def execute_script(script_name)
@@ -103,30 +132,28 @@ module Bcome::Node
103
132
  results
104
133
  end
105
134
 
106
- def pack_metadata
107
- ::Bcome::Encryptor.instance.pack
135
+ def hide?
136
+ return true if @views.key?(:hidden) && @views[:hidden]
137
+
138
+ false
108
139
  end
109
140
 
110
- def unpack_metadata
111
- ::Bcome::Encryptor.instance.unpack
112
- end
113
-
114
141
  def validate_attributes
115
- validate_identifier
116
- raise ::Bcome::Exception::MissingDescriptionOnView.new(@views.inspect) if requires_description? && !@description
117
- raise ::Bcome::Exception::MissingTypeOnView.new(@views.inspect) if requires_type? && !@type
142
+ validate_identifier
143
+ raise ::Bcome::Exception::MissingDescriptionOnView, views.inspect if requires_description? && !defined?(:description)
144
+ raise ::Bcome::Exception::MissingTypeOnView, views.inspect if requires_type? && !defined?(:type)
118
145
  end
119
146
 
120
147
  def validate_identifier
121
- @identifier = DEFAULT_IDENTIFIER if is_top_level_node? && !@identifier && !is_a?(::Bcome::Node::Server::Base)
148
+ @identifier = DEFAULT_IDENTIFIER.dup if is_top_level_node? && !@identifier && !is_a?(::Bcome::Node::Server::Base)
122
149
 
123
- @identifier = "NO-ID_#{Time.now.to_i}" unless @identifier
150
+ @identifier ||= "NO-ID_#{Time.now.to_i}".dup
124
151
 
125
- #raise ::Bcome::Exception::MissingIdentifierOnView.new(@views.inspect) unless @identifier
126
- @identifier.gsub!(/\s/, "_") # Remove whitespace
127
- @identifier.gsub!("-", "_") # change hyphens to undescores, hyphens don't play well in var names in irb
152
+ # raise ::Bcome::Exception::MissingIdentifierOnView.new(@views.inspect) unless @identifier
153
+ @identifier.gsub!(/\s/, '_') # Remove whitespace
154
+ @identifier.gsub!('-', '_') # change hyphens to undescores, hyphens don't play well in var names in irb
128
155
 
129
- #raise ::Bcome::Exception::InvalidIdentifier.new("'#{@identifier}' contains whitespace") if @identifier =~ /\s/
156
+ # raise ::Bcome::Exception::InvalidIdentifier.new("'#{@identifier}' contains whitespace") if @identifier =~ /\s/
130
157
  end
131
158
 
132
159
  def requires_description?
@@ -144,7 +171,7 @@ module Bcome::Node
144
171
  def nodes_loaded?
145
172
  resources.any?
146
173
  end
147
-
174
+
148
175
  def resources
149
176
  @resources ||= ::Bcome::Node::Resources::Base.new
150
177
  end
@@ -155,16 +182,16 @@ module Bcome::Node
155
182
 
156
183
  def invoke(method_name, arguments = [])
157
184
  if method_is_available_on_node?(method_name)
158
- if respond_to?(method_name)
185
+ if respond_to?(method_name)
159
186
  # Invoke a method on node that's defined by the system
160
187
  begin
161
- if arguments && arguments.any?
188
+ if arguments&.any?
162
189
  send(method_name, *arguments)
163
190
  else
164
191
  send(method_name)
165
192
  end
166
193
  rescue ArgumentError => e
167
- raise ::Bcome::Exception::ArgumentErrorInvokingMethodFromCommmandLine.new method_name + "error message - #{e.message}"
194
+ raise ::Bcome::Exception::ArgumentErrorInvokingMethodFromCommmandLine, method_name + " error message - #{e.message}"
168
195
  end
169
196
  else
170
197
  # Invoke a user defined (registry) method
@@ -173,7 +200,7 @@ module Bcome::Node
173
200
  end
174
201
  else
175
202
  # Final crumb is neither a node level context nor an executable method on the penultimate node level context
176
- raise ::Bcome::Exception::InvalidBreadcrumb.new("Method '#{method_name}' is not available on bcome node of type #{self.class}, at namespace #{namespace}")
203
+ raise ::Bcome::Exception::InvalidBreadcrumb, "Method '#{method_name}' is not available on bcome node of type #{self.class}, at namespace #{namespace}"
177
204
  end
178
205
  end
179
206
 
@@ -183,20 +210,20 @@ module Bcome::Node
183
210
 
184
211
  def recurse_resource_for_identifier(identifier)
185
212
  resource = resource_for_identifier(identifier)
186
- return resource ? resource : (has_parent? ? parent.recurse_resource_for_identifier(identifier) : nil)
213
+ resource || (has_parent? ? parent.recurse_resource_for_identifier(identifier) : nil)
187
214
  end
188
215
 
189
216
  def prompt_breadcrumb
190
- "#{has_parent? ? "#{parent.prompt_breadcrumb}> " : "" }#{ is_current_context? ? (has_parent? ? identifier.terminal_prompt : identifier) : identifier}"
217
+ "#{has_parent? ? "#{parent.prompt_breadcrumb}> " : ''}#{current_context? ? (has_parent? ? identifier.terminal_prompt : identifier) : identifier}"
191
218
  end
192
219
 
193
220
  def namespace
194
- "#{ parent ? "#{parent.namespace}:" : "" }#{identifier}"
221
+ "#{parent ? "#{parent.namespace}:" : ''}#{identifier}"
195
222
  end
196
223
 
197
224
  def keyed_namespace
198
- splits = namespace.split(":") ;
199
- splits[1..splits.size].join(":")
225
+ splits = namespace.split(':')
226
+ splits[1..splits.size].join(':')
200
227
  end
201
228
 
202
229
  def has_parent?
@@ -205,10 +232,10 @@ module Bcome::Node
205
232
 
206
233
  def is_top_level_node?
207
234
  !has_parent?
208
- end
235
+ end
209
236
 
210
237
  def list_attributes
211
- {
238
+ {
212
239
  "Identifier": :identifier,
213
240
  "Description": :description,
214
241
  "Type": :type
@@ -216,49 +243,65 @@ module Bcome::Node
216
243
  end
217
244
 
218
245
  def close_ssh_connections
219
- machines.pmap do |machine|
220
- machine.close_ssh_connection
221
- end
222
- return
223
- end
224
-
225
- def open_ssh_connections
226
- machines.pmap do |machine|
227
- machine.open_ssh_connection unless machine.has_ssh_connection?
246
+ # For every loaded server, we'll close any lingering ssh connection
247
+ if resources.any?
248
+ resources.pmap do |resource|
249
+ if resource.is_a?(::Bcome::Node::Server::Base)
250
+ resource.close_ssh_connection
251
+ else
252
+ resource.close_ssh_connections
253
+ end
254
+ end
228
255
  end
229
- return
256
+ nil
230
257
  end
231
258
 
232
259
  def execute_local(command)
233
- puts "(local) > #{command}"
260
+ puts "(local) > #{command}" unless ::Bcome::Orchestrator.instance.command_output_silenced?
234
261
  system(command)
262
+ puts ''
235
263
  end
236
264
 
237
265
  def data_print_from_hash(data, heading)
238
266
  puts "\n#{heading.title}"
239
- puts ""
267
+ puts ''
240
268
 
241
269
  if data.keys.any?
242
270
  data.each do |key, value|
243
271
  puts "#{key.to_s.resource_key}: #{value.to_s.informational}"
244
272
  end
245
273
  else
246
- puts "No values found".warning
274
+ puts 'No values found'.warning
247
275
  end
248
- puts ""
276
+ puts ''
249
277
  end
250
278
 
251
279
  private
252
280
 
281
+ def singleton_class
282
+ class << self
283
+ self
284
+ end
285
+ end
286
+
253
287
  def set_view_attributes
254
- @views.keys.each do |view_attribute_key|
288
+ @identifier = @views[:identifier]
289
+
290
+ @views.keys.sort.each do |view_attribute_key|
255
291
  next if view_attributes_to_skip_on_setup.include?(view_attribute_key)
256
- instance_variable_set("@#{view_attribute_key}", @views[view_attribute_key])
292
+
293
+ next if view_attribute_key == :identifier
294
+
295
+ singleton_class.class_eval do
296
+ define_method(view_attribute_key) do
297
+ @views[view_attribute_key]
298
+ end
299
+ end
257
300
  end
258
301
  end
259
302
 
260
303
  def view_attributes_to_skip_on_setup
261
- [:views]
304
+ [:views]
262
305
  end
263
306
 
264
307
  private
@@ -268,6 +311,5 @@ module Bcome::Node
268
311
  # with thanks to https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html & http://yehudakatz.com/2010/01/02/the-craziest-fing-bug-ive-ever-seen/
269
312
  nil
270
313
  end
271
-
272
314
  end
273
315
  end