viaduct-toolkit 0.0.3 → 0.1.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: 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