bcome 1.4.0 → 2.0.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bcome.rb +7 -0
  3. data/lib/objects/bcome/version.rb +3 -3
  4. data/lib/objects/bootup.rb +4 -3
  5. data/lib/objects/driver/base.rb +16 -2
  6. data/lib/objects/driver/ec2.rb +11 -2
  7. data/lib/objects/driver/gcp.rb +49 -5
  8. data/lib/objects/driver/gcp/authentication/base.rb +36 -0
  9. data/lib/objects/driver/gcp/authentication/oauth.rb +24 -29
  10. data/lib/objects/driver/gcp/authentication/oauth_client_config.rb +22 -0
  11. data/lib/objects/driver/gcp/authentication/oauth_session_store.rb +22 -0
  12. data/lib/objects/driver/gcp/authentication/service_account.rb +57 -2
  13. data/lib/objects/driver/gcp/authentication/signet/service_account.rb +27 -0
  14. data/lib/objects/driver/gcp/authentication/utilities.rb +42 -0
  15. data/lib/objects/encryptor.rb +83 -0
  16. data/lib/objects/exception/base.rb +10 -3
  17. data/lib/objects/exception/ec2_driver_missing_authorization_keys.rb +11 -0
  18. data/lib/objects/exception/empty_namespace_tree.rb +11 -0
  19. data/lib/objects/exception/gcp_auth_service_account_missing_credentials.rb +11 -0
  20. data/lib/objects/exception/invalid_metadata_encryption_key.rb +1 -1
  21. data/lib/objects/exception/missing_gcp_service_account_credentials_filename.rb +11 -0
  22. data/lib/objects/exception/user_orchestration_error.rb +11 -0
  23. data/lib/objects/initialization/factory.rb +36 -0
  24. data/lib/objects/initialization/structure.rb +18 -0
  25. data/lib/objects/initialization/utils.rb +20 -0
  26. data/lib/objects/loading_bar/handler.rb +1 -1
  27. data/lib/objects/loading_bar/indicator/base.rb +1 -0
  28. data/lib/objects/modules/draw.rb +49 -0
  29. data/lib/objects/modules/tree.rb +157 -0
  30. data/lib/objects/modules/workspace_commands.rb +2 -32
  31. data/lib/objects/modules/workspace_menu.rb +113 -48
  32. data/lib/objects/node/attributes.rb +6 -0
  33. data/lib/objects/node/base.rb +27 -7
  34. data/lib/objects/node/cache_handler.rb +1 -1
  35. data/lib/objects/node/factory.rb +15 -11
  36. data/lib/objects/node/inventory/base.rb +9 -3
  37. data/lib/objects/node/inventory/defined.rb +18 -15
  38. data/lib/objects/node/inventory/merge.rb +9 -1
  39. data/lib/objects/node/inventory/subselect.rb +6 -4
  40. data/lib/objects/node/meta_data_factory.rb +1 -1
  41. data/lib/objects/node/meta_data_loader.rb +2 -2
  42. data/lib/objects/node/resources/inventory.rb +19 -0
  43. data/lib/objects/node/resources/merged.rb +23 -14
  44. data/lib/objects/node/resources/sub_inventory.rb +6 -5
  45. data/lib/objects/node/server/base.rb +35 -22
  46. data/lib/objects/node/server/dynamic/ec2.rb +0 -1
  47. data/lib/objects/node/server/dynamic/gcp.rb +0 -1
  48. data/lib/objects/node/server/static.rb +22 -9
  49. data/lib/objects/orchestration/base.rb +7 -1
  50. data/lib/objects/orchestration/interactive_terraform.rb +10 -16
  51. data/lib/objects/registry/command/external.rb +6 -2
  52. data/lib/objects/registry/command/group.rb +5 -1
  53. data/lib/objects/registry/loader.rb +3 -0
  54. data/lib/objects/ssh/command.rb +4 -8
  55. data/lib/objects/ssh/command_exec.rb +3 -1
  56. data/lib/objects/ssh/connection_wrangler.rb +34 -17
  57. data/lib/objects/ssh/connector.rb +17 -9
  58. data/lib/objects/ssh/driver.rb +7 -18
  59. data/lib/objects/ssh/driver_concerns/connection.rb +3 -11
  60. data/lib/objects/ssh/driver_concerns/functions.rb +7 -7
  61. data/lib/objects/ssh/proxy_chain.rb +19 -0
  62. data/lib/objects/ssh/proxy_chain_link.rb +26 -0
  63. data/lib/objects/ssh/proxy_hop.rb +47 -18
  64. data/lib/objects/ssh/script_exec.rb +9 -11
  65. data/lib/objects/startup.rb +7 -1
  66. data/lib/objects/terraform/output.rb +5 -1
  67. data/lib/objects/workspace.rb +10 -0
  68. data/patches/irb.rb +35 -1
  69. data/patches/string.rb +13 -0
  70. metadata +71 -25
  71. data/lib/objects/driver/static.rb +0 -6
@@ -13,14 +13,14 @@ module Bcome
13
13
  puts "\n\n" + visual_hierarchy.hierarchy + "\n"
14
14
  puts "\t" + "Available #{list_key}s:" + "\n\n"
15
15
 
16
- iterate_over = active_only ? @resources.active : @resources
16
+ iterate_over = active_only ? resources.active : resources
17
17
 
18
18
  if iterate_over.any?
19
19
 
20
20
  iterate_over.sort_by(&:identifier).each do |resource|
21
21
  next if resource.hide?
22
22
 
23
- is_active = @resources.is_active_resource?(resource)
23
+ is_active = resources.is_active_resource?(resource)
24
24
  puts resource.pretty_description(is_active)
25
25
 
26
26
  puts "\n"
@@ -43,38 +43,12 @@ module Bcome
43
43
  ::Bcome::Interactive::Session.run(self, :interactive_ssh)
44
44
  end
45
45
 
46
- def tree
47
- puts "\nTree view\n".title
48
- tab = ''
49
- print_tree_view_for_resource(tab, self)
50
- list_in_tree("#{tab}\t", resources)
51
- print "\n"
52
- end
53
-
54
46
  def parents
55
47
  ps = []
56
48
  ps << [parent, parent.parents] if has_parent?
57
49
  ps.flatten
58
50
  end
59
51
 
60
- def list_in_tree(tab, resources)
61
- resources.sort_by(&:identifier).each do |resource|
62
- next if resource.parent && !resource.parent.resources.is_active_resource?(resource)
63
- next if resource.hide?
64
-
65
- resource.load_nodes if resource.inventory? && !resource.nodes_loaded?
66
- print_tree_view_for_resource(tab, resource)
67
- list_in_tree("#{tab}\t", resource.resources)
68
- end
69
- end
70
-
71
- def print_tree_view_for_resource(tab, resource)
72
- separator = '-'
73
- tree_item = tab.to_s + separator.resource_key + " #{resource.type.resource_key} \s#{resource.identifier.resource_value}"
74
- tree_item += ' (empty set)' if !resource.server? && !resource.resources.has_active_nodes?
75
- puts tree_item
76
- end
77
-
78
52
  def cd(identifier)
79
53
  if (resource = resources.for_identifier(identifier))
80
54
  if resource.parent.resources.is_active_resource?(resource)
@@ -124,10 +98,6 @@ module Bcome
124
98
  desc
125
99
  end
126
100
 
127
- def back
128
- exit
129
- end
130
-
131
101
  def disable(*ids)
132
102
  ids.each { |id| resources.do_disable(id) }
133
103
  end
@@ -4,20 +4,43 @@ module Bcome
4
4
  module WorkspaceMenu
5
5
  def menu
6
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]
7
+ puts 'COMMAND MENU'.bc_cyan + "\sfor #{self.class} #{namespace}".resource_value
11
8
 
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]}"
9
+ grouped_menu_items = menu_items.group_by { |m| m[1][:group] }
10
+ grouped_menu_items.each do |group_key, items|
11
+ # If we're not in a console session, we filter out console only methods
12
+ items = items.reject { |item| item[1][:console_only] } unless ::Bcome::System::Local.instance.in_console_session?
13
+
14
+ next if items.empty?
15
+
16
+ s_heading = "/ #{menu_group_names[group_key]}"
17
+ print "\n\n" + tab_spacing + s_heading.upcase.bc_cyan
18
+ print item_spacing(s_heading) + ("\s" * 110).to_s.bc_cyan.underline
19
+ print "\n\n"
20
+ print_menu_items(items)
21
+ end
22
+
23
+ nil
24
+ end
25
+
26
+ def print_menu_items(items)
27
+ items.each_with_index do |item, _index|
28
+ key = item[0]
29
+ config = item[1]
30
+
31
+ next if !::Bcome::System::Local.instance.in_console_session? && config[:console_only]
32
+
33
+ puts tab_spacing + key.to_s.resource_key + item_spacing(key) + (config[:description]).to_s.resource_value
34
+ if config[:usage] || config[:terminal_usage]
35
+ usage_string = if ::Bcome::System::Local.instance.in_console_session?
36
+ config[:usage]
37
+ else
38
+ "bcome #{keyed_namespace.empty? ? '' : "#{keyed_namespace}:"}#{config[:terminal_usage]}"
39
+ end
15
40
  puts tab_spacing + ("\s" * menu_item_spacing_length) + 'usage: '.instructional + usage_string
16
41
  end
17
42
  puts "\n"
18
43
  end
19
-
20
- nil
21
44
  end
22
45
 
23
46
  def mode
@@ -36,102 +59,144 @@ module Bcome
36
59
  "\s" * 3
37
60
  end
38
61
 
62
+ def menu_group_names
63
+ {
64
+ ssh: 'Ssh',
65
+ informational: 'Informational',
66
+ selection: 'Selections',
67
+ file: 'File & Script',
68
+ navigation: 'Navigational',
69
+ miscellany: 'Miscellaneous',
70
+ command_list: 'Command lists'
71
+ }
72
+ end
73
+
39
74
  def menu_items
40
75
  {
76
+ routes: {
77
+ description: 'Print SSH routing tree',
78
+ console_only: false,
79
+ group: :informational
80
+ },
41
81
  ls: {
42
- description: 'list all available resources',
43
- console_only: false
82
+ description: 'list all available namespaces',
83
+ console_only: false,
84
+ group: :informational
44
85
  },
45
86
  lsa: {
46
- description: 'list all active resources',
47
- console_only: true
87
+ description: 'list all active namespaces',
88
+ console_only: true,
89
+ group: :informational
48
90
  },
49
91
  workon: {
50
- description: 'work on specific resources only, inactivating all others from this selection',
92
+ description: 'work on specific namespaces only, inactivating all others from this selection',
51
93
  usage: 'workon identifier1, identifier2 ...',
52
- console_only: true
94
+ console_only: true,
95
+ group: :selection
53
96
  },
54
97
  disable: {
55
- description: 'remove a resource from this selection',
98
+ description: 'remove a namespace from this selection',
56
99
  usage: 'disable identifier1, identifier2 ...',
57
- console_only: true
100
+ console_only: true,
101
+ group: :selection
58
102
  },
59
103
  enable: {
60
- description: 're-enable a resource within this selection',
104
+ description: 're-enable a namespace within this selection',
61
105
  usage: 'enable identifier1, identifier2 ...',
62
- console_only: true
106
+ console_only: true,
107
+ group: :selection
63
108
  },
64
109
  enable!: {
65
- description: 'enable all resources within this selection',
66
- console_only: true
110
+ description: 'enable all namespaces within this selection',
111
+ console_only: true,
112
+ group: :selection
67
113
  },
68
114
  disable!: {
69
- description: 'disable all resources within this selection',
70
- console_only: true
115
+ description: 'disable all namespaces within this selection',
116
+ console_only: true,
117
+ group: :selection
71
118
  },
72
119
  run: {
73
- description: 'execute a command to be run over ssh against all active resources',
120
+ description: 'execute a command to be run over ssh against all active namespaces',
74
121
  usage: "run 'command1', 'command2', ...",
75
122
  console_only: false,
76
- terminal_usage: "run 'command1' 'command2' ..."
123
+ terminal_usage: "run 'command1' 'command2' ...",
124
+ group: :ssh
77
125
  },
78
126
  interactive: {
79
- description: 'enter an interactive command session for all active resources',
80
- console_only: false
127
+ description: 'enter an interactive command session for all active namespaces',
128
+ console_only: false,
129
+ group: :ssh
81
130
  },
82
131
  tree: {
83
- description: 'print a tree view for all resources and their sub-resources',
84
- console_only: false
132
+ description: 'print a tree view for all namespaces and their sub-namespaces',
133
+ console_only: false,
134
+ group: :informational
85
135
  },
86
136
  ping: {
87
- description: 'ping all resources to test connectivity',
88
- console_only: false
137
+ description: 'ping all namespaces to test connectivity',
138
+ console_only: false,
139
+ group: :ssh
89
140
  },
90
141
  put: {
91
142
  description: 'upload a file or directory using scp',
92
143
  usage: "put 'local/path','remote/path'",
93
144
  console_only: false,
94
- terminal_usage: "put 'local/path' 'remote/path'"
145
+ terminal_usage: "put 'local/path' 'remote/path'",
146
+ group: :file
95
147
  },
96
148
  put_str: {
97
149
  description: 'Write a file /to/remote/path from a string',
98
150
  usage: 'put_str "string" "remote/path"',
99
151
  console_only: false,
100
- terminal_usage: "put_str '<file contents>', 'remote/path'"
152
+ terminal_usage: "put_str '<file contents>', 'remote/path'",
153
+ group: :file
101
154
  },
102
155
  rsync: {
103
156
  description: 'upload a file or directory using rsync (faster)',
104
157
  usage: "rsync 'local/path','remote/path'",
105
158
  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"
159
+ terminal_usage: "rsync 'local/path' 'remote/path'",
160
+ group: :file
113
161
  },
114
162
  cd: {
115
- description: 'enter the namespace for a resource from this selection',
163
+ description: 'enter a console session for a child namespace from this selection',
116
164
  usage: 'cd identifier',
117
- console_only: true
165
+ console_only: true,
166
+ group: :navigation
167
+ },
168
+ quit: {
169
+ description: 'Quit out of bcome',
170
+ usage: 'quit',
171
+ console_only: true,
172
+ group: :navigation
118
173
  },
119
- save: {
120
- description: 'Save the current tree state',
121
- console_only: true
174
+ back: {
175
+ description: 'Go back up a namespace, or quit',
176
+ usage: 'back',
177
+ console_only: true,
178
+ group: :navigation
122
179
  },
123
180
  meta: {
124
- description: 'Print out all metadata related to this node'
181
+ description: 'Print out all metadata related to this node',
182
+ group: :informational
125
183
  },
126
184
  registry: {
127
185
  description: 'List all user defined commands present in your registry, and available to this namespace',
128
- console_only: false
186
+ console_only: false,
187
+ group: :command_list
188
+ },
189
+ menu: {
190
+ description: 'List all available commands',
191
+ console_only: false,
192
+ group: :command_list
129
193
  },
130
194
  execute_script: {
131
195
  description: 'execute a bash script',
132
196
  console_only: false,
133
197
  usage: 'execute_script "script_name"',
134
- terminal_usage: 'execute_script script_name'
198
+ terminal_usage: 'execute_script script_name',
199
+ group: :ssh
135
200
  }
136
201
  }
137
202
  end
@@ -7,6 +7,10 @@ module Bcome::Node::Attributes
7
7
  @identifier
8
8
  end
9
9
 
10
+ def ssh_driver=(alternative_ssh_driver)
11
+ @ssh_driver = alternative_ssh_driver
12
+ end
13
+
10
14
  def ssh_driver
11
15
  @ssh_driver ||= ::Bcome::Ssh::Driver.new(ssh_data, self)
12
16
  end
@@ -19,6 +23,8 @@ module Bcome::Node::Attributes
19
23
  recurse_hash_data_for_instance_key(:network, :network_data)
20
24
  end
21
25
 
26
+ # From 2.0.0 onwards, filters can be loaded from the network block only. The older key, 'ec2_filters'
27
+ #  is retained at this level for backwards compatibility.
22
28
  def filters
23
29
  recurse_hash_data_for_instance_key(:ec2_filters, :filters)
24
30
  end
@@ -8,6 +8,7 @@ module Bcome::Node
8
8
  include Bcome::WorkspaceMenu
9
9
  include Bcome::Node::LocalMetaDataFactory
10
10
  include Bcome::Node::RegistryManagement
11
+ include Bcome::Tree
11
12
 
12
13
  def inspect
13
14
  "<##{self.class}: #{namespace} @network_driver=#{network_driver}>"
@@ -34,10 +35,13 @@ module Bcome::Node
34
35
  @parent = params[:parent]
35
36
  @type = params[:type]
36
37
  @metadata = {}
38
+ @nodes_loaded = false
37
39
 
38
40
  set_view_attributes if @views
39
41
  validate_attributes
40
42
 
43
+ @original_identifier = @identifier
44
+
41
45
  ::Bcome::Registry::Loader.instance.set_command_group_for_node(self)
42
46
  end
43
47
 
@@ -87,6 +91,14 @@ module Bcome::Node
87
91
  ssh_driver.proxy
88
92
  end
89
93
 
94
+ def proxy_chain
95
+ ssh_driver.proxy_chain
96
+ end
97
+
98
+ def proxy_chain_link
99
+ @proxy_chain_link ||= ::Bcome::Ssh::ProxyChainLink.new(self)
100
+ end
101
+
90
102
  def scoped_resources
91
103
  # Active & not hidden
92
104
  resources.active.reject(&:hide?)
@@ -117,7 +129,7 @@ module Bcome::Node
117
129
 
118
130
  def put_str(string, remote_path, connect = true)
119
131
  ssh_connect if connect # Initiate connect at highest namespace level
120
- scoped_resources.each do |resource|
132
+ scoped_resources.pmap do |resource|
121
133
  resource.put_str(string, remote_path, false)
122
134
  end
123
135
  nil
@@ -169,7 +181,13 @@ module Bcome::Node
169
181
  end
170
182
 
171
183
  def nodes_loaded?
172
- resources.any?
184
+ # resources.any? # This was buggy: an inventory may validly contain no resources. This does not mean that we haven't attempted to load them
185
+ # we no explicitly set a flag for when we've loaded nodes. This will prevents uneccessary lookups over the wire
186
+ @nodes_loaded
187
+ end
188
+
189
+ def nodes_loaded!
190
+ @nodes_loaded = true
173
191
  end
174
192
 
175
193
  def resources
@@ -214,7 +232,11 @@ module Bcome::Node
214
232
  end
215
233
 
216
234
  def prompt_breadcrumb
217
- "#{has_parent? ? "#{parent.prompt_breadcrumb}> " : ''}#{current_context? ? (has_parent? ? identifier.terminal_prompt : identifier) : identifier}"
235
+ "#{has_parent? ? "#{parent.prompt_breadcrumb}> " : ''}#{if current_context?
236
+ has_parent? ? identifier.terminal_prompt : identifier
237
+ else
238
+ identifier
239
+ end}"
218
240
  end
219
241
 
220
242
  def namespace
@@ -244,13 +266,13 @@ module Bcome::Node
244
266
 
245
267
  def close_ssh_connections
246
268
  # For every loaded server, we'll close any lingering ssh connection
247
- if resources.any?
269
+ if @resources&.any?
248
270
  resources.pmap do |resource|
249
271
  if resource.is_a?(::Bcome::Node::Server::Base)
250
272
  resource.close_ssh_connection
251
273
  else
252
274
  resource.close_ssh_connections
253
- end
275
+ end
254
276
  end
255
277
  end
256
278
  nil
@@ -304,8 +326,6 @@ module Bcome::Node
304
326
  [:views]
305
327
  end
306
328
 
307
- private
308
-
309
329
  def to_ary
310
330
  # due to my method_missing implementation, the following is required.
311
331
  # 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/
@@ -13,7 +13,7 @@ module Bcome::Node
13
13
  end
14
14
 
15
15
  def write_to_in_memory_cache!(nodes)
16
- @inventory_node.views[:load_machines_from_cache] = true
16
+ # @inventory_node.views[:load_machines_from_cache] = true
17
17
  static_server_data = dynamic_nodes_to_cache_hash(nodes)
18
18
  @inventory_node.views[:static_servers] = static_server_data
19
19
  nil
@@ -8,7 +8,7 @@ module Bcome::Node
8
8
 
9
9
  CONFIG_PATH = 'bcome'
10
10
  DEFAULT_CONFIG_NAME = 'networks.yml'
11
- SERVER_OVERRIDE_CONFIG_NAME = 'machines-data.yml'
11
+ SERVER_OVERRIDE_CONFIG_NAME = 'server-overrides.yml'
12
12
  LOCAL_OVERRIDE_CONFIG_NAME = 'me.yml'
13
13
 
14
14
  INVENTORY_KEY = 'inventory'
@@ -24,6 +24,7 @@ module Bcome::Node
24
24
  end
25
25
 
26
26
  def init_tree
27
+ raise ::Bcome::Exception::EmptyNamespaceTree, "no namespaces found in #{config_path}.\n\nPlease refer to the documentation for assistance at https://docs.bcome.com." if estate_config.nil?
27
28
  @estate = create_node(estate_config)
28
29
  @estate
29
30
  end
@@ -55,7 +56,7 @@ module Bcome::Node
55
56
  end
56
57
 
57
58
  def create_node(config, parent = nil)
58
- raise Bcome::Exception::InvalidNetworkConfig, 'missing config type' unless config[:type]
59
+ raise Bcome::Exception::InvalidNetworkConfig, "missing config type for config #{config}" unless config[:type]
59
60
 
60
61
  klass = klass_for_view_type[config[:type]]
61
62
 
@@ -65,6 +66,11 @@ module Bcome::Node
65
66
  create_tree(node, config[:views]) if config[:views]&.any?
66
67
  parent.resources << node if parent
67
68
 
69
+ # Load inventory resources as early as possible
70
+ if node.is_a?(Bcome::Node::Inventory::Base)
71
+ node.load_nodes unless node.nodes_loaded?
72
+ end
73
+
68
74
  bucket[node.keyed_namespace] = node
69
75
 
70
76
  node
@@ -73,7 +79,6 @@ module Bcome::Node
73
79
  def validate_view(breadcrumb, data)
74
80
  raise Bcome::Exception::InvalidNetworkConfig, "Missing namespace type for namespace '#{breadcrumb}'" unless data && data[:type]
75
81
 
76
-
77
82
  raise Bcome::Exception::InvalidNetworkConfig, "Invalid View Type '#{data[:type]}' for namespace '#{breadcrumb}'. Expecting View Type to be one of: #{klass_for_view_type.keys.join(', ')}" unless is_valid_view_type?(data[:type])
78
83
  end
79
84
 
@@ -103,12 +108,6 @@ module Bcome::Node
103
108
  machines_data[namespace] || {}
104
109
  end
105
110
 
106
- def rewrite_estate_config(data)
107
- File.open(config_path, 'w') do |file|
108
- file.write data.to_yaml
109
- end
110
- end
111
-
112
111
  def load_estate_config
113
112
  config = YAML.load_file(config_path).deep_symbolize_keys
114
113
  config.deep_merge(local_data)
@@ -134,13 +133,18 @@ module Bcome::Node
134
133
  end
135
134
 
136
135
  def local_data_path
137
- "#{CONFIG_PATH}/#{LOCAL_OVERRIDE_CONFIG_NAME}"
136
+ ENV['ME'] || "#{CONFIG_PATH}/#{LOCAL_OVERRIDE_CONFIG_NAME}"
138
137
  end
139
138
 
140
139
  def load_local_data
141
140
  return {} unless File.exist?(local_data_path)
142
141
 
143
- config = YAML.load_file(local_data_path)
142
+ begin
143
+ config = YAML.load_file(local_data_path).deep_symbolize_keys
144
+ rescue StandardError => e
145
+ raise ::Bcome::Exception::Generic, "Error parsing configuration file #{local_data_path}"
146
+ end
147
+
144
148
  return {} if config.nil?
145
149
 
146
150
  config