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,17 +1,15 @@
1
- module Bcome::Node::Server
2
- class Dynamic < Bcome::Node::Server::Base
1
+ # frozen_string_literal: true
2
+
3
+ module Bcome::Node::Server::Dynamic
4
+ class Ec2 < Bcome::Node::Server::Dynamic::Base
3
5
  class << self
4
- def to_s
5
- 'dynamic server'
6
+ def dynamic_server_type
7
+ :ec2
6
8
  end
7
9
 
8
10
  def new_from_fog_instance(fog_instance, parent)
9
11
  identifier = fog_instance.tags['Name']
10
-
11
- if parent.override_server_identifier?
12
- identifier =~ /#{parent.override_identifier}/
13
- identifier = Regexp.last_match(1) if Regexp.last_match(1)
14
- end
12
+ identifier = override_identifier(parent, identifier)
15
13
 
16
14
  params = {
17
15
  identifier: identifier,
@@ -22,17 +20,20 @@ module Bcome::Node::Server
22
20
  ec2_server: fog_instance
23
21
  }
24
22
 
25
- new(parent: parent,
26
- views: params)
23
+ new(parent: parent, views: params)
27
24
  end
28
25
  end
29
26
 
27
+ def host
28
+ 'EC2'
29
+ end
30
+
30
31
  def do_generate_cloud_tags
31
- raw_tags = ec2_server ? ec2_server.tags.deep_symbolize_keys : {}
32
+ raw_tags = cloud_server ? cloud_server.tags.deep_symbolize_keys : {}
32
33
  ::Bcome::Node::Meta::Cloud.new(raw_tags)
33
34
  end
34
35
 
35
- def ec2_server
36
+ def cloud_server
36
37
  views[:ec2_server]
37
38
  end
38
39
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bcome::Node::Server::Dynamic
4
+ class Gcp < Bcome::Node::Server::Dynamic::Base
5
+ class << self
6
+ def dynamic_server_type
7
+ :gcp
8
+ end
9
+
10
+ def new_from_gcp_instance(gcp_instance, parent)
11
+ identifier = gcp_instance.name
12
+ identifier = override_identifier(parent, identifier)
13
+
14
+ ## For now we support only the first network interface
15
+ first_interface = gcp_instance.network_interfaces.first
16
+ network_ip = first_interface.network_ip
17
+
18
+ ## And we get the first access config (terraform uses the same pattern for accessing GCP machines also)
19
+ first_access_config = first_interface.access_configs ? first_interface.access_configs.first : nil
20
+ nat_ip = first_access_config ? first_access_config.nat_ip : nil
21
+
22
+ params = {
23
+ identifier: identifier,
24
+ description: "GCP server - #{identifier}",
25
+ internal_ip_address: network_ip,
26
+ public_ip_address: nat_ip,
27
+ gcp_server: gcp_instance
28
+ }
29
+
30
+ new(parent: parent, views: params)
31
+ end
32
+ end
33
+
34
+ def host
35
+ 'GCP'
36
+ end
37
+
38
+ def do_generate_cloud_tags
39
+ raw_labels = cloud_server.labels ? cloud_server.labels.deep_symbolize_keys : {}
40
+ ::Bcome::Node::Meta::Cloud.new(raw_labels)
41
+ end
42
+
43
+ def cloud_server
44
+ views[:gcp_server]
45
+ end
46
+ end
47
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Node::Server
2
4
  class Static < Bcome::Node::Server::Base
3
- def self.to_s
4
- 'static server'
5
+ def host
6
+ 'static'
5
7
  end
6
8
 
7
9
  def initialize(params)
@@ -10,12 +12,21 @@ module Bcome::Node::Server
10
12
  @public_ip_address = config[:public_ip_address]
11
13
  @internal_ip_address = config[:internal_ip_address]
12
14
  @cloud_tags = config[:cloud_tags]
15
+ @description = config[:description]
13
16
  verify_we_have_at_least_one_interface(config)
14
17
  super
15
18
  end
16
19
 
17
20
  attr_reader :cloud_tags
18
21
 
22
+ attr_reader :public_ip_address
23
+
24
+ attr_reader :internal_ip_address
25
+
26
+ attr_reader :cloud_tags
27
+
28
+ attr_reader :description
29
+
19
30
  def verify_we_have_at_least_one_interface(config)
20
31
  raise Bcome::Exception::MissingIpaddressOnServer, config unless has_at_least_one_interface?
21
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Orchestration
2
4
  class Base
3
5
  def initialize(node, arguments)
@@ -7,7 +9,15 @@ module Bcome::Orchestration
7
9
 
8
10
  def do_execute
9
11
  raise Bcome::Exception::MissingExecuteOnRegistryObject, self.class.to_s unless respond_to?(:execute)
12
+
10
13
  execute
11
14
  end
15
+
16
+ def method_missing(method_sym, *_arguments)
17
+ ## A thread error deep in the bowels of IRB is not playing well with orchestration missing methods within the orchestration namespace. Until this can be resolved,
18
+ ## I've re-implemented it here.
19
+
20
+ raise NameError, "NameError (undefined local variable or method '#{method_sym}' for #{self.class}"
21
+ end
12
22
  end
13
23
  end
@@ -1,18 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Orchestration
2
- class InteractiveTerraform < Bcome::Orchestration::Base
4
+ class InteractiveTerraform < Bcome::Orchestration::Base
5
+ ## Prototype interactive terraform shell embedded within bcome.
6
+
7
+ # * Provides access to the metadata framework, so that data may be shared between Orchestrative processes and Terraform
8
+ # * Transparent authorization, by passing in cloud authorisation details from the bcome session
9
+ # * Passes in SSH credentials directly, which can be used to bootstrap machines.
3
10
 
4
- QUIT = "\\q"
5
- COMMAND_PROMPT = "enter command or '#{QUIT}' to quit: " + "terraform".informational + "\s"
11
+ QUIT = '\\q'
12
+ COMMAND_PROMPT = "enter command or '#{QUIT}' to quit: " + 'terraform'.informational + "\s"
6
13
 
7
14
  def execute
8
15
  show_intro_text
9
16
  wait_for_command_input
10
17
  end
11
-
18
+
12
19
  def show_intro_text
13
20
  puts "\n"
14
21
  puts "INTERACTIVE TERRAFORM\n".underline
15
- puts "Namespace:\s" + "#{@node.namespace}".informational
22
+ puts "Namespace:\s" + @node.namespace.to_s.informational
16
23
  puts "Configuration Path:\s" + "#{path_to_env_config}/*".informational
17
24
  puts "\nConfigured metadata:\s" + terraform_metadata.inspect.informational
18
25
 
@@ -22,6 +29,13 @@ module Bcome::Orchestration
22
29
  # PROCESSING INTERACTIVE COMMANDS
23
30
  #
24
31
  def process_command(raw_command)
32
+ if raw_command =~ /destroy/
33
+ are_you_sure_message = "Are you SURE you want to 'destroy'? Make sure you know what will be destroyed before you continue. (y/n):".warning
34
+ response = wait_for_input(are_you_sure_message)
35
+ response = wait_for_input(are_you_sure_message) until %w[y n].include?(response)
36
+ return if response == 'n'
37
+ end
38
+
25
39
  full_command = command(raw_command)
26
40
  @node.execute_local(full_command)
27
41
  wait_for_command_input
@@ -31,50 +45,71 @@ module Bcome::Orchestration
31
45
  #
32
46
  def wait_for_command_input
33
47
  raw_command = wait_for_input
34
- unless raw_command == QUIT
35
- process_command(raw_command)
36
- end
48
+ process_command(raw_command) unless raw_command == QUIT
37
49
  end
38
-
50
+
39
51
  def wait_for_input(message = COMMAND_PROMPT)
40
52
  ::Readline.readline("\n#{message}", true).squeeze('').to_s
41
- end
53
+ end
42
54
 
43
55
  # COMMAND PROCESSING
44
56
  def terraform_metadata
45
- @terraform_metadata ||= @node.metadata.fetch("terraform", @node.metadata.fetch(:terraform, {}))
46
- end
57
+ @terraform_metadata ||= @node.metadata.fetch('terraform', @node.metadata.fetch(:terraform, {}))
58
+ end
47
59
 
48
- # Get the terraform variables for this stack, and merge in with our EC2 access keys
60
+ # Get the terraform variables for this stack, and merge in with our networking & ssh credentials
49
61
  def form_var_string
50
62
  terraform_vars = terraform_metadata
51
- ec2_credentials = @node.network_driver.raw_fog_credentials
52
-
53
- cleaned_data = terraform_vars.select{|k,v|
54
- !v.is_a?(Hash) && !v.is_a?(Array)
55
- } # we can't yet handle nested terraform metadata on the command line so no arrays or hashes
56
-
57
- all_vars = cleaned_data.merge({
58
- :access_key => ec2_credentials["aws_access_key_id"],
59
- :secret_key => ec2_credentials["aws_secret_access_key"]
60
- })
61
-
62
- all_vars.collect{|key, value| "-var #{key}=\"#{value}\""}.join("\s")
63
+
64
+ terraform_vars.each do |key, value|
65
+ # Join arrays into a string (note we cannot handle nested arrays yet)
66
+ terraform_vars[key] = value.join(',') if value.is_a?(Array)
67
+ end
68
+
69
+ cleaned_data = terraform_vars.reject do |_k, v|
70
+ v.is_a?(Hash)
71
+ end # we can't yet handle nested terraform metadata on the command line so no hashes
72
+
73
+ all_vars = cleaned_data
74
+
75
+ if @node.network_driver.has_network_credentials?
76
+ network_credentials = @node.network_driver.network_credentials
77
+ all_vars = cleaned_data.merge(network_credentials)
78
+ end
79
+
80
+ all_vars[:ssh_user] = @node.ssh_driver.user
81
+ all_vars[:ssh_key_path] = @node.ssh_driver.ssh_keys.first
82
+
83
+ all_vars.collect { |key, value| "-var #{key}=\"#{value}\"" }.join("\s")
63
84
  end
64
85
 
65
86
  def var_string
66
87
  @var_string ||= form_var_string
67
88
  end
68
89
 
90
+ def backend_config_parameter_string
91
+ ## Backend configs are loaded before Terraform Core which means that we cannot use variables directly in our backend config.
92
+ ## This is a pain as we'll have authorised with GCP via the console, and so all sesssion have an access token readily available.
93
+ ## This patch passes the access token directly to terraform as a parameter.
94
+
95
+ ## GCP only for now. Support for AWS may come later as needed/requested.
96
+ return '' unless @node.network_driver.is_a?(::Bcome::Driver::Gcp)
97
+
98
+ "\s-backend-config \"access_token=#{@node.network_driver.network_credentials[:access_token]}\"\s"
99
+ end
100
+
69
101
  # Retrieve the path to the terraform configurations for this stack
70
102
  def path_to_env_config
71
- @path_to_env_config ||= "terraform/environments/#{@node.namespace.gsub(":","_")}"
103
+ @path_to_env_config ||= "terraform/environments/#{@node.namespace.gsub(':', '_')}"
72
104
  end
73
105
 
74
106
  # Formulate a terraform command
75
107
  def command(raw_command)
108
+ # if raw_command == "init"
109
+ # "cd #{path_to_env_config} ; terraform #{raw_command} #{backend_config_parameter_string}"
110
+ # else
76
111
  "cd #{path_to_env_config} ; terraform #{raw_command} #{var_string}"
112
+ # end
77
113
  end
78
-
79
114
  end
80
115
  end
@@ -1,10 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ::Bcome::Orchestrator
2
4
  include ::Singleton
3
5
 
4
6
  attr_reader :context
5
7
 
6
8
  def initialize
9
+ reset!
10
+ end
11
+
12
+ def reset!
7
13
  @silence = false
14
+ @tail_command_output = false
15
+ @multi_node = false
16
+ end
17
+
18
+ def is_multi_node?
19
+ @multi_node == true
8
20
  end
9
21
 
10
22
  def silence_command_output!
@@ -15,9 +27,19 @@ class ::Bcome::Orchestrator
15
27
  @silence == true
16
28
  end
17
29
 
30
+ def tail_all_command_output!(node)
31
+ @multi_node = node.machines.size > 1
32
+ @tail_command_output = true
33
+ end
34
+
35
+ def tail_all_command_output?
36
+ @tail_command_output == true
37
+ end
38
+
18
39
  def get(breadcrumb = nil)
19
40
  context = ::Bcome::Bootup.traverse(breadcrumb)
20
41
  raise Bcome::Exception::NoNodeFoundForBreadcrumb, breadcrumb unless context
42
+
21
43
  context.load_nodes if context.inventory? && !context.nodes_loaded?
22
44
  context
23
45
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Parser
2
4
  class BreadCrumb
3
5
  attr_reader :crumbs
@@ -25,7 +27,7 @@ module Bcome::Parser
25
27
  end
26
28
 
27
29
  def validate!
28
- #raise Bcome::Exception::InvalidBcomeBreadcrumb.new "- letters, numbers & underscores only" unless @raw_crumbs =~ /^([a-z0-9A-Z_]+)(:\s*[a-z0-9A-Z_]+)*:?$/i
30
+ # raise Bcome::Exception::InvalidBcomeBreadcrumb.new "- letters, numbers & underscores only" unless @raw_crumbs =~ /^([a-z0-9A-Z_]+)(:\s*[a-z0-9A-Z_]+)*:?$/i
29
31
  end
30
32
  end
31
33
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Registry::Arguments
2
4
  class Base
3
5
  attr_reader :arguments, :defaults, :processed_arguments, :merged_arguments
@@ -10,7 +12,7 @@ module Bcome::Registry::Arguments
10
12
  end
11
13
 
12
14
  def initialize(_arguments, defaults)
13
- @defaults = defaults ? defaults : {}
15
+ @defaults = defaults || {}
14
16
  validate
15
17
  end
16
18
 
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Registry::Arguments
2
4
  class CommandLine < Base
3
5
  def initialize(arguments, defaults)
4
- @arguments = arguments ? arguments : []
6
+ @arguments = arguments || []
5
7
  @processed_arguments = {}
6
8
  super
7
9
  end
@@ -21,14 +23,17 @@ module Bcome::Registry::Arguments
21
23
  @arguments.each do |argument|
22
24
  argument =~ /^(.+)=(.+)$/
23
25
  raise Bcome::Exception::MalformedCommandLineArguments, argument unless Regexp.last_match(1) || Regexp.last_match(2)
26
+
24
27
  key = Regexp.last_match(1).to_sym; value = Regexp.last_match(2)
25
28
  raise Bcome::Exception::DuplicateCommandLineArgumentKey, "'#{key}'" if @processed_arguments.key?(key)
29
+
26
30
  @processed_arguments[key] = value
27
31
  end
28
32
  end
29
33
 
30
34
  def validate
31
35
  raise Bcome::Exception::InvalidRegistryArgumentType, 'invalid argument format' unless @arguments.is_a?(Array)
36
+
32
37
  super
33
38
  end
34
39
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Registry::Arguments
2
4
  class Console < Base
3
5
  def initialize(arguments, defaults)
4
- @arguments = arguments ? arguments : {}
6
+ @arguments = arguments || {}
5
7
  super
6
8
  end
7
9
 
@@ -9,6 +11,7 @@ module Bcome::Registry::Arguments
9
11
 
10
12
  def validate
11
13
  raise Bcome::Exception::InvalidRegistryArgumentType, 'invalid argument format' unless @arguments.is_a?(Hash)
14
+
12
15
  super
13
16
  end
14
17
  end
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Registry::Command
2
4
  class Base
3
5
  class << self
4
6
  def new_from_raw_command(data)
5
7
  raise Bcome::Exception::InvalidContextCommand, "#{data.inspect} is missing key type" unless data[:type]
6
8
  raise Bcome::Exception::InvalidContextCommand, "#{data.inspect} has invalid type '#{data[:type]}'" unless is_valid_type?(data[:type])
9
+
7
10
  valid_types[data[:type].to_sym].new(data)
8
11
  end
9
12
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Registry::Command
2
4
  class External < Base
3
5
  # In which the bcome context is passed to an external call
@@ -28,8 +30,8 @@ module Bcome::Registry::Command
28
30
  error_message_suffix = "- missing '#{substitution}' from command '#{local_command}'"
29
31
  raise Bcome::Exception::MissingArgumentForRegistryCommand, error_message_suffix
30
32
  end
31
-
32
- substitute_with = [TrueClass, FalseClass].include?(substitute_with.class) ? (substitute_with ? "true" : "false") : substitute_with
33
+
34
+ substitute_with = [TrueClass, FalseClass].include?(substitute_with.class) ? (substitute_with ? 'true' : 'false') : substitute_with
33
35
  substituted_command.gsub!("%#{substitution}%", substitute_with)
34
36
  end
35
37
  substituted_command
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bcome::Registry::Command
2
4
  class Group
3
5
  def initialize(node)
@@ -32,7 +34,8 @@ module Bcome::Registry::Command
32
34
  end
33
35
 
34
36
  def item_spacing(item)
35
- raise ::Bcome::Exception::InvalidRegistryCommandNameLength.new "command '#{item}' exceeds length limit of #{menu_item_spacing_length}" if item.length > menu_item_spacing_length
37
+ raise ::Bcome::Exception::InvalidRegistryCommandNameLength, "command '#{item}' exceeds length limit of #{menu_item_spacing_length}" if item.length > menu_item_spacing_length
38
+
36
39
  "\s" * (menu_item_spacing_length - item.length)
37
40
  end
38
41
 
@@ -48,7 +51,7 @@ module Bcome::Registry::Command
48
51
  ::Bcome::System::Local.instance.in_console_session?
49
52
  end
50
53
 
51
- def pretty_print ## TODO - revisit. This is a mess
54
+ def pretty_print
52
55
  puts "\nRegistry commands".title + "\sfor #{@node.class} #{@node.keyed_namespace}".resource_value + "\n\n"
53
56
  all_commands.sort.each do |group_name, commands|
54
57
  puts tab_spacing + group_name.title + "\n\n"
@@ -63,7 +66,7 @@ module Bcome::Registry::Command
63
66
  puts tab_spacing + ("\s" * menu_item_spacing_length) + 'usage: '.instructional + usage_string
64
67
 
65
68
  if defaults.keys.any?
66
- defaults_usage = in_console_session? ? "\s\"#{defaults.collect { |key, _value| "#{key}=your-value" }.join(',')}\"" : "\s" + defaults.collect { |key, _value| "#{key}=your-value" }.join("\s")
69
+ defaults_usage = in_console_session? ? "\s#{defaults.collect { |key, _value| "\"#{key}=your-value\"" }.join(",\s")}" : "\s" + defaults.collect { |key, _value| "#{key}=your-value" }.join("\s")
67
70
  puts tab_spacing + ("\s" * menu_item_spacing_length) + "defaults:\s".instructional + defaults.collect { |k, v| "#{k}=#{v}" }.join(', ')
68
71
  puts tab_spacing + ("\s" * menu_item_spacing_length) + "override:\s".instructional + usage_string + defaults_usage
69
72
  end