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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e74b426a21bcd09ed6d55df3caeccb100ac0e83b
4
- data.tar.gz: 659ef1f517c899b2ebf5f69e80f221aecad3af75
3
+ metadata.gz: 3de7f4fcc1044f4d5ef119608fcb1dab981382c8
4
+ data.tar.gz: 9dff6dd8840043b0d91c8c080d2946fa466568d3
5
5
  SHA512:
6
- metadata.gz: 218b9c6b7bba9286de733666a97bde7c0b4f0d10ab65e23ab28534771db1f402284ede76c7c1621061d038730d4e12561c613575c999c9ce6cbbc64b84509539
7
- data.tar.gz: c3ba43711e4928386dfe4fd9fa1d7d1af1f43b601259fffb5e3e71c2c84d0a4133d5b66457fe9fd679a7ddfed399d5d89ce2bf115ca50e3bba5e75dc8c69a646
6
+ metadata.gz: 8c95ca7b91a199502f5b9a8032e2722ac30850d41d10a72a10bd4ac4727d25d1c6a1aadaf46e3dafedf34ea696a80cf97a94a67f599b92a7a336a18c8688d058
7
+ data.tar.gz: db2ed5d0b4da511570cbbbc0d7919164d1768f28cac0c12fe214f9952826590d7d52f4f62443664a96a0fc3e5d0e63df58473ee42e1f86e1bd205a626ee01068
data/bin/vdt CHANGED
@@ -2,4 +2,9 @@
2
2
  $:.unshift(File.expand_path(File.join('..', '..', 'lib'), __FILE__))
3
3
  require 'viaduct/toolkit'
4
4
  Viaduct::Toolkit.add_commands
5
- Viaduct::Toolkit.cli.run!
5
+ begin
6
+ Viaduct::Toolkit.cli.run!
7
+ rescue Interrupt
8
+ puts
9
+ exit
10
+ end
@@ -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 DATABASE_ID", String, "The ID of the database to display further information for"
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'][(opts.database.to_i - 1).abs]
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 "Database", db['stack']['name']
37
+ field "Engine", db['stack']['name']
37
38
  process_details(db['process'])
38
39
  end
39
40
  else
40
- puts "No database found with ID '#{opts.database}'".red
41
+ puts "No database found matching '#{opts.database}'".red
41
42
  exit 1
42
43
  end
43
44
 
44
45
  else
45
46
 
46
- puts "Deployment Details".yellow
47
- details do
48
- puts "+" + '-' * 78 + '+'
49
- field "Number", response.data['deployment']['number']
50
- field 'Version', response.data['deployment']['version']['id']
51
- field "Description", response.data['deployment']['version']['description']
52
- field "Source", response.data['deployment']['triggered_from']
53
- field "Deployer", response.data['deployment']['user'] ? response.data['deployment']['user']['name'] : response.data['deployment']['triggerer']
54
- field "Started", time(response.data['deployment']['timing']['started_at'])
55
- end
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
- processes = response.data['processes'].map do |p|
58
- memory_used = (p['process']['resources']['memory_usage'] / 1024 / 1024).to_s + "MB"
59
- memory_available = (p['process']['resources']['max_memory'] / 1024 / 1024).to_s + "MB"
60
- memory = "#{memory_used}/#{memory_available}"
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
- respawns = "#{p['process']['respawning']['current']}/#{p['process']['respawning']['maximum']}"
63
- [p['label'], p['process']['status'].capitalize, memory, p['container']['command'], respawns]
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
- memory_used = (d['process']['resources']['memory_usage'] / 1024 / 1024).to_s + "MB"
73
- memory_available = (d['process']['resources']['max_memory'] / 1024 / 1024).to_s + "MB"
74
- memory = "#{memory_used}/#{memory_available}"
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
- [count, d['label'], d['process']['status'].capitalize, d['stack']['name'], memory, respawns, d['process']['networking']['ip_address']]
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 ['#', 'Label', 'Status', 'Type', 'Memory', 'Respawns', 'IP Address'], databases
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
- if args[0].nil?
11
- error "You need to specify a database name"
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
- error "Couldn't get database details" unless database.success?
21
- if command = database.data['database']['console_command']
22
- chech_ssh_key_presence
23
- console = get_application_console_port_forward(app)
24
- puts command
25
- exec_console_command(console, "ssh -t vdt@#{console['ip_address']} -p #{console['port']} '#{command}'")
26
- else
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(1)
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)
@@ -1,5 +1,5 @@
1
1
  module Viaduct
2
2
  module Toolkit
3
- VERSION = '0.1.0'
3
+ VERSION = '1.0.0'
4
4
  end
5
5
  end
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: 0.1.0
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-04 00:00:00.000000000 Z
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