viaduct-toolkit 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a7eceb02225b5d2bdba774374a4b0cc66ad28d43
4
+ data.tar.gz: 3af40448a600abcf1708c9e15d05bbdeed9d898f
5
+ SHA512:
6
+ metadata.gz: bfd1069aada93499f1ede946a415bce09be8e1733e2b9acdabd29b632dc4c8748fb445daa78243e59b5c9c5aaf696e46fe49d8a1193b07924158bc8084eb247b
7
+ data.tar.gz: da954154572bede916028769b4dac835d2976c54fb13504281e2d0f35544948ff025c877567328bace915fdf8c6014d0f4fe520e91e3edac1e0bbafa177177cb
@@ -0,0 +1,76 @@
1
+ require 'yaml'
2
+ require 'colorize'
3
+ require 'commander'
4
+ require 'viaduct/toolkit/version'
5
+ require 'viaduct/api'
6
+
7
+ # Hardcoded for this application.
8
+ Viaduct::API.application_token = '3148984b-8a50-424c-98f5-117e8dea2971'
9
+
10
+ # Add our helpers to Commander
11
+ require 'viaduct/toolkit/helpers'
12
+ Commander::Methods.send :include, Viaduct::Toolkit::Helpers
13
+
14
+ module Viaduct
15
+ module Toolkit
16
+
17
+ class Error < StandardError
18
+ end
19
+
20
+ class << self
21
+
22
+ def binary
23
+ File.expand_path(File.join('..', '..', '..', 'bin', 'viaduct'), __FILE__)
24
+ end
25
+
26
+ def cli
27
+ @cli ||= begin
28
+ c = Commander::Runner.instance
29
+ c.program :name, "Viaduct Toolkit"
30
+ c.program :version, Viaduct::Toolkit::VERSION
31
+ c.program :description, "A CLI toolkit for Viaduct developers"
32
+ c.global_option('-c', '--config FILE', 'The config file to store local credentials within') { |file| $config_file_path = file }
33
+ c.default_command :help
34
+ c
35
+ end
36
+ end
37
+
38
+ def add_commands
39
+ Dir[File.expand_path(File.join('..', 'toolkit', 'commands', '*.rb'), __FILE__)].each do |file|
40
+ require file
41
+ end
42
+ end
43
+
44
+ def api
45
+ @api ||= begin
46
+ Viaduct::API::Client.new(config['token'], config['secret'])
47
+ end
48
+ end
49
+
50
+ def reset_api
51
+ @api = nil
52
+ end
53
+
54
+ def config_file_path
55
+ $config_file_path || File.join(ENV['HOME'], '.viaduct')
56
+ end
57
+
58
+ def config
59
+ @config ||= begin
60
+ if File.exist?(config_file_path)
61
+ YAML.load_file(config_file_path)
62
+ else
63
+ {}
64
+ end
65
+ end
66
+ end
67
+
68
+ def save_config
69
+ File.open(config_file_path, 'w') do |f|
70
+ f.write self.config.to_yaml
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,136 @@
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"
5
+ c.option "--disable", "Disable access to the SSH console"
6
+ c.option "--enable", "Enable access to the SSH console"
7
+ c.option "--status", "Display the status of the port forward"
8
+
9
+ c.action do |args, opts|
10
+ include Commander::Methods
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
+
54
+ if opts.status
55
+ details do
56
+ heading "SSH console access"
57
+ field "Status", console['enabled'] ? "Enabled" : "Disabled"
58
+ field "Auto disable?", console['auto_disable_at'] ? time(console['auto_disable_at']) : ''
59
+ field "Connection", "#{console['ip_address']}:#{console['port']}"
60
+ console['allowed_ips'].each_with_index do |ip, i|
61
+ field i == 0 ? 'Allowed IPs' : '', ip
62
+ end
63
+ end
64
+
65
+ elsif opts.disable
66
+
67
+ #
68
+ # Just disable console access
69
+ #
70
+
71
+ if console['enabled']
72
+ response = Viaduct::Toolkit.api.port_forwards.save(:id => console['id'], :enabled => 0)
73
+ if response.success?
74
+ puts "Console access has been disabled.".green
75
+ else
76
+ error "We couldn't disable console access at this time. Please try later."
77
+ end
78
+ else
79
+ puts "Console access isn't currently enabled.".yellow
80
+ end
81
+
82
+ elsif opts.enable
83
+
84
+ #
85
+ # Just enable console access
86
+ #
87
+
88
+ if console['enabled']
89
+ puts "Console is already enabled.".yellow
90
+ else
91
+ auto_disable = agree("Would you like to disable this again after an hour?".blue)
92
+ response = Viaduct::Toolkit.api.port_forwards.save(:id => console['id'], :enabled => 1, :auto_disable_at => (auto_disable ? '1 hour from now' : nil))
93
+ if response.success?
94
+ if auto_disable
95
+ puts "Console access has been enaled and will be automatically disabled again in 1 hour.".green
96
+ else
97
+ puts "Console access has been enabled.".green
98
+ end
99
+ else
100
+ error "We couldn't enable console access at this time. Please try later."
101
+ end
102
+ end
103
+
104
+ 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)
127
+ end
128
+
129
+
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+
136
+ Viaduct::Toolkit.cli.alias_command "app:ssh", "app:console"
@@ -0,0 +1,25 @@
1
+ Viaduct::Toolkit.cli.command "app:deployments" do |c|
2
+
3
+ c.syntax = "app:deployments SUBDOMAIN_OF_APP"
4
+ c.description = "List all deployments for an application"
5
+ c.option "--page PAGE", Integer, "The page of deployments to return"
6
+
7
+ c.action do |args, opts|
8
+ include Commander::Methods
9
+ ensure_logged_in!
10
+ if application = find_application(args[0])
11
+ response = Viaduct::Toolkit.api.applications.deployments(:application => application['subdomain'], :page => opts.page ? opts.page.to_i : 1)
12
+ if response.success?
13
+
14
+ require 'terminal-table'
15
+ rows = response.data.map do |d|
16
+ [d['number'], d['status'], d['version']['description'].to_s[0,30], d['user'] ? d['user']['username'] : '', d['timing']['created_at']]
17
+ end
18
+ puts Terminal::Table.new :rows => rows, :headings => ['#', 'Status', 'Description', 'User', 'Time']
19
+
20
+ else
21
+ error "Couldn't get application deployment list"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ Viaduct::Toolkit.cli.command "app:env" do |c|
2
+
3
+ c.syntax = "app:env SUBDOMAIN_OF_APP"
4
+ c.description = "Show all environment variables for an application"
5
+ c.option "--simple", "Return environment variables "
6
+ c.option "--yaml", "Return environment variables as YAML file"
7
+ c.option "--export", "Return environment variables as export lines"
8
+ c.action do |args, opts|
9
+ include Commander::Methods
10
+ ensure_logged_in!
11
+ if application = find_application(args[0])
12
+ response = Viaduct::Toolkit.api.applications.environment_variables(:application => application['subdomain'])
13
+ if response.success?
14
+ if opts.simple
15
+ response.data.each do |key, value|
16
+ puts "#{key}: #{value}"
17
+ end
18
+ elsif opts.yaml
19
+ require 'yaml'
20
+ puts response.data.to_yaml
21
+ elsif opts.export
22
+ response.data.each do |key, value|
23
+ puts "export #{key}=\"#{value}\""
24
+ end
25
+ else
26
+ require 'terminal-table'
27
+ puts Terminal::Table.new :rows => response.data.to_a
28
+ end
29
+ else
30
+ error "Couldn't get environment variables"
31
+ end
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,42 @@
1
+ Viaduct::Toolkit.cli.command "app:info" do |c|
2
+
3
+ c.syntax = "app:info SUBDOMAIN_OF_APP"
4
+ c.description = "Show details of an existing application"
5
+ c.action do |args, opts|
6
+ include Commander::Methods
7
+ ensure_logged_in!
8
+ if application = find_application(args[0])
9
+ details do
10
+ heading "Application Details"
11
+ field "Name", application['name']
12
+ field "Viaduct Domain", application['viaduct_domain']
13
+ field "Status", application['status']
14
+ field "Maintenance", application['maintenance?'] ? 'Yes' : 'No'
15
+ field 'Owner', "#{application['user']['name']} (#{application['user']['username']})"
16
+ field "Zone", application['zone']['name']
17
+ field "Platform", "#{application['platform']['name']} (on #{application['platform']['stack']['name']} stack)"
18
+ field "Subnet(s)", application['subnets'].map { |s| s['description'] }.join(', ')
19
+ if application['repository'] && application['source_backend_module'] == 'Viaduct::SourceBackends::Repository'
20
+ heading "Repository"
21
+ field 'URL', application['repository']['repository']['url']
22
+ field 'Status', application['repository']['repository']['status']
23
+ field 'Last update', application['repository']['repository']['last_updated_at']
24
+ field 'Username', application['repository']['repository']['username']
25
+ field 'Branch', application['repository']['branch']
26
+ end
27
+
28
+ if application['deployment']
29
+ heading "Active Deployment"
30
+ field 'Number', application['deployment']['number']
31
+ field 'Started at', application['deployment']['timing']['created_at']
32
+ field 'Time', application['deployment']['timing']['time'].round(1).to_s + "s"
33
+ field 'Description', application['deployment']['version']['description']
34
+ if application['deployment']['user']
35
+ field 'Deployer', "#{application['deployment']['user']['name']} (#{application['deployment']['user']['username']})"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,36 @@
1
+ Viaduct::Toolkit.cli.command "app:list" do |c|
2
+ c.syntax = "app:list"
3
+ c.description = "Show a list of all applications you have access to"
4
+ c.option "--simple", "Return just a list of subdomains"
5
+ c.action do |args, opts|
6
+ include Commander::Methods
7
+ ensure_logged_in!
8
+
9
+ pages_seen = 0
10
+ applications = []
11
+ loop do
12
+ response = Viaduct::Toolkit.api.applications.all(:page => pages_seen + 1)
13
+ if response.success?
14
+ applications = applications | response.data
15
+ else
16
+ error "Couldn't get list of applications."
17
+ end
18
+ pages_seen += 1
19
+ if pages_seen == response.flags['paginated']['page']
20
+ break
21
+ end
22
+ end
23
+
24
+ if opts.simple
25
+ applications.each do |application|
26
+ puts application['subdomain']
27
+ end
28
+ else
29
+ rows = applications.map do |app|
30
+ [app['name'], app['subdomain'], app['status'], app['user']['name']]
31
+ end
32
+ table ['Name', 'Subdomain', 'Status', 'Owner'], rows
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ Viaduct::Toolkit.cli.command "app:public_key" do |c|
2
+ c.syntax = "app:public_key NAME_OF_APP"
3
+ c.description = "Return the public key for a given application"
4
+ c.action do |args, opts|
5
+ include Commander::Methods
6
+ ensure_logged_in!
7
+ if app = find_application(args[0])
8
+ puts app['public_key'] + " Viaduct key for #{app['subdomain']}"
9
+ end
10
+ end
11
+ end
12
+ Viaduct::Toolkit.cli.alias_command "app:pk", "app:public_key"
@@ -0,0 +1,118 @@
1
+ Viaduct::Toolkit.cli.command "app:status" do |c|
2
+ c.syntax = "app:status NAME_OF_APP"
3
+ c.description = "Return current status of an application"
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"
6
+
7
+ c.action do |args, opts|
8
+ include Commander::Methods
9
+ ensure_logged_in!
10
+ if app = find_application(args[0])
11
+ response = Viaduct::Toolkit.api.applications.status(:application => app['subdomain'])
12
+ if response.success?
13
+
14
+ if opts.process
15
+
16
+ if process = response.data['processes'].select { |p| p['label'] == opts.process.to_s }.first
17
+ details do
18
+ heading "Details"
19
+ field "Label", process['label']
20
+ field "Command", process['container']['command']
21
+ field "Public?", process['container']['public'] ? 'Yes' : 'No'
22
+ field "Status", process['process']['status'].capitalize
23
+ process_details(process['process'])
24
+ end
25
+ else
26
+ puts "No process found matching '#{opts.process}'".red
27
+ exit 1
28
+ end
29
+
30
+
31
+ elsif opts.database
32
+
33
+ if db = response.data['databases'][(opts.database.to_i - 1).abs]
34
+ details do
35
+ heading "Database Details"
36
+ field "Label", db['label']
37
+ field "Database", db['stack']['name']
38
+ process_details(db['process'])
39
+ end
40
+ else
41
+ puts "No database found with ID '#{opts.database}'".red
42
+ exit 1
43
+ end
44
+
45
+ else
46
+
47
+ puts "Deployment Details".yellow
48
+ details do
49
+ puts "+" + '-' * 78 + '+'
50
+ field "Number", response.data['deployment']['number']
51
+ field 'Version', response.data['deployment']['version']['id']
52
+ field "Description", response.data['deployment']['version']['description']
53
+ field "Deployer", response.data['deployment']['user'] ? response.data['deployment']['user']['full_name'] : ''
54
+ field "Started", time(response.data['deployment']['timing']['started_at'])
55
+ end
56
+
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}"
61
+
62
+ respawns = "#{p['process']['respawning']['current']}/#{p['process']['respawning']['maximum']}"
63
+ [p['label'], p['process']['status'].capitalize, memory, p['container']['command'], respawns]
64
+ end
65
+ puts
66
+ puts "Processes".yellow
67
+ table ['Label', 'Status', 'Memory', 'Command', 'Respawns'], processes
68
+
69
+ count = 0
70
+ databases = response.data['databases'].map do |d|
71
+ 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}"
75
+ respawns = "#{d['process']['respawning']['current']}/#{d['process']['respawning']['maximum']}"
76
+
77
+ [count, d['label'], d['process']['status'].capitalize, d['stack']['name'], memory, respawns, d['process']['networking']['ip_address']]
78
+ end
79
+ unless databases.empty?
80
+ puts
81
+ puts "Dedicated Databases".yellow
82
+ table ['#', 'Label', 'Status', 'Type', 'Memory', 'Respawns', 'IP Address'], databases
83
+ end
84
+ end
85
+
86
+ else
87
+ error "Couldn't get application status"
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def process_details(p)
94
+ if p['host'] && p['lxc_name']
95
+ heading "Host (admin only)"
96
+ field "Host", p['host']
97
+ field "LXC Name", p['lxc_name']
98
+ end
99
+
100
+ heading "Networking"
101
+ field "IP Address", p['networking']['ip_address']
102
+ field "MAC Address", p['networking']['mac_address']
103
+ field "Data", "RX: #{p['networking']['rx']} TX: #{p['networking']['tx']}"
104
+
105
+ heading "Timing"
106
+ field "Started", time(p['timing']['started'])
107
+ field "Run time", length_of_time(p['timing']['run_time'])
108
+ field "Last seen", time(p['timing']['last_seen_at'])
109
+
110
+ heading "Resources"
111
+ field "Memory", "#{p['resources']['memory_usage'] /1024/1024}MB of #{p['resources']['max_memory']/1024/1024}MB"
112
+ field "CPU Usage", p['resources']['cpu_usage']
113
+
114
+ heading "Respawning"
115
+ field "Respawns", "#{p['respawning']['current']} / #{p['respawning']['maximum']}"
116
+ field "Last respawn", time(p['respawning']['last'])
117
+
118
+ end
@@ -0,0 +1,19 @@
1
+ Viaduct::Toolkit.cli.command "domain:list" do |c|
2
+ c.syntax = "domain:list NAME_OF_APP"
3
+ c.description = "Return a list of domains for an application"
4
+ c.action do |args, opts|
5
+ include Commander::Methods
6
+ ensure_logged_in!
7
+ if app = find_application(args[0])
8
+ response = Viaduct::Toolkit.api.domains.all(:application => app['subdomain'])
9
+ if response.success?
10
+ rows = response.data.map do |d|
11
+ [d['name'], boolean(d['verification']['verified?']), d['ssl'], d['routing']['cname'], d['routing']['ip']]
12
+ end
13
+ table ['Name', 'Verified', 'SSL', 'CNAME', 'IP'], rows
14
+ else
15
+ error "Couldn't get domain list"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,70 @@
1
+ Viaduct::Toolkit.cli.command "login" do |c|
2
+ c.syntax = "login"
3
+ c.description = "Authenticate this computer with your Viaduct account"
4
+ c.action do |args, options|
5
+
6
+ Viaduct::Toolkit.config['token'] = nil
7
+ Viaduct::Toolkit.config['secret'] = nil
8
+ Viaduct::Toolkit.save_config
9
+
10
+ response = Viaduct::Toolkit.api.authentication.create_login_token
11
+ if response.success?
12
+
13
+ puts "To log you in we need to open a browser window to allow".magenta
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
+
27
+ puts
28
+ puts "Please wait while we verify your login...".magenta
29
+ puts
30
+ check_response = nil
31
+ 100.times do
32
+ sleep 3
33
+ check_response = Viaduct::Toolkit.api.authentication.exchange(:token => response.data['token'])
34
+ if check_response.success?
35
+ if check_response.data['status'] == 'approved'
36
+ Viaduct::Toolkit.reset_api
37
+ @authorised = true
38
+ break
39
+ elsif check_response.data['status'] == 'denied'
40
+ error "The login request was rejected. Ensure that you approve the login request."
41
+ end
42
+ else
43
+ error "Couldn't successfully exchange login token for an API token. Please try again later."
44
+ end
45
+ end
46
+
47
+ if @authorised
48
+ Viaduct::Toolkit.config['token'] = check_response.data['token']['token']
49
+ Viaduct::Toolkit.config['secret'] = check_response.data['token']['secret']
50
+
51
+ user_check = Viaduct::Toolkit.api.user.details
52
+ if user_check.success?
53
+ Viaduct::Toolkit.save_config
54
+ puts "Hello #{user_check.data['name']}!".green
55
+ puts "Your user account is now authorised. Your login details are".magenta
56
+ puts "stored in a .viaduct file in your home directory.".magenta
57
+ puts
58
+ else
59
+ error "We couldn't verify your user details. Please try again."
60
+ end
61
+ else
62
+ error "We didn't receive a login response in a timely manner. Please try again."
63
+ end
64
+
65
+ else
66
+ error "Couldn't generate a remote login token. Please try again."
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,40 @@
1
+ Viaduct::Toolkit.cli.command "ssh_key:add" do |c|
2
+
3
+ c.syntax = "ssh_keys:add PATH_TO_PUBLIC_KEY"
4
+ c.description = "Add a new SSH public key to your user account"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+
10
+ key_path = args[0]
11
+
12
+ default_key_path = File.join(ENV['HOME'], '.ssh', 'id_rsa.pub')
13
+ if key_path.nil? && File.exist?(default_key_path)
14
+ puts "You haven't provided an SSH key to this command.".yellow
15
+ if agree("Shall we use your default key at #{default_key_path}?".blue)
16
+ key_path = default_key_path
17
+ else
18
+ exit(1)
19
+ end
20
+ end
21
+
22
+ if File.exist?(key_path)
23
+ response = Viaduct::Toolkit.api.ssh_keys.add(:label => "Added from #{`hostname`}", :key => File.read(key_path))
24
+ if response.success?
25
+ puts "Key successfully added to your account".green
26
+ else
27
+ if response.is_a?(MoonropeClient::Responses::ValidationError)
28
+ puts "Errors occurred while adding your key:".red
29
+ validation_errors response.data['errors']
30
+ else
31
+ error "Couldn't add your key"
32
+ end
33
+ end
34
+ else
35
+ puts "No public key found at '#{key_path}'".red
36
+ exit(1)
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,26 @@
1
+ Viaduct::Toolkit.cli.command "ssh_key:list" do |c|
2
+
3
+ c.syntax = "ssh_key:list"
4
+ c.description = "List the keys associated with your account"
5
+
6
+ c.action do |args, opts|
7
+ include Commander::Methods
8
+ ensure_logged_in!
9
+
10
+ response = Viaduct::Toolkit.api.ssh_keys.all
11
+ if response.success?
12
+ require 'terminal-table'
13
+ rows = response.data.map do |app|
14
+ [app['label'], app['fingerprint']]
15
+ end
16
+ table = Terminal::Table.new :rows => rows, :headings => ['Label', 'Fingerprint']
17
+ puts table
18
+
19
+ else
20
+ error "Couldn't get the SSH key list."
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,111 @@
1
+ require 'open3'
2
+
3
+ module Viaduct
4
+ module Toolkit
5
+ module Helpers
6
+ def ensure_logged_in!
7
+ if Viaduct::Toolkit.config['token'].nil? && Viaduct::Toolkit.config['secret'].nil?
8
+ puts "You need to login before using this toolkit. Use the command below".yellow
9
+ puts "to login to your Viaduct account.".yellow
10
+ puts
11
+ puts " $ vdt login"
12
+ puts
13
+ exit 1
14
+ end
15
+ end
16
+
17
+ def length_of_time(seconds)
18
+ "#{seconds} seconds"
19
+ end
20
+
21
+ def time(time)
22
+ require 'time'
23
+ time = Time.parse(time) rescue nil
24
+ time ? time.strftime("%d %B %Y at %H:%M:%S UTC") : ''
25
+ end
26
+
27
+ def boolean(bool)
28
+ bool ? "\u2713".green : "-".red
29
+ end
30
+
31
+ def table(headings, rows)
32
+ require 'terminal-table'
33
+ puts Terminal::Table.new :rows => rows, :headings => headings.map(&:blue)
34
+ end
35
+
36
+ def validation_errors(errors)
37
+ errors.each do |field, messages|
38
+ messages.each do |message|
39
+ puts " * #{field} #{message}".red
40
+ end
41
+ end
42
+ end
43
+
44
+ def error(message)
45
+ raise Viaduct::Toolkit::Error, message
46
+ end
47
+
48
+ def run(*commands)
49
+ stdin, stdout, stderr, w = Open3.popen3(*commands)
50
+ [stdout.gets(nil), stderr.gets(nil), w.value]
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)
56
+ if app.success?
57
+ return app.data
58
+ else
59
+ puts "Couldn't find application with subdomain matching '#{subdomain}'".red
60
+ exit(1)
61
+ end
62
+ else
63
+ # Look up from repo
64
+ out, err, status = run("git", "remote", "-v")
65
+ if status == 0
66
+ potential_repositories = out.split("\n").map { |l| l.split(/\s+/)[1] }.uniq
67
+ app = Viaduct::Toolkit.api.applications.all(:filter => {:repo => potential_repositories})
68
+ if app.success?
69
+ if app.data.empty?
70
+ puts "No Viaduct applications found for any of the following repositories:".red
71
+ potential_repositories.each do |repo|
72
+ puts " * #{repo}".red
73
+ end
74
+ exit(1)
75
+ elsif app.data.size == 1
76
+ return find_application(app.data.first['subdomain'])
77
+ else
78
+ puts "Multiple applications found matching your repository. Choose an application...".yellow
79
+ choice = choose('', *app.data.map { |a| "#{a['subdomain']}: #{a['name']}"})
80
+ choice = choice.split(":", 2).first
81
+ return find_application(choice)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ puts "Couldn't determine a Viaduct application from command.".red
88
+ exit(1)
89
+ end
90
+
91
+ def heading(title)
92
+ puts "+" + ("-" * 78) + "+"
93
+ puts "| #{title.ljust(76).yellow} |"
94
+ puts "+" + ("-" * 78) + "+"
95
+ end
96
+
97
+ def field(key, value)
98
+ key = key[0,16].ljust(16, ' ')
99
+ value = value.to_s[0,58].ljust(58)
100
+
101
+ puts "| #{key.blue}| #{value} |"
102
+ end
103
+
104
+ def details(&block)
105
+ block.call
106
+ puts "+" + ("-" * 78) + "+"
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,5 @@
1
+ module Viaduct
2
+ module Toolkit
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: viaduct-toolkit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Adam Cooke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: viaduct-api
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: colorize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.7'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: terminal-table
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.4.5
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '1.4'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.4.5
75
+ description: A set of useful tools to help developers use & manage their Viaduct applications.
76
+ email:
77
+ - adam@viaduct.io
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - lib/viaduct/toolkit.rb
83
+ - lib/viaduct/toolkit/commands/app_console.rb
84
+ - lib/viaduct/toolkit/commands/app_deployments.rb
85
+ - lib/viaduct/toolkit/commands/app_env.rb
86
+ - lib/viaduct/toolkit/commands/app_info.rb
87
+ - lib/viaduct/toolkit/commands/app_list.rb
88
+ - lib/viaduct/toolkit/commands/app_public_key.rb
89
+ - lib/viaduct/toolkit/commands/app_status.rb
90
+ - lib/viaduct/toolkit/commands/domain_list.rb
91
+ - lib/viaduct/toolkit/commands/login.rb
92
+ - lib/viaduct/toolkit/commands/ssh_key_add.rb
93
+ - lib/viaduct/toolkit/commands/ssh_key_list.rb
94
+ - lib/viaduct/toolkit/helpers.rb
95
+ - lib/viaduct/toolkit/version.rb
96
+ homepage: http://viaduct.io
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.2.2
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: A developer toolkit for working with Viaduct from an CLI
120
+ test_files: []
121
+ has_rdoc: