bcome 1.3.6 → 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.
- checksums.yaml +4 -4
- data/bin/bcome +13 -8
- data/lib/bcome.rb +7 -11
- data/lib/objects/bcome/version.rb +19 -1
- data/lib/objects/bootup.rb +13 -5
- data/lib/objects/command/local.rb +2 -0
- data/lib/objects/config_factory.rb +3 -0
- data/lib/objects/driver/base.rb +36 -4
- data/lib/objects/driver/bucket.rb +6 -4
- data/lib/objects/driver/ec2.rb +35 -4
- data/lib/objects/driver/gcp.rb +124 -0
- data/lib/objects/driver/gcp/authentication/api_key.rb +6 -0
- data/lib/objects/driver/gcp/authentication/oauth.rb +101 -0
- data/lib/objects/driver/gcp/authentication/service_account.rb +7 -0
- data/lib/objects/driver/static.rb +2 -0
- data/lib/objects/encryptor.rb +26 -24
- data/lib/objects/exception/argument_error_invoking_method_from_command_line.rb +8 -4
- data/lib/objects/exception/base.rb +14 -10
- data/lib/objects/exception/can_only_subselect_on_inventory.rb +8 -4
- data/lib/objects/exception/cannot_authenticate_to_gcp.rb +11 -0
- data/lib/objects/exception/cannot_find_internal_registry_klass.rb +8 -4
- data/lib/objects/exception/cannot_find_inventory.rb +11 -0
- data/lib/objects/exception/cannot_find_subselection_parent.rb +8 -4
- data/lib/objects/exception/cant_find_key_in_cloud_tags.rb +8 -4
- data/lib/objects/exception/cant_find_key_in_metadata.rb +8 -4
- data/lib/objects/exception/cant_find_proxy_host_by_identifier.rb +8 -4
- data/lib/objects/exception/cant_find_proxy_host_by_namespace.rb +8 -4
- data/lib/objects/exception/could_not_initiate_ssh_connection.rb +8 -4
- data/lib/objects/exception/could_not_initiate_ssh_connection_through_backend_proxy.rb +8 -4
- data/lib/objects/exception/could_not_retrieve_terraform_output.rb +11 -0
- data/lib/objects/exception/deprecation_warning.rb +9 -7
- data/lib/objects/exception/duplicate_command_line_argument_key.rb +8 -4
- data/lib/objects/exception/ec2_driver_missing_provisioning_region.rb +8 -4
- data/lib/objects/exception/failed_to_run_local_command.rb +8 -4
- data/lib/objects/exception/generic.rb +11 -0
- data/lib/objects/exception/interactive_session_halt.rb +6 -2
- data/lib/objects/exception/invalid_bcome_breadcrumb.rb +8 -4
- data/lib/objects/exception/invalid_breadcrumb.rb +8 -4
- data/lib/objects/exception/invalid_context_command.rb +8 -4
- data/lib/objects/exception/invalid_gcp_authentication_scheme.rb +11 -0
- data/lib/objects/exception/invalid_identifier.rb +8 -4
- data/lib/objects/exception/invalid_machines_cache_config.rb +8 -4
- data/lib/objects/exception/invalid_matcher_query.rb +8 -4
- data/lib/objects/exception/invalid_meta_data_config.rb +8 -4
- data/lib/objects/exception/invalid_metadata_encryption_key.rb +8 -4
- data/lib/objects/exception/invalid_network_config.rb +8 -4
- data/lib/objects/exception/invalid_network_driver_type.rb +8 -4
- data/lib/objects/exception/invalid_port_forward_request.rb +11 -0
- data/lib/objects/exception/invalid_proxy_config.rb +8 -4
- data/lib/objects/exception/invalid_regexp_matcher_in_registry.rb +8 -4
- data/lib/objects/exception/invalid_registry_arguments_type.rb +8 -4
- data/lib/objects/exception/invalid_registry_command_name_length.rb +8 -4
- data/lib/objects/exception/invalid_registry_data_config.rb +8 -4
- data/lib/objects/exception/invalid_restriction_key_in_registry.rb +8 -4
- data/lib/objects/exception/invalid_ssh_config.rb +8 -4
- data/lib/objects/exception/inventories_cannot_have_subviews.rb +8 -4
- data/lib/objects/exception/malformed_command_line_arguments.rb +8 -4
- data/lib/objects/exception/method_invocation_requires_parameter.rb +8 -4
- data/lib/objects/exception/method_name_conflict_in_registry.rb +8 -4
- data/lib/objects/exception/missing_argument_for_registry_command.rb +8 -4
- data/lib/objects/exception/missing_description_on_view.rb +8 -4
- data/lib/objects/exception/missing_execute_on_registry_object.rb +8 -4
- data/lib/objects/exception/missing_gcp_authentication_scheme.rb +11 -0
- data/lib/objects/exception/missing_gcp_service_scopes.rb +11 -0
- data/lib/objects/exception/missing_identifier_on_view.rb +8 -4
- data/lib/objects/exception/missing_inventory_contributors.rb +11 -0
- data/lib/objects/exception/missing_ip_address_on_server.rb +8 -4
- data/lib/objects/exception/missing_network_config.rb +8 -4
- data/lib/objects/exception/missing_or_invalid_client_secrets.rb +11 -0
- data/lib/objects/exception/missing_params_for_rsync.rb +8 -4
- data/lib/objects/exception/missing_params_for_scp.rb +8 -4
- data/lib/objects/exception/missing_subselection_key.rb +8 -4
- data/lib/objects/exception/missing_type_on_view.rb +8 -4
- data/lib/objects/exception/no_node_found_for_breadcrumb.rb +8 -4
- data/lib/objects/exception/no_node_named_by_identifier.rb +8 -4
- data/lib/objects/exception/node_identifiers_must_be_unique.rb +8 -4
- data/lib/objects/exception/orchestration_script_does_not_exist.rb +8 -4
- data/lib/objects/exception/proxy_host_node_does_not_have_public_ip_address.rb +8 -4
- data/lib/objects/exception/unknown_dynamic_server_type.rb +11 -0
- data/lib/objects/exception/unknown_method_for_namespace.rb +8 -4
- data/lib/objects/interactive/session.rb +4 -1
- data/lib/objects/interactive/session_item/base.rb +2 -0
- data/lib/objects/interactive/session_item/capture_input.rb +2 -0
- data/lib/objects/interactive/session_item/transparent_ssh.rb +29 -23
- data/lib/objects/loading_bar/handler.rb +80 -0
- data/lib/objects/loading_bar/indicator/base.rb +64 -0
- data/lib/objects/loading_bar/indicator/basic.rb +34 -0
- data/lib/objects/loading_bar/indicator/progress.rb +26 -0
- data/lib/objects/loading_bar/pid_bucket.rb +27 -0
- data/lib/objects/modules/context.rb +13 -9
- data/lib/objects/modules/registry_management.rb +16 -10
- data/lib/objects/modules/ui_output.rb +10 -6
- data/lib/objects/modules/workspace_commands.rb +159 -155
- data/lib/objects/modules/workspace_menu.rb +129 -130
- data/lib/objects/node/attributes.rb +13 -21
- data/lib/objects/node/base.rb +113 -71
- data/lib/objects/node/cache_handler.rb +2 -0
- data/lib/objects/node/collection.rb +10 -9
- data/lib/objects/node/factory.rb +35 -28
- data/lib/objects/node/inventory/base.rb +100 -100
- data/lib/objects/node/inventory/defined.rb +110 -89
- data/lib/objects/node/inventory/merge.rb +43 -0
- data/lib/objects/node/inventory/subselect.rb +64 -46
- data/lib/objects/node/kube/base.rb +51 -0
- data/lib/objects/node/kube/container.rb +9 -0
- data/lib/objects/node/kube/estate.rb +19 -0
- data/lib/objects/node/kube/namespace.rb +24 -0
- data/lib/objects/node/kube/pod.rb +24 -0
- data/lib/objects/node/kube_wrap.rb +26 -0
- data/lib/objects/node/meta/base.rb +8 -1
- data/lib/objects/node/meta/cloud.rb +2 -0
- data/lib/objects/node/meta/local.rb +2 -0
- data/lib/objects/node/meta_data_factory.rb +3 -1
- data/lib/objects/node/meta_data_loader.rb +27 -28
- data/lib/objects/node/resources/base.rb +5 -1
- data/lib/objects/node/resources/inventory.rb +7 -5
- data/lib/objects/node/resources/merged.rb +38 -0
- data/lib/objects/node/resources/sub_inventory.rb +7 -4
- data/lib/objects/node/server/base.rb +88 -66
- data/lib/objects/node/server/dynamic/base.rb +23 -0
- data/lib/objects/node/server/{dynamic.rb → dynamic/ec2.rb} +14 -13
- data/lib/objects/node/server/dynamic/gcp.rb +47 -0
- data/lib/objects/node/server/static.rb +13 -2
- data/lib/objects/orchestration/base.rb +10 -0
- data/lib/objects/orchestration/interactive_terraform.rb +62 -27
- data/lib/objects/orchestrator.rb +22 -0
- data/lib/objects/parser/bread_crumb.rb +3 -1
- data/lib/objects/registry/arguments/base.rb +3 -1
- data/lib/objects/registry/arguments/command_line.rb +6 -1
- data/lib/objects/registry/arguments/console.rb +4 -1
- data/lib/objects/registry/command/base.rb +3 -0
- data/lib/objects/registry/command/external.rb +4 -2
- data/lib/objects/registry/command/group.rb +6 -3
- data/lib/objects/registry/command/internal.rb +3 -1
- data/lib/objects/registry/command/shortcut.rb +17 -9
- data/lib/objects/registry/command_list.rb +2 -0
- data/lib/objects/registry/loader.rb +10 -10
- data/lib/objects/ssh/bootstrap.rb +3 -1
- data/lib/objects/ssh/command.rb +10 -5
- data/lib/objects/ssh/command_exec.rb +13 -9
- data/lib/objects/ssh/connection_wrangler.rb +105 -0
- data/lib/objects/ssh/connector.rb +100 -0
- data/lib/objects/ssh/driver.rb +27 -230
- data/lib/objects/ssh/driver_concerns/command_strings.rb +17 -0
- data/lib/objects/ssh/driver_concerns/connection.rb +78 -0
- data/lib/objects/ssh/driver_concerns/functions.rb +89 -0
- data/lib/objects/ssh/driver_concerns/user.rb +32 -0
- data/lib/objects/ssh/{proxy_data.rb → proxy_hop.rb} +52 -7
- data/lib/objects/ssh/script_exec.rb +4 -1
- data/lib/objects/ssh/tunnel/local_port_forward.rb +5 -6
- data/lib/objects/ssh/tunnel_keeper.rb +21 -0
- data/lib/objects/ssh/window.rb +31 -0
- data/lib/objects/startup.rb +52 -0
- data/lib/objects/system/local.rb +3 -0
- data/lib/objects/terraform/output.rb +41 -0
- data/lib/objects/workspace.rb +3 -14
- data/patches/irb.rb +27 -3
- data/patches/string-encrypt.rb +20 -23
- data/patches/string.rb +5 -1
- data/patches/string_stylesheet.rb +2 -0
- metadata +95 -18
- data/lib/objects/progress_bar.rb +0 -30
- data/lib/objects/ssh/connection_handler.rb +0 -101
- data/lib/objects/terraform/parser.rb +0 -23
- data/lib/objects/terraform/state.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ace465761e84db321e1de7eea860a3ade94ecda5d5e091e8784740b1cb07ea4
|
4
|
+
data.tar.gz: 996329541843570edfef238c8a1dd46830402fd04586530b66810478b303b59c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db096f8fdde0c83e57519c5d09089d3d8e2bf26a4e4f07c675cf18aafb42a279ca7788114378dd7737e84f4279bbc09e141a1612669de6bea792370bd419fffd
|
7
|
+
data.tar.gz: 4ed639e3378da6b8cefef9727c640d8462ff3fe01f35f63d30b28ef4cd3c50c8975cf7226f4b74f789068223238e860dd7f8300cc4861b18f25b6dec4149b9a7
|
data/bin/bcome
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'bcome'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
::Bcome::Bootup.set_and_do({ breadcrumbs: ARGV[0], arguments: arguments }, spawn_into_console)
|
6
|
+
breadcrumbs = ARGV[0]
|
7
|
+
arguments = ARGV - [ARGV[0]]
|
8
|
+
handler = ::Bcome::Startup.new(breadcrumbs, arguments)
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
trap('SIGINT') do
|
11
|
+
handler.stop_loading_bars
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
trap('INT') do
|
15
|
+
handler.stop_loading_bars
|
15
16
|
end
|
17
|
+
|
18
|
+
Thread.report_on_exception = false
|
19
|
+
|
20
|
+
handler.do
|
data/lib/bcome.rb
CHANGED
@@ -1,17 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'irb'
|
2
|
-
require 'irb/completion'
|
3
|
-
require 'rainbow'
|
4
|
-
require 'net/scp'
|
5
|
-
require 'net/ssh/proxy/command'
|
6
|
-
require 'fog/aws'
|
7
|
-
require 'require_all'
|
8
|
-
require 'pmap'
|
9
|
-
require 'singleton'
|
10
4
|
require 'active_support'
|
11
5
|
require 'active_support/core_ext'
|
12
|
-
require '
|
13
|
-
require '
|
14
|
-
require '
|
6
|
+
require 'pmap'
|
7
|
+
require 'singleton'
|
8
|
+
require 'require_all'
|
9
|
+
require 'tty-cursor'
|
10
|
+
require 'pry'
|
15
11
|
|
16
12
|
require_all "#{File.dirname(__FILE__)}/../patches"
|
17
13
|
require_all "#{File.dirname(__FILE__)}/../lib/objects"
|
@@ -1,3 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bcome
|
2
|
-
|
4
|
+
module Version
|
5
|
+
def self.name
|
6
|
+
'bcome'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.release
|
10
|
+
'1.4.0'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.release_name
|
14
|
+
'multicloud'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.display
|
18
|
+
"#{name} #{release} #{release_name}"
|
19
|
+
end
|
20
|
+
end
|
3
21
|
end
|
data/lib/objects/bootup.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bcome
|
2
4
|
class Bootup
|
3
5
|
def self.set_and_do(params, spawn_into_console = true)
|
4
6
|
instance.set(params, spawn_into_console)
|
5
7
|
instance.do
|
6
|
-
rescue Bcome::Exception::Base => e
|
7
|
-
puts e.pretty_display
|
8
|
-
rescue Excon::Error::Socket => e
|
9
|
-
puts "\nNo network access - please check your connection and try again\n".red
|
10
8
|
end
|
11
9
|
|
12
10
|
def self.traverse(breadcrumbs = nil, _spawn_into_console = false)
|
@@ -31,6 +29,7 @@ module Bcome
|
|
31
29
|
|
32
30
|
def init_context(context)
|
33
31
|
if @spawn_into_console
|
32
|
+
puts "\n\n"
|
34
33
|
::Bcome::Workspace.instance.set(context: context)
|
35
34
|
else
|
36
35
|
context
|
@@ -55,7 +54,6 @@ module Bcome
|
|
55
54
|
end
|
56
55
|
starting_context = next_context
|
57
56
|
end
|
58
|
-
|
59
57
|
# Set our workspace to our last context - we're not invoking a method call and so we're entering a console session
|
60
58
|
init_context(starting_context)
|
61
59
|
end
|
@@ -64,6 +62,16 @@ module Bcome
|
|
64
62
|
@estate ||= ::Bcome::Node::Factory.instance.init_tree
|
65
63
|
end
|
66
64
|
|
65
|
+
def estate_loaded?
|
66
|
+
!@estate.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
def close_ssh_connections
|
70
|
+
return unless estate_loaded?
|
71
|
+
|
72
|
+
estate.close_ssh_connections
|
73
|
+
end
|
74
|
+
|
67
75
|
def parser
|
68
76
|
::Bcome::Parser::BreadCrumb.new(@breadcrumbs)
|
69
77
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Bcome::ConfigFactory
|
2
4
|
attr_reader :tree
|
3
5
|
|
@@ -31,6 +33,7 @@ class Bcome::ConfigFactory
|
|
31
33
|
|
32
34
|
def hash_for_identifier_from_view(identifier, views)
|
33
35
|
raise Bcome::Exception::InventoriesCannotHaveSubViews, 'Inventories cannot hold other inventories - invalid network config' unless views.key?(:views)
|
36
|
+
|
34
37
|
views[:views].select { |v| v[:identifier].to_s == identifier.to_s }.first
|
35
38
|
end
|
36
39
|
end
|
data/lib/objects/driver/base.rb
CHANGED
@@ -1,26 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bcome::Driver
|
2
4
|
class Base
|
3
5
|
class << self
|
4
|
-
def create_from_config(config)
|
6
|
+
def create_from_config(config, node)
|
5
7
|
raise Bcome::Exception::InvalidNetworkDriverType, 'Your network configurtion is invalid' unless config.is_a?(Hash)
|
6
8
|
raise Bcome::Exception::InvalidNetworkDriverType, "Missing config parameter 'type'" unless config[:type]
|
9
|
+
|
7
10
|
config_klass_key = config[:type].to_sym
|
8
11
|
driver_klass = klass_for_type[config_klass_key]
|
9
12
|
raise Bcome::Exception::InvalidNetworkDriverType, config unless driver_klass
|
10
|
-
|
13
|
+
|
14
|
+
driver = driver_klass.new(config, node)
|
11
15
|
driver
|
12
16
|
end
|
13
17
|
|
14
18
|
def klass_for_type
|
15
19
|
{
|
16
20
|
static: ::Bcome::Driver::Static,
|
17
|
-
ec2: ::Bcome::Driver::Ec2
|
21
|
+
ec2: ::Bcome::Driver::Ec2,
|
22
|
+
gcp: ::Bcome::Driver::Gcp
|
18
23
|
}
|
19
24
|
end
|
20
25
|
end
|
21
26
|
|
22
|
-
|
27
|
+
include ::Bcome::LoadingBar::Handler
|
28
|
+
|
29
|
+
def initialize(params, node)
|
23
30
|
@params = params
|
31
|
+
@node = node
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_network_credentials?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def loader_title
|
39
|
+
'Loading' + "\s#{pretty_provider_name.bc_blue.bold}\s#{pretty_resource_location.underline}".bc_green
|
40
|
+
end
|
41
|
+
|
42
|
+
def loader_completed_title
|
43
|
+
'done'
|
44
|
+
end
|
45
|
+
|
46
|
+
def pretty_provider_name
|
47
|
+
raise 'Should be overriden'
|
48
|
+
end
|
49
|
+
|
50
|
+
def pretty_resource_location
|
51
|
+
raise 'Should be overidden'
|
52
|
+
end
|
53
|
+
|
54
|
+
def network_credentials
|
55
|
+
raise 'Should be overidden'
|
24
56
|
end
|
25
57
|
|
26
58
|
def config
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Bcome::Driver
|
2
4
|
class Bucket
|
3
5
|
include Singleton
|
@@ -6,13 +8,13 @@ module Bcome::Driver
|
|
6
8
|
@drivers = []
|
7
9
|
end
|
8
10
|
|
9
|
-
def driver_for_network_data(network_data)
|
11
|
+
def driver_for_network_data(network_data, node)
|
10
12
|
found_driver = @drivers.select { |driver| driver.config == network_data }.first
|
11
|
-
found_driver
|
13
|
+
found_driver || create_network_driver(network_data, node)
|
12
14
|
end
|
13
15
|
|
14
|
-
def create_network_driver(network_data)
|
15
|
-
driver = ::Bcome::Driver::Base.create_from_config(network_data)
|
16
|
+
def create_network_driver(network_data, node)
|
17
|
+
driver = ::Bcome::Driver::Base.create_from_config(network_data, node)
|
16
18
|
@drivers << driver
|
17
19
|
driver
|
18
20
|
end
|
data/lib/objects/driver/ec2.rb
CHANGED
@@ -1,20 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fog/aws'
|
4
|
+
|
1
5
|
module Bcome::Driver
|
2
6
|
class Ec2 < Bcome::Driver::Base
|
3
|
-
|
4
|
-
PATH_TO_FOG_CREDENTIALS = "#{ENV['HOME']}/.fog".freeze
|
7
|
+
PATH_TO_FOG_CREDENTIALS = "#{ENV['HOME']}/.fog"
|
5
8
|
|
6
9
|
def initialize(*params)
|
7
10
|
super
|
8
11
|
raise Bcome::Exception::Ec2DriverMissingProvisioningRegion, params.inspect unless provisioning_region
|
9
12
|
end
|
10
13
|
|
14
|
+
def pretty_provider_name
|
15
|
+
'EC2'
|
16
|
+
end
|
17
|
+
|
18
|
+
def pretty_resource_location
|
19
|
+
@node.network_data[:provisioning_region]
|
20
|
+
end
|
21
|
+
|
11
22
|
def fog_client
|
12
23
|
@fog_client ||= get_fog_client
|
13
24
|
end
|
14
25
|
|
15
26
|
def fetch_server_list(filters)
|
16
|
-
|
17
|
-
|
27
|
+
wrap_indicator type: :basic, title: loader_title, completed_title: loader_completed_title do
|
28
|
+
begin
|
29
|
+
@servers = unfiltered_server_list.all(filters)
|
30
|
+
signal_success
|
31
|
+
rescue Exception => e
|
32
|
+
signal_failure
|
33
|
+
raise e
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
@servers
|
18
38
|
end
|
19
39
|
|
20
40
|
def unfiltered_server_list
|
@@ -25,6 +45,17 @@ module Bcome::Driver
|
|
25
45
|
fog_client.servers.all({})
|
26
46
|
end
|
27
47
|
|
48
|
+
def has_network_credentials?
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def network_credentials
|
53
|
+
{
|
54
|
+
access_key: raw_fog_credentials['aws_access_key_id'],
|
55
|
+
secret_key: raw_fog_credentials['aws_secret_access_key']
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
28
59
|
def raw_fog_credentials
|
29
60
|
@raw_fog_credentials ||= YAML.load_file(PATH_TO_FOG_CREDENTIALS)[credentials_key]
|
30
61
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'google/apis/compute_beta'
|
4
|
+
|
5
|
+
module Bcome::Driver
|
6
|
+
class Gcp < Bcome::Driver::Base
|
7
|
+
APPLICATION_NAME = 'Bcome console'
|
8
|
+
|
9
|
+
def initialize(*params)
|
10
|
+
super
|
11
|
+
validate_service_scopes
|
12
|
+
validate_authentication_scheme
|
13
|
+
end
|
14
|
+
|
15
|
+
def pretty_provider_name
|
16
|
+
'GCP'
|
17
|
+
end
|
18
|
+
|
19
|
+
def pretty_resource_location
|
20
|
+
"#{@params[:project]}/#{@params[:zone]}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch_server_list(_filters)
|
24
|
+
unless authentication_scheme.authorized?
|
25
|
+
get_authenticated_gcp_service
|
26
|
+
raise ::Bcome::Exception::Generic, 'GCP authentication process failed' unless authentication_scheme.authorized?
|
27
|
+
end
|
28
|
+
|
29
|
+
wrap_indicator type: :basic, title: loader_title, completed_title: loader_completed_title do
|
30
|
+
begin
|
31
|
+
@instances = do_fetch_server_list(_filters)
|
32
|
+
signal_success
|
33
|
+
rescue Exception => e
|
34
|
+
signal_failure
|
35
|
+
raise e
|
36
|
+
end
|
37
|
+
end
|
38
|
+
@instances.items
|
39
|
+
end
|
40
|
+
|
41
|
+
def do_fetch_server_list(_filters)
|
42
|
+
gcp_service.list_instances(@params[:project], @params[:zone])
|
43
|
+
rescue Google::Apis::AuthorizationError
|
44
|
+
raise ::Bcome::Exception::CannotAuthenticateToGcp
|
45
|
+
rescue Google::Apis::ClientError => e
|
46
|
+
raise ::Bcome::Exception::Generic, "Namespace #{@node.namespace} / #{e.message}"
|
47
|
+
rescue Google::Apis::TransmissionError => e
|
48
|
+
raise ::Bcome::Exception::Generic, 'Cannot reach GCP - do you have an internet connection?'
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_network_credentials?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def network_credentials
|
56
|
+
{
|
57
|
+
access_token: access_token,
|
58
|
+
project_name: @params[:project]
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def validate_authentication_scheme
|
65
|
+
raise ::Bcome::Exception::MissingGcpAuthenticationScheme, "node #{@node.namespace}" if @params[:authentication_scheme].nil? || @params[:authentication_scheme].empty?
|
66
|
+
raise ::Bcome::Exception::InvalidGcpAuthenticationScheme, "Invalid GCP authentication scheme '#{@params[:authentication_scheme]}' for node #{@node.namespace}" unless auth_scheme
|
67
|
+
end
|
68
|
+
|
69
|
+
def invalid_auth_scheme?
|
70
|
+
!auth_schemes.keys.include?(@params[:authentication_scheme].to_sym)
|
71
|
+
end
|
72
|
+
|
73
|
+
def auth_scheme
|
74
|
+
auth_schemes[@params[:authentication_scheme].to_sym]
|
75
|
+
end
|
76
|
+
|
77
|
+
def auth_schemes
|
78
|
+
{
|
79
|
+
oauth: ::Bcome::Driver::Gcp::Authentication::Oauth,
|
80
|
+
serviceaccount: ::Bcome::Driver::Gcp::Authentication::ServiceAccount,
|
81
|
+
api_key: ::Bcome::Driver::Gcp::Authentication::ApiKey
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def compute_service
|
86
|
+
@compute_service ||= ::Google::Apis::ComputeBeta::ComputeService.new
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_authenticated_gcp_service
|
90
|
+
authentication_scheme.do!
|
91
|
+
compute_service
|
92
|
+
end
|
93
|
+
|
94
|
+
def authentication_scheme
|
95
|
+
# Service scopes are specified directly from the network config
|
96
|
+
# A minumum scope of https://www.googleapis.com/auth/compute.readonly is required in order to list resources.
|
97
|
+
@authentication_scheme ||= auth_scheme.new(self, compute_service, service_scopes, @node, @params[:secrets_path])
|
98
|
+
end
|
99
|
+
|
100
|
+
def gcp_service
|
101
|
+
@gcp_service ||= get_authenticated_gcp_service
|
102
|
+
end
|
103
|
+
|
104
|
+
def access_token
|
105
|
+
gcp_service.authorization.access_token
|
106
|
+
end
|
107
|
+
|
108
|
+
def authorization
|
109
|
+
gcp_service.authorization
|
110
|
+
end
|
111
|
+
|
112
|
+
def service_scopes
|
113
|
+
@params[:service_scopes]
|
114
|
+
end
|
115
|
+
|
116
|
+
def validate_service_scopes
|
117
|
+
raise ::Bcome::Exception::MissingGcpServiceScopes, 'Please define as minimum https://www.googleapis.com/auth/compute.readonly' unless has_service_scopes_defined?
|
118
|
+
end
|
119
|
+
|
120
|
+
def has_service_scopes_defined?
|
121
|
+
service_scopes&.any?
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'google/api_client/auth/storage'
|
4
|
+
require 'google/api_client/auth/storages/file_store'
|
5
|
+
require 'google/api_client/client_secrets'
|
6
|
+
|
7
|
+
module Bcome::Driver::Gcp::Authentication
|
8
|
+
class Oauth
|
9
|
+
credential_directory = '.gauth'
|
10
|
+
credential_file_suffix = 'oauth2.json'
|
11
|
+
|
12
|
+
include ::Bcome::LoadingBar::Handler
|
13
|
+
|
14
|
+
def initialize(driver, service, scopes, node, path_to_secrets)
|
15
|
+
@service = service
|
16
|
+
@scopes = scopes
|
17
|
+
@node = node
|
18
|
+
@driver = driver
|
19
|
+
|
20
|
+
@path_to_secrets = "#{credential_directory}/#{path_to_secrets}"
|
21
|
+
# All credentials are held in .gauth
|
22
|
+
ensure_credential_directory
|
23
|
+
end
|
24
|
+
|
25
|
+
def authorized?
|
26
|
+
storage && !@storage.authorization.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
def storage
|
30
|
+
@storage ||= ::Google::APIClient::Storage.new(Google::APIClient::FileStore.new(full_path_to_credential_file))
|
31
|
+
end
|
32
|
+
|
33
|
+
def credential_directory
|
34
|
+
'.gauth'
|
35
|
+
end
|
36
|
+
|
37
|
+
def credential_file_suffix
|
38
|
+
'oauth2.json'
|
39
|
+
end
|
40
|
+
|
41
|
+
def full_path_to_credential_file
|
42
|
+
"#{credential_directory}/#{credential_file}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def credential_file
|
46
|
+
"#{@node.keyed_namespace}:#{credential_file_suffix}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def authorize!
|
50
|
+
@service.authorization = storage.authorize
|
51
|
+
end
|
52
|
+
|
53
|
+
def client_secrets
|
54
|
+
@client_secrets ||= load_client_secrets
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_client_secrets
|
58
|
+
::Google::APIClient::ClientSecrets.load(@path_to_secrets)
|
59
|
+
rescue Exception => e
|
60
|
+
raise ::Bcome::Exception::MissingOrInvalidClientSecrets, "#{@path_to_secrets}. Gcp exception: #{e.class} #{e.message}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def loader_title
|
64
|
+
'Authenticating' + "\s#{@driver.pretty_provider_name.bc_blue.bold}\s#{@driver.pretty_resource_location.underline}".bc_green
|
65
|
+
end
|
66
|
+
|
67
|
+
def do!
|
68
|
+
authorize!
|
69
|
+
if @storage.authorization.nil?
|
70
|
+
# Total bloat from google here. Thanks google... requiring at last possible moment.
|
71
|
+
require 'google/api_client/auth/installed_app'
|
72
|
+
|
73
|
+
wrap_indicator type: :basic, title: loader_title, completed_title: '' do
|
74
|
+
flow = Google::APIClient::InstalledAppFlow.new(
|
75
|
+
client_id: client_secrets.client_id,
|
76
|
+
client_secret: client_secrets.client_secret,
|
77
|
+
scope: @scopes
|
78
|
+
)
|
79
|
+
|
80
|
+
begin
|
81
|
+
@service.authorization = flow.authorize(storage)
|
82
|
+
signal_success
|
83
|
+
rescue ArgumentError => e
|
84
|
+
signal_failure
|
85
|
+
raise ::Bcome::Exception::MissingOrInvalidClientSecrets, "#{@path_to_secrets}. Gcp exception: #{e.class} #{e.message}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
@service
|
91
|
+
end
|
92
|
+
|
93
|
+
def notify_success
|
94
|
+
print "[\s" + "Credentials file written to\s" + full_path_to_credential_file + "\s]" + "\n"
|
95
|
+
end
|
96
|
+
|
97
|
+
def ensure_credential_directory
|
98
|
+
`mkdir -p #{credential_directory}`
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|