ugc 0.0.6 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ugc (0.0.6)
4
+ ugc (0.9.0)
5
5
  command_line_reporter
6
6
  gli (= 2.5.0)
7
7
  highline
8
- usergrid_iron
8
+ usergrid_iron (>= 0.0.9)
9
9
 
10
10
  GEM
11
11
  remote: http://rubygems.org/
@@ -41,7 +41,7 @@ GEM
41
41
  mime-types (>= 1.16)
42
42
  rspec-expectations (2.12.1)
43
43
  diff-lcs (~> 1.1.3)
44
- usergrid_iron (0.0.8)
44
+ usergrid_iron (0.0.9)
45
45
  multi_json
46
46
  rest-client
47
47
 
data/README.md CHANGED
@@ -5,10 +5,14 @@ ugc enables convenient terminal access to Apigee's App Services (aka Usergrid).
5
5
  ## Features
6
6
 
7
7
  * Multiple connection/login profiles
8
- * Simple syntax
9
- * Use relative (or absolute) URLs
8
+ * Simple syntax to Usergrid data
9
+ * Use relative or absolute URLs
10
+ * Convenient path reference '@n' to previous list entities
10
11
  * Easy-to-read tabular output
11
- * Optionally also emits raw output (--verbose switch)
12
+ * Simplified json-generating syntax for data (key: 'value')
13
+ * Ruby evaluation within data elements
14
+ * Can optionally emits raw output (--verbose switch)
15
+ * Extended SQL syntax (adds 'from' and 'limit' clauses to standard Usergrid syntax)
12
16
 
13
17
  ## Installation
14
18
 
@@ -18,41 +22,168 @@ Note: Requires Ruby 1.9.3+. If you have issues, check your version:
18
22
 
19
23
  $ ruby -v
20
24
 
21
- If necessary, install a new version of Ruby. [RVM](Ruby 1.9.x
22
- ) is recommended:
25
+ If necessary, install a new version of Ruby. [RVM](https://rvm.io) is recommended:
23
26
 
24
27
  $ \curl -L https://get.rvm.io | bash -s stable --ruby
25
28
 
26
29
  ## Usage
27
30
 
28
- ### Help
31
+ ### Commands
29
32
 
30
- $ ugc help
33
+ delete - delete an entity
34
+ get, show, ls, list - retrieve a collection or entity
35
+ help - Shows a list of commands or help for one command
36
+ login - Describe login here
37
+ post, create - non-idempotent create or update (usually create)
38
+ profile, profiles - set the current profile
39
+ put, update - idempotent create or update (usually an update)
40
+ query - query
41
+ target - set the base url, org, and app
31
42
 
32
43
  ### Setup
33
44
 
34
- Connect to an Apigee administrator account:
45
+ #### Create a profile:
35
46
 
36
47
  $ ugc profile apigee
48
+
49
+ #### Set targets:
50
+
51
+ $ ugc target base https://api.usergrid.com
52
+ base_url = https://api.usergrid.com
53
+
37
54
  $ ugc target organization scottganyo
38
55
  organization = scottganyo
56
+
39
57
  $ ugc target app messagee
40
58
  application = messagee
59
+
60
+ #### (Alternatively, you can just specify the whole url at once)
61
+
62
+ $ ugc target url https://api.usergrid.com/scottganyo/messagee
63
+ base_url = https://api.usergrid.com
64
+ organization = scottganyo
65
+ application = messagee
66
+
67
+ #### Login:
68
+
69
+ (Note the user in this case is an admin user)
70
+
41
71
  $ ugc login --admin scott@ganyo.com
42
72
  password: **********
43
73
  logged in user: scott@ganyo.com
44
-
74
+
75
+ #### Verify your profile:
76
+
77
+ $ ugc profile apigee
78
+ Set active profile:
79
+ *apigee
80
+ base_url: https://api.usergrid.com
81
+ organization: scottganyo
82
+ application: messagee
83
+ access_token: YWMtKgZnO1ULEeKKqQLoGuZA3AAAATwesjMsUYmz_ZGk8vkTwp0lh66Cv_CCEM4
84
+
45
85
 
46
86
  ### Examples
47
87
 
48
- ![image](https://github.com/scottganyo/ugc/raw/master/examples.jpeg)
88
+ #### list all Usergrid entity collections
89
+
90
+ $ ugc list collections
91
+ title count name type
92
+ Assets 0 assets asset
93
+ Users 0 users user
94
+ Events 0 events event
95
+ Roles 3 roles role
96
+ Folders 0 folders folder
97
+ Activities 0 activities activity
98
+ Devices 0 devices device
99
+ Groups 0 groups group
100
+
101
+ What? No dogs? A travesty!
102
+
103
+ #### create a dog
104
+
105
+ (Note the use of simplified json syntax)
106
+
107
+ $ ugc create dog "breed: 'Black Mouth Cur', name: 'Old Yeller'"
108
+ name value
109
+ uuid 91833fd9-56c5-11e2-a6b8-14109fd49581
110
+ name Old Yeller
111
+ created 1357341732438
112
+ modified 1357341732438
113
+ breed Black Mouth Cur
114
+
115
+ #### he's lonely. we need more dogs.
116
+
117
+ (Note use of square brackets to create an array of dogs)
118
+
119
+ $ ugc create dogs "[{ name: 'Tramp' },{ breed: 'Cocker Spaniel', name: 'Lady' }]"
120
+ # uuid name created modified breed
121
+ 1 79dfb563-56cb-11e2-a6b8-14109fd49581 Tramp 1357344269759 1357344269759
122
+ 2 79e11500-56cb-11e2-a6b8-14109fd49581 Lady 1357344269768 1357344269768 Cocker Spaniel
123
+
124
+ All the created dogs were returned as a list.
125
+
126
+ #### oops, show that first dog
127
+
128
+ (Note use of @1 to reference the 1st row from the previous list.)
129
+
130
+ $ ugc show @1
131
+ name value
132
+ uuid 79dfb563-56cb-11e2-a6b8-14109fd49581
133
+ name Tramp
134
+ created 1357344269759
135
+ modified 1357344269768
136
+
137
+ Note synonym commands:
138
+
139
+ $ ugc show dogs/79dfb563-56cb-11e2-a6b8-14109fd49581
140
+ $ ugc show dogs/Tramp
141
+
142
+
143
+ #### yup. forgot to set the breed, update that dog
144
+
145
+ (Note use of standard json data)
146
+
147
+ $ ugc update @1 '{ "breed" : "Mixed" }'
148
+ name value
149
+ uuid 79dfb563-56cb-11e2-a6b8-14109fd49581
150
+ name Tramp
151
+ created 1357344269759
152
+ modified 1357344537483
153
+ breed Mixed
154
+
155
+ #### show off our latest dogs
156
+
157
+ $ ugc query dogs 'select name, breed where modified >= 1357344269768'
158
+ # name breed
159
+ 1 Einstein Mixed
160
+ 2 Lady Cocker Spaniel
161
+
162
+ Note: with ugc, you can also use extended sql syntax...
163
+
164
+ $ ugc query 'select name, breed from dogs where modified >= 1357344269768 limit 1'
165
+ # name breed
166
+ 1 Einstein Mixed
167
+
168
+ #### -- Special note on specifying column names in queries --
169
+
170
+ If you specify column names in your query, you will be unable to reference the returned rows by @1 reference in later commands. (The current Usergrid implementation doesn't return any metadata for the entries.) In addition, for your safety the history will be cleared so that you don't inadvertently reference entities from a previous list.
49
171
 
50
172
  ## Release notes
51
173
 
174
+ ### 0.9.0
175
+ * New features
176
+ 1. path reference '@n' in commands to previous list entities
177
+ * eg. `$ ugc put @1 foo: 'bar'`
178
+ 2. added --no-border flag
179
+ 3. added rm alias for delete
180
+ * Bug fixes
181
+ 1. lock required version of usergrid_iron
182
+
52
183
  ### 0.0.6
53
184
  * New features
54
185
  1. Ruby eval of data in put and post commands
55
- * eg. may now use "key: 'value'" for json instead of '{"key": "value"}'
186
+ * eg. may now use `key: 'value'` for json instead of `{"key": "value"}`
56
187
  2. Added alias: 'show' for 'get'
57
188
  3. Made 'list' an alias of 'get' and updated get to include 'list' functionality
58
189
  4. smart column width for entities
data/bin/ugc CHANGED
@@ -13,7 +13,11 @@ program_desc 'Usergrid Command Line'
13
13
  version Ugc::VERSION
14
14
 
15
15
  desc 'verbose'
16
- switch [:v,:verbose]
16
+ switch [:v,:verbose], negatable: false
17
+
18
+ desc 'draw table border'
19
+ default_value true
20
+ switch [:b,:border]
17
21
 
18
22
  desc 'settings directory'
19
23
  arg_name 'settings directory'
@@ -33,7 +37,7 @@ pre do |global_options,command,options,args|
33
37
  Usergrid::LOG.level = Logger::WARN
34
38
  end
35
39
 
36
- $settings = Ugc::Settings.new global_options[:settings]
40
+ $settings = Ugc::Settings.new global_options
37
41
  if pre_login.include? command.name
38
42
  true
39
43
  elsif command.name == :login && $settings.configured?
@@ -21,5 +21,14 @@ module Ugc
21
21
  $settings.access_token = auth_token
22
22
  end
23
23
 
24
+ def [](uri)
25
+ uri = perform_substitutions uri
26
+ if URI.parse(uri).host
27
+ Usergrid::Resource.new(uri, nil, $application.options) # absolute
28
+ else
29
+ super # relative
30
+ end
31
+ end
32
+
24
33
  end
25
34
  end
@@ -1,12 +1,12 @@
1
1
  desc 'delete an entity'
2
2
  arg_name 'url'
3
3
 
4
- command :delete do |c|
4
+ command :rm,:del,:delete do |c|
5
5
 
6
6
  c.action do |global_options,options,args|
7
7
  help_now! unless args[0]
8
8
 
9
- format_result resource(args[0]).delete
9
+ format_response $application[args[0]].delete
10
10
  end
11
11
 
12
12
  end
@@ -8,7 +8,7 @@ command :get,:show,:ls,:list do |c|
8
8
  c2.action do |global_options,options,args|
9
9
  help_now! unless args[0]
10
10
 
11
- format_result $application[args[0]].get
11
+ format_response $application[args[0]].get
12
12
  end
13
13
  end
14
14
 
@@ -18,7 +18,7 @@ command :get,:show,:ls,:list do |c|
18
18
  c2.action do |global_options,options,args|
19
19
  app = $application.entity
20
20
  collections = app['metadata']['collections']
21
- table border: true do
21
+ table border: $settings.table_border? do
22
22
  row header: true do
23
23
  collections.first[1].each_key do |k|
24
24
  column k
@@ -40,7 +40,9 @@ command :get,:show,:ls,:list do |c|
40
40
  c.desc e
41
41
  c.command [e.to_sym] do |c2|
42
42
  c2.action do |global_options,options,args|
43
- format_collection($application[e].collection)
43
+ response = $application[e].get
44
+ format_collection response.collection
45
+ save_response response
44
46
  end
45
47
  end
46
48
  end
@@ -7,7 +7,7 @@ command :post,:create do |c|
7
7
  c.action do |global_options,options,args|
8
8
  help_now! unless args[0]
9
9
 
10
- format_result resource(args[0]).post parse_data(options[:data] || args[1])
10
+ format_response $application[args[0]].post parse_data(options[:data] || args[1])
11
11
  end
12
12
 
13
13
  end
@@ -7,7 +7,7 @@ command :put,:update do |c|
7
7
  c.action do |global_options,options,args|
8
8
  help_now! unless args[0]
9
9
 
10
- format_result resource(args[0]).put parse_data(options[:data] || args[1])
10
+ format_response $application[args[0]].put parse_data(options[:data] || args[1])
11
11
  end
12
12
 
13
13
  end
@@ -21,6 +21,7 @@ command :query do |c|
21
21
  type = parsed_query['from']
22
22
  query.gsub! /from\s+#{type}/i, ''
23
23
  end
24
+ help_now! 'collection_name or sql from clause is required' unless type
24
25
 
25
26
  params = {}
26
27
  if parsed_query['limit']
@@ -32,6 +33,7 @@ command :query do |c|
32
33
  response = $application[type].query query, params
33
34
 
34
35
  format_collection response.collection, parsed_query['select']
36
+ save_response response
35
37
  end
36
38
 
37
39
  end
@@ -36,7 +36,7 @@ command :target do |c|
36
36
  if args[0]
37
37
  app_name = args[0].split('/')[-1]
38
38
  org_name = args[0].split('/')[-2]
39
- base_url = args[0][0..url.index(org_name)-2]
39
+ base_url = args[0][0..args[0].index(org_name)-2]
40
40
  $settings.base_url = base_url
41
41
  $settings.organization = org_name
42
42
  $settings.application = app_name
@@ -1,20 +1,23 @@
1
1
  SKIP_ATTRS = %w(metadata uri type)
2
+ INDEX_COL_WIDTH = 2
2
3
 
3
- def format_result(response)
4
+ def format_response(response)
4
5
  if response.multiple_entities? && response.collection.size > 1
5
- format_collection(response.collection)
6
+ format_collection response.collection
6
7
  else
7
- format_entity(response.entity)
8
+ format_entity response.entity
8
9
  end
9
10
  end
10
11
 
11
- INDEX_COL_WIDTH = 2
12
- COL_OVERHEAD = 3
12
+ def col_overhead
13
+ $settings.table_border? ? 3 : 1
14
+ end
13
15
 
14
16
  def format_collection(collection, headers=nil)
15
17
  if collection && collection.size > 0
18
+ save_response collection.response
16
19
  metadata = collection_metadata collection, headers
17
- table border: true do
20
+ table border: $settings.table_border? do
18
21
  row header: true do
19
22
  headers ||= metadata.keys
20
23
  column '#', width: INDEX_COL_WIDTH
@@ -46,10 +49,11 @@ def format_entity(entity)
46
49
  name_cols = [name_cols, k.size].max
47
50
  value_cols = [value_cols, v.to_s.size].max
48
51
  end
49
- table border: true do
52
+ table border: $settings.table_border? do
50
53
  row header: true do
51
- column 'name', width: [name_cols, 20].min
52
- column 'value', width: [value_cols, HighLine.new.output_cols - 28].min
54
+ name_width = [name_cols, 20].min
55
+ column 'name', width: name_width
56
+ column 'value', width: [value_cols, HighLine.new.output_cols - name_width - (3 * col_overhead)].min
53
57
  end
54
58
  entity.data.reject{|k,v| SKIP_ATTRS.include? k}.each do |k,v|
55
59
  row do
@@ -86,7 +90,7 @@ def collection_metadata(collection, headers=nil)
86
90
  total + meta[:max_size]
87
91
  end
88
92
  terminal_columns = HighLine.new.output_cols
89
- overhead = (result.keys.size + 2) * COL_OVERHEAD + INDEX_COL_WIDTH
93
+ overhead = (result.keys.size + 2) * col_overhead + INDEX_COL_WIDTH
90
94
  if total_size + overhead < terminal_columns
91
95
  result.each {|col,meta| meta[:size] = meta[:max_size]}
92
96
  else
@@ -0,0 +1,25 @@
1
+ def save_response(response)
2
+ if response && response.multiple_entities? && response.collection.size > 1
3
+ paths = response.entities.collect {|e| e['metadata']['path'][1..-1] } rescue []
4
+ blob = Marshal.dump paths
5
+ $settings.save_profile_blob 'last_response', blob
6
+ end
7
+ end
8
+
9
+ def replacement_for(replacement_parm)
10
+ unless @last_response
11
+ blob = $settings.load_profile_blob 'last_response'
12
+ @last_response = Marshal.load blob
13
+ end
14
+ index = replacement_parm[1..-1].to_i
15
+ raise "no data for replacement param: #{replacement_parm}" unless @last_response[index-1]
16
+ @last_response[index-1]
17
+ end
18
+
19
+ def perform_substitutions(string)
20
+ string = string.clone
21
+ string.scan(/@[0-9]+/).uniq.each do |e|
22
+ string.gsub! e, replacement_for(e)
23
+ end
24
+ string
25
+ end
@@ -25,8 +25,9 @@ end
25
25
 
26
26
  # returns a json string
27
27
  def parse_data(input)
28
+ return unless input
28
29
  # must be wrapped in {}
29
- input = "{#{input}}" unless input.start_with? '{'
30
+ input = "{#{input}}" unless input.start_with? '{' or input.start_with? '['
30
31
  # must be a json string or 1.9 hash format
31
32
  begin
32
33
  MultiJson.dump(eval(input))
data/lib/ugc/settings.rb CHANGED
@@ -3,9 +3,10 @@ module Ugc
3
3
 
4
4
  SETTINGS_FILE = 'settings.yml'
5
5
 
6
- def initialize(directory)
7
- @file = File.join directory, SETTINGS_FILE
8
- @settings = YAML.load_file(@file) rescue default_settings
6
+ def initialize(global_options)
7
+ @draw_table_border = global_options[:border]
8
+ @settings_file = File.join global_options[:settings], SETTINGS_FILE
9
+ @settings = YAML.load_file(@settings_file) rescue default_settings
9
10
  end
10
11
 
11
12
  def active_profile_name
@@ -15,14 +16,14 @@ module Ugc
15
16
  def active_profile_name=(name)
16
17
  raise "unknown profile: #{name}" unless profile(name)
17
18
  @settings['active_profile'] = name
18
- save
19
+ save_profile
19
20
  end
20
21
 
21
22
  def delete_profile(name)
22
23
  raise "cannot delete active profile" if active_profile_name == name
23
24
  raise "unknown profile: #{name}" unless profiles[name]
24
25
  profiles.delete name
25
- save
26
+ save_profile
26
27
  end
27
28
 
28
29
  def profile(name=nil)
@@ -71,20 +72,39 @@ module Ugc
71
72
  base_url && organization && application
72
73
  end
73
74
 
75
+ def table_border?
76
+ !!@draw_table_border
77
+ end
78
+
74
79
  def logged_in?
75
80
  !!access_token
76
81
  end
77
82
 
83
+ def save_profile_blob(name, data)
84
+ file = File.join settings_dir, "#{active_profile_name}.#{name}"
85
+ File.open(file, 'w') do |out|
86
+ out.write data
87
+ end
88
+ end
89
+
90
+ def load_profile_blob(name)
91
+ IO.read File.join settings_dir, "#{active_profile_name}.#{name}"
92
+ end
93
+
78
94
  private
79
95
 
80
96
  def set_profile(prop, value)
81
97
  profile[prop] = value
82
- save
98
+ save_profile
99
+ end
100
+
101
+ def settings_dir
102
+ File.dirname(@settings_file)
83
103
  end
84
104
 
85
- def save
86
- Dir.mkdir(File.dirname(@file)) unless Dir.exist?(File.dirname(@file))
87
- File.open(@file, 'w') do |out|
105
+ def save_profile
106
+ Dir.mkdir(settings_dir) unless Dir.exist?(settings_dir)
107
+ File.open(@settings_file, 'w') do |out|
88
108
  YAML.dump(@settings, out)
89
109
  end
90
110
  end
data/lib/ugc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ugc
2
- VERSION = '0.0.6'
2
+ VERSION = '0.9.0'
3
3
  end
data/ugc.gemspec CHANGED
@@ -19,7 +19,7 @@ spec = Gem::Specification.new do |s|
19
19
  s.add_development_dependency('rdoc')
20
20
  s.add_development_dependency('aruba')
21
21
  s.add_runtime_dependency('gli','2.5.0')
22
- s.add_runtime_dependency('usergrid_iron')
22
+ s.add_runtime_dependency('usergrid_iron','>= 0.0.9')
23
23
  s.add_runtime_dependency('highline')
24
24
  s.add_runtime_dependency('command_line_reporter')
25
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ugc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.9.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-04 00:00:00.000000000 Z
12
+ date: 2013-01-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -82,7 +82,7 @@ dependencies:
82
82
  requirements:
83
83
  - - ! '>='
84
84
  - !ruby/object:Gem::Version
85
- version: '0'
85
+ version: 0.0.9
86
86
  type: :runtime
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  requirements:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
- version: '0'
93
+ version: 0.0.9
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: highline
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -140,7 +140,6 @@ files:
140
140
  - README.rdoc
141
141
  - Rakefile
142
142
  - bin/ugc
143
- - examples.jpeg
144
143
  - features/step_definitions/ugc_steps.rb
145
144
  - features/support/env.rb
146
145
  - features/ugc.feature
@@ -155,8 +154,8 @@ files:
155
154
  - lib/ugc/commands/query.rb
156
155
  - lib/ugc/commands/target.rb
157
156
  - lib/ugc/helpers/format.rb
157
+ - lib/ugc/helpers/history.rb
158
158
  - lib/ugc/helpers/parse.rb
159
- - lib/ugc/helpers/uri.rb
160
159
  - lib/ugc/management.rb
161
160
  - lib/ugc/settings.rb
162
161
  - lib/ugc/version.rb
@@ -184,7 +183,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
184
183
  version: '0'
185
184
  segments:
186
185
  - 0
187
- hash: -2161769601695807419
186
+ hash: 1424632812538279797
188
187
  required_rubygems_version: !ruby/object:Gem::Requirement
189
188
  none: false
190
189
  requirements:
@@ -193,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
192
  version: '0'
194
193
  segments:
195
194
  - 0
196
- hash: -2161769601695807419
195
+ hash: 1424632812538279797
197
196
  requirements: []
198
197
  rubyforge_project:
199
198
  rubygems_version: 1.8.24
data/examples.jpeg DELETED
Binary file
@@ -1,7 +0,0 @@
1
- def resource(uri)
2
- if URI.parse(uri).host
3
- Usergrid::Resource.new(uri, nil, $application.options) # absolute
4
- else
5
- $application[uri] # relative
6
- end
7
- end