spacialdb 0.0.1 → 0.0.2

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.
@@ -67,11 +67,32 @@ class Spacialdb::Client
67
67
  def process(method, uri, extra_headers={}, payload=nil)
68
68
  headers = spacialdb_headers.merge(extra_headers)
69
69
  args = [method, payload, headers].compact
70
- response = resource(uri).send(*args)
71
70
 
71
+ resource_options = default_resource_options_for_uri(uri)
72
+
73
+ begin
74
+ response = resource(uri, resource_options).send(*args)
75
+ rescue RestClient::SSLCertificateNotVerified => ex
76
+ host = URI.parse(realize_full_uri(uri)).host
77
+ error "WARNING: Unable to verify SSL certificate for #{host}\nTo disable SSL verification, run with SPACIALDB_SSL_VERIFY=disable"
78
+ end
79
+
80
+ extract_warning(response)
72
81
  response
73
82
  end
74
83
 
84
+ def extract_warning(response)
85
+ return unless response
86
+ if response.headers[:x_spacialdb_warning] && @warning_callback
87
+ warning = response.headers[:x_spacialdb_warning]
88
+ @displayed_warnings ||= {}
89
+ unless @displayed_warnings[warning]
90
+ @warning_callback.call(warning)
91
+ @displayed_warnings[warning] = true
92
+ end
93
+ end
94
+ end
95
+
75
96
  def spacialdb_headers # :nodoc:
76
97
  {
77
98
  'X-Spacialdb-API-Version' => '1',
@@ -81,7 +102,7 @@ class Spacialdb::Client
81
102
  }
82
103
  end
83
104
 
84
- def resource(uri)
105
+ def resource(uri, options={})
85
106
  RestClient.proxy = ENV['HTTP_PROXY'] || ENV['http_proxy']
86
107
  resource = RestClient::Resource.new(realize_full_uri(uri),
87
108
  :user => login,
@@ -91,12 +112,27 @@ class Spacialdb::Client
91
112
  end
92
113
 
93
114
  def realize_full_uri(given)
94
- full_host = (host =~ /^http/) ? host : "http://#{host}"
115
+ full_host = (host =~ /^http/) ? host : "https://#{host}"
95
116
  host = URI.parse(full_host)
96
117
  uri = URI.parse(given)
97
118
  uri.host ||= host.host
98
- uri.scheme ||= host.scheme || "http"
119
+ uri.scheme ||= host.scheme || "https"
99
120
  uri.path = (uri.path[0..0] == "/") ? uri.path : "/#{uri.path}"
121
+ uri.port = host.port if full_host =~ /\:\d+/
100
122
  uri.to_s
101
123
  end
124
+
125
+ def default_resource_options_for_uri(uri)
126
+ if ENV["SPACIALDB_SSL_VERIFY"] == "disable"
127
+ {}
128
+ elsif realize_full_uri(uri) =~ %r|^https://beta.spacialdb.com|
129
+ { :verify_ssl => OpenSSL::SSL::VERIFY_PEER, :ssl_ca_file => local_ca_file }
130
+ else
131
+ {}
132
+ end
133
+ end
134
+
135
+ def local_ca_file
136
+ File.expand_path("../../../data/cacert.pem", __FILE__)
137
+ end
102
138
  end
@@ -48,8 +48,9 @@ module Spacialdb
48
48
 
49
49
  global_option :db, "--db DB", "-d"
50
50
  global_option :confirm, "--confirm DB"
51
+ global_option :help, "--help", "-h"
51
52
 
52
- def self.run(cmd, args=[])
53
+ def self.prepare_run(cmd, args=[])
53
54
 
54
55
  command = parse(cmd)
55
56
 
@@ -85,31 +86,37 @@ module Spacialdb
85
86
  retry
86
87
  end
87
88
 
88
- if opts[:help]
89
- run "help", [cmd]
90
- return
91
- end
89
+ raise OptionParser::ParseError if opts[:help]
92
90
 
93
91
  args.concat(invalid_options)
94
92
 
95
- begin
96
- object = command[:klass].new(args.dup, opts.dup)
97
- object.send(command[:method])
98
- rescue InvalidCommand
99
- error "Unknown command. Run 'spacialdb help' for usage information."
100
- rescue RestClient::Unauthorized
101
- puts "Authentication failure"
102
- run "login"
93
+ [ command[:klass].new(args.dup, opts.dup), command[:method] ]
94
+ end
95
+
96
+ def self.run(cmd, arguments=[])
97
+ object, method = prepare_run(cmd, arguments)
98
+ object.send(method)
99
+ rescue InvalidCommand
100
+ error "Unknown command. Run 'spacialdb help' for usage information."
101
+ rescue RestClient::Unauthorized
102
+ puts "Authentication failure"
103
+ run "login"
104
+ retry
105
+ rescue RestClient::ResourceNotFound => e
106
+ error extract_not_found(e.http_body)
107
+ rescue RestClient::Locked => e
108
+ db = e.response.headers[:x_confirmation_required]
109
+ message = extract_error(e.response.body)
110
+ if confirmation_required(db, message)
111
+ opts[:confirm] = db
103
112
  retry
104
- rescue RestClient::ResourceNotFound => e
105
- error extract_not_found(e.http_body)
106
- rescue RestClient::RequestFailed => e
107
- error extract_error(e.http_body)
108
- rescue RestClient::RequestTimeout
109
- error "API request timed out. Please try again, or contact support@spacialdb.com if this issue persists."
110
- rescue CommandFailed => e
111
- error e.message
112
113
  end
114
+ rescue RestClient::RequestFailed => e
115
+ error extract_error(e.http_body)
116
+ rescue RestClient::RequestTimeout
117
+ error "API request timed out. Please try again, or contact support@spacialdb.com if this issue persists."
118
+ rescue CommandFailed => e
119
+ error e.message
113
120
  rescue OptionParser::ParseError => ex
114
121
  commands[cmd] ? run("help", [cmd]) : run("help")
115
122
  rescue Interrupt => e
@@ -128,7 +135,7 @@ module Spacialdb
128
135
  msg = parse_error_json(body) || parse_error_plain(body) || 'Internal server error'
129
136
  msg.split("\n").map { |line| ' ! ' + line }.join("\n")
130
137
  end
131
-
138
+
132
139
  def self.parse_error_json(body)
133
140
  json = json_decode(body.to_s)
134
141
  json ? json['error'] : nil
@@ -138,5 +145,20 @@ module Spacialdb
138
145
  return unless body.respond_to?(:headers) && body.headers[:content_type].to_s.include?("text/plain")
139
146
  body.to_s
140
147
  end
148
+
149
+ def self.confirmation_required(db, message)
150
+ display
151
+ display
152
+ display message
153
+ display " ! To proceed, type \"#{db}\" or re-run this command with --confirm #{db}"
154
+ display
155
+ display "> ", false
156
+ if ask.downcase != app
157
+ display " ! Input did not match #{db}. Aborted."
158
+ false
159
+ else
160
+ true
161
+ end
162
+ end
141
163
  end
142
164
  end
@@ -24,7 +24,7 @@ class Spacialdb::Command::Base
24
24
  protected
25
25
 
26
26
  def self.inherited(klass)
27
- help = extract_help(*(caller.first.split(":")[0..1])).strip
27
+ help = extract_help_from_caller(caller.first)
28
28
 
29
29
  Spacialdb::Command.register_namespace(
30
30
  :name => klass.namespace,
@@ -37,13 +37,10 @@ protected
37
37
  return if private_method_defined?(method)
38
38
  return if protected_method_defined?(method)
39
39
 
40
- help = extract_help(*(caller.first.split(":")[0..1]))
41
-
40
+ help = extract_help_from_caller(caller.first)
42
41
  resolved_method = (method.to_s == "index") ? nil : method.to_s
43
-
44
42
  default_command = [ self.namespace, resolved_method ].compact.join(":")
45
43
  command = extract_command(help) || default_command
46
-
47
44
  banner = extract_banner(help) || command
48
45
  permute = !banner.index("*")
49
46
  banner.gsub!("*", "")
@@ -67,6 +64,14 @@ protected
67
64
  Spacialdb::Command.command_aliases[new] = old
68
65
  end
69
66
 
67
+ def self.extract_help_from_caller(line)
68
+ # pull out of the caller the information for the file path and line number
69
+ if line =~ /^(.+?):(\d+)/
70
+ return extract_help($1, $2)
71
+ end
72
+ raise "unable to extract help from caller: #{line}"
73
+ end
74
+
70
75
  def self.extract_help(file, line)
71
76
  buffer = []
72
77
  lines = File.read(file).split("\n")
@@ -100,7 +105,7 @@ protected
100
105
  end
101
106
 
102
107
  def self.extract_description(help)
103
- lines = help.split("\n").map(&:strip)
108
+ lines = help.split("\n").map { |l| l.strip }
104
109
  lines.shift
105
110
  lines.reject do |line|
106
111
  line =~ /^-(.+)#(.+)/
@@ -108,11 +113,11 @@ protected
108
113
  end
109
114
 
110
115
  def self.extract_options(help)
111
- help.split("\n").map(&:strip).select do |line|
116
+ help.split("\n").map { |l| l.strip }.select do |line|
112
117
  line =~ /^-(.+)#(.+)/
113
118
  end.inject({}) do |hash, line|
114
119
  description = line.split("#", 2).last.strip
115
- long = line.match(/--([A-Za-z ]+)/)[1].strip
120
+ long = line.match(/--([A-Za-z\- ]+)/)[1].strip
116
121
  short = line.match(/-([A-Za-z ])/)[1].strip
117
122
  hash.update(long.split(" ").first => { :desc => description, :short => short, :long => long })
118
123
  end
@@ -16,7 +16,7 @@ class Spacialdb::Command::Db < Spacialdb::Command::Base
16
16
 
17
17
  # db:create
18
18
  #
19
- # create your databases
19
+ # create a new database
20
20
  #
21
21
  def create
22
22
  display spacialdb.create
@@ -1,155 +1,131 @@
1
1
  require "spacialdb/command/base"
2
+ require "spacialdb/deprecated/help"
2
3
 
3
- module Spacialdb::Command
4
+ # list commands and display help
5
+ #
6
+ class Spacialdb::Command::Help < Spacialdb::Command::Base
4
7
 
5
- # show this help
6
- #
7
- class Help < Base
8
-
9
- class HelpGroup < Array
10
- attr_reader :title
11
-
12
- def initialize(title)
13
- @title = title
14
- end
8
+ PRIMARY_NAMESPACES = %w( auth db )
15
9
 
16
- def command(name, description)
17
- self << [name, description]
18
- end
19
-
20
- def space
21
- self << ['', '']
22
- end
23
- end
24
-
25
- def self.groups
26
- @groups ||= []
27
- end
28
-
29
- def self.group(title, &block)
30
- groups << begin
31
- group = HelpGroup.new(title)
32
- yield group
33
- group
34
- end
35
- end
10
+ include Spacialdb::Deprecated::Help
36
11
 
37
- def index
38
- if command = args.shift
39
- help_for_command(command)
40
- else
41
- help_for_root
42
- end
12
+ # help [COMMAND]
13
+ #
14
+ # list available commands or display help for a specific command
15
+ #
16
+ def index
17
+ if command = args.shift
18
+ help_for_command(command)
19
+ else
20
+ help_for_root
43
21
  end
22
+ end
44
23
 
45
- private
24
+ private
46
25
 
47
- def commands_for_namespace(name)
48
- Spacialdb::Command.commands.values.select do |command|
49
- command[:namespace] == name && command[:method] != :index
50
- end
26
+ def commands_for_namespace(name)
27
+ Spacialdb::Command.commands.values.select do |command|
28
+ command[:namespace] == name && command[:method] != :index
51
29
  end
30
+ end
52
31
 
53
- def namespaces
54
- namespaces = Spacialdb::Command.namespaces
55
- end
32
+ def namespaces
33
+ namespaces = Spacialdb::Command.namespaces
34
+ end
56
35
 
57
- def commands
58
- commands = Spacialdb::Command.commands
59
- Spacialdb::Command.command_aliases.each do |new, old|
60
- commands[new] = commands[old].dup
61
- commands[new][:banner] = "#{new} #{commands[new][:banner].split(" ", 2)[1]}"
62
- commands[new][:command] = new
63
- commands[new][:namespace] = nil
64
- end
65
- commands
36
+ def commands
37
+ commands = Spacialdb::Command.commands
38
+ Spacialdb::Command.command_aliases.each do |new, old|
39
+ commands[new] = commands[old].dup
40
+ commands[new][:banner] = "#{new} #{commands[new][:banner].split(" ", 2)[1]}"
41
+ commands[new][:command] = new
42
+ commands[new][:namespace] = nil
66
43
  end
44
+ commands
45
+ end
67
46
 
68
- def legacy_help_for_namespace(namespace)
69
- instance = Spacialdb::Command::Help.groups.map do |group|
70
- [ group.title, group.select { |c| c.first =~ /^#{namespace}/ }.length ]
71
- end.sort_by(&:last).last
72
- return nil unless instance
73
- return nil if instance.last.zero?
74
- instance.first
75
- end
47
+ def legacy_help_for_namespace(namespace)
48
+ instance = Spacialdb::Command::Help.groups.map do |group|
49
+ [ group.title, group.select { |c| c.first =~ /^#{namespace}/ }.length ]
50
+ end.sort_by { |l| l.last }.last
51
+ return nil unless instance
52
+ return nil if instance.last.zero?
53
+ instance.first
54
+ end
76
55
 
77
- def legacy_help_for_command(command)
78
- Spacialdb::Command::Help.groups.each do |group|
79
- group.each do |cmd, description|
80
- return description if cmd.split(" ").first == command
81
- end
56
+ def legacy_help_for_command(command)
57
+ Spacialdb::Command::Help.groups.each do |group|
58
+ group.each do |cmd, description|
59
+ return description if cmd.split(" ").first == command
82
60
  end
83
- nil
84
61
  end
62
+ nil
63
+ end
85
64
 
86
- PRIMARY_NAMESPACES = %w( auth db )
87
-
88
- def primary_namespaces
89
- PRIMARY_NAMESPACES.map { |name| namespaces[name] }.compact
90
- end
65
+ def primary_namespaces
66
+ PRIMARY_NAMESPACES.map { |name| namespaces[name] }.compact
67
+ end
91
68
 
92
- def additional_namespaces
93
- (namespaces.values - primary_namespaces).sort_by { |n| n[:name] }
94
- end
69
+ def additional_namespaces
70
+ (namespaces.values - primary_namespaces).sort_by { |n| n[:name] }
71
+ end
95
72
 
96
- def summary_for_namespaces(namespaces)
97
- size = longest(namespaces.map { |n| n[:name] })
98
- namespaces.each do |namespace|
99
- name = namespace[:name]
100
- namespace[:description] ||= legacy_help_for_namespace(name)
101
- puts " %-#{size}s # %s" % [ name, namespace[:description] ]
102
- end
73
+ def summary_for_namespaces(namespaces)
74
+ size = longest(namespaces.map { |n| n[:name] })
75
+ namespaces.each do |namespace|
76
+ name = namespace[:name]
77
+ namespace[:description] ||= legacy_help_for_namespace(name)
78
+ puts " %-#{size}s # %s" % [ name, namespace[:description] ]
103
79
  end
80
+ end
104
81
 
105
- def help_for_root
106
- puts "Usage: spacialdb COMMAND [command-specific-options]"
107
- puts
108
- puts "Primary help topics, type \"spacialdb help TOPIC\" for more details:"
109
- puts
110
- summary_for_namespaces(primary_namespaces)
111
- puts
112
- puts "Additional topics:"
113
- puts
114
- summary_for_namespaces(additional_namespaces)
115
- puts
116
- end
82
+ def help_for_root
83
+ puts "Usage: spacialdb COMMAND [command-specific-options]"
84
+ puts
85
+ puts "Primary help topics, type \"spacialdb help TOPIC\" for more details:"
86
+ puts
87
+ summary_for_namespaces(primary_namespaces)
88
+ puts
89
+ puts "Additional topics:"
90
+ puts
91
+ summary_for_namespaces(additional_namespaces)
92
+ puts
93
+ end
117
94
 
118
- def help_for_namespace(name)
119
- namespace_commands = commands_for_namespace(name)
95
+ def help_for_namespace(name)
96
+ namespace_commands = commands_for_namespace(name)
120
97
 
121
- unless namespace_commands.empty?
122
- size = longest(namespace_commands.map { |c| c[:banner] })
123
- namespace_commands.sort_by { |c| c[:method].to_s }.each do |command|
124
- next if command[:help] =~ /DEPRECATED/
125
- command[:summary] ||= legacy_help_for_command(command[:command])
126
- puts " %-#{size}s # %s" % [ command[:banner], command[:summary] ]
127
- end
98
+ unless namespace_commands.empty?
99
+ size = longest(namespace_commands.map { |c| c[:banner] })
100
+ namespace_commands.sort_by { |c| c[:method].to_s }.each do |command|
101
+ next if command[:help] =~ /DEPRECATED/
102
+ command[:summary] ||= legacy_help_for_command(command[:command])
103
+ puts " %-#{size}s # %s" % [ command[:banner], command[:summary] ]
128
104
  end
129
105
  end
106
+ end
130
107
 
131
- def help_for_command(name)
132
- command = commands[name]
133
-
134
- if command
135
- if command[:help].strip.length > 0
136
- print "Usage: spacialdb #{command[:banner]}"
137
- puts command[:help].split("\n")[1..-1].join("\n")
138
- puts
139
- else
140
- puts "Usage: spacialdb #{command[:banner]}"
141
- puts
142
- puts " " + legacy_help_for_command(name).to_s
143
- puts
144
- end
145
- end
108
+ def help_for_command(name)
109
+ command = commands[name]
146
110
 
147
- unless commands_for_namespace(name).empty?
148
- puts "Additional commands, type \"spacialdb help COMMAND\" for more details:"
111
+ if command
112
+ if command[:help].strip.length > 0
113
+ print "Usage: spacialdb #{command[:banner]}"
114
+ puts command[:help].split("\n")[1..-1].join("\n")
149
115
  puts
150
- help_for_namespace(name)
116
+ else
117
+ puts "Usage: spacialdb #{command[:banner]}"
118
+ puts
119
+ puts " " + legacy_help_for_command(name).to_s
151
120
  puts
152
121
  end
153
122
  end
123
+
124
+ unless commands_for_namespace(name).empty?
125
+ puts "Additional commands, type \"spacialdb help COMMAND\" for more details:"
126
+ puts
127
+ help_for_namespace(name)
128
+ puts
129
+ end
154
130
  end
155
131
  end