console_kit 1.2.0 → 1.3.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/.DS_Store +0 -0
- data/.reek.yml.new +0 -0
- data/lib/console_kit/configuration.rb +3 -2
- data/lib/console_kit/connections/base_connection_handler.rb +4 -10
- data/lib/console_kit/connections/elasticsearch_connection_handler.rb +39 -27
- data/lib/console_kit/connections/mongo_connection_handler.rb +38 -22
- data/lib/console_kit/connections/redis_connection_handler.rb +34 -35
- data/lib/console_kit/connections/sql_connection_handler.rb +27 -23
- data/lib/console_kit/console_helpers.rb +35 -18
- data/lib/console_kit/output.rb +13 -4
- data/lib/console_kit/prompt.rb +3 -5
- data/lib/console_kit/setup.rb +5 -84
- data/lib/console_kit/tenant_configurator/context_wrapper.rb +79 -0
- data/lib/console_kit/tenant_configurator.rb +63 -59
- data/lib/console_kit/tenant_orchestrator.rb +108 -0
- data/lib/console_kit/version.rb +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 348d99d0b8d74a78d96ffa4e74f7ee2baf25aab659700b5d44929d2e3cd87104
|
|
4
|
+
data.tar.gz: 9c5e7514f498818e2ffe8b0a9376511cbf364e81336a266df7fe02d143a26cf4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5e56f04db89485e9b0a3a23b667062a8998287a8ab9ad67dc793f3202730ba6f54dcf02f45ab65ff739e3aef23ec7c65574ba32c4aafe7cebc1a6dcff63c907f
|
|
7
|
+
data.tar.gz: 86d6d4457bb2ad62e8ac2ecdd22c3afc0fa72313f4625cf4b304bbd1f0436a67033e0a2c4190d995895b12aba4aef77c68465ffa1fe1dcf6815d93909f355394
|
data/.DS_Store
ADDED
|
Binary file
|
data/.reek.yml.new
ADDED
|
File without changes
|
|
@@ -39,8 +39,9 @@ module ConsoleKit
|
|
|
39
39
|
private
|
|
40
40
|
|
|
41
41
|
def resolve_context_class(val)
|
|
42
|
-
val.to_s.
|
|
43
|
-
|
|
42
|
+
klass = val.to_s.safe_constantize
|
|
43
|
+
return klass if klass
|
|
44
|
+
|
|
44
45
|
raise Error, "ConsoleKit: context_class '#{val}' could not be found. " \
|
|
45
46
|
'Ensure the class is defined before configuration is accessed.'
|
|
46
47
|
end
|
|
@@ -29,7 +29,6 @@ module ConsoleKit
|
|
|
29
29
|
if thread.join(timeout)
|
|
30
30
|
result_wrapper[:value] || error_diagnostics(handler_name, StandardError.new('Unknown error'))
|
|
31
31
|
else
|
|
32
|
-
thread.kill
|
|
33
32
|
timeout_diagnostics(handler_name, timeout)
|
|
34
33
|
end
|
|
35
34
|
end
|
|
@@ -38,29 +37,24 @@ module ConsoleKit
|
|
|
38
37
|
|
|
39
38
|
def spawn_diagnostic_thread(handler_name)
|
|
40
39
|
wrapper = { value: nil }
|
|
41
|
-
thread = Thread.new { wrapper[:value] = run_diagnostics_safely(handler_name) }
|
|
40
|
+
thread = Thread.new { wrapper[:value] = run_diagnostics_safely(handler_name) { diagnostics } }
|
|
42
41
|
[thread, wrapper]
|
|
43
42
|
end
|
|
44
43
|
|
|
45
44
|
def run_diagnostics_safely(name)
|
|
46
|
-
|
|
45
|
+
yield
|
|
47
46
|
rescue StandardError => e
|
|
48
47
|
error_diagnostics(name, e)
|
|
49
48
|
end
|
|
50
49
|
|
|
51
|
-
def context_attribute(name)
|
|
52
|
-
@context.respond_to?(name, true) ? @context.send(name) : nil
|
|
53
|
-
end
|
|
54
|
-
|
|
55
50
|
def measure_latency
|
|
56
51
|
start = clock_time
|
|
57
52
|
yield
|
|
58
53
|
((clock_time - start) * 1000).round(1)
|
|
59
54
|
end
|
|
60
55
|
|
|
61
|
-
def
|
|
62
|
-
|
|
63
|
-
end
|
|
56
|
+
def context_attribute(name) = @context.try(name)
|
|
57
|
+
def unavailable_diagnostics(name) = { name: name, status: :unavailable, latency_ms: nil, details: {} }
|
|
64
58
|
end
|
|
65
59
|
end
|
|
66
60
|
end
|
|
@@ -6,54 +6,66 @@ module ConsoleKit
|
|
|
6
6
|
module Connections
|
|
7
7
|
# Handles Elasticsearch connections
|
|
8
8
|
class ElasticsearchConnectionHandler < BaseConnectionHandler
|
|
9
|
+
class << self
|
|
10
|
+
def elasticsearch_available?
|
|
11
|
+
return false unless defined?(Elasticsearch::Model)
|
|
12
|
+
|
|
13
|
+
Elasticsearch::Model.method(:client)
|
|
14
|
+
true
|
|
15
|
+
rescue NameError
|
|
16
|
+
false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def apply_prefix(prefix)
|
|
20
|
+
return unless defined?(Elasticsearch::Model)
|
|
21
|
+
|
|
22
|
+
Elasticsearch::Model.try(:index_name_prefix=, prefix)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
9
26
|
def connect
|
|
10
27
|
prefix = context_attribute(:tenant_elasticsearch_prefix).presence
|
|
11
28
|
Output.print_info(switch_message(prefix))
|
|
12
29
|
Thread.current[:console_kit_elasticsearch_prefix] = prefix
|
|
13
|
-
|
|
30
|
+
self.class.apply_prefix(prefix)
|
|
14
31
|
end
|
|
15
32
|
|
|
16
|
-
def available?
|
|
17
|
-
!!(defined?(Elasticsearch::Model) && Elasticsearch::Model.respond_to?(:client))
|
|
18
|
-
end
|
|
33
|
+
def available? = self.class.elasticsearch_available?
|
|
19
34
|
|
|
20
35
|
def diagnostics
|
|
21
|
-
|
|
22
|
-
return unavailable_diagnostics(name) unless available?
|
|
36
|
+
return unavailable_diagnostics('Elasticsearch') unless available?
|
|
23
37
|
|
|
24
|
-
|
|
25
|
-
latency = measure_latency { client.ping }
|
|
26
|
-
build_elasticsearch_diagnostics(client, latency)
|
|
38
|
+
perform_diagnostics
|
|
27
39
|
rescue StandardError => e
|
|
28
|
-
error_diagnostics(
|
|
40
|
+
error_diagnostics('Elasticsearch', e)
|
|
29
41
|
end
|
|
30
42
|
|
|
31
43
|
private
|
|
32
44
|
|
|
33
|
-
def
|
|
45
|
+
def perform_diagnostics
|
|
46
|
+
client = Elasticsearch::Model.client
|
|
47
|
+
latency = measure_latency do
|
|
48
|
+
client.ping
|
|
49
|
+
rescue StandardError
|
|
50
|
+
nil
|
|
51
|
+
end
|
|
52
|
+
health = client.cluster.health
|
|
53
|
+
build_elasticsearch_diagnostics(health['cluster_name'], health['status'], latency)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def build_elasticsearch_diagnostics(cluster, status, latency)
|
|
34
57
|
{
|
|
35
58
|
name: 'Elasticsearch',
|
|
36
59
|
status: :connected,
|
|
37
60
|
latency_ms: latency,
|
|
38
|
-
details:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
prefix: context_attribute(:tenant_elasticsearch_prefix),
|
|
45
|
-
cluster: health['cluster_name'],
|
|
46
|
-
health: health['status']
|
|
61
|
+
details: {
|
|
62
|
+
prefix: context_attribute(:tenant_elasticsearch_prefix),
|
|
63
|
+
cluster: cluster,
|
|
64
|
+
health: status
|
|
65
|
+
}
|
|
47
66
|
}
|
|
48
67
|
end
|
|
49
68
|
|
|
50
|
-
def apply_model_index_prefix(prefix)
|
|
51
|
-
return unless defined?(Elasticsearch::Model)
|
|
52
|
-
return unless Elasticsearch::Model.respond_to?(:index_name_prefix=)
|
|
53
|
-
|
|
54
|
-
Elasticsearch::Model.index_name_prefix = prefix
|
|
55
|
-
end
|
|
56
|
-
|
|
57
69
|
def switch_message(prefix)
|
|
58
70
|
prefix ? "Setting Elasticsearch index prefix: #{prefix}" : 'Resetting Elasticsearch index prefix to default'
|
|
59
71
|
end
|
|
@@ -8,51 +8,67 @@ module ConsoleKit
|
|
|
8
8
|
class MongoConnectionHandler < BaseConnectionHandler
|
|
9
9
|
def connect
|
|
10
10
|
db = context_attribute(:tenant_mongo_db).presence
|
|
11
|
-
|
|
12
|
-
Mongoid.override_database(db)
|
|
11
|
+
switch_mongo(db)
|
|
13
12
|
rescue NoMethodError
|
|
14
|
-
Output.print_warning('Mongoid
|
|
13
|
+
Output.print_warning('Mongoid client override is not available in this version of Mongoid.')
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
def available? = defined?(Mongoid)
|
|
18
17
|
|
|
19
18
|
def diagnostics
|
|
20
|
-
|
|
21
|
-
return unavailable_diagnostics(name) unless available?
|
|
19
|
+
return unavailable_diagnostics('MongoDB') unless available?
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
latency = measure_latency { db.command(ping: 1) }
|
|
25
|
-
build_mongo_diagnostics(db, latency)
|
|
21
|
+
perform_diagnostics
|
|
26
22
|
rescue StandardError => e
|
|
27
|
-
error_diagnostics(
|
|
23
|
+
error_diagnostics('MongoDB', e)
|
|
28
24
|
end
|
|
29
25
|
|
|
30
26
|
private
|
|
31
27
|
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
client.use(override).database
|
|
28
|
+
def perform_diagnostics
|
|
29
|
+
db = tenant_database
|
|
30
|
+
latency = measure_latency { db.command(ping: 1) }
|
|
31
|
+
info = db.command(buildInfo: 1).first
|
|
32
|
+
build_mongo_diagnostics(db.name, info['version'], latency)
|
|
38
33
|
end
|
|
39
34
|
|
|
40
|
-
def build_mongo_diagnostics(
|
|
41
|
-
build_info = database.command(buildInfo: 1).first
|
|
35
|
+
def build_mongo_diagnostics(name, version, latency)
|
|
42
36
|
{
|
|
43
37
|
name: 'MongoDB',
|
|
44
38
|
status: :connected,
|
|
45
39
|
latency_ms: latency,
|
|
46
|
-
details:
|
|
40
|
+
details: { database: name, version: version }
|
|
47
41
|
}
|
|
48
42
|
end
|
|
49
43
|
|
|
50
|
-
def
|
|
51
|
-
|
|
44
|
+
def tenant_database
|
|
45
|
+
override = context_attribute(:tenant_mongo_db).presence
|
|
46
|
+
client = Mongoid.default_client
|
|
47
|
+
(override ? client.use(override) : client).database
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def switch_mongo(db)
|
|
51
|
+
if db.nil?
|
|
52
|
+
Output.print_info('Resetting MongoDB client to default')
|
|
53
|
+
reset_overrides
|
|
54
|
+
elsif named_client?(db)
|
|
55
|
+
Output.print_info("Switching to MongoDB client: #{db}")
|
|
56
|
+
Mongoid.override_client(db)
|
|
57
|
+
else
|
|
58
|
+
Output.print_info("Switching to MongoDB database: #{db}")
|
|
59
|
+
Mongoid.override_database(db)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def reset_overrides
|
|
64
|
+
Mongoid.override_client(nil) if Mongoid.respond_to?(:override_client)
|
|
65
|
+
Mongoid.override_database(nil)
|
|
52
66
|
end
|
|
53
67
|
|
|
54
|
-
def
|
|
55
|
-
|
|
68
|
+
def named_client?(name)
|
|
69
|
+
Mongoid::Config.clients.key?(name.to_s)
|
|
70
|
+
rescue StandardError
|
|
71
|
+
false
|
|
56
72
|
end
|
|
57
73
|
end
|
|
58
74
|
end
|
|
@@ -8,68 +8,67 @@ module ConsoleKit
|
|
|
8
8
|
class RedisConnectionHandler < BaseConnectionHandler
|
|
9
9
|
DEFAULT_REDIS_DB = 0
|
|
10
10
|
|
|
11
|
+
class << self
|
|
12
|
+
def redis_client = Redis.try(:current)
|
|
13
|
+
|
|
14
|
+
def warn_no_auto_select(db_index)
|
|
15
|
+
Output.print_warning("Redis DB #{db_index} configured but auto-select not supported with RedisClient. " \
|
|
16
|
+
'Ensure your Redis configuration sets the correct DB.')
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
11
20
|
def connect
|
|
12
|
-
|
|
13
|
-
Output.print_info(switch_message(
|
|
14
|
-
select_redis_db(
|
|
21
|
+
db_index = context_attribute(:tenant_redis_db) || DEFAULT_REDIS_DB
|
|
22
|
+
Output.print_info(switch_message(db_index))
|
|
23
|
+
select_redis_db(db_index)
|
|
15
24
|
end
|
|
16
25
|
|
|
17
26
|
def available? = defined?(Redis)
|
|
18
27
|
|
|
19
28
|
def diagnostics
|
|
20
|
-
|
|
21
|
-
return unavailable_diagnostics(
|
|
29
|
+
redis = self.class.redis_client if available?
|
|
30
|
+
return unavailable_diagnostics('Redis') unless redis
|
|
22
31
|
|
|
23
|
-
redis
|
|
24
|
-
return unavailable_diagnostics(name) unless redis
|
|
25
|
-
|
|
26
|
-
latency = measure_latency { redis.ping }
|
|
27
|
-
build_redis_diagnostics(redis.info, latency)
|
|
32
|
+
perform_diagnostics(redis)
|
|
28
33
|
rescue StandardError => e
|
|
29
|
-
error_diagnostics(
|
|
34
|
+
error_diagnostics('Redis', e)
|
|
30
35
|
end
|
|
31
36
|
|
|
32
37
|
private
|
|
33
38
|
|
|
34
|
-
def
|
|
35
|
-
|
|
39
|
+
def perform_diagnostics(redis)
|
|
40
|
+
latency = measure_latency { redis.ping }
|
|
41
|
+
info = redis.info
|
|
42
|
+
build_redis_diagnostics(info['redis_version'], info['used_memory_human'], latency)
|
|
36
43
|
end
|
|
37
44
|
|
|
38
|
-
def build_redis_diagnostics(
|
|
45
|
+
def build_redis_diagnostics(version, memory, latency)
|
|
39
46
|
{
|
|
40
47
|
name: 'Redis',
|
|
41
48
|
status: :connected,
|
|
42
49
|
latency_ms: latency,
|
|
43
|
-
details:
|
|
50
|
+
details: {
|
|
51
|
+
db: context_attribute(:tenant_redis_db) || DEFAULT_REDIS_DB,
|
|
52
|
+
version: version,
|
|
53
|
+
memory: memory
|
|
54
|
+
}
|
|
44
55
|
}
|
|
45
56
|
end
|
|
46
57
|
|
|
47
|
-
def
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
version: info['redis_version'],
|
|
51
|
-
memory: info['used_memory_human']
|
|
52
|
-
}
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def select_redis_db(db)
|
|
56
|
-
redis = fetch_redis_client
|
|
58
|
+
def select_redis_db(db_index)
|
|
59
|
+
klass = self.class
|
|
60
|
+
redis = klass.redis_client
|
|
57
61
|
if redis
|
|
58
|
-
redis.select(
|
|
59
|
-
elsif defined?(RedisClient) &&
|
|
60
|
-
|
|
62
|
+
redis.select(db_index)
|
|
63
|
+
elsif defined?(RedisClient) && db_index != DEFAULT_REDIS_DB
|
|
64
|
+
klass.warn_no_auto_select(db_index)
|
|
61
65
|
end
|
|
62
66
|
rescue NoMethodError
|
|
63
67
|
Output.print_warning('Redis.current is not available (deprecated in Redis v5+).')
|
|
64
68
|
end
|
|
65
69
|
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
'Ensure your Redis configuration sets the correct DB.')
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def switch_message(db)
|
|
72
|
-
db ? "Switching to Redis DB: #{db}" : 'Resetting Redis connection to default'
|
|
70
|
+
def switch_message(db_index)
|
|
71
|
+
db_index ? "Switching to Redis DB: #{db_index}" : 'Resetting Redis connection to default'
|
|
73
72
|
end
|
|
74
73
|
end
|
|
75
74
|
end
|
|
@@ -6,6 +6,16 @@ module ConsoleKit
|
|
|
6
6
|
module Connections
|
|
7
7
|
# Handles SQL connections
|
|
8
8
|
class SqlConnectionHandler < BaseConnectionHandler
|
|
9
|
+
class << self
|
|
10
|
+
def sql_version(conn)
|
|
11
|
+
conn.select_value('SELECT version()')
|
|
12
|
+
rescue StandardError
|
|
13
|
+
nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def base_class_name = ConsoleKit.configuration.sql_base_class
|
|
17
|
+
end
|
|
18
|
+
|
|
9
19
|
def connect
|
|
10
20
|
shard = context_attribute(:tenant_shard).presence&.to_sym
|
|
11
21
|
Output.print_info("#{connection_message(shard)} via #{base_class}")
|
|
@@ -13,25 +23,26 @@ module ConsoleKit
|
|
|
13
23
|
shard ? base_class.establish_connection(shard) : base_class.establish_connection
|
|
14
24
|
end
|
|
15
25
|
|
|
16
|
-
def available? =
|
|
26
|
+
def available? = self.class.base_class_name.to_s.safe_constantize.present?
|
|
17
27
|
|
|
18
28
|
def diagnostics
|
|
19
|
-
|
|
20
|
-
return unavailable_diagnostics(name) unless available?
|
|
29
|
+
return unavailable_diagnostics('SQL') unless available?
|
|
21
30
|
|
|
22
|
-
|
|
23
|
-
latency = measure_latency { conn.execute('SELECT 1') }
|
|
24
|
-
build_sql_diagnostics(conn, latency)
|
|
31
|
+
perform_diagnostics
|
|
25
32
|
rescue StandardError => e
|
|
26
|
-
error_diagnostics(
|
|
33
|
+
error_diagnostics('SQL', e)
|
|
27
34
|
end
|
|
28
35
|
|
|
29
36
|
private
|
|
30
37
|
|
|
31
|
-
def
|
|
32
|
-
|
|
38
|
+
def perform_diagnostics
|
|
39
|
+
conn = base_class.connection
|
|
40
|
+
latency = measure_latency { conn.execute('SELECT 1') }
|
|
41
|
+
build_sql_diagnostics(conn, latency)
|
|
42
|
+
end
|
|
33
43
|
|
|
34
|
-
|
|
44
|
+
def disconnect_existing_pool
|
|
45
|
+
pool = base_class.try(:connection_pool)
|
|
35
46
|
pool&.disconnect!
|
|
36
47
|
end
|
|
37
48
|
|
|
@@ -43,29 +54,22 @@ module ConsoleKit
|
|
|
43
54
|
details: {
|
|
44
55
|
adapter: conn.adapter_name,
|
|
45
56
|
pool_size: base_class.connection_pool.size,
|
|
46
|
-
version:
|
|
57
|
+
version: self.class.sql_version(conn).to_s.truncate(50)
|
|
47
58
|
}
|
|
48
59
|
}
|
|
49
60
|
end
|
|
50
61
|
|
|
51
|
-
def fetch_sql_version(conn)
|
|
52
|
-
conn.select_value('SELECT version()')
|
|
53
|
-
rescue StandardError
|
|
54
|
-
nil
|
|
55
|
-
end
|
|
56
|
-
|
|
57
62
|
def base_class
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
@base_class ||= begin
|
|
64
|
+
name = self.class.base_class_name
|
|
65
|
+
klass = name.to_s.safe_constantize
|
|
66
|
+
klass || raise(Error, "ConsoleKit: sql_base_class '#{name}' could not be found.")
|
|
67
|
+
end
|
|
62
68
|
end
|
|
63
69
|
|
|
64
70
|
def connection_message(shard)
|
|
65
71
|
shard ? "Establishing SQL connection to shard: #{shard}" : 'Resetting SQL connection to default'
|
|
66
72
|
end
|
|
67
|
-
|
|
68
|
-
def sql_base_class_name = ConsoleKit.configuration.sql_base_class
|
|
69
73
|
end
|
|
70
74
|
end
|
|
71
75
|
end
|
|
@@ -3,24 +3,27 @@
|
|
|
3
3
|
module ConsoleKit
|
|
4
4
|
# Helper methods available in the Rails console
|
|
5
5
|
module ConsoleHelpers
|
|
6
|
-
def switch_tenant
|
|
6
|
+
def switch_tenant
|
|
7
|
+
ConsoleKit.reset_current_tenant
|
|
8
|
+
self
|
|
9
|
+
end
|
|
7
10
|
|
|
8
11
|
def tenant_info
|
|
9
12
|
tenant = ConsoleKit::Setup.current_tenant
|
|
10
|
-
unless tenant
|
|
11
|
-
ConsoleKit::Output.print_warning('No tenant is currently configured.')
|
|
12
|
-
return
|
|
13
|
-
end
|
|
13
|
+
return no_tenant_warning unless tenant
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
display_tenant_info(tenant)
|
|
16
|
+
nil
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def dashboard
|
|
19
|
+
def dashboard
|
|
20
|
+
ConsoleKit::Connections::Dashboard.display
|
|
21
|
+
self
|
|
22
|
+
end
|
|
20
23
|
|
|
21
24
|
def tenants
|
|
22
25
|
names = ConsoleKit.configuration.tenants&.keys || []
|
|
23
|
-
|
|
26
|
+
print_available_tenants(names)
|
|
24
27
|
names
|
|
25
28
|
end
|
|
26
29
|
|
|
@@ -31,17 +34,31 @@ module ConsoleKit
|
|
|
31
34
|
|
|
32
35
|
private
|
|
33
36
|
|
|
34
|
-
def
|
|
35
|
-
ConsoleKit::Output.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
def no_tenant_warning
|
|
38
|
+
ConsoleKit::Output.print_warning('No tenant is currently configured.')
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def display_tenant_info(tenant)
|
|
43
|
+
constants = ConsoleKit.configuration.tenants[tenant]&.[](:constants) || {}
|
|
44
|
+
ConsoleHelpers.print_tenant_details(tenant, constants)
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def print_available_tenants(names)
|
|
49
|
+
ConsoleKit::Output.print_list(names, header: 'Available Tenants')
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class << self
|
|
54
|
+
def print_tenant_details(tenant, constants)
|
|
55
|
+
ConsoleKit::Output.print_header("Tenant: #{tenant}")
|
|
56
|
+
DETAIL_LABELS.each do |label, key|
|
|
57
|
+
next unless constants.key?(key)
|
|
58
|
+
|
|
59
|
+
ConsoleKit::Output.print_info(" #{label.ljust(13)}#{constants[key]}")
|
|
42
60
|
end
|
|
43
61
|
end
|
|
44
|
-
nil
|
|
45
62
|
end
|
|
46
63
|
end
|
|
47
64
|
end
|
data/lib/console_kit/output.rb
CHANGED
|
@@ -63,12 +63,21 @@ module ConsoleKit
|
|
|
63
63
|
|
|
64
64
|
def print_with(type, text, options = {})
|
|
65
65
|
opts = options.is_a?(Hash) ? options : { timestamp: options }
|
|
66
|
+
message = build_formatted_message(type, text, opts[:timestamp])
|
|
67
|
+
|
|
68
|
+
opts.fetch(:newline, true) ? puts(message) : print(message)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def build_formatted_message(type, text, timestamp)
|
|
66
72
|
meta = TYPES.fetch(type)
|
|
67
|
-
message = build_message(text, meta[:symbol],
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
message = build_message(text, meta[:symbol], timestamp)
|
|
74
|
+
colorize(message, meta[:color])
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def colorize(message, color)
|
|
78
|
+
return message unless ConsoleKit.configuration.pretty_output && color
|
|
70
79
|
|
|
71
|
-
|
|
80
|
+
"\e[#{color}m#{message}\e[0m"
|
|
72
81
|
end
|
|
73
82
|
|
|
74
83
|
def build_message(text, symbol, timestamp)
|
data/lib/console_kit/prompt.rb
CHANGED
|
@@ -41,11 +41,9 @@ module ConsoleKit
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def build_pry_prompt(procs)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
procs
|
|
48
|
-
end
|
|
44
|
+
return procs unless defined?(Pry::Prompt)
|
|
45
|
+
|
|
46
|
+
Pry::Prompt.try(:new, 'console_kit', 'ConsoleKit tenant prompt', procs) || procs
|
|
49
47
|
end
|
|
50
48
|
end
|
|
51
49
|
end
|
data/lib/console_kit/setup.rb
CHANGED
|
@@ -4,6 +4,7 @@ require_relative 'tenant_selector'
|
|
|
4
4
|
require_relative 'tenant_configurator'
|
|
5
5
|
require_relative 'output'
|
|
6
6
|
require_relative 'setup_ui'
|
|
7
|
+
require_relative 'tenant_orchestrator'
|
|
7
8
|
|
|
8
9
|
# Core Logic for initial Setup
|
|
9
10
|
module ConsoleKit
|
|
@@ -16,91 +17,11 @@ module ConsoleKit
|
|
|
16
17
|
Thread.current[:console_kit_current_tenant] = val
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
def setup =
|
|
20
|
+
def setup = TenantOrchestrator.run
|
|
20
21
|
def tenant_setup_successful? = !current_tenant.to_s.empty?
|
|
21
|
-
|
|
22
|
-
def
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Output.silence { TenantConfigurator.configure_tenant(current_tenant) }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def reset_current_tenant
|
|
29
|
-
return warn_no_tenants unless tenants?
|
|
30
|
-
|
|
31
|
-
perform_tenant_reset
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
|
|
36
|
-
def perform_tenant_reset
|
|
37
|
-
key = select_tenant_key
|
|
38
|
-
return cancel_switch if key == :abort || key.blank?
|
|
39
|
-
|
|
40
|
-
clear_current_tenant
|
|
41
|
-
return skip_tenant_message if %i[exit none].include?(key)
|
|
42
|
-
|
|
43
|
-
configure(key)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def run_setup
|
|
47
|
-
return if tenant_setup_successful?
|
|
48
|
-
|
|
49
|
-
config = ConsoleKit.configuration
|
|
50
|
-
config.validate!
|
|
51
|
-
select_and_configure
|
|
52
|
-
rescue StandardError => e
|
|
53
|
-
handle_error(e)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def select_and_configure
|
|
57
|
-
key = select_tenant_key
|
|
58
|
-
return handle_selection_result(key) if %i[exit abort none].include?(key) || key.blank?
|
|
59
|
-
|
|
60
|
-
configure(key)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def handle_selection_result(key)
|
|
64
|
-
exit_on_key if %i[exit abort].include?(key)
|
|
65
|
-
|
|
66
|
-
skip_tenant_message if key == :none
|
|
67
|
-
Output.print_error('Tenant selection failed. Loading without tenant configuration.') if key.blank?
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def exit_on_key
|
|
71
|
-
Output.print_info('Exiting console...')
|
|
72
|
-
Kernel.exit
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def configure(key)
|
|
76
|
-
TenantConfigurator.configure_tenant(key)
|
|
77
|
-
return unless TenantConfigurator.configuration_success
|
|
78
|
-
|
|
79
|
-
self.current_tenant = key
|
|
80
|
-
Prompt.apply
|
|
81
|
-
SetupUI.print_tenant_banner(key, ConsoleKit.configuration)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def tenants = ConsoleKit.configuration.tenants
|
|
85
|
-
def tenants? = tenants&.any?
|
|
86
|
-
def select_tenant_key = auto_select? ? tenants.keys.first : TenantSelector.select
|
|
87
|
-
def auto_select? = (tenants.size == 1) || !$stdin.tty?
|
|
88
|
-
def warn_no_tenants = Output.print_warning('Cannot reset tenant: No tenants configured.')
|
|
89
|
-
def cancel_switch = Output.print_warning('Tenant switch cancelled.')
|
|
90
|
-
def skip_tenant_message = Output.print_info('No tenant selected. Loading without tenant configuration.')
|
|
91
|
-
|
|
92
|
-
def clear_current_tenant
|
|
93
|
-
if current_tenant
|
|
94
|
-
Output.print_warning("Resetting tenant: #{current_tenant}")
|
|
95
|
-
TenantConfigurator.clear
|
|
96
|
-
end
|
|
97
|
-
self.current_tenant = nil
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def handle_error(error)
|
|
101
|
-
Output.print_error("Error setting up tenant: #{error.message}")
|
|
102
|
-
Output.print_backtrace(error)
|
|
103
|
-
end
|
|
22
|
+
def reapply = TenantOrchestrator.reapply
|
|
23
|
+
def reset_current_tenant = TenantOrchestrator.reset
|
|
24
|
+
def auto_select? = TenantOrchestrator.auto_select?
|
|
104
25
|
end
|
|
105
26
|
end
|
|
106
27
|
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ConsoleKit
|
|
4
|
+
module TenantConfigurator
|
|
5
|
+
# Encapsulates context and attributes to resolve DataClump smells
|
|
6
|
+
class ContextWrapper
|
|
7
|
+
HANDLER_ATTRIBUTES = {
|
|
8
|
+
Connections::SqlConnectionHandler => :tenant_shard,
|
|
9
|
+
Connections::MongoConnectionHandler => :tenant_mongo_db,
|
|
10
|
+
Connections::RedisConnectionHandler => :tenant_redis_db,
|
|
11
|
+
Connections::ElasticsearchConnectionHandler => :tenant_elasticsearch_prefix
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
attr_reader :ctx, :attributes
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def for_context(ctx)
|
|
18
|
+
new(ctx, detect_attributes(ctx))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def detect_attributes(ctx)
|
|
24
|
+
methods = ctx.public_methods
|
|
25
|
+
partner_attrs(methods) + handler_attrs(methods)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def partner_attrs(methods)
|
|
29
|
+
methods.include?(:partner_identifier=) ? [:partner_identifier] : []
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def handler_attrs(methods)
|
|
33
|
+
HANDLER_ATTRIBUTES.each_with_object([]) do |(handler, attr), list|
|
|
34
|
+
next unless methods.include?(:"#{attr}=")
|
|
35
|
+
next unless handler_available?(handler)
|
|
36
|
+
|
|
37
|
+
list << attr
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def handler_available?(handler_class)
|
|
42
|
+
handler_class.new(nil).available?
|
|
43
|
+
rescue NotImplementedError, StandardError
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def initialize(ctx, attributes)
|
|
49
|
+
@ctx = ctx
|
|
50
|
+
@attributes = attributes
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def any_set?
|
|
54
|
+
attributes.any? { |attr| ctx.public_send(attr).present? }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def reset
|
|
58
|
+
attributes.each { |attr| ctx.public_send("#{attr}=", nil) }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def assign(constant, mapping)
|
|
62
|
+
attributes.map do |attr|
|
|
63
|
+
existing = safe_read(attr)
|
|
64
|
+
new_value = constant[mapping[attr]]
|
|
65
|
+
ctx.public_send("#{attr}=", new_value)
|
|
66
|
+
[attr, existing, new_value]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def safe_read(attr)
|
|
73
|
+
ctx.public_send(attr)
|
|
74
|
+
rescue StandardError
|
|
75
|
+
nil
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -3,53 +3,70 @@
|
|
|
3
3
|
require_relative 'output'
|
|
4
4
|
require_relative 'connections/connection_manager'
|
|
5
5
|
require_relative 'connections/dashboard'
|
|
6
|
+
require_relative 'tenant_configurator/context_wrapper'
|
|
6
7
|
|
|
7
8
|
module ConsoleKit
|
|
8
9
|
# For tenant configuration
|
|
9
10
|
module TenantConfigurator
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
CONTEXT_MAPPING = {
|
|
12
|
+
partner_identifier: :partner_code,
|
|
13
|
+
tenant_shard: :shard,
|
|
14
|
+
tenant_mongo_db: :mongo_db,
|
|
15
|
+
tenant_redis_db: :redis_db,
|
|
16
|
+
tenant_elasticsearch_prefix: :elasticsearch_prefix
|
|
17
|
+
}.freeze
|
|
17
18
|
|
|
19
|
+
class << self
|
|
18
20
|
def configuration_success = Thread.current[:console_kit_configuration_success]
|
|
19
21
|
|
|
20
22
|
def configuration_success=(val)
|
|
21
23
|
Thread.current[:console_kit_configuration_success] = val
|
|
22
24
|
end
|
|
23
25
|
|
|
26
|
+
def current_tenant_key = Thread.current[:console_kit_current_tenant_key]
|
|
27
|
+
|
|
28
|
+
def current_tenant_key=(val)
|
|
29
|
+
Thread.current[:console_kit_current_tenant_key] = val
|
|
30
|
+
end
|
|
31
|
+
|
|
24
32
|
def configure_tenant(key)
|
|
25
|
-
|
|
26
|
-
return missing_config_error(key) unless constants
|
|
33
|
+
return true if key == current_tenant_key && configuration_success
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
attempt_configuration(key)
|
|
29
36
|
rescue StandardError => e
|
|
30
|
-
handle_error(e, key)
|
|
37
|
+
handle_error?(e, key)
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
def clear
|
|
34
41
|
ctx = ConsoleKit.configuration.context_class
|
|
35
42
|
return unless ctx
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
Output.print_info('Tenant context has been cleared.')
|
|
44
|
+
perform_clear(ContextWrapper.for_context(ctx))
|
|
39
45
|
end
|
|
40
46
|
|
|
41
47
|
private
|
|
42
48
|
|
|
43
|
-
def
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
def attempt_configuration(key)
|
|
50
|
+
constants = ConsoleKit.configuration.tenants[key]&.[](:constants)
|
|
51
|
+
return missing_config_error?(key) unless constants
|
|
52
|
+
|
|
53
|
+
execute_configuration(key, constants)
|
|
54
|
+
configuration_success
|
|
47
55
|
end
|
|
48
56
|
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
def perform_clear(wrapper)
|
|
58
|
+
return unless configuration_success || wrapper.any_set?
|
|
59
|
+
|
|
60
|
+
reset_tenant(wrapper)
|
|
61
|
+
Output.print_info('Tenant context has been cleared.')
|
|
62
|
+
true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def reset_tenant(wrapper)
|
|
66
|
+
self.configuration_success = false
|
|
67
|
+
self.current_tenant_key = nil
|
|
68
|
+
wrapper.reset
|
|
69
|
+
setup_connections(wrapper.ctx)
|
|
53
70
|
end
|
|
54
71
|
|
|
55
72
|
def validate_constants!(constants)
|
|
@@ -57,67 +74,54 @@ module ConsoleKit
|
|
|
57
74
|
raise Error, "Tenant constants missing keys: #{missing.join(', ')}" unless missing.empty?
|
|
58
75
|
end
|
|
59
76
|
|
|
60
|
-
def missing_config_error(key)
|
|
77
|
+
def missing_config_error?(key)
|
|
61
78
|
self.configuration_success = false
|
|
62
79
|
Output.print_error("No configuration found for tenant: #{key}")
|
|
80
|
+
false
|
|
63
81
|
end
|
|
64
82
|
|
|
65
|
-
def
|
|
83
|
+
def execute_configuration(key, constants)
|
|
66
84
|
validate_constants!(constants)
|
|
67
85
|
apply_context(constants)
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def handler_available?(handler_class)
|
|
72
|
-
handler_class.new(nil).available?
|
|
73
|
-
rescue NotImplementedError, StandardError
|
|
74
|
-
false
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def available_context_attributes(ctx)
|
|
78
|
-
attributes = ctx.respond_to?(:partner_identifier=) ? [:partner_identifier] : []
|
|
79
|
-
|
|
80
|
-
HANDLER_ATTRIBUTES.each_with_object(attributes) do |(handler, attr), list|
|
|
81
|
-
next unless ctx.respond_to?("#{attr}=")
|
|
82
|
-
next unless handler_available?(handler)
|
|
83
|
-
|
|
84
|
-
list << attr
|
|
85
|
-
end
|
|
86
|
+
mark_success(key)
|
|
86
87
|
end
|
|
87
88
|
|
|
88
89
|
def apply_context(constant)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
wrapper = ContextWrapper.for_context(ConsoleKit.configuration.context_class)
|
|
91
|
+
wrapper.assign(constant, CONTEXT_MAPPING).each do |attr, existing, configured|
|
|
92
|
+
warn_case_mismatch(attr, existing, configured) if case_mismatch?(existing, configured)
|
|
93
|
+
end
|
|
94
|
+
setup_connections(wrapper.ctx)
|
|
92
95
|
end
|
|
93
96
|
|
|
94
|
-
def
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
tenant_mongo_db: :mongo_db,
|
|
99
|
-
tenant_redis_db: :redis_db,
|
|
100
|
-
tenant_elasticsearch_prefix: :elasticsearch_prefix
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
available_context_attributes(ctx).each do |attr|
|
|
104
|
-
ctx.public_send("#{attr}=", constant[attribute_to_constant[attr]])
|
|
105
|
-
end
|
|
97
|
+
def case_mismatch?(existing, new_value)
|
|
98
|
+
existing.is_a?(String) && new_value.is_a?(String) &&
|
|
99
|
+
existing != new_value &&
|
|
100
|
+
existing.casecmp(new_value).zero?
|
|
106
101
|
end
|
|
107
102
|
|
|
108
103
|
def setup_connections(context)
|
|
109
|
-
|
|
104
|
+
Connections::ConnectionManager.available_handlers(context).each(&:connect)
|
|
110
105
|
end
|
|
111
106
|
|
|
112
|
-
def
|
|
107
|
+
def mark_success(key)
|
|
113
108
|
Output.print_success("Tenant set to: #{key}")
|
|
114
109
|
self.configuration_success = true
|
|
110
|
+
self.current_tenant_key = key
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def warn_case_mismatch(attr, existing, configured)
|
|
114
|
+
Output.print_warning(
|
|
115
|
+
"#{attr} case mismatch: context had '#{existing}', config set '#{configured}'. " \
|
|
116
|
+
'Check your ConsoleKit tenant configuration.'
|
|
117
|
+
)
|
|
115
118
|
end
|
|
116
119
|
|
|
117
|
-
def handle_error(error, key)
|
|
120
|
+
def handle_error?(error, key)
|
|
118
121
|
self.configuration_success = false
|
|
119
122
|
Output.print_error("Failed to configure tenant '#{key}': #{error.message}")
|
|
120
123
|
Output.print_backtrace(error)
|
|
124
|
+
false
|
|
121
125
|
end
|
|
122
126
|
end
|
|
123
127
|
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ConsoleKit
|
|
4
|
+
# Orchestrates tenant lifecycle, selection, and configuration
|
|
5
|
+
class TenantOrchestrator
|
|
6
|
+
class << self
|
|
7
|
+
def auto_select? = (tenants.size == 1) || !$stdin.tty?
|
|
8
|
+
|
|
9
|
+
def current_tenant = Setup.current_tenant
|
|
10
|
+
|
|
11
|
+
def current_tenant=(val)
|
|
12
|
+
Setup.current_tenant = val
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def reapply
|
|
16
|
+
return unless tenant_setup_successful?
|
|
17
|
+
|
|
18
|
+
Output.silence do
|
|
19
|
+
TenantConfigurator.current_tenant_key = nil
|
|
20
|
+
TenantConfigurator.configure_tenant(current_tenant)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def reset
|
|
25
|
+
return warn_no_tenants unless tenants?
|
|
26
|
+
|
|
27
|
+
perform_reset
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def run
|
|
31
|
+
return if tenant_setup_successful?
|
|
32
|
+
|
|
33
|
+
perform_setup
|
|
34
|
+
rescue StandardError => e
|
|
35
|
+
handle_error(e)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def tenants = ConsoleKit.configuration.tenants
|
|
39
|
+
def tenants? = tenants&.any?
|
|
40
|
+
def select_tenant_key = auto_select? ? tenants.keys.first : TenantSelector.select
|
|
41
|
+
def warn_no_tenants = Output.print_warning('Cannot reset tenant: No tenants configured.')
|
|
42
|
+
def cancel_switch = Output.print_warning('Tenant switch cancelled.')
|
|
43
|
+
def skip_tenant_message = Output.print_info('No tenant selected. Loading without tenant configuration.')
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def tenant_setup_successful? = !current_tenant.to_s.empty?
|
|
48
|
+
|
|
49
|
+
def perform_reset
|
|
50
|
+
key = select_tenant_key
|
|
51
|
+
return cancel_switch if key == :abort || key.blank?
|
|
52
|
+
return already_on_tenant?(key) if key == current_tenant
|
|
53
|
+
|
|
54
|
+
clear_current_tenant
|
|
55
|
+
return skip_tenant_message if %i[exit none].include?(key)
|
|
56
|
+
|
|
57
|
+
configure(key)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def perform_setup
|
|
61
|
+
ConsoleKit.configuration.validate!
|
|
62
|
+
key = select_tenant_key
|
|
63
|
+
return handle_selection_result(key) if %i[exit abort none].include?(key) || key.blank?
|
|
64
|
+
|
|
65
|
+
configure(key)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def handle_selection_result(key)
|
|
69
|
+
exit_on_key if %i[exit abort].include?(key)
|
|
70
|
+
|
|
71
|
+
skip_tenant_message if key == :none
|
|
72
|
+
Output.print_error('Tenant selection failed. Loading without tenant configuration.') if key.blank?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def exit_on_key
|
|
76
|
+
Output.print_info('Exiting console...')
|
|
77
|
+
Kernel.exit
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def configure(key)
|
|
81
|
+
TenantConfigurator.configure_tenant(key)
|
|
82
|
+
return unless TenantConfigurator.configuration_success
|
|
83
|
+
|
|
84
|
+
Setup.current_tenant = key
|
|
85
|
+
Prompt.apply
|
|
86
|
+
SetupUI.print_tenant_banner(key, ConsoleKit.configuration)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def already_on_tenant?(key)
|
|
90
|
+
Output.print_info("Already using tenant: #{key}. No changes made.")
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def clear_current_tenant
|
|
95
|
+
if current_tenant
|
|
96
|
+
Output.print_warning("Resetting tenant: #{current_tenant}")
|
|
97
|
+
TenantConfigurator.clear
|
|
98
|
+
end
|
|
99
|
+
self.current_tenant = nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def handle_error(error)
|
|
103
|
+
Output.print_error("Error setting up tenant: #{error.message}")
|
|
104
|
+
Output.print_backtrace(error)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
data/lib/console_kit/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: console_kit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Soumyadeep Pal
|
|
@@ -58,6 +58,8 @@ executables: []
|
|
|
58
58
|
extensions: []
|
|
59
59
|
extra_rdoc_files: []
|
|
60
60
|
files:
|
|
61
|
+
- ".DS_Store"
|
|
62
|
+
- ".reek.yml.new"
|
|
61
63
|
- LICENSE.txt
|
|
62
64
|
- lib/console_kit.rb
|
|
63
65
|
- lib/console_kit/configuration.rb
|
|
@@ -78,6 +80,8 @@ files:
|
|
|
78
80
|
- lib/console_kit/setup.rb
|
|
79
81
|
- lib/console_kit/setup_ui.rb
|
|
80
82
|
- lib/console_kit/tenant_configurator.rb
|
|
83
|
+
- lib/console_kit/tenant_configurator/context_wrapper.rb
|
|
84
|
+
- lib/console_kit/tenant_orchestrator.rb
|
|
81
85
|
- lib/console_kit/tenant_selector.rb
|
|
82
86
|
- lib/console_kit/version.rb
|
|
83
87
|
- lib/generators/console_kit/install_generator.rb
|