viaduct-toolkit 0.0.1

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