cabal 0.4.2 → 0.5.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: 1911f5bc4c94b10fa7b62a071ae93dfdcbd66eec
4
- data.tar.gz: 6d118c1dbecf0394f7197ca0a1c350ef09b2ee73
3
+ metadata.gz: 54c08e765a34142602ac7933207bd41adb423cbf
4
+ data.tar.gz: d66b1d6dab67a5d5c91be6732a7e00551cf499ba
5
5
  SHA512:
6
- metadata.gz: 4777b7b6b3881852f0bdb365e35316f889e73e0ff86ba821d37fb8a178c401e87c56e6f3e6d3dc7ff3f5dfa0a497b6f22a9994597399000de31fdb5ae7abe8a9
7
- data.tar.gz: e9a2f6cd1155d03a5c394b5ab2b6ff3d451fb1005d840325785cdfada262be305bffbcfb7ff7555e78ee8a8a1bc14bfff5886687a233134e56c6d68ee5fc5f99
6
+ metadata.gz: 6684c86512ddafaf29c7eb002dc87de2262f9c6e6a2b4bc3656cc3ba0a73acb4399485b0e8a17e8fb464300b56ff05ad4d4d2512ced8066b7d070ea142582060
7
+ data.tar.gz: e33cdbf4db6a8dc8fde6d86bb2093aa6c8e8e1b6596c96a8bebaaaee7f7a8655ba2a92a00b390db8a865eb492c03a3b5408258a2272ff13a3c21bd0830104be5
@@ -1,3 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.2.2
4
+
data/README.md CHANGED
@@ -10,13 +10,13 @@ Cabal is a simple system for SSH key distribution and consumption. This is a CLI
10
10
 
11
11
  ## Usage ##
12
12
 
13
- To get started, you'll need to create `.cabal.yml` in your user's home directory, and you'll need to provide at least the URL of your Cabal::API. If you plan to use the `ssh` command to connect to a server that has an authorized Cabal key, you'll also need to specify your access key and secret key:
13
+ To get started, you'll need to create `.cabal.yml` in your user's home directory, and you'll need to provide at least the URL of your Cabal::API. If you plan to use the `ssh` command to connect to a server that has an authorized Cabal key, you'll also need to specify your access token and secret token (provided by your Cabal::API administrator):
14
14
 
15
15
  ```yaml
16
16
  ---
17
17
  :url: http://your-cabal-hostname/path/to/the/api
18
- :access_key: your-access-key
19
- :secret_key: your-secret-key
18
+ :access_key: your-access-token
19
+ :secret_key: your-secret-token
20
20
  ```
21
21
 
22
22
  ### Getting Help ###
@@ -24,38 +24,43 @@ To get started, you'll need to create `.cabal.yml` in your user's home directory
24
24
  The `cabal` application provides some nicely-formatted help on the command line. To access the help, provided that you've created your `~/.cabal.yml`, run the following:
25
25
 
26
26
  ```
27
- cabal help
27
+ cabal --help
28
28
  ```
29
29
 
30
30
  That will output something like this:
31
31
 
32
32
  ```
33
33
  NAME
34
- cabal - An interface to the Cabal API
34
+ cabal - An interface to the Cabal API
35
35
 
36
36
  SYNOPSIS
37
- cabal [global options] command [command options] [arguments...]
37
+ cabal command
38
38
 
39
- VERSION
40
- 0.2.0
41
-
42
- GLOBAL OPTIONS
43
- --help - Show this message
44
- --version - Display the program version
39
+ OPTIONS
40
+ -h, --help - Shows this message
45
41
 
46
42
  COMMANDS
47
- help - Shows a list of commands or help for one command
48
- key - Get the public key for a cluster
49
- ssh - Connect to a node on a cluster
43
+ key - Get the public key for a cluster
44
+ ssh - Connect to a node on a cluster
50
45
  ```
51
46
 
52
- To get help on a specific command, you can `cabal help command` (ie `cabal help key`).
47
+ To get help on a specific command, you can `cabal command --help` (ie `cabal key --help`).
53
48
 
54
- ### Getting A Public Key ###
49
+ ### Listing Known Clusters ###
50
+
51
+ ***To learn more, check out `cabal list --help`***
52
+
53
+ This is a privileged call, so you need an access key and a secret key in your configuration file.
55
54
 
56
- ***To learn more, check out `cabal help key`***
55
+ To get a list of the clusters that Cabal knows about, you'd do the following:
57
56
 
58
- This is an unprivileged call, so you won't actually need an access key or a secret key. This is more for somebody that wants to use the cabal cli utility to rather than curl or the like to grab a public key from the API to install as an authorized key on their servers.
57
+ ```
58
+ cabal list
59
+ ```
60
+
61
+ ### Getting A Public Key ###
62
+
63
+ ***To learn more, check out `cabal key --help`***
59
64
 
60
65
  To get a public key for a cluster named "totallyarealcluster," you'd do the following:
61
66
 
@@ -72,9 +77,20 @@ cabal key Totally a real clusteR
72
77
  cabal key totallyarealcluster
73
78
  ```
74
79
 
80
+ This command is an alternative to hitting the API endpoint via curl (or similar) to grab a public key, which might be used when installing an authorized key on a server. The following example would append the key for "totallyarealcluster" to the current user's authorized_keys file if it wasn't already present:
81
+
82
+ ```
83
+ if ! grep -q totallyarealcluster ~/.ssh/authorized_keys
84
+ then
85
+ cabal key totallyarealcluster >> ~/.ssh/authorized_keys
86
+ fi
87
+ ```
88
+
89
+ This is an unprivileged call, so you won't actually need an access key or a secret key.
90
+
75
91
  ### Connecting To A Server ###
76
92
 
77
- ***To learn more, check out `cabal help ssh`***
93
+ ***To learn more, check out `cabal ssh --help`***
78
94
 
79
95
  This is a privileged call, so you need an access key and a secret key in your configuration file.
80
96
 
@@ -91,6 +107,10 @@ This basically does the following:
91
107
  * Connects you to the server, forwarding your ssh-agent
92
108
  * Removes the key and **ALL** ssh-agent identities on disconnect
93
109
 
110
+ By default, the forwarded ssh-agent will only have access to the private key for 30 minutes. To change this, you can use the `--lifetime` option to specify a different lifetime for your session.
111
+
112
+ For tasks that may take a very long time (cluster upgrades, etc), you can pass a lifetime of `0` to keep the agent forwarding in place for the entirety of your session.
113
+
94
114
  ## Development ##
95
115
 
96
116
  Branches and releases for this project are managed by [git-flow](https://github.com/nvie/gitflow).
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ require 'cucumber/rake/task'
4
+
5
+ RSpec::Core::RakeTask.new
6
+ Cucumber::Rake::Task.new
7
+
8
+ task :default => [:spec, :cucumber]
@@ -26,10 +26,10 @@ Gem::Specification.new do |spec|
26
26
  spec.add_development_dependency 'factis', '~> 1.0'
27
27
  spec.add_development_dependency 'simplecov', '~> 0.10'
28
28
  spec.add_development_dependency 'webmock', '~> 1.22'
29
- spec.add_development_dependency 'cabal-api', '~> 0.1'
29
+ spec.add_development_dependency 'toady', '~> 0.0'
30
30
 
31
31
  spec.add_runtime_dependency 'cabal-util', '~> 0.1'
32
- spec.add_runtime_dependency 'gli', '~> 2.13'
32
+ spec.add_runtime_dependency 'belafonte', '~> 0.5'
33
33
  spec.add_runtime_dependency 'oj', '~> 2.12'
34
34
  spec.add_runtime_dependency 'faraday', '~> 0.9'
35
35
  end
data/exe/cabal CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'cabal/cli'
4
4
 
5
- exit Cabal::CLI.new(ARGV, STDIN, STDOUT, STDERR, Kernel).execute!
5
+ exit Cabal::CLI::Main.new(ARGV, STDIN, STDOUT, STDERR, Kernel).execute!
@@ -3,6 +3,7 @@ require 'cabal/util'
3
3
  require 'cabal/client'
4
4
  require 'cabal/ssh'
5
5
 
6
+ # A library and CLI application for working with servers configured to work
7
+ # with Cabal::API
6
8
  module Cabal
7
- # Your code goes here...
8
9
  end
@@ -1,60 +1,50 @@
1
- require 'gli'
2
1
  require 'yaml'
3
2
  require 'cabal'
4
- require 'cabal/commands/key'
5
- require 'cabal/commands/ssh'
3
+ require 'cabal/cli/ssh'
4
+ require 'cabal/cli/key'
5
+ require 'cabal/cli/list'
6
+ require 'cabal/cli/main'
6
7
 
7
8
  module Cabal
8
- class CLI
9
- include GLI::App
9
+ # Bootstrap and configure the CLI application
10
+ module CLI
11
+ # The expected config file does not exist
12
+ NoConfig = Class.new(StandardError)
10
13
 
11
- attr_reader :stdin, :stdout, :stderr, :kernel, :argv
14
+ # The config file does not contain a :url
15
+ NoURLDefinition = Class.new(StandardError)
12
16
 
13
- def initialize(argv, stdin=STDIN, stdout=STDOUT, stderr=STDERR, kernel=Kernel)
14
- @argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
15
- end
16
-
17
- def register_command(command)
18
- command.bootstrap(self)
19
- end
17
+ # The config file does not contain :access_key and :secret_key
18
+ NoPrivateConfig = Class.new(StandardError)
20
19
 
21
- def cabal_yml
22
- File.expand_path(File.join(ENV['HOME'], '.cabal.yml'))
20
+ # Calculates the expected path of the Cabal config file
21
+ # @return [String] the config file path
22
+ def self.cabal_yml
23
+ File.expand_path(File.join(ENV['HOME'], '.cabal.yml'))
23
24
  end
24
25
 
25
- def execute!
26
- unless File.exist?(cabal_yml)
27
- stderr.puts "Please create your config in #{cabal_yml}"
28
- exit(1)
29
- end
30
-
31
- program_desc 'An interface to the Cabal API'
32
- version Cabal::VERSION
33
- subcommand_option_handling :normal
34
- arguments :strict
35
-
36
- pre do |global,command,options,args|
37
- if File.exist?(cabal_yml)
38
- config = YAML.load(File.read(cabal_yml))
39
- global.merge!(config)
40
- true
41
- else
42
- stderr.puts "Please create #{cabal_yml} and try again"
43
- false
44
- end
45
- end
46
-
47
- post do |global,command,options,args|
48
- end
26
+ # Parses the config file and sets up the global configuration
27
+ # @return [nil]
28
+ def self.setup
29
+ if File.exist?(cabal_yml)
30
+ @config = YAML.load(File.read(cabal_yml))
49
31
 
50
- on_error do |exception|
51
- true
32
+ raise NoURLDefinition.new("#{cabal_yml} must contain a :url: definition") unless config[:url]
33
+ else
34
+ raise NoConfig.new("Please create #{cabal_yml} and try again")
52
35
  end
36
+ end
53
37
 
54
- register_command(Cabal::Commands::Key)
55
- register_command(Cabal::Commands::SSH)
38
+ # The global config for the CLI
39
+ # @return [Hash] the current configuration
40
+ def self.config
41
+ @config ||= {}
42
+ end
56
43
 
57
- kernel.exit run(argv)
44
+ # Clears the global configuration
45
+ # @return [nil]
46
+ def self.reset
47
+ @config = {}
58
48
  end
59
49
  end
60
50
  end
@@ -0,0 +1,27 @@
1
+ require 'belafonte'
2
+ require 'cabal/cli'
3
+
4
+ module Cabal
5
+ module CLI
6
+ module Authenticated
7
+ def with_authentication(config, &block)
8
+ begin
9
+ unless config[:access_key] && config[:secret_key]
10
+ raise Cabal::CLI::NoPrivateConfig
11
+ end
12
+
13
+ block.call
14
+
15
+ rescue Cabal::CLI::NoPrivateConfig
16
+ stderr.puts "You must have an access key and a secret key"
17
+ rescue Cabal::Client::UnauthorizedError
18
+ stderr.puts "You are not authorized to use the private API."
19
+ kernel.exit(1)
20
+ rescue Cabal::Client::NotFoundError
21
+ stderr.puts "The cluster '#{option(:cluster_name)}' does not exist."
22
+ kernel.exit(1)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,18 @@
1
+ require 'belafonte'
2
+ require 'cabal/cli'
3
+
4
+ module Cabal
5
+ module CLI
6
+ class Key < Belafonte::App
7
+ title 'key'
8
+ summary 'Get the public key for a cluster'
9
+
10
+ arg :cluster_name,
11
+ times: :unlimited
12
+
13
+ def handle
14
+ stdout.puts partake(:client).public_key(arg(:cluster_name).join(' '))
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ require 'belafonte'
2
+ require 'cabal/cli'
3
+ require 'cabal/cli/authenticated'
4
+
5
+ module Cabal
6
+ module CLI
7
+ class List < Belafonte::App
8
+ include Authenticated
9
+
10
+ title 'list'
11
+ summary 'List all known clusters'
12
+ description "Displays the list of all known clusters, one line at a time"
13
+
14
+ arg :cluster_name,
15
+ times: :unlimited
16
+
17
+ def handle
18
+ with_authentication(partake(:config)) do
19
+ stdout.puts partake(:client).clusters.join("\n")
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ require 'cabal/cli/key'
2
+ require 'cabal/cli/list'
3
+ require 'cabal/cli/ssh'
4
+
5
+ module Cabal
6
+ module CLI
7
+ class Main < Belafonte::App
8
+ title 'cabal'
9
+ summary 'An interface to the Cabal API'
10
+
11
+ mount Cabal::CLI::Key
12
+ mount Cabal::CLI::List
13
+ mount Cabal::CLI::SSH
14
+
15
+ def setup
16
+ Cabal::CLI.setup
17
+ config = Cabal::CLI.config
18
+ client = Cabal::Client.new(
19
+ api_base: config[:url],
20
+ access_key: config[:access_key],
21
+ secret_key: config[:secret_key]
22
+ )
23
+
24
+ share(:config, config)
25
+ share(:client, client)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ require 'belafonte'
2
+ require 'cabal/cli'
3
+ require 'cabal/cli/authenticated'
4
+ require 'cabal/ssh'
5
+
6
+ module Cabal
7
+ module CLI
8
+ class SSH < Belafonte::App
9
+ include Authenticated
10
+
11
+ title "ssh"
12
+ summary "Connect to a node on a cluster"
13
+
14
+ option :cluster_name,
15
+ short: 'c',
16
+ long: 'cluster-name',
17
+ argument: 'CLUSTER_NAME',
18
+ description: 'The name of the cluster to connect'
19
+
20
+ option :lifetime,
21
+ short: 'l',
22
+ long: 'lifetime',
23
+ argument: 'MINUTES',
24
+ description: 'How long should we forward SSH identities (default: 30, 0 for no timeout)'
25
+
26
+ arg :ssh_signature
27
+
28
+ def handle
29
+ with_authentication(partake(:config)) do
30
+ Cabal::SSH.connect(
31
+ cluster: option(:cluster_name),
32
+ ssh_signature: arg(:ssh_signature).first,
33
+ client: partake(:client),
34
+ identity_timeout: lifetime,
35
+ kernel: kernel
36
+ )
37
+ end
38
+ end
39
+
40
+ def lifetime
41
+ return nil unless option(:lifetime)
42
+ option(:lifetime).to_i * 60
43
+ end
44
+ end
45
+ end
46
+ end
@@ -2,11 +2,27 @@ require 'faraday'
2
2
  require 'oj'
3
3
 
4
4
  module Cabal
5
+ # A client interface for an upstream Cabal::API
5
6
  class Client
7
+ # The requested upstream resource was not found
8
+ NotFoundError = Class.new(StandardError)
9
+
10
+ # The user is not authorized to use a given upstream resource
11
+ UnauthorizedError = Class.new(StandardError)
12
+
13
+ # @return [String] the base URL for the v3 API
6
14
  attr_reader :api_base
7
15
 
16
+ # Create a new client instance
17
+ # @param options [Hash]
18
+ # @option options [String] :api_base the base URL for the upstream API
19
+ # (required)
20
+ # @option options [String] :access_key the access key to use for
21
+ # authenticated API endpoints (optional)
22
+ # @option options [String] :secret_key the secret key to use for
23
+ # authenticated API endpoints (optional)
8
24
  def initialize(options = {})
9
- @api_base = "#{options[:api_base]}/v2"
25
+ @api_base = "#{options[:api_base]}/v3"
10
26
  @access_key = options[:access_key]
11
27
  @secret_key = options[:secret_key]
12
28
  @connector = Faraday.new(url: api_base) do |faraday|
@@ -15,15 +31,34 @@ module Cabal
15
31
  end
16
32
  end
17
33
 
34
+ # Retrieves a list of cluster names from the upstream API
35
+ # @return [Array<String>] the names of the known clusters
36
+ def clusters
37
+ get("clusters").map {|cluster| cluster['name']}
38
+ end
39
+
40
+ # Retrieves a private SSH key from the upstream API
41
+ # @param cluster_name [String] the name of the cluster
42
+ # @return [String] the contents of the cluster's private key
18
43
  def private_key(cluster_name)
19
44
  get("private-key/#{URI.encode(cluster_name)}")['private_ssh_key']
20
45
  end
21
46
 
47
+ # Retrieves a public SSH key from teh upstream API
48
+ # @param cluster_name [String] the name of the cluster
49
+ # @return [String] the contents of the cluster's public key
22
50
  def public_key(cluster_name)
23
51
  get("key/#{URI.encode(cluster_name)}")['public_ssh_key']
24
52
  end
25
53
 
26
- def get(endpoint, authenticated = nil)
54
+ # Does an HTTP GET against the upstream API for the provided endpoint
55
+ # @param endpoint [String] the relative API path to GET
56
+ # @return [Object] the parsed JSON response
57
+ # @raise [Cabal::Client::NotFoundError] if the upstream API returns a
58
+ # 404 status
59
+ # @raise [Cabal::Client::UnauthorizedError] if the upstream API retirns
60
+ # a 401 status
61
+ def get(endpoint)
27
62
  response = connector.get {|req|
28
63
  req.url endpoint
29
64
  req.headers['Content-Type'] = 'application/json'
@@ -34,9 +69,9 @@ module Cabal
34
69
  when 200
35
70
  Oj.load(response.body)
36
71
  when 404
37
- raise "Cabal::Client::NotFoundError"
72
+ raise Cabal::Client::NotFoundError
38
73
  when 401
39
- raise "Cabal::Client::UnauthorizedError"
74
+ raise Cabal::Client::UnauthorizedError
40
75
  end
41
76
  end
42
77
 
@@ -1,15 +1,32 @@
1
1
  module Cabal
2
+ # Manages ssh-agent sessions for forwarding identity information via
3
+ # Cabal::SSH
2
4
  class IdentityManager
5
+
6
+ # @return [String] the environment settings for the running ssh-agent
3
7
  attr_reader :env
4
8
 
9
+ # Spawns an ssh-agent process and records its related environment settings
10
+ # @return [nil]
5
11
  def start
6
- @env = `ssh-agent`.
12
+ @env = start_agent.
7
13
  split(/(\;|\n)/).
8
- select {|x| x =~ /^SSH_/}.
14
+ select {|line| line =~ /^SSH_/}.
9
15
  join(' ')
10
16
  end
11
17
 
18
+ # Stops a running ssh-agent that was previously spawned
19
+ # @return [nil]
12
20
  def stop
21
+ stop_agent
22
+ end
23
+
24
+ private
25
+ def start_agent
26
+ `ssh-agent`
27
+ end
28
+
29
+ def stop_agent
13
30
  `#{env} ssh-agent -k`
14
31
  end
15
32
  end
@@ -7,37 +7,79 @@ require 'uri'
7
7
  require 'fileutils'
8
8
 
9
9
  module Cabal
10
+ # Generates SSH sessions for remote server interaction
10
11
  class SSH
11
- def self.connect(cluster, ssh_signature, client)
12
- new(cluster, ssh_signature, client).connect
12
+ # Create a new instance and use it to generate an SSH session
13
+ # @param options [Hash] the options to pass along to the new instance
14
+ # @option options [String] :cluster the name of the cluster key to
15
+ # use (required)
16
+ # @option options [String] :ssh_signature the user@hostname
17
+ # that would be passed if the normal ssh CLI utility were used (required)
18
+ # @option options [Cabal::Client] :client the instance of
19
+ # Cabal::Client to use for key retrieval (required)
20
+ # @option options [Integer] :identity_timeout the number of seconds
21
+ # that keys should be forwarded in the resulting SSH session (optional)
22
+ # @option options [Kernel] :kernel the Kernel-compliant object used for
23
+ # issuing calls to #system for the SSH session (optional)
24
+ # @return [nil]
25
+ def self.connect(options = {})
26
+ new(
27
+ options[:cluster],
28
+ options[:ssh_signature],
29
+ options[:client],
30
+ options[:identity_timeout] || 1800,
31
+ options[:kernel] || Kernel
32
+ ).connect
13
33
  end
14
34
 
15
- def initialize(cluster, ssh_signature, client)
35
+ def initialize(cluster, ssh_signature, client, identity_timeout, kernel)
16
36
  @cluster = cluster
17
37
  @ssh_signature = ssh_signature
18
38
  @client = client
19
- @key_file = Tempfile.new(SecureRandom.hex(8))
39
+ @identity_timeout = identity_timeout
40
+ @kernel = kernel
41
+ end
42
+
43
+ # The lifetime option that would be passed to ssh-add for this session
44
+ # @return [String] the empty string for immortal sessions,
45
+ # "-t identity_timeout" for sessions with a defined lifetime
46
+ def lifetime
47
+ return '' if identity_timeout == 0
48
+ "-t #{identity_timeout}"
20
49
  end
21
50
 
51
+ # Initiate an SSH connection in the current terminal
52
+ # @return [nil]
22
53
  def connect
54
+ begin
55
+ write_private_key
56
+ initiate_connection
57
+ ensure
58
+ terminate_connection
59
+ end
60
+ end
61
+
62
+ private
63
+ def write_private_key
23
64
  private_key = client.private_key(cluster)
24
65
  @key_file = Tempfile.new(SecureRandom.hex(8))
25
66
  key_file.write(private_key)
26
67
  key_file.close
68
+ FileUtils.chmod(0700, key_file.path)
69
+ end
27
70
 
28
- begin
29
- FileUtils.chmod(0700, key_file.path)
30
- agent.start
31
- Kernel.system("#{agent.env} ssh-add #{key_file.path} > /dev/null 2>&1")
32
- Kernel.system("#{agent.env} ssh -A #{ssh_signature}")
33
- ensure
34
- Kernel.system("#{agent.env} ssh-add -D > /dev/null 2>&1")
35
- agent.stop
36
- key_file.unlink
37
- end
71
+ def initiate_connection
72
+ agent.start
73
+ kernel.system("#{agent.env} ssh-add #{lifetime} #{key_file.path} > /dev/null 2>&1")
74
+ kernel.system("#{agent.env} ssh -A #{ssh_signature}")
75
+ end
76
+
77
+ def terminate_connection
78
+ kernel.system("#{agent.env} ssh-add -D > /dev/null 2>&1")
79
+ agent.stop
80
+ key_file.unlink unless key_file.nil?
38
81
  end
39
82
 
40
- private
41
83
  def key_file
42
84
  @key_file
43
85
  end
@@ -57,5 +99,13 @@ module Cabal
57
99
  def agent
58
100
  @agent ||= Cabal::IdentityManager.new
59
101
  end
102
+
103
+ def identity_timeout
104
+ @identity_timeout
105
+ end
106
+
107
+ def kernel
108
+ @kernel
109
+ end
60
110
  end
61
111
  end
@@ -1,3 +1,3 @@
1
1
  module Cabal
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cabal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dennis Walters
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-19 00:00:00.000000000 Z
11
+ date: 2016-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -123,19 +123,19 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1.22'
125
125
  - !ruby/object:Gem::Dependency
126
- name: cabal-api
126
+ name: toady
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '0.1'
131
+ version: '0.0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '0.1'
138
+ version: '0.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: cabal-util
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -151,19 +151,19 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0.1'
153
153
  - !ruby/object:Gem::Dependency
154
- name: gli
154
+ name: belafonte
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '2.13'
159
+ version: '0.5'
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '2.13'
166
+ version: '0.5'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: oj
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -213,9 +213,12 @@ files:
213
213
  - exe/cabal
214
214
  - lib/cabal.rb
215
215
  - lib/cabal/cli.rb
216
+ - lib/cabal/cli/authenticated.rb
217
+ - lib/cabal/cli/key.rb
218
+ - lib/cabal/cli/list.rb
219
+ - lib/cabal/cli/main.rb
220
+ - lib/cabal/cli/ssh.rb
216
221
  - lib/cabal/client.rb
217
- - lib/cabal/commands/key.rb
218
- - lib/cabal/commands/ssh.rb
219
222
  - lib/cabal/identity_manager.rb
220
223
  - lib/cabal/ssh.rb
221
224
  - lib/cabal/version.rb
@@ -1,32 +0,0 @@
1
- module Cabal
2
- module Commands
3
- module Key
4
- def self.bootstrap(obj)
5
- obj.instance_eval do
6
- desc 'Get the public key for a cluster'
7
- long_desc <<-KEYDESC
8
- In order to allow logins for Cabal users, you'll need to retrieve
9
- a public SSH key for your cluster.
10
- KEYDESC
11
-
12
- arg 'cluster name'
13
- command :key do |c|
14
- c.action do |global_options, options, args|
15
- unless global_options[:url]
16
- stderr.puts "#{cabal_yml} must contain a :url: definition"
17
- exit(1)
18
- end
19
-
20
- client = Cabal::Client.new(
21
- api_base: global_options[:url],
22
- access_key: global_options[:access_key],
23
- secret_key: global_options[:secret_key],
24
- )
25
- stdout.puts client.public_key(args.join(' '))
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,36 +0,0 @@
1
- require 'cabal/ssh'
2
-
3
- module Cabal
4
- module Commands
5
- module SSH
6
- def self.bootstrap(obj)
7
- obj.instance_eval do
8
- desc 'Connect to a node on a cluster'
9
- long_desc <<-SSHDESC
10
- SSHDESC
11
-
12
- arg 'ssh signature'
13
- command :ssh do |c|
14
- c.desc 'The name of the cluster'
15
- c.arg_name 'cluster'
16
- c.flag [:c, :cluster]
17
- c.action do |global_options, options, args|
18
- unless global_options[:access_key] && global_options[:secret_key]
19
- stderr.puts "You must have an access key and secret key"
20
- exit(1)
21
- end
22
-
23
- client = Cabal::Client.new(
24
- api_base: global_options[:url],
25
- access_key: global_options[:access_key],
26
- secret_key: global_options[:secret_key]
27
- )
28
-
29
- Cabal::SSH.connect(options[:cluster], args.shift, client)
30
- end
31
- end
32
- end
33
- end
34
- end
35
- end
36
- end