viaduct-toolkit 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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