bcome 1.3.6 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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