viaduct-toolkit 0.0.3 → 0.1.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: c66db3a1f9b8d5e872b2f57ee3d9a35cc3245132
4
- data.tar.gz: 1f04ed00771efe833b09995d41150d82e9d93b67
3
+ metadata.gz: e74b426a21bcd09ed6d55df3caeccb100ac0e83b
4
+ data.tar.gz: 659ef1f517c899b2ebf5f69e80f221aecad3af75
5
5
  SHA512:
6
- metadata.gz: b08a5b7a585a79629031522a60a81c807c691ba6aaae34347b889c981a64244dc367f6d6940e9eb619e12af2ecf7eef5deae625ad3cbd2bdd960ac82fec15369
7
- data.tar.gz: 23006e3fada77da25e3c9ea3c747b73bbd723412d92219f225bff2990122c2663d77edabcf7434040210d1ccd1d5a0c40727bdf57b56b6ed9bbd30513d6ca0eb
6
+ metadata.gz: 218b9c6b7bba9286de733666a97bde7c0b4f0d10ab65e23ab28534771db1f402284ede76c7c1621061d038730d4e12561c613575c999c9ce6cbbc64b84509539
7
+ data.tar.gz: c3ba43711e4928386dfe4fd9fa1d7d1af1f43b601259fffb5e3e71c2c84d0a4133d5b66457fe9fd679a7ddfed399d5d89ce2bf115ca50e3bba5e75dc8c69a646
@@ -1,56 +1,19 @@
1
1
  Viaduct::Toolkit.cli.command "app:console" do |c|
2
-
3
- c.syntax = "app:console SUBDOMAIN_OF_APP"
4
- c.description = "Start a new SSH-based console session"
2
+
3
+ c.syntax = "app:console"
4
+ c.description = "Start a new console session"
5
5
  c.option "--disable", "Disable access to the SSH console"
6
6
  c.option "--enable", "Enable access to the SSH console"
7
7
  c.option "--status", "Display the status of the port forward"
8
-
8
+
9
9
  c.action do |args, opts|
10
10
  include Commander::Methods
11
11
  ensure_logged_in!
12
- if app = find_application(args[0])
13
-
14
- # Check the user's SSH keys
15
- response = Viaduct::Toolkit.api.ssh_keys.all
16
- if response.success?
17
-
18
- if response.data.empty?
19
- puts "You haven't uploaded any SSH keys to your Viaduct user account.".red
20
- puts "You cannot use SSH console access without them.".red
21
- puts
22
- puts "Upload your key using the command below".blue
23
- puts
24
- puts " $ vdt ssh_keys:add".blue
25
- puts
26
- exit(1)
27
- else
28
- stdout, stderr, status = run("ssh-add -l")
29
- if status == 0
30
- remote_fingerprints = response.data.map { |d| d['fingerprint'] }
31
- local_fingerprints = stdout.split(/\n/).map { |l| l.split(/\s+/)[1] }
32
- unless remote_fingerprints.any? { |f| local_fingerprints.include?(f) }
33
- puts "Warning: it doesn't seem as though your SSH key has been uploaded".yellow
34
- puts "to your Viaduct account. This session may not succeed. If it doesn't".yellow
35
- puts "ensure that you have uploaded to your SSH key to your Viaduct account.".yellow
36
- end
37
- end
38
- end
39
-
40
- else
41
- error "Couldn't verify remote SSH keys. Please try again."
42
- end
43
-
44
- # Get the console port forward for the application
45
- response = Viaduct::Toolkit.api.port_forwards.all(:application => app['subdomain'])
46
- if response.success?
47
- unless console = response.data.select { |c| c['mode'] == 'console'}.first
48
- error "Console access is not supported by this application. Please contact support."
49
- end
50
- else
51
- error "Couldn't get port forward information from API for application."
52
- end
53
-
12
+ if app = find_application
13
+
14
+ chech_ssh_key_presence
15
+ console = get_application_console_port_forward(app)
16
+
54
17
  if opts.status
55
18
  details do
56
19
  heading "SSH console access"
@@ -61,13 +24,13 @@ Viaduct::Toolkit.cli.command "app:console" do |c|
61
24
  field i == 0 ? 'Allowed IPs' : '', ip
62
25
  end
63
26
  end
64
-
27
+
65
28
  elsif opts.disable
66
-
67
- #
29
+
30
+ #
68
31
  # Just disable console access
69
32
  #
70
-
33
+
71
34
  if console['enabled']
72
35
  response = Viaduct::Toolkit.api.port_forwards.save(:id => console['id'], :enabled => 0)
73
36
  if response.success?
@@ -78,13 +41,13 @@ Viaduct::Toolkit.cli.command "app:console" do |c|
78
41
  else
79
42
  puts "Console access isn't currently enabled.".yellow
80
43
  end
81
-
44
+
82
45
  elsif opts.enable
83
-
46
+
84
47
  #
85
48
  # Just enable console access
86
49
  #
87
-
50
+
88
51
  if console['enabled']
89
52
  puts "Console is already enabled.".yellow
90
53
  else
@@ -100,37 +63,13 @@ Viaduct::Toolkit.cli.command "app:console" do |c|
100
63
  error "We couldn't enable console access at this time. Please try later."
101
64
  end
102
65
  end
103
-
66
+
104
67
  else
105
-
106
- #
107
- # Enable if needed and connect.
108
- #
109
- unless console['enabled']
110
- puts "SSH Console access is not currently enabled for this application.".magenta
111
- if enable = agree("Would you like to enable it now?".blue)
112
- disable_after_hour = agree("Would you like to disable this again after an hour?".blue)
113
- response = Viaduct::Toolkit.api.port_forwards.save(:id => console['id'], :enabled => 1, :auto_disable_at => (disable_after_hour ? "1 hour from now" : nil))
114
- unless response.success?
115
- puts response.inspect
116
- error "We couldn't enable console access at this time. Please try later."
117
- end
118
- else
119
- puts "Unfortunately, unless enabled you cannot use this command.".red
120
- exit(1)
121
- end
122
- end
123
-
124
- command = "ssh vdt@#{console['ip_address']} -p #{console['port']}"
125
-
126
- exec(command)
68
+ exec_console_command(console, "ssh vdt@#{console['ip_address']} -p #{console['port']}")
127
69
  end
128
-
129
-
130
70
  end
131
71
  end
132
-
133
- end
134
72
 
73
+ end
135
74
 
136
- Viaduct::Toolkit.cli.alias_command "app:ssh", "app:console"
75
+ Viaduct::Toolkit.cli.alias_command "console", "app:console"
@@ -1,18 +1,18 @@
1
1
  Viaduct::Toolkit.cli.command "app:deployments" do |c|
2
-
3
- c.syntax = "app:deployments SUBDOMAIN_OF_APP"
2
+
3
+ c.syntax = "app:deployments"
4
4
  c.description = "List all deployments for an application"
5
5
  c.option "--page PAGE", Integer, "The page of deployments to return"
6
-
6
+
7
7
  c.action do |args, opts|
8
8
  include Commander::Methods
9
9
  ensure_logged_in!
10
- if application = find_application(args[0])
10
+ if application = find_application
11
11
  response = Viaduct::Toolkit.api.applications.deployments(:application => application['subdomain'], :page => opts.page ? opts.page.to_i : 1)
12
12
  if response.success?
13
13
 
14
14
  require 'terminal-table'
15
-
15
+
16
16
  colourer = Proc.new do |d, field|
17
17
  if d['status'] == 'deployed'
18
18
  field.to_s.green
@@ -22,7 +22,7 @@ Viaduct::Toolkit.cli.command "app:deployments" do |c|
22
22
  field
23
23
  end
24
24
  end
25
-
25
+
26
26
  rows = response.data.map do |d|
27
27
  [
28
28
  colourer.call(d, d['number']),
@@ -0,0 +1,23 @@
1
+ Viaduct::Toolkit.cli.command "app:download" do |c|
2
+
3
+ c.syntax = "app:download [REMOTE_PATH] [LOCAL_PATH]"
4
+ c.description = "Download files from your application"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+ if app = find_application
10
+
11
+ if args[0].nil?
12
+ error "must specify path to file to download"
13
+ end
14
+
15
+ chech_ssh_key_presence
16
+ console = get_application_console_port_forward(app)
17
+ exec_console_command(console, "scp -r -P #{console['port']} vdt@#{console['ip_address']}:#{args[0]} #{args[1] || './'}")
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ Viaduct::Toolkit.cli.alias_command "download", "app:download"
@@ -1,6 +1,6 @@
1
1
  Viaduct::Toolkit.cli.command "app:env" do |c|
2
-
3
- c.syntax = "app:env SUBDOMAIN_OF_APP"
2
+
3
+ c.syntax = "app:env"
4
4
  c.description = "Show all environment variables for an application"
5
5
  c.option "--simple", "Return environment variables "
6
6
  c.option "--yaml", "Return environment variables as YAML file"
@@ -8,7 +8,7 @@ Viaduct::Toolkit.cli.command "app:env" do |c|
8
8
  c.action do |args, opts|
9
9
  include Commander::Methods
10
10
  ensure_logged_in!
11
- if application = find_application(args[0])
11
+ if application = find_application
12
12
  response = Viaduct::Toolkit.api.applications.environment_variables(:application => application['subdomain'])
13
13
  if response.success?
14
14
  if opts.simple
@@ -1,11 +1,11 @@
1
1
  Viaduct::Toolkit.cli.command "app:info" do |c|
2
-
3
- c.syntax = "app:info SUBDOMAIN_OF_APP"
2
+
3
+ c.syntax = "app:info"
4
4
  c.description = "Show details of an existing application"
5
5
  c.action do |args, opts|
6
6
  include Commander::Methods
7
7
  ensure_logged_in!
8
- if application = find_application(args[0])
8
+ if application = find_application
9
9
  details do
10
10
  heading "Application Details"
11
11
  field "Name", application['name']
@@ -20,16 +20,17 @@ Viaduct::Toolkit.cli.command "app:info" do |c|
20
20
  heading "Repository"
21
21
  field 'URL', application['repository']['repository']['url']
22
22
  field 'Status', application['repository']['repository']['status']
23
- field 'Last update', application['repository']['repository']['last_updated_at']
24
- field 'Username', application['repository']['repository']['username']
23
+ field 'Last updated', application['repository']['repository']['last_updated_at']
24
+ if application['repository']['repository']['username']
25
+ field 'Username', application['repository']['repository']['username']
26
+ end
25
27
  field 'Branch', application['repository']['branch']
26
28
  end
27
-
29
+
28
30
  if application['deployment']
29
31
  heading "Active Deployment"
30
32
  field 'Number', application['deployment']['number']
31
33
  field 'Started at', application['deployment']['timing']['created_at']
32
- field 'Time', application['deployment']['timing']['time'].round(1).to_s + "s"
33
34
  field 'Description', application['deployment']['version']['description']
34
35
  field 'Source', application['deployment']['triggered_from']
35
36
  if application['deployment']['user']
@@ -41,5 +42,5 @@ Viaduct::Toolkit.cli.command "app:info" do |c|
41
42
  end
42
43
  end
43
44
  end
44
-
45
- end
45
+
46
+ end
@@ -5,7 +5,7 @@ Viaduct::Toolkit.cli.command "app:list" do |c|
5
5
  c.action do |args, opts|
6
6
  include Commander::Methods
7
7
  ensure_logged_in!
8
-
8
+
9
9
  pages_seen = 0
10
10
  applications = []
11
11
  loop do
@@ -31,6 +31,6 @@ Viaduct::Toolkit.cli.command "app:list" do |c|
31
31
  end
32
32
  table ['Name', 'Subdomain', 'Status', 'Owner'], rows
33
33
  end
34
-
34
+
35
35
  end
36
36
  end
@@ -0,0 +1,60 @@
1
+ Viaduct::Toolkit.cli.command "app:logs" do |c|
2
+ c.syntax = "app:logs"
3
+ c.description = "Stream logs from the remote server to your screen"
4
+ c.option "--process PROCESS_NAME", String, "Only show logs for the given process"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+ if app = find_application
10
+ response = Viaduct::Toolkit.api.applications.status(:application => app['subdomain'])
11
+ if response.success?
12
+
13
+ processes = response.data['processes'].select do |p|
14
+ if opts.process
15
+ p['label'] =~ /\A#{opts.process}/
16
+ else
17
+ true
18
+ end
19
+ end
20
+
21
+ if processes.empty?
22
+ error "No processes found to stream"
23
+ end
24
+
25
+ process_map = processes.inject({}) do |hash, process|
26
+ hash[process['id']] = process['label']
27
+ hash
28
+ end
29
+
30
+ require 'eventmachine'
31
+
32
+ begin
33
+ EM.run do
34
+ Viaduct::Toolkit.api.push.connected do |event|
35
+ process_map.keys.each do |process_id|
36
+ Viaduct::Toolkit.api.push.subscribe :application_process_logs, process_id
37
+ end
38
+ end
39
+
40
+ Viaduct::Toolkit.api.push.receive do |exchange, process_id, data|
41
+ if exchange == :application_process_logs
42
+ tag = "#{process_map[process_id.to_i].rjust(15)} ".blue
43
+ puts "#{tag} #{data['line']}"
44
+ elsif exchange == :global && data['type'] == 'subscribed'
45
+ puts "Streaming logs for #{process_map[data['routing_key'].to_i]}...".yellow
46
+ end
47
+ end
48
+ end
49
+ rescue Interrupt
50
+ puts "Disconnecting..."
51
+ end
52
+ else
53
+ error "Couldn't get application status to determine process list"
54
+ end
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ Viaduct::Toolkit.cli.alias_command "logs", "app:logs"
@@ -0,0 +1,17 @@
1
+ Viaduct::Toolkit.cli.command "app:open" do |c|
2
+
3
+ c.syntax = "app:open"
4
+ c.description = "Open application in the Viaduct web UI"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+ if application = find_application
10
+ require 'launchy'
11
+ Launchy.open("https://my.viaduct.io/applications/#{application['subdomain']}")
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ Viaduct::Toolkit.cli.alias_command "open", "app:open"
@@ -1,12 +1,11 @@
1
1
  Viaduct::Toolkit.cli.command "app:public_key" do |c|
2
- c.syntax = "app:public_key NAME_OF_APP"
2
+ c.syntax = "app:public_key"
3
3
  c.description = "Return the public key for a given application"
4
4
  c.action do |args, opts|
5
5
  include Commander::Methods
6
6
  ensure_logged_in!
7
- if app = find_application(args[0])
7
+ if app = find_application
8
8
  puts app['public_key'] + " Viaduct key for #{app['subdomain']}"
9
9
  end
10
10
  end
11
11
  end
12
- Viaduct::Toolkit.cli.alias_command "app:pk", "app:public_key"
@@ -1,18 +1,17 @@
1
1
  Viaduct::Toolkit.cli.command "app:status" do |c|
2
- c.syntax = "app:status NAME_OF_APP"
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
5
  c.option "--database DATABASE_ID", 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
9
9
  ensure_logged_in!
10
- if app = find_application(args[0])
10
+ if app = find_application
11
11
  response = Viaduct::Toolkit.api.applications.status(:application => app['subdomain'])
12
12
  if response.success?
13
-
14
13
  if opts.process
15
-
14
+
16
15
  if process = response.data['processes'].select { |p| p['label'] == opts.process.to_s }.first
17
16
  details do
18
17
  heading "Details"
@@ -26,10 +25,10 @@ Viaduct::Toolkit.cli.command "app:status" do |c|
26
25
  puts "No process found matching '#{opts.process}'".red
27
26
  exit 1
28
27
  end
29
-
30
-
28
+
29
+
31
30
  elsif opts.database
32
-
31
+
33
32
  if db = response.data['databases'][(opts.database.to_i - 1).abs]
34
33
  details do
35
34
  heading "Database Details"
@@ -41,9 +40,9 @@ Viaduct::Toolkit.cli.command "app:status" do |c|
41
40
  puts "No database found with ID '#{opts.database}'".red
42
41
  exit 1
43
42
  end
44
-
43
+
45
44
  else
46
-
45
+
47
46
  puts "Deployment Details".yellow
48
47
  details do
49
48
  puts "+" + '-' * 78 + '+'
@@ -51,22 +50,22 @@ Viaduct::Toolkit.cli.command "app:status" do |c|
51
50
  field 'Version', response.data['deployment']['version']['id']
52
51
  field "Description", response.data['deployment']['version']['description']
53
52
  field "Source", response.data['deployment']['triggered_from']
54
- field "Deployer", response.data['deployment']['user'] ? response.data['deployment']['user']['full_name'] : response.data['deployment']['triggerer']
53
+ field "Deployer", response.data['deployment']['user'] ? response.data['deployment']['user']['name'] : response.data['deployment']['triggerer']
55
54
  field "Started", time(response.data['deployment']['timing']['started_at'])
56
55
  end
57
-
56
+
58
57
  processes = response.data['processes'].map do |p|
59
58
  memory_used = (p['process']['resources']['memory_usage'] / 1024 / 1024).to_s + "MB"
60
59
  memory_available = (p['process']['resources']['max_memory'] / 1024 / 1024).to_s + "MB"
61
60
  memory = "#{memory_used}/#{memory_available}"
62
-
61
+
63
62
  respawns = "#{p['process']['respawning']['current']}/#{p['process']['respawning']['maximum']}"
64
63
  [p['label'], p['process']['status'].capitalize, memory, p['container']['command'], respawns]
65
64
  end
66
65
  puts
67
66
  puts "Processes".yellow
68
67
  table ['Label', 'Status', 'Memory', 'Command', 'Respawns'], processes
69
-
68
+
70
69
  count = 0
71
70
  databases = response.data['databases'].map do |d|
72
71
  count += 1
@@ -74,7 +73,7 @@ Viaduct::Toolkit.cli.command "app:status" do |c|
74
73
  memory_available = (d['process']['resources']['max_memory'] / 1024 / 1024).to_s + "MB"
75
74
  memory = "#{memory_used}/#{memory_available}"
76
75
  respawns = "#{d['process']['respawning']['current']}/#{d['process']['respawning']['maximum']}"
77
-
76
+
78
77
  [count, d['label'], d['process']['status'].capitalize, d['stack']['name'], memory, respawns, d['process']['networking']['ip_address']]
79
78
  end
80
79
  unless databases.empty?
@@ -83,12 +82,13 @@ Viaduct::Toolkit.cli.command "app:status" do |c|
83
82
  table ['#', 'Label', 'Status', 'Type', 'Memory', 'Respawns', 'IP Address'], databases
84
83
  end
85
84
  end
86
-
85
+
87
86
  else
88
87
  error "Couldn't get application status"
89
88
  end
90
89
  end
91
90
  end
91
+
92
92
  end
93
93
 
94
94
  def process_details(p)
@@ -97,23 +97,25 @@ def process_details(p)
97
97
  field "Host", p['host']
98
98
  field "LXC Name", p['lxc_name']
99
99
  end
100
-
100
+
101
101
  heading "Networking"
102
102
  field "IP Address", p['networking']['ip_address']
103
103
  field "MAC Address", p['networking']['mac_address']
104
104
  field "Data", "RX: #{p['networking']['rx']} TX: #{p['networking']['tx']}"
105
-
105
+
106
106
  heading "Timing"
107
107
  field "Started", time(p['timing']['started'])
108
108
  field "Run time", length_of_time(p['timing']['run_time'])
109
109
  field "Last seen", time(p['timing']['last_seen_at'])
110
-
110
+
111
111
  heading "Resources"
112
112
  field "Memory", "#{p['resources']['memory_usage'] /1024/1024}MB of #{p['resources']['max_memory']/1024/1024}MB"
113
113
  field "CPU Usage", p['resources']['cpu_usage']
114
-
114
+
115
115
  heading "Respawning"
116
116
  field "Respawns", "#{p['respawning']['current']} / #{p['respawning']['maximum']}"
117
117
  field "Last respawn", time(p['respawning']['last'])
118
118
 
119
119
  end
120
+
121
+ Viaduct::Toolkit.cli.alias_command "status", "app:status"
@@ -0,0 +1,23 @@
1
+ Viaduct::Toolkit.cli.command "app:upload" do |c|
2
+
3
+ c.syntax = "app:upload [LOCAL_PATH] [REMOTE_PATH]"
4
+ c.description = "Upload files to your application"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+ if app = find_application
10
+
11
+ if args[0].nil?
12
+ error "must specify path to file to upload"
13
+ end
14
+
15
+ chech_ssh_key_presence
16
+ console = get_application_console_port_forward(app)
17
+ exec_console_command(console, "scp -r -P #{console['port']} #{args[0]} vdt@#{console['ip_address']}:#{args[1] || './'}")
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ Viaduct::Toolkit.cli.alias_command "upload", "app:upload"
@@ -0,0 +1,17 @@
1
+ Viaduct::Toolkit.cli.command "app:visit" do |c|
2
+
3
+ c.syntax = "app:visit"
4
+ c.description = "Visit application in a web browser"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+ if application = find_application
10
+ require 'launchy'
11
+ Launchy.open("https://#{application['main_domain'] ? application['main_domain']['name'] : application['viaduct_domain']}")
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ Viaduct::Toolkit.cli.alias_command "visit", "app:visit"
@@ -0,0 +1,33 @@
1
+ Viaduct::Toolkit.cli.command "db:console" do |c|
2
+
3
+ c.syntax = "db:console"
4
+ c.description = "Open a console session for the given database"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+
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
19
+
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
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,31 @@
1
+ Viaduct::Toolkit.cli.command "db:list" do |c|
2
+
3
+ c.syntax = "db:list"
4
+ c.description = "List all databases assigned to this application"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+ if app = find_application
10
+
11
+ shared_databases = Viaduct::Toolkit.api.shared_databases.all(:application => app['subdomain'])
12
+ error "Couldn't get shared databases" unless shared_databases.success?
13
+ dedicated_databases = Viaduct::Toolkit.api.dedicated_databases.all(:application => app['subdomain'])
14
+ error "Couldn't get dedicated databaes" unless dedicated_databases.success?
15
+
16
+
17
+ rows = []
18
+ shared_databases.data.each do |db|
19
+ rows << [db['fruit'], db['label'], 'Hobby/Dev', db['type'].split('::').last]
20
+ end
21
+
22
+ dedicated_databases.data.each do |db|
23
+ rows << [db['fruit'], db['label'], 'Production', db['stack']['name']]
24
+ end
25
+
26
+ table ['ID', 'Label', 'Type', 'Engine'], rows.sort_by { |r| r[0] }
27
+
28
+ end
29
+ end
30
+
31
+ end
@@ -1,10 +1,10 @@
1
1
  Viaduct::Toolkit.cli.command "domain:list" do |c|
2
- c.syntax = "domain:list NAME_OF_APP"
2
+ c.syntax = "domain:list"
3
3
  c.description = "Return a list of domains for an application"
4
4
  c.action do |args, opts|
5
5
  include Commander::Methods
6
6
  ensure_logged_in!
7
- if app = find_application(args[0])
7
+ if app = find_application
8
8
  response = Viaduct::Toolkit.api.domains.all(:application => app['subdomain'])
9
9
  if response.success?
10
10
  rows = response.data.map do |d|
@@ -2,31 +2,21 @@ Viaduct::Toolkit.cli.command "login" do |c|
2
2
  c.syntax = "login"
3
3
  c.description = "Authenticate this computer with your Viaduct account"
4
4
  c.action do |args, options|
5
-
6
- Viaduct::Toolkit.config['token'] = nil
7
- Viaduct::Toolkit.config['secret'] = nil
5
+
6
+ Viaduct::Toolkit.env_config['token'] = nil
7
+ Viaduct::Toolkit.env_config['secret'] = nil
8
8
  Viaduct::Toolkit.save_config
9
-
9
+
10
10
  response = Viaduct::Toolkit.api.authentication.create_login_token
11
11
  if response.success?
12
-
13
- puts "To log you in we need to open a browser window to allow".magenta
12
+
13
+ puts "To log you in we've opened a browser window to allow".magenta
14
14
  puts "you to enter your login details. ".magenta
15
- puts
16
- if agree("Shall we open this for you?".blue)
17
- system("open", response.data['url'])
18
- else
19
- puts
20
- puts "That's fine. Just go to the URL below in your browser.".magenta
21
- puts "This command will continue to run until you complete this".magenta
22
- puts "action.".magenta
23
- puts
24
- puts response.data['url']
25
- end
26
-
15
+ require 'launchy'
16
+ Launchy.open(response.data['url'])
17
+
27
18
  puts
28
19
  puts "Please wait while we verify your login...".magenta
29
- puts
30
20
  check_response = nil
31
21
  100.times do
32
22
  sleep 3
@@ -43,14 +33,15 @@ Viaduct::Toolkit.cli.command "login" do |c|
43
33
  error "Couldn't successfully exchange login token for an API token. Please try again later."
44
34
  end
45
35
  end
46
-
36
+
47
37
  if @authorised
48
- Viaduct::Toolkit.config['token'] = check_response.data['token']['token']
49
- Viaduct::Toolkit.config['secret'] = check_response.data['token']['secret']
38
+ Viaduct::Toolkit.env_config['token'] = check_response.data['token']['token']
39
+ Viaduct::Toolkit.env_config['secret'] = check_response.data['token']['secret']
50
40
 
51
41
  user_check = Viaduct::Toolkit.api.user.details
52
42
  if user_check.success?
53
43
  Viaduct::Toolkit.save_config
44
+ puts
54
45
  puts "Hello #{user_check.data['name']}!".green
55
46
  puts "Your user account is now authorised. Your login details are".magenta
56
47
  puts "stored in a .viaduct file in your home directory.".magenta
@@ -61,10 +52,10 @@ Viaduct::Toolkit.cli.command "login" do |c|
61
52
  else
62
53
  error "We didn't receive a login response in a timely manner. Please try again."
63
54
  end
64
-
55
+
65
56
  else
66
57
  error "Couldn't generate a remote login token. Please try again."
67
58
  end
68
-
59
+
69
60
  end
70
- end
61
+ end
@@ -1,14 +1,14 @@
1
1
  Viaduct::Toolkit.cli.command "ssh_key:add" do |c|
2
-
2
+
3
3
  c.syntax = "ssh_keys:add PATH_TO_PUBLIC_KEY"
4
4
  c.description = "Add a new SSH public key to your user account"
5
-
5
+
6
6
  c.action do |args, opts|
7
7
  include Commander::Methods
8
8
  ensure_logged_in!
9
-
9
+
10
10
  key_path = args[0]
11
-
11
+
12
12
  default_key_path = File.join(ENV['HOME'], '.ssh', 'id_rsa.pub')
13
13
  if key_path.nil? && File.exist?(default_key_path)
14
14
  puts "You haven't provided an SSH key to this command.".yellow
@@ -18,7 +18,7 @@ Viaduct::Toolkit.cli.command "ssh_key:add" do |c|
18
18
  exit(1)
19
19
  end
20
20
  end
21
-
21
+
22
22
  if File.exist?(key_path)
23
23
  response = Viaduct::Toolkit.api.ssh_keys.add(:label => "Added from #{`hostname`}", :key => File.read(key_path))
24
24
  if response.success?
@@ -36,5 +36,5 @@ Viaduct::Toolkit.cli.command "ssh_key:add" do |c|
36
36
  exit(1)
37
37
  end
38
38
  end
39
-
39
+
40
40
  end
@@ -1,12 +1,12 @@
1
1
  Viaduct::Toolkit.cli.command "ssh_key:list" do |c|
2
-
2
+
3
3
  c.syntax = "ssh_key:list"
4
4
  c.description = "List the keys associated with your account"
5
-
5
+
6
6
  c.action do |args, opts|
7
7
  include Commander::Methods
8
8
  ensure_logged_in!
9
-
9
+
10
10
  response = Viaduct::Toolkit.api.ssh_keys.all
11
11
  if response.success?
12
12
  require 'terminal-table'
@@ -15,12 +15,12 @@ Viaduct::Toolkit.cli.command "ssh_key:list" do |c|
15
15
  end
16
16
  table = Terminal::Table.new :rows => rows, :headings => ['Label', 'Fingerprint']
17
17
  puts table
18
-
18
+
19
19
  else
20
20
  error "Couldn't get the SSH key list."
21
21
  end
22
-
22
+
23
23
  end
24
-
24
+
25
25
  end
26
26
 
@@ -4,7 +4,7 @@ module Viaduct
4
4
  module Toolkit
5
5
  module Helpers
6
6
  def ensure_logged_in!
7
- if Viaduct::Toolkit.config['token'].nil? && Viaduct::Toolkit.config['secret'].nil?
7
+ if Viaduct::Toolkit.env_config['token'].nil? && Viaduct::Toolkit.env_config['secret'].nil?
8
8
  puts "You need to login before using this toolkit. Use the command below".yellow
9
9
  puts "to login to your Viaduct account.".yellow
10
10
  puts
@@ -13,26 +13,26 @@ module Viaduct
13
13
  exit 1
14
14
  end
15
15
  end
16
-
16
+
17
17
  def length_of_time(seconds)
18
18
  "#{seconds} seconds"
19
19
  end
20
-
20
+
21
21
  def time(time)
22
22
  require 'time'
23
23
  time = Time.parse(time) rescue nil
24
24
  time ? time.strftime("%d %B %Y at %H:%M:%S UTC") : ''
25
25
  end
26
-
26
+
27
27
  def boolean(bool)
28
28
  bool ? "\u2713".green : "-".red
29
29
  end
30
-
30
+
31
31
  def table(headings, rows)
32
32
  require 'terminal-table'
33
33
  puts Terminal::Table.new :rows => rows, :headings => headings.map(&:blue)
34
34
  end
35
-
35
+
36
36
  def validation_errors(errors)
37
37
  errors.each do |field, messages|
38
38
  messages.each do |message|
@@ -40,23 +40,23 @@ module Viaduct
40
40
  end
41
41
  end
42
42
  end
43
-
43
+
44
44
  def error(message)
45
45
  raise Viaduct::Toolkit::Error, message
46
46
  end
47
-
47
+
48
48
  def run(*commands)
49
49
  stdin, stdout, stderr, w = Open3.popen3(*commands)
50
50
  [stdout.gets(nil), stderr.gets(nil), w.value]
51
51
  end
52
-
53
- def find_application(subdomain)
54
- if subdomain.is_a?(String) && subdomain.length > 0
55
- app = Viaduct::Toolkit.api.applications.info(:application => subdomain)
52
+
53
+ def find_application
54
+ if $app.is_a?(String) && $app.length > 0
55
+ app = Viaduct::Toolkit.api.applications.info(:application => $app)
56
56
  if app.success?
57
57
  return app.data
58
58
  else
59
- puts "Couldn't find application with subdomain matching '#{subdomain}'".red
59
+ puts "Couldn't find application with subdomain matching '#{$app}'".red
60
60
  exit(1)
61
61
  end
62
62
  else
@@ -73,39 +73,95 @@ module Viaduct
73
73
  end
74
74
  exit(1)
75
75
  elsif app.data.size == 1
76
- return find_application(app.data.first['subdomain'])
76
+ $app = app.data.first['subdomain']
77
+ return find_application
77
78
  else
78
79
  puts "Multiple applications found matching your repository. Choose an application...".yellow
79
80
  choice = choose('', *app.data.map { |a| "#{a['subdomain']}: #{a['name']}"})
80
81
  choice = choice.split(":", 2).first
81
- return find_application(choice)
82
+ $app = choice
83
+ return find_application()
82
84
  end
83
85
  end
84
86
  end
85
87
  end
86
-
88
+
87
89
  puts "Couldn't determine a Viaduct application from command.".red
88
90
  exit(1)
89
91
  end
90
-
92
+
91
93
  def heading(title)
92
- puts "+" + ("-" * 78) + "+"
94
+ puts "+" + ("-" * 78) + "+"
93
95
  puts "| #{title.ljust(76).yellow} |"
94
- puts "+" + ("-" * 78) + "+"
96
+ puts "+" + ("-" * 78) + "+"
95
97
  end
96
-
98
+
97
99
  def field(key, value)
98
100
  key = key[0,16].ljust(16, ' ')
99
101
  value = value.to_s[0,58].ljust(58)
100
-
102
+
101
103
  puts "| #{key.blue}| #{value} |"
102
104
  end
103
-
105
+
104
106
  def details(&block)
105
107
  block.call
106
- puts "+" + ("-" * 78) + "+"
108
+ puts "+" + ("-" * 78) + "+"
109
+ end
110
+
111
+ def chech_ssh_key_presence
112
+ response = Viaduct::Toolkit.api.ssh_keys.all
113
+ if response.success?
114
+
115
+ if response.data.empty?
116
+ puts "You haven't uploaded any SSH keys to your Viaduct user account.".red
117
+ puts "You cannot use SSH console access without them.".red
118
+ puts
119
+ puts "Upload your key using the command below".blue
120
+ puts
121
+ puts " $ vdt ssh_keys:add".blue
122
+ puts
123
+ exit(1)
124
+ else
125
+ stdout, stderr, status = run("ssh-add -l")
126
+ if status == 0
127
+ remote_fingerprints = response.data.map { |d| d['fingerprint'] }
128
+ local_fingerprints = stdout.split(/\n/).map { |l| l.split(/\s+/)[1] }
129
+ unless remote_fingerprints.any? { |f| local_fingerprints.include?(f) }
130
+ puts "Warning: it doesn't seem as though your SSH key has been uploaded".yellow
131
+ puts "to your Viaduct account. This session may not succeed. If it doesn't".yellow
132
+ puts "ensure that you have uploaded to your SSH key to your Viaduct account.".yellow
133
+ end
134
+ end
135
+ end
136
+ else
137
+ error "Couldn't verify remote SSH keys. Please try again."
138
+ end
107
139
  end
108
-
140
+
141
+ def get_application_console_port_forward(app)
142
+ response = Viaduct::Toolkit.api.port_forwards.all(:application => app['subdomain'])
143
+ if response.success?
144
+ if console = response.data.select { |c| c['mode'] == 'console'}.first
145
+ console
146
+ else
147
+ error "Console access is not supported by this application. Please contact support."
148
+ end
149
+ else
150
+ error "Couldn't get port forward information from API for application."
151
+ end
152
+ end
153
+
154
+ def exec_console_command(console, command)
155
+ unless console['enabled']
156
+ response = Viaduct::Toolkit.api.port_forwards.save(:id => console['id'], :enabled => 1, :auto_disable_at => '5 minutes from now')
157
+ unless response.success?
158
+ error "We couldn't enable console access at this time. Please try later."
159
+ end
160
+ end
161
+ puts "Connecting...".magenta
162
+ exec(command)
163
+ end
164
+
109
165
  end
110
166
  end
111
167
  end
@@ -1,5 +1,5 @@
1
1
  module Viaduct
2
2
  module Toolkit
3
- VERSION = '0.0.3'
3
+ VERSION = '0.1.0'
4
4
  end
5
5
  end
@@ -13,16 +13,16 @@ Commander::Methods.send :include, Viaduct::Toolkit::Helpers
13
13
 
14
14
  module Viaduct
15
15
  module Toolkit
16
-
16
+
17
17
  class Error < StandardError
18
18
  end
19
-
19
+
20
20
  class << self
21
-
21
+
22
22
  def binary
23
23
  File.expand_path(File.join('..', '..', '..', 'bin', 'viaduct'), __FILE__)
24
24
  end
25
-
25
+
26
26
  def cli
27
27
  @cli ||= begin
28
28
  c = Commander::Runner.instance
@@ -30,47 +30,59 @@ module Viaduct
30
30
  c.program :version, Viaduct::Toolkit::VERSION
31
31
  c.program :description, "A CLI toolkit for Viaduct developers"
32
32
  c.global_option('-c', '--config FILE', 'The config file to store local credentials within') { |file| $config_file_path = file }
33
+ c.global_option('--app NAME', 'The application to work on') { |name| $app = name }
34
+ c.global_option('--dev', 'Connect to local development installation of Viaduct (dev only)') { $dev = true }
33
35
  c.default_command :help
34
36
  c
35
37
  end
36
38
  end
37
-
39
+
38
40
  def add_commands
39
41
  Dir[File.expand_path(File.join('..', 'toolkit', 'commands', '*.rb'), __FILE__)].each do |file|
40
42
  require file
41
43
  end
42
44
  end
43
-
45
+
44
46
  def api
45
47
  @api ||= begin
46
- Viaduct::API::Client.new(config['token'], config['secret'])
48
+ if $dev
49
+ Viaduct::API.host = 'localhost'
50
+ Viaduct::API.port = 5000
51
+ Viaduct::API.ssl = false
52
+ Viaduct::API.application_token = 'example'
53
+ end
54
+ Viaduct::API::Client.new(env_config['token'], env_config['secret'])
47
55
  end
48
56
  end
49
-
57
+
50
58
  def reset_api
51
59
  @api = nil
52
60
  end
53
-
61
+
54
62
  def config_file_path
55
63
  $config_file_path || File.join(ENV['HOME'], '.viaduct')
56
64
  end
57
-
65
+
66
+ def env_config
67
+ config[$dev ? 'dev' : 'live'] ||= {}
68
+ end
69
+
58
70
  def config
59
71
  @config ||= begin
60
72
  if File.exist?(config_file_path)
61
- YAML.load_file(config_file_path)
73
+ YAML.load_file(config_file_path) || {}
62
74
  else
63
75
  {}
64
76
  end
65
77
  end
66
78
  end
67
-
79
+
68
80
  def save_config
69
81
  File.open(config_file_path, 'w') do |f|
70
82
  f.write self.config.to_yaml
71
83
  end
72
84
  end
73
-
85
+
74
86
  end
75
87
  end
76
88
  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.0.3
4
+ version: 0.1.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-10-21 00:00:00.000000000 Z
11
+ date: 2014-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.0'
33
+ version: 1.0.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.0'
40
+ version: 1.0.5
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: colorize
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +72,26 @@ dependencies:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
74
  version: 1.4.5
75
+ - !ruby/object:Gem::Dependency
76
+ name: launchy
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 2.4.2
82
+ - - "<"
83
+ - !ruby/object:Gem::Version
84
+ version: '3.0'
85
+ type: :runtime
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 2.4.2
92
+ - - "<"
93
+ - !ruby/object:Gem::Version
94
+ version: '3.0'
75
95
  description: A set of useful tools to help developers use & manage their Viaduct applications.
76
96
  email:
77
97
  - adam@viaduct.io
@@ -84,11 +104,18 @@ files:
84
104
  - lib/viaduct/toolkit.rb
85
105
  - lib/viaduct/toolkit/commands/app_console.rb
86
106
  - lib/viaduct/toolkit/commands/app_deployments.rb
107
+ - lib/viaduct/toolkit/commands/app_download.rb
87
108
  - lib/viaduct/toolkit/commands/app_env.rb
88
109
  - lib/viaduct/toolkit/commands/app_info.rb
89
110
  - lib/viaduct/toolkit/commands/app_list.rb
111
+ - lib/viaduct/toolkit/commands/app_logs.rb
112
+ - lib/viaduct/toolkit/commands/app_open.rb
90
113
  - lib/viaduct/toolkit/commands/app_public_key.rb
91
114
  - lib/viaduct/toolkit/commands/app_status.rb
115
+ - lib/viaduct/toolkit/commands/app_upload.rb
116
+ - lib/viaduct/toolkit/commands/app_visit.rb
117
+ - lib/viaduct/toolkit/commands/db_console.rb
118
+ - lib/viaduct/toolkit/commands/db_list.rb
92
119
  - lib/viaduct/toolkit/commands/domain_list.rb
93
120
  - lib/viaduct/toolkit/commands/login.rb
94
121
  - lib/viaduct/toolkit/commands/ssh_key_add.rb