droppper 0.1.0 → 0.2.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: 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