viaduct-toolkit 0.1.0 → 1.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.
- checksums.yaml +4 -4
- data/bin/vdt +6 -1
- data/lib/viaduct/toolkit/commands/app_deploy.rb +117 -0
- data/lib/viaduct/toolkit/commands/app_status.rb +37 -28
- data/lib/viaduct/toolkit/commands/db_console.rb +10 -19
- data/lib/viaduct/toolkit/commands/db_export.rb +79 -0
- data/lib/viaduct/toolkit/commands/db_import.rb +68 -0
- data/lib/viaduct/toolkit/helpers.rb +22 -1
- data/lib/viaduct/toolkit/version.rb +1 -1
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3de7f4fcc1044f4d5ef119608fcb1dab981382c8
|
4
|
+
data.tar.gz: 9dff6dd8840043b0d91c8c080d2946fa466568d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c95ca7b91a199502f5b9a8032e2722ac30850d41d10a72a10bd4ac4727d25d1c6a1aadaf46e3dafedf34ea696a80cf97a94a67f599b92a7a336a18c8688d058
|
7
|
+
data.tar.gz: db2ed5d0b4da511570cbbbc0d7919164d1768f28cac0c12fe214f9952826590d7d52f4f62443664a96a0fc3e5d0e63df58473ee42e1f86e1bd205a626ee01068
|
data/bin/vdt
CHANGED
@@ -0,0 +1,117 @@
|
|
1
|
+
Viaduct::Toolkit.cli.command "app:deploy" do |c|
|
2
|
+
c.syntax = "app:deploy [VERSION]"
|
3
|
+
c.description = "Deploy the given version (or latest) for an application"
|
4
|
+
c.option "-y", "Always deploy the latest commit without asking"
|
5
|
+
c.option "-f", "--force-build", "Build the application if even it isn't needed"
|
6
|
+
c.option "-i", "--no-inherit-build-env", "Do not inherit the build environment for this deployment"
|
7
|
+
c.option "-b", "--branch BRANCH", "The branch/commit you wish to deploy (defaults to application default)"
|
8
|
+
c.action do |args, opts|
|
9
|
+
include Commander::Methods
|
10
|
+
ensure_logged_in!
|
11
|
+
|
12
|
+
puts "Getting latest commit information...".magenta
|
13
|
+
if app = find_application
|
14
|
+
|
15
|
+
#
|
16
|
+
# Get the latest commits for the remote repository
|
17
|
+
#
|
18
|
+
commits = Viaduct::Toolkit.api.repositories.commits(:application => app['subdomain'], :limit => 1, :update => true, :branch => opts.branch)
|
19
|
+
unless commits.success? && commit = commits.data['commits'][0]
|
20
|
+
puts
|
21
|
+
puts "We couldn't find any commits on `#{commits.data['branch']}` branch.".red
|
22
|
+
puts "Please check that you have pushed your code to your repository."
|
23
|
+
puts
|
24
|
+
puts " Your repository is hosted at: #{commits.data['repository']['url'].underline}"
|
25
|
+
puts
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
29
|
+
details do
|
30
|
+
heading "Latest commit for #{app['subdomain']}"
|
31
|
+
field "Repository", commits.data['repository']['url']
|
32
|
+
field "Branch", commits.data['branch']
|
33
|
+
field "Commit", commit['ref'][0, 10]
|
34
|
+
field "Message", commit['message']
|
35
|
+
end
|
36
|
+
|
37
|
+
unless opts.y || agree("Do you wish to deploy this commit?".blue)
|
38
|
+
puts "OK then. We won't do anything.".green
|
39
|
+
exit 0
|
40
|
+
end
|
41
|
+
|
42
|
+
deployment_params = {
|
43
|
+
:application => app['subdomain'],
|
44
|
+
:version => commit['ref'],
|
45
|
+
:hold => true,
|
46
|
+
:force_build => opts.force_build,
|
47
|
+
:inherit_build_environment => opts.no_inherit_build_env == false ? false : true
|
48
|
+
}
|
49
|
+
deployment_response = Viaduct::Toolkit.api.deployments.start(deployment_params)
|
50
|
+
if deployment_response.success?
|
51
|
+
|
52
|
+
puts
|
53
|
+
puts "Deployment will now start. You can view the full log in your web browser:"
|
54
|
+
puts "https://my.viaduct.io/applications/#{app['subdomain']}/deployments/#{deployment_response.data['number']}".underline
|
55
|
+
puts
|
56
|
+
print "Waiting for capacity to deploy".ljust(40)
|
57
|
+
$stdout.flush
|
58
|
+
|
59
|
+
statuses_seen = []
|
60
|
+
require 'eventmachine'
|
61
|
+
EM.run do
|
62
|
+
Viaduct::Toolkit.api.push.connected do |event|
|
63
|
+
Viaduct::Toolkit.api.push.subscribe :deployment_status, deployment_response.data['id'].to_i
|
64
|
+
end
|
65
|
+
|
66
|
+
Viaduct::Toolkit.api.push.receive do |exchange, process_id, data|
|
67
|
+
if exchange == :deployment_status
|
68
|
+
if statuses_seen.include?(data['status'])
|
69
|
+
next
|
70
|
+
end
|
71
|
+
statuses_seen << data['status']
|
72
|
+
case data['status']
|
73
|
+
when 'building'
|
74
|
+
puts "[ OK ]".green
|
75
|
+
print "Building package".ljust(40)
|
76
|
+
$stdout.flush
|
77
|
+
when 'starting'
|
78
|
+
puts "[ OK ]".green
|
79
|
+
print "Starting application".ljust(40)
|
80
|
+
$stdout.flush
|
81
|
+
when 'activating'
|
82
|
+
puts "[ OK ]".green
|
83
|
+
print "Activating deployment".ljust(40)
|
84
|
+
$stdout.flush
|
85
|
+
when 'deployed'
|
86
|
+
puts "[ OK ]".green
|
87
|
+
puts "Deployment completed successfully!".green
|
88
|
+
puts
|
89
|
+
puts "You can view your application at:"
|
90
|
+
if app['main_domain']
|
91
|
+
puts "http://#{app['main_domain']['name']}".underline
|
92
|
+
else
|
93
|
+
puts "http://#{app['viaduct_domain']}".underline
|
94
|
+
end
|
95
|
+
puts
|
96
|
+
exit 0
|
97
|
+
when 'failed'
|
98
|
+
puts "[ FAIL ]".red
|
99
|
+
puts
|
100
|
+
puts "Deployment did not completed successfully.".red
|
101
|
+
puts "You can review information about this failure at the URL provided above."
|
102
|
+
puts
|
103
|
+
exit 0
|
104
|
+
end
|
105
|
+
elsif exchange == :global && data['type'] == 'subscribed'
|
106
|
+
Viaduct::Toolkit.api.push.send(:remove_deployment_hold, {'deployment_id' => deployment_response.data['id'].to_i})
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
else
|
111
|
+
error "We couldn't start this deployment at this time."
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
Viaduct::Toolkit.cli.alias_command "deploy", "app:deploy"
|
@@ -2,7 +2,7 @@ Viaduct::Toolkit.cli.command "app:status" do |c|
|
|
2
2
|
c.syntax = "app:status"
|
3
3
|
c.description = "Return current status of an application"
|
4
4
|
c.option "--process PROCESS_TYPE", String, "A process to show expanded information for"
|
5
|
-
c.option "--database
|
5
|
+
c.option "--database FRUIT", String, "The ID of the database to display further information for"
|
6
6
|
|
7
7
|
c.action do |args, opts|
|
8
8
|
include Commander::Methods
|
@@ -29,57 +29,66 @@ Viaduct::Toolkit.cli.command "app:status" do |c|
|
|
29
29
|
|
30
30
|
elsif opts.database
|
31
31
|
|
32
|
-
if db = response.data['databases'][
|
32
|
+
if db = response.data['databases'].select { |d| d['fruit'] == opts.database }.first
|
33
33
|
details do
|
34
34
|
heading "Database Details"
|
35
|
+
field "Fruit", db['fruit']
|
35
36
|
field "Label", db['label']
|
36
|
-
field "
|
37
|
+
field "Engine", db['stack']['name']
|
37
38
|
process_details(db['process'])
|
38
39
|
end
|
39
40
|
else
|
40
|
-
puts "No database found
|
41
|
+
puts "No database found matching '#{opts.database}'".red
|
41
42
|
exit 1
|
42
43
|
end
|
43
44
|
|
44
45
|
else
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
47
|
+
if response.data['deployment']
|
48
|
+
puts "Deployment Details".yellow
|
49
|
+
details do
|
50
|
+
puts "+" + '-' * 78 + '+'
|
51
|
+
field "Number", response.data['deployment']['number']
|
52
|
+
field 'Version', response.data['deployment']['version']['id']
|
53
|
+
field "Description", response.data['deployment']['version']['description']
|
54
|
+
field "Source", response.data['deployment']['triggered_from']
|
55
|
+
field "Deployer", response.data['deployment']['user'] ? response.data['deployment']['user']['name'] : response.data['deployment']['triggerer']
|
56
|
+
field "Started", time(response.data['deployment']['timing']['started_at'])
|
57
|
+
end
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
processes = response.data['processes'].map do |p|
|
60
|
+
memory_used = (p['process']['resources']['memory_usage'] / 1024 / 1024).to_s + "MB"
|
61
|
+
memory_available = (p['process']['resources']['max_memory'] / 1024 / 1024).to_s + "MB"
|
62
|
+
memory = "#{memory_used}/#{memory_available}"
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
+
respawns = "#{p['process']['respawning']['current']}/#{p['process']['respawning']['maximum']}"
|
65
|
+
[p['label'], p['process']['status'].capitalize, memory, p['container']['command'], respawns]
|
66
|
+
end
|
67
|
+
puts
|
68
|
+
puts "Processes".yellow
|
69
|
+
table ['Label', 'Status', 'Memory', 'Command', 'Respawns'], processes
|
70
|
+
else
|
71
|
+
puts "No process info available. Not deployed yet.".yellow
|
64
72
|
end
|
65
|
-
puts
|
66
|
-
puts "Processes".yellow
|
67
|
-
table ['Label', 'Status', 'Memory', 'Command', 'Respawns'], processes
|
68
73
|
|
69
74
|
count = 0
|
70
75
|
databases = response.data['databases'].map do |d|
|
71
76
|
count += 1
|
72
|
-
|
73
|
-
|
74
|
-
|
77
|
+
if d['process']['resources']['memory_usage']
|
78
|
+
memory_used = (d['process']['resources']['memory_usage'] / 1024 / 1024).to_s + "MB"
|
79
|
+
memory_available = (d['process']['resources']['max_memory'] / 1024 / 1024).to_s + "MB"
|
80
|
+
memory = "#{memory_used}/#{memory_available}"
|
81
|
+
else
|
82
|
+
memory = ""
|
83
|
+
end
|
75
84
|
respawns = "#{d['process']['respawning']['current']}/#{d['process']['respawning']['maximum']}"
|
76
85
|
|
77
|
-
[
|
86
|
+
[d['fruit'], d['label'], d['process']['status'].capitalize, d['stack']['name'], memory, respawns, d['process']['networking']['ip_address']]
|
78
87
|
end
|
79
88
|
unless databases.empty?
|
80
89
|
puts
|
81
90
|
puts "Dedicated Databases".yellow
|
82
|
-
table ['
|
91
|
+
table ['Fruit', 'Label', 'Status', 'Type', 'Memory', 'Respawns', 'IP Address'], databases
|
83
92
|
end
|
84
93
|
end
|
85
94
|
|
@@ -2,31 +2,22 @@ Viaduct::Toolkit.cli.command "db:console" do |c|
|
|
2
2
|
|
3
3
|
c.syntax = "db:console"
|
4
4
|
c.description = "Open a console session for the given database"
|
5
|
+
c.option "-d FRUIT", "--database FRUIT", String, "The name of the database to import into (uses the main DB by default)"
|
5
6
|
|
6
7
|
c.action do |args, opts|
|
7
8
|
include Commander::Methods
|
8
9
|
ensure_logged_in!
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
if app = find_application
|
14
|
-
database = Viaduct::Toolkit.api.applications.database(:application => app['subdomain'], :database => args[0])
|
15
|
-
if database.status == 'not-found'
|
16
|
-
puts "No database found named '#{args[0]}'".red
|
17
|
-
exit 1
|
18
|
-
end
|
11
|
+
app = find_application
|
12
|
+
database = find_database(app, opts.database)
|
19
13
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
puts "Console access is not available for this database type.".red
|
28
|
-
exit 1
|
29
|
-
end
|
14
|
+
if command = database['database']['console_command']
|
15
|
+
chech_ssh_key_presence
|
16
|
+
console = get_application_console_port_forward(app)
|
17
|
+
exec_console_command(console, "ssh -t vdt@#{console['ip_address']} -p #{console['port']} '#{command}'")
|
18
|
+
else
|
19
|
+
puts "Console access is not available for this database type.".red
|
20
|
+
exit 1
|
30
21
|
end
|
31
22
|
end
|
32
23
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
Viaduct::Toolkit.cli.command "db:export" do |c|
|
2
|
+
|
3
|
+
c.syntax = "db:export [PATH]"
|
4
|
+
c.description = "Download an export for a given database"
|
5
|
+
c.option "-d FRUIT", "--database FRUIT", String, "The name of the database to export (uses the main DB by default)"
|
6
|
+
|
7
|
+
c.action do |args, opts|
|
8
|
+
include Commander::Methods
|
9
|
+
ensure_logged_in!
|
10
|
+
|
11
|
+
# Get the application
|
12
|
+
app = find_application
|
13
|
+
database = find_database(app, opts.database)
|
14
|
+
|
15
|
+
# Set some parameters to create our new export with
|
16
|
+
export_params = {}
|
17
|
+
export_params[:application] = app['subdomain']
|
18
|
+
export_params[:database] = database['database']['fruit']
|
19
|
+
|
20
|
+
# If this is e-mail only, set that falg
|
21
|
+
if args[0].nil?
|
22
|
+
export_params[:email] = true
|
23
|
+
end
|
24
|
+
|
25
|
+
# Create our new export
|
26
|
+
export = Viaduct::Toolkit.api.database_exports.start(export_params)
|
27
|
+
|
28
|
+
# Is an export in progress?
|
29
|
+
if export.is_a?(MoonropeClient::Responses::ValidationError) && (export.errors['base'] || []).any? { |e| e =~ /already in progress/}
|
30
|
+
puts "An export is already in progress for this database. Please try again later.".red
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
# Any other export starting errors?
|
35
|
+
unless export.success?
|
36
|
+
puts "The database export could not be started for this database.".red
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
# If this is an email, we're done now. Just let the user know and exit.
|
41
|
+
if args[0].nil?
|
42
|
+
puts "Export of #{database['database']['fruit']} database has been started.".green
|
43
|
+
puts "You'll receive an email shortly.".green
|
44
|
+
exit 0
|
45
|
+
end
|
46
|
+
|
47
|
+
# Keep checking the export status and download the file when it's ready to
|
48
|
+
# be downloaded.
|
49
|
+
puts "Exporting #{database['database']['fruit']} database...".magenta
|
50
|
+
checks = 0
|
51
|
+
loop do
|
52
|
+
checks += 1
|
53
|
+
export = Viaduct::Toolkit.api.database_exports.info(:id => export.data['id'])
|
54
|
+
if export.success?
|
55
|
+
if export.data['status'] == 'complete' && export.data['can_download?']
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
if checks > 600
|
61
|
+
puts "Export did not build in time. Please try again through the web interface"
|
62
|
+
puts "and request that the result be e-mailed to you."
|
63
|
+
exit 1
|
64
|
+
else
|
65
|
+
sleep 2
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
puts "Export build successfully. Downloading...".magenta
|
70
|
+
if system("curl #{export.data['download_url']} -o #{args[0]}")
|
71
|
+
puts "Export downloaded successfully to #{args[0]}".green
|
72
|
+
else
|
73
|
+
puts "Could not download using `curl`. Ensure you have curl installed to".red
|
74
|
+
puts "download file using the Viaduct Toolkit.".red
|
75
|
+
exit 1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
Viaduct::Toolkit.cli.command "db:import" do |c|
|
2
|
+
|
3
|
+
c.syntax = "db:import [PATH]"
|
4
|
+
c.description = "Import a dump file to a database"
|
5
|
+
c.option "--database FRUIT", String, "The name of the database to import into (uses the main DB by default)"
|
6
|
+
|
7
|
+
c.action do |args, opts|
|
8
|
+
include Commander::Methods
|
9
|
+
ensure_logged_in!
|
10
|
+
|
11
|
+
if args[0].nil? || !File.file?(args[0])
|
12
|
+
puts "You must provide a path to the dump file to import".red
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get the application
|
17
|
+
app = find_application
|
18
|
+
|
19
|
+
# Get the database
|
20
|
+
database = find_database(app, opts.database)
|
21
|
+
|
22
|
+
# Set some parameters to create our new export with
|
23
|
+
import_params = {}
|
24
|
+
import_params[:application] = app['subdomain']
|
25
|
+
import_params[:database] = database['database']['fruit']
|
26
|
+
import_params[:file] = Base64.encode64(File.read(args[0]))
|
27
|
+
|
28
|
+
# Start the import
|
29
|
+
puts "Uploading #{args[0]} to Viaduct...".magenta
|
30
|
+
import = Viaduct::Toolkit.api.database_imports.import(import_params)
|
31
|
+
unless import.success?
|
32
|
+
puts "Couldn't start this import. Ensure that the type of database supports importing.".red
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "Importing #{args[0]} into #{database['database']['fruit']} database...".magenta
|
37
|
+
|
38
|
+
# Keep checking in on the status
|
39
|
+
count = 0
|
40
|
+
loop do
|
41
|
+
count += 1
|
42
|
+
import = Viaduct::Toolkit.api.database_imports.info(:id => import.data['id'])
|
43
|
+
if import.success? && ['complete', 'failed'].include?(import.data['status'])
|
44
|
+
case import.data['status']
|
45
|
+
when 'complete'
|
46
|
+
puts "Database has been imported successfully.".green
|
47
|
+
else
|
48
|
+
puts "The database import failed. You can use the console to try and".red
|
49
|
+
puts "import your file directly into your database. See documentation".red
|
50
|
+
puts "for further details".red
|
51
|
+
end
|
52
|
+
exit 0
|
53
|
+
end
|
54
|
+
|
55
|
+
if count > 600
|
56
|
+
break
|
57
|
+
else
|
58
|
+
sleep 2
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Oh no, it timed out.
|
63
|
+
puts "The database import did not complete in a timely manner. Please try".red
|
64
|
+
puts "again later or contact support.".red
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -87,7 +87,28 @@ module Viaduct
|
|
87
87
|
end
|
88
88
|
|
89
89
|
puts "Couldn't determine a Viaduct application from command.".red
|
90
|
-
exit
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
|
93
|
+
def find_database(app, database_name = nil)
|
94
|
+
# Is there a DB?
|
95
|
+
if database_name
|
96
|
+
database_fruit = database_name
|
97
|
+
elsif app['main_database']
|
98
|
+
database_fruit = app['main_database']['fruit']
|
99
|
+
else
|
100
|
+
puts "There is no database specified and you don't have a main database for".red
|
101
|
+
puts "this application. Try again using the --database option.".red
|
102
|
+
exit 1
|
103
|
+
end
|
104
|
+
|
105
|
+
database = Viaduct::Toolkit.api.applications.database(:application => app['subdomain'], :database => database_fruit)
|
106
|
+
if database.success?
|
107
|
+
database.data
|
108
|
+
else
|
109
|
+
puts "No database found matching '#{database_fruit}'".red
|
110
|
+
exit 1
|
111
|
+
end
|
91
112
|
end
|
92
113
|
|
93
114
|
def heading(title)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: viaduct-toolkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Cooke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: commander
|
@@ -29,6 +29,9 @@ dependencies:
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
- - ">="
|
32
35
|
- !ruby/object:Gem::Version
|
33
36
|
version: 1.0.5
|
34
37
|
type: :runtime
|
@@ -36,6 +39,9 @@ dependencies:
|
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
41
|
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '1.0'
|
44
|
+
- - ">="
|
39
45
|
- !ruby/object:Gem::Version
|
40
46
|
version: 1.0.5
|
41
47
|
- !ruby/object:Gem::Dependency
|
@@ -103,6 +109,7 @@ files:
|
|
103
109
|
- bin/vdt
|
104
110
|
- lib/viaduct/toolkit.rb
|
105
111
|
- lib/viaduct/toolkit/commands/app_console.rb
|
112
|
+
- lib/viaduct/toolkit/commands/app_deploy.rb
|
106
113
|
- lib/viaduct/toolkit/commands/app_deployments.rb
|
107
114
|
- lib/viaduct/toolkit/commands/app_download.rb
|
108
115
|
- lib/viaduct/toolkit/commands/app_env.rb
|
@@ -115,6 +122,8 @@ files:
|
|
115
122
|
- lib/viaduct/toolkit/commands/app_upload.rb
|
116
123
|
- lib/viaduct/toolkit/commands/app_visit.rb
|
117
124
|
- lib/viaduct/toolkit/commands/db_console.rb
|
125
|
+
- lib/viaduct/toolkit/commands/db_export.rb
|
126
|
+
- lib/viaduct/toolkit/commands/db_import.rb
|
118
127
|
- lib/viaduct/toolkit/commands/db_list.rb
|
119
128
|
- lib/viaduct/toolkit/commands/domain_list.rb
|
120
129
|
- lib/viaduct/toolkit/commands/login.rb
|