bcome 1.3.2 → 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 +5 -5
  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 -124
  95. data/lib/objects/node/attributes.rb +13 -21
  96. data/lib/objects/node/base.rb +116 -67
  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 +29 -23
  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 +91 -65
  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 -215
  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 +29 -6
  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 +101 -23
  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 -34
@@ -1,134 +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
- rsync: {
93
- description: 'upload a file or directory using rsync (faster)',
94
- usage: "rsync 'local/path','remote/path'",
95
- console_only: false,
96
- terminal_usage: "rsync 'local/path' 'remote/path'"
97
- },
98
- get: {
99
- description: 'download a file',
100
- usage: "get 'remote/path', 'local/path'",
101
- console_only: false,
102
- terminal_usage: "get 'remote/path' 'local/path"
103
- },
104
- cd: {
105
- description: 'enter the namespace for a resource from this selection',
106
- usage: 'cd identifier',
107
- console_only: true
108
- },
109
- save: {
110
- description: 'Save the current tree state',
111
- console_only: true
112
- },
113
- meta: {
114
- description: 'Print out all metadata related to this node'
115
- },
116
- pack_metadata: {
117
- description: 'Encrypt your metadata files',
118
- },
119
- unpack_metadata: {
120
- description: 'Decrypt and expose your encrypted metadata files',
121
- },
122
- registry: {
123
- description: 'List all user defined commands present in your registry, and available to this namespace',
124
- console_only: false
125
- },
126
- execute_script: {
127
- description: 'execute a bash script',
128
- console_only: false,
129
- usage: 'execute_script "script_name"',
130
- 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
+ }
131
136
  }
132
- }
137
+ end
133
138
  end
134
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,41 +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, :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
116
+ end
117
+
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)
122
+ end
123
+ nil
88
124
  end
89
125
 
90
126
  def execute_script(script_name)
@@ -96,30 +132,28 @@ module Bcome::Node
96
132
  results
97
133
  end
98
134
 
99
- def pack_metadata
100
- ::Bcome::Encryptor.instance.pack
135
+ def hide?
136
+ return true if @views.key?(:hidden) && @views[:hidden]
137
+
138
+ false
101
139
  end
102
140
 
103
- def unpack_metadata
104
- ::Bcome::Encryptor.instance.unpack
105
- end
106
-
107
141
  def validate_attributes
108
- validate_identifier
109
- raise ::Bcome::Exception::MissingDescriptionOnView.new(@views.inspect) if requires_description? && !@description
110
- 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)
111
145
  end
112
146
 
113
147
  def validate_identifier
114
- @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)
115
149
 
116
- @identifier = "NO-ID_#{Time.now.to_i}" unless @identifier
150
+ @identifier ||= "NO-ID_#{Time.now.to_i}".dup
117
151
 
118
- #raise ::Bcome::Exception::MissingIdentifierOnView.new(@views.inspect) unless @identifier
119
- @identifier.gsub!(/\s/, "_") # Remove whitespace
120
- @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
121
155
 
122
- #raise ::Bcome::Exception::InvalidIdentifier.new("'#{@identifier}' contains whitespace") if @identifier =~ /\s/
156
+ # raise ::Bcome::Exception::InvalidIdentifier.new("'#{@identifier}' contains whitespace") if @identifier =~ /\s/
123
157
  end
124
158
 
125
159
  def requires_description?
@@ -137,7 +171,7 @@ module Bcome::Node
137
171
  def nodes_loaded?
138
172
  resources.any?
139
173
  end
140
-
174
+
141
175
  def resources
142
176
  @resources ||= ::Bcome::Node::Resources::Base.new
143
177
  end
@@ -148,16 +182,16 @@ module Bcome::Node
148
182
 
149
183
  def invoke(method_name, arguments = [])
150
184
  if method_is_available_on_node?(method_name)
151
- if respond_to?(method_name)
185
+ if respond_to?(method_name)
152
186
  # Invoke a method on node that's defined by the system
153
187
  begin
154
- if arguments && arguments.any?
188
+ if arguments&.any?
155
189
  send(method_name, *arguments)
156
190
  else
157
191
  send(method_name)
158
192
  end
159
193
  rescue ArgumentError => e
160
- raise ::Bcome::Exception::ArgumentErrorInvokingMethodFromCommmandLine.new method_name + "error message - #{e.message}"
194
+ raise ::Bcome::Exception::ArgumentErrorInvokingMethodFromCommmandLine, method_name + " error message - #{e.message}"
161
195
  end
162
196
  else
163
197
  # Invoke a user defined (registry) method
@@ -166,7 +200,7 @@ module Bcome::Node
166
200
  end
167
201
  else
168
202
  # Final crumb is neither a node level context nor an executable method on the penultimate node level context
169
- 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}"
170
204
  end
171
205
  end
172
206
 
@@ -176,20 +210,20 @@ module Bcome::Node
176
210
 
177
211
  def recurse_resource_for_identifier(identifier)
178
212
  resource = resource_for_identifier(identifier)
179
- return resource ? resource : (has_parent? ? parent.recurse_resource_for_identifier(identifier) : nil)
213
+ resource || (has_parent? ? parent.recurse_resource_for_identifier(identifier) : nil)
180
214
  end
181
215
 
182
216
  def prompt_breadcrumb
183
- "#{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}"
184
218
  end
185
219
 
186
220
  def namespace
187
- "#{ parent ? "#{parent.namespace}:" : "" }#{identifier}"
221
+ "#{parent ? "#{parent.namespace}:" : ''}#{identifier}"
188
222
  end
189
223
 
190
224
  def keyed_namespace
191
- splits = namespace.split(":") ;
192
- splits[1..splits.size].join(":")
225
+ splits = namespace.split(':')
226
+ splits[1..splits.size].join(':')
193
227
  end
194
228
 
195
229
  def has_parent?
@@ -198,10 +232,10 @@ module Bcome::Node
198
232
 
199
233
  def is_top_level_node?
200
234
  !has_parent?
201
- end
235
+ end
202
236
 
203
237
  def list_attributes
204
- {
238
+ {
205
239
  "Identifier": :identifier,
206
240
  "Description": :description,
207
241
  "Type": :type
@@ -209,49 +243,65 @@ module Bcome::Node
209
243
  end
210
244
 
211
245
  def close_ssh_connections
212
- machines.pmap do |machine|
213
- machine.close_ssh_connection
214
- end
215
- return
216
- end
217
-
218
- def open_ssh_connections
219
- machines.pmap do |machine|
220
- 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
221
255
  end
222
- return
256
+ nil
223
257
  end
224
258
 
225
259
  def execute_local(command)
226
- puts "(local) > #{command}"
260
+ puts "(local) > #{command}" unless ::Bcome::Orchestrator.instance.command_output_silenced?
227
261
  system(command)
262
+ puts ''
228
263
  end
229
264
 
230
265
  def data_print_from_hash(data, heading)
231
266
  puts "\n#{heading.title}"
232
- puts ""
267
+ puts ''
233
268
 
234
269
  if data.keys.any?
235
270
  data.each do |key, value|
236
271
  puts "#{key.to_s.resource_key}: #{value.to_s.informational}"
237
272
  end
238
273
  else
239
- puts "No values found".warning
274
+ puts 'No values found'.warning
240
275
  end
241
- puts ""
276
+ puts ''
242
277
  end
243
278
 
244
279
  private
245
280
 
281
+ def singleton_class
282
+ class << self
283
+ self
284
+ end
285
+ end
286
+
246
287
  def set_view_attributes
247
- @views.keys.each do |view_attribute_key|
288
+ @identifier = @views[:identifier]
289
+
290
+ @views.keys.sort.each do |view_attribute_key|
248
291
  next if view_attributes_to_skip_on_setup.include?(view_attribute_key)
249
- 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
250
300
  end
251
301
  end
252
302
 
253
303
  def view_attributes_to_skip_on_setup
254
- [:views]
304
+ [:views]
255
305
  end
256
306
 
257
307
  private
@@ -261,6 +311,5 @@ module Bcome::Node
261
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/
262
312
  nil
263
313
  end
264
-
265
314
  end
266
315
  end