droppper 0.1.0 → 0.2.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: 2d00c6930b33d61b10304c6f22866d59fffc9515
4
- data.tar.gz: 24f9f5d6504cce0a322ff6a4b35c122327503846
3
+ metadata.gz: 7ffc7cf76b3d021c1c299b62e31feb439372e306
4
+ data.tar.gz: 8b11d5ae7b9b96a343e807538165b0b52dd3e675
5
5
  SHA512:
6
- metadata.gz: 3bcebe5092bc70bb95f410fed1a502b2cd694f48fbe7a9d3de9e6d8de2bed188c5a3bba33911f92945cdb8aa551fd608e6c9425369e4be8c916a2f2c8507b677
7
- data.tar.gz: aaeb0c898cba2f93d0bd6e44ed2f198afbc932e714b91e3d31d34076750bbfc7db0785611f156f4478ff6d7013c166509849b7eb29dc334700dde57530354db9
6
+ metadata.gz: f6a9be8e7b899b326ab0455fefeebce164ec07d38c41f1d04fad0e7ec49a99866254c662039d2d8249d334c4bc5f41df27890f9b5e2182e8919c435697da18d8
7
+ data.tar.gz: 6f78dc91488a3ec83b83c5b48efe4cf01a32c6464087e7d4e2415672b248c88ba3d99a7bb7323996a90609615c0c7009725177bdeced896dde90417899692a8f
data/bin/droppper CHANGED
@@ -1,51 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- Signal.trap("INT") { exit 1 }
4
-
5
- require 'gli'
6
3
  require 'droppper'
7
-
8
- include GLI::App
9
-
10
- subcommand_option_handling :normal
11
-
12
- program_desc 'Droppper is a CLI for your DigitalOcean cloud'
13
- sort_help :manually
14
-
15
- flag [:token], desc: "DigitalOcean Token", arg_name: "token", optional: true
16
-
17
- # This gem commands
18
- commands = Dir[File.join(File.expand_path("../../lib", __FILE__), "**", "commands", "*.rb")]
19
-
20
- # Commands from other gems
21
- Gem::Specification.latest_specs.select{|g| g.name =~ /droppper-/ }.each do |g|
22
- begin
23
- g.full_require_paths.each do |path|
24
- Dir[File.join(path, "**", "commands", "*.rb")].each do |commands_files|
25
- commands += commands_files
26
- end
27
- end
28
- rescue
29
- end
30
- end
31
-
32
- commands.each do |file|
33
- require file
34
- end
35
-
36
-
37
- pre do |global,command,options,args|
38
- token = global[:token] || Droppper::Utils.find_token
39
- help_now! "You must provide a DigitalOcean API v2 token. You can specify it in the command line or write it in a .droppper file. When running droppper it will try to use the 'nearest' .droppper file (in current dir or parent dir and so on; it defaults to ~/.droppper) " unless token
40
- Droppper.client = DropletKit::Client.new(access_token: token)
41
- true
42
- end
43
-
44
- post do |global,command,options,args|
45
- end
46
-
47
- on_error do |exception|
48
- true
49
- end
50
-
51
- exit run(ARGV)
4
+ Signal.trap("INT") { exit 1 }
5
+ Droppper::CLI.start(ARGV)
data/droppper.gemspec CHANGED
@@ -19,10 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency "gli", ">= 2.0"
23
- spec.add_dependency "highline"
22
+ spec.add_dependency "thor"
24
23
  spec.add_dependency "table_print"
25
24
  spec.add_dependency "droplet_kit"
25
+ spec.add_dependency "hashie"
26
+ spec.add_dependency "highline"
26
27
 
27
28
  spec.add_development_dependency "bundler", "~> 1.10"
28
29
  spec.add_development_dependency "rake", "~> 10.0"
data/lib/droppper.rb CHANGED
@@ -1,63 +1,22 @@
1
- require "droppper/version"
2
- require "droppper/utils"
3
- require "droplet_kit"
4
- require 'table_print'
1
+ require 'droppper/version'
2
+ require 'droppper/utils'
3
+ require 'droppper/config'
4
+ require 'droplet_kit'
5
+ require 'hashie/mash'
6
+ require 'droppper/commands/droplets'
7
+ require 'droppper/droplets'
8
+ require 'droppper/cli'
5
9
  require 'highline/import'
10
+ require 'table_print'
6
11
 
7
12
  module Droppper
8
13
  class << self
9
- def client
10
- @client
11
- end
12
-
13
- def client=(client)
14
- @client = client
15
- end
16
-
17
- def droplets(*args)
18
- args = args.flatten
19
- data = client.droplets.all.to_a
20
- if args.size > 0
21
- data = data.select do |d|
22
- (args.size==1 and (d.id.to_s == args[0] or d.name == args[0])) or (d.name =~ Regexp.new(args.join(".*")))
23
- end
24
- end
25
- data
26
- end
27
-
28
- def droplet(*args)
29
- list = droplets(*args)
30
- if list.size == 0
31
- puts "Cannot find droplet"
32
- elsif list.size == 1
33
- list.first
34
- else
35
- select_droplet(list)
36
- end
37
- end
38
-
39
- def select_droplet(list)
40
- choose do |menu|
41
- menu.prompt = "Multiple droplets found. Select one:"
42
- list.each do |droplet|
43
- menu.choice droplet.name do droplet end
44
- end
45
- end
46
- end
14
+ attr_accessor :client, :config
47
15
 
48
- def ssh(droplet, options={})
49
- cmd_options = [
50
- "-o", "IdentitiesOnly=yes",
51
- "-o", "LogLevel=ERROR",
52
- "-o", "StrictHostKeyChecking=no",
53
- "-o", "UserKnownHostsFile=/dev/null",
54
- "-i", "#{Dir.home}/.ssh/id_rsa"
55
- ]
56
- cmd_options.push "-l", "#{options[:user]}" if options[:user]
57
- cmd_options.push "-p", "#{options[:port]}" if options[:port]
58
- cmd_options << droplet.public_ip
59
- # puts "Executing: ssh #{cmd_options.join(" ")}"
60
- Kernel.exec("ssh", *cmd_options)
16
+ def setup(options)
17
+ self.config = Droppper::Config.new
18
+ self.config.token = options["token"] if options["token"]
19
+ self.client = DropletKit::Client.new(access_token: config.token)
61
20
  end
62
21
  end
63
22
  end
@@ -0,0 +1,39 @@
1
+ require 'thor'
2
+
3
+ module Droppper
4
+ class CLI < Thor
5
+ include Thor::Actions
6
+
7
+ def initialize(args = [], local_options = {}, config = {})
8
+ super
9
+ Droppper.setup(options)
10
+ end
11
+
12
+ class_option :token, type: :string, desc: "DigitalOcean API v2 token (needed unless included in the .droppper file)"
13
+
14
+ desc "config", "Show your current config information"
15
+ long_desc "This shows the current information in the .droppper config files
16
+ being used by the app. Droppper can use more than one config file the one
17
+ being closer to the current directory having precedence.
18
+ "
19
+ def config
20
+ Droppper.config.print
21
+ end
22
+
23
+ desc "droplets", "Actions related to droplets"
24
+ subcommand "droplets", Droppper::Commands::Droplets
25
+
26
+ desc "ssh [SEARCH_STRING_OR_DROPLET_ID]", "Starts a SSH to a droplet"
27
+ method_option "user",
28
+ :type => :string,
29
+ :aliases => "-u",
30
+ :desc => "Specifies which user to log in as (default from .droppper files or root)"
31
+ method_option "port",
32
+ :type => :string,
33
+ :aliases => "-p",
34
+ :desc => "Specifies which post to use for the ssh connection (default from .droppper files or 22)"
35
+ def ssh(*args)
36
+ Droppper::Droplets.ssh(*args, options)
37
+ end
38
+ end
39
+ end
@@ -1,48 +1,32 @@
1
- desc "Manage your DigitalOcean droplets"
2
- command :droplets do |c|
3
- c.default_command :list
1
+ require 'thor'
4
2
 
5
- c.desc "List droplets"
6
- c.arg "search_string"
7
- c.command :list do |list|
8
- list.action do |global,options,args|
9
- data = Droppper.droplets(args)
10
- if data.size == 0
11
- puts "No droplets found"
12
- else
13
- tp data, {id: {display_name: "ID"}},
14
- {name: {display_name: "NAME"}},
15
- {"region.slug" => {display_name: "REGION"}},
16
- {"size_slug" => {display_name: "SIZE"}},
17
- :status,
18
- :locked
3
+ module Droppper
4
+ module Commands
5
+ class Droplets < Thor
6
+ default_command :list
7
+
8
+ desc "list [SEARCH_STRING_OR_DROPLET_ID]", "Retrieve a list of your droplets"
9
+ def list(*args)
10
+ Droppper::Droplets.list(*args)
11
+ end
12
+
13
+ desc "show [SEARCH_STRING_OR_DROPLET_ID]", "Show full details about a droplet"
14
+ def show(*args)
15
+ Droppper::Droplets.show(*args)
19
16
  end
20
- end
21
- end
22
17
 
23
- c.desc "Show a droplet details"
24
- c.arg "droplet_id_or_search_string"
25
- c.command :show do |show|
26
- show.action do |global,options,args|
27
- droplet = Droppper.droplet(args)
28
- puts Droppper::Utils.print_hash droplet.as_json
29
- puts ""
18
+ desc "ssh [SEARCH_STRING_OR_DROPLET_ID]", "Starts a SSH to a droplet"
19
+ method_option "user",
20
+ :type => :string,
21
+ :aliases => "-u",
22
+ :desc => "Specifies which user to log in as (default from .droppper files or root)"
23
+ method_option "port",
24
+ :type => :string,
25
+ :aliases => "-p",
26
+ :desc => "Specifies which post to use for the ssh connection (default from .droppper files or 22)"
27
+ def ssh(*args)
28
+ Droppper::Droplets.ssh(*args, options)
29
+ end
30
30
  end
31
31
  end
32
-
33
- # c.desc "Create a droplet"
34
- # c.command :create do |create|
35
- # create.flag :name, desc: "Hostname"
36
- # create.flag :region, desc: "Region slug"
37
- # create.flag :size, desc: "Droplet size slug"
38
- # create.flag :image, desc: "Image ID or slug"
39
- # create.flag :ssh_keys, desc: "Comma separated SSH keys IDs or names or fingerprint. Pass 'all' to enable all SSH keys", default: "all"
40
- # create.switch :backups, default: true, desc: "Enable backups"
41
- # create.switch :ipv6, default: true, desc: "Enable IPv6"
42
- # create.switch :private_networking, default: true, desc: "Enable private networking"
43
-
44
- # create.action do |global,options,args|
45
- # end
46
- # end
47
-
48
32
  end
@@ -0,0 +1,78 @@
1
+ module Droppper
2
+ class Config
3
+ attr_accessor :data, :files
4
+
5
+ DEFAULT = {
6
+ token: nil,
7
+ ssh: {
8
+ user: "root",
9
+ port: "22",
10
+ keyfile: "~/.ssh/id_rsa"
11
+ },
12
+ create: {
13
+ region: "nyc3",
14
+ image: "ubuntu-14-04-x64",
15
+ size: "512mb",
16
+ keys: []
17
+ }
18
+ }
19
+
20
+ def initialize
21
+ load_config
22
+ end
23
+
24
+ def print
25
+ puts Droppper::Utils.print_hash(data)
26
+ end
27
+
28
+ def token
29
+ data.token
30
+ end
31
+
32
+ def token=(new_token)
33
+ data.token = new_token
34
+ end
35
+
36
+ def ssh
37
+ data.ssh
38
+ end
39
+
40
+ def create
41
+ data.create
42
+ end
43
+
44
+ protected
45
+ def load_config
46
+ find_config_files
47
+ parse_config_files
48
+ end
49
+
50
+ def find_config_files
51
+ self.files = []
52
+ root = Dir.pwd
53
+ while root != '/'
54
+ add_file File.expand_path(".droppper", root)
55
+ root = File.expand_path("..", root)
56
+ end
57
+ add_file File.join(File.expand_path("~"), ".droppper")
58
+ end
59
+
60
+ def parse_config_files
61
+ self.data = Hashie::Mash.new(DEFAULT)
62
+ files.reverse.each do |file|
63
+ self.data.deep_merge! parse_config_file(file)
64
+ end
65
+ end
66
+
67
+ def parse_config_file(file)
68
+ require 'yaml'
69
+ YAML.load_file(file)
70
+ rescue
71
+ {}
72
+ end
73
+
74
+ def add_file(f)
75
+ files << f if File.exists?(f)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,88 @@
1
+ require 'time'
2
+
3
+ module Droppper
4
+ module Droplets extend self
5
+
6
+ def list(*args)
7
+ data = droplets(*args)
8
+ tp data, {id: {display_name: "ID"}},
9
+ {name: {display_name: "NAME"}},
10
+ {"region.slug" => {display_name: "REGION"}},
11
+ {"size_slug" => {display_name: "SIZE"}},
12
+ :status,
13
+ :locked
14
+ end
15
+
16
+ def show(*args)
17
+ d = droplet(*args)
18
+ puts <<-eos
19
+ ID: #{d.id}
20
+ Name: #{d.name}
21
+ Memory: #{d.memory}MB
22
+ vCPUs: #{d.vcpus}
23
+ Disk: #{d.disk}G
24
+ Created on: #{Time.parse(d.created_at).rfc2822}
25
+ Status: #{d.status}
26
+ Backups: #{d.backup_ids.size}
27
+ Features: #{d.features.join(", ")}
28
+ Region: #{d.region.name}
29
+ Image: #{d.image.name}
30
+ Kernel: #{d.kernel.name}
31
+ eos
32
+ puts "Networking:"
33
+ [['v4', 'public'], ['v4', 'private'], ['v6', 'public'], ['v6', 'private']].each do |pair|
34
+ version, publicity = pair
35
+ if net = d.networks.send(version).find{|net| net.type == publicity}
36
+ puts " IP#{version} (#{publicity}):".ljust(18) +"#{net.ip_address}"
37
+ end
38
+ end
39
+ end
40
+
41
+ def ssh(*args, options)
42
+ d = droplet(*args)
43
+ cmd_options = [
44
+ "-o", "IdentitiesOnly=yes",
45
+ "-o", "LogLevel=ERROR",
46
+ "-o", "StrictHostKeyChecking=no",
47
+ "-o", "UserKnownHostsFile=/dev/null",
48
+ "-i", File.expand_path(Droppper.config.ssh.keyfile)
49
+ ]
50
+ cmd_options.push "-l", "#{options['user']||Droppper.config.ssh.user}"
51
+ cmd_options.push "-p", "#{options['port']||Droppper.config.ssh.port}"
52
+ cmd_options << d.public_ip
53
+ puts "Executing: ssh #{cmd_options.join(" ")}"
54
+ Kernel.exec("ssh", *cmd_options)
55
+ end
56
+
57
+ def droplets(*args)
58
+ args = Array(args).flatten
59
+ data = Droppper.client.droplets.all.to_a
60
+ if args.size > 0
61
+ data = data.select do |d|
62
+ (args.size==1 and (d.id.to_s == args[0] or d.name == args[0])) or (d.name =~ Regexp.new(args.join(".*")))
63
+ end
64
+ end
65
+ data
66
+ end
67
+
68
+ def droplet(*args)
69
+ list = droplets(*args)
70
+ if list.size == 0
71
+ puts "Cannot find droplet"
72
+ elsif list.size == 1
73
+ list.first
74
+ else
75
+ select_droplet(list)
76
+ end
77
+ end
78
+
79
+ def select_droplet(list)
80
+ choose do |menu|
81
+ menu.prompt = "Multiple droplets found. Select one:"
82
+ list.each do |droplet|
83
+ menu.choice droplet.name do droplet end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -1,26 +1,5 @@
1
1
  module Droppper
2
2
  module Utils extend self
3
- def find_token
4
- f = find_dot_dropper_file
5
- File.open(f).read.strip if f
6
- end
7
-
8
- def find_dot_dropper_file
9
- find_nearest_dot_dropper_file || default_drop_droppper_file
10
- end
11
-
12
- def find_nearest_dot_dropper_file(root=Dir.pwd)
13
- f = File.expand_path ".droppper", root
14
- return f if File.exists?(f)
15
- return nil if root=='/'
16
- find_nearest_dot_dropper_file(File.expand_path("..", root))
17
- end
18
-
19
- def default_drop_droppper_file
20
- f = File.join(File.expand_path("~"), ".droppper")
21
- return f if File.exists?(f)
22
- end
23
-
24
3
  def print_hash(hash, include_empty=false)
25
4
  lines = []
26
5
  recursive_flatten_hash(hash).each do |key, value|
@@ -1,3 +1,3 @@
1
1
  module Droppper
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: droppper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cristian Bica
@@ -11,21 +11,21 @@ cert_chain: []
11
11
  date: 2015-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: gli
14
+ name: thor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: highline
28
+ name: table_print
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: table_print
42
+ name: droplet_kit
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,21 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: droplet_kit
56
+ name: hashie
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: highline
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
@@ -109,8 +123,10 @@ files:
109
123
  - bin/droppper
110
124
  - droppper.gemspec
111
125
  - lib/droppper.rb
126
+ - lib/droppper/cli.rb
112
127
  - lib/droppper/commands/droplets.rb
113
- - lib/droppper/commands/ssh.rb
128
+ - lib/droppper/config.rb
129
+ - lib/droppper/droplets.rb
114
130
  - lib/droppper/utils.rb
115
131
  - lib/droppper/version.rb
116
132
  homepage: https://github.com/cristianbica/droppper
@@ -1,14 +0,0 @@
1
- desc "SSH to your DigitalOcean droplets"
2
- command :ssh do |cmd|
3
- cmd.flag [:u, :user], desc: "SSH Username", default_value: 'deploy'
4
- cmd.flag [:p, :port], desc: "SSH Port", default_value: '22'
5
-
6
- cmd.action do |global,options,args|
7
- droplet = Droppper.droplet(args)
8
- if droplet
9
- Droppper.ssh droplet, user: options[:user], port: options[:port]
10
- else
11
- puts "Cannot find any droplet"
12
- end
13
- end
14
- end