spacialdb 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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