cabal 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 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