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,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