af 0.3.18.4 → 0.3.18.5

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.
@@ -208,6 +208,14 @@ module VMC::Cli::Command
208
208
  rescue VMC::Client::NotFound, VMC::Client::TargetError
209
209
  err 'No such file or directory'
210
210
  end
211
+
212
+ def download(appname, path=nil)
213
+ path = File.expand_path(path || "#{appname}.zip" )
214
+ banner = "Downloading last pushed source code to #{path}: "
215
+ display banner, false
216
+ client.app_download(appname, path)
217
+ display 'OK'.green
218
+ end
211
219
 
212
220
  def pull(appname, path=nil)
213
221
  path = File.expand_path(path || appname)
@@ -217,6 +225,78 @@ module VMC::Cli::Command
217
225
  display 'OK'.green
218
226
  end
219
227
 
228
+ def clone(src_appname, dest_appname, dest_infra=nil)
229
+
230
+ # FIXME need to ask for dest_appname if nil
231
+
232
+ err "Application '#{dest_appname}' already exists" if app_exists?(dest_appname)
233
+
234
+ app = client.app_info(src_appname)
235
+
236
+ if client.infra_supported?
237
+ dest_infra = @options[:infra] || client.infra_name_for_description(
238
+ ask("Select Infrastructure",:indexed => true, :choices => client.infra_descriptions))
239
+ client.infra = dest_infra
240
+ end
241
+
242
+ url_template = "#{dest_appname}.${target-base}"
243
+ url_resolved = url_template.dup
244
+ resolve_lexically(url_resolved)
245
+
246
+ url = @options[:url] || ask("Application Deployed URL", :default => url_resolved)
247
+
248
+ Dir.mktmpdir do |dir|
249
+ zip_path = File.join(dir,src_appname)
250
+ pull(src_appname,zip_path)
251
+
252
+ display "Cloning '#{src_appname}' to '#{dest_appname}': "
253
+
254
+ manifest = {
255
+ :name => "#{dest_appname}",
256
+ :staging => app[:staging],
257
+ :uris => [ url ],
258
+ :instances => app[:instances],
259
+ :resources => app[:resources]
260
+ }
261
+ manifest[:staging][:command] = app[:staging][:command] if app[:staging][:command]
262
+ manifest[:infra] = { :provider => dest_infra } if dest_infra
263
+
264
+ client.create_app(dest_appname, manifest)
265
+
266
+ # Stage and upload the app bits.
267
+ upload_app_bits(dest_appname, zip_path, dest_infra)
268
+
269
+ # Clone services
270
+ client.services.select { |s| app[:services].include?(s[:name])}.each do |service|
271
+ display "Exporting data from #{service[:name]}: ", false
272
+ export_info = client.export_service(service[:name])
273
+ if export_info
274
+ display 'OK'.green
275
+ else
276
+ err "Export data from '#{service}': failed"
277
+ end
278
+ cloned_service_name = generate_cloned_service_name(src_appname,dest_appname,service[:name],dest_infra)
279
+ display "Creating service #{cloned_service_name}: ", false
280
+ client.create_service(dest_infra, service[:vendor], cloned_service_name)
281
+ display 'OK'.green
282
+ display "Binding service #{cloned_service_name}: ", false
283
+ client.bind_service(cloned_service_name, dest_appname)
284
+ display 'OK'.green
285
+ display "Importing data to #{cloned_service_name}: ", false
286
+ import_info = client.import_service(cloned_service_name,export_info[:uri])
287
+ if import_info
288
+ display 'OK'.green
289
+ else
290
+ err "Import data into '#{service}' failed"
291
+ end
292
+ end
293
+
294
+ no_start = @options[:nostart]
295
+ start(dest_appname, true) unless no_start
296
+
297
+ end
298
+ end
299
+
220
300
  def logs(appname)
221
301
  # Check if we have an app before progressing further
222
302
  client.app_info(appname)
@@ -946,7 +1026,7 @@ module VMC::Cli::Command
946
1026
  runtime = info(:runtime)
947
1027
  infra = info(:infra)
948
1028
 
949
- if infra
1029
+ if client.infra_supported? && infra
950
1030
  err "Infra '#{infra}' is not valid" unless client.infra_valid?(infra)
951
1031
  end
952
1032
 
@@ -93,7 +93,28 @@ module VMC::Cli::Command
93
93
  services.each { |service| bind_service_banner(service, dest_app, false) }
94
94
  check_app_for_restart(dest_app)
95
95
  end
96
-
96
+
97
+ def export_service(service)
98
+ display "Exporting data from '#{service}': ", false
99
+ export_info = client.export_service(service)
100
+ if export_info
101
+ display 'OK'.green
102
+ puts export_info[:uri]
103
+ else
104
+ err "Export data from '#{service}': failed"
105
+ end
106
+ end
107
+
108
+ def import_service(service,url)
109
+ display "Importing data into '#{service}': ", false
110
+ import_info = client.import_service(service,url)
111
+ if import_info
112
+ display 'OK'.green
113
+ else
114
+ err "Import data into '#{service}' failed"
115
+ end
116
+ end
117
+
97
118
  def tunnel(service=nil, client_name=nil)
98
119
  unless defined? Caldecott
99
120
  display "To use `af tunnel', you must first install Caldecott:"
@@ -128,12 +149,11 @@ module VMC::Cli::Command
128
149
 
129
150
  raise VMC::Client::AuthError unless client.logged_in?
130
151
 
131
- infra_name = info[:infra] ? info[:infra][:name] : default_infra
132
-
133
- if infra_name
152
+ infra_name = nil
153
+ if client.infra_supported?
154
+ infra_name = info[:infra] ? info[:infra][:name] : default_infra
134
155
  err "Infra '#{infra_name}' is not valid" unless client.infra_valid?(infra_name)
135
156
  end
136
-
137
157
 
138
158
  if not tunnel_pushed?(infra_name)
139
159
  display "Deploying tunnel application '#{tunnel_appname(infra_name)}'."
@@ -286,6 +286,14 @@ class VMC::Cli::Runner
286
286
  set_cmd(:apps, :files, 2)
287
287
  end
288
288
 
289
+ when 'download'
290
+ usage('af download <appname> [path]')
291
+ if @args.size == 1
292
+ set_cmd(:apps, :download, 1)
293
+ else
294
+ set_cmd(:apps, :download, 2)
295
+ end
296
+
289
297
  when 'pull'
290
298
  usage('af pull <appname> [path]')
291
299
  if @args.size == 1
@@ -374,6 +382,19 @@ class VMC::Cli::Runner
374
382
  usage('af clone-services <src-app> <dest-app>')
375
383
  set_cmd(:services, :clone_services, 2)
376
384
 
385
+ when 'export-service'
386
+ usage('af export-service <service-name>')
387
+ set_cmd(:services, :export_service, 1)
388
+
389
+ when 'import-service'
390
+ usage('af import-service <service-name> <url>')
391
+ set_cmd(:services, :import_service, 2)
392
+
393
+ when 'clone'
394
+ usage('af clone <src-app> <dest-app> [<infra>]')
395
+ set_cmd(:apps, :clone, 2) if @args.size == 2
396
+ set_cmd(:apps, :clone, 3) if @args.size == 3
397
+
377
398
  when 'aliases'
378
399
  usage('af aliases')
379
400
  set_cmd(:misc, :aliases)
@@ -80,6 +80,19 @@ module VMC::Cli
80
80
  r = "%04x" % [rand(0x0100000)]
81
81
  "#{service.to_s}-#{r}"
82
82
  end
83
+
84
+ def generate_cloned_service_name(src_appname,dest_appname,src_servicename,dest_infra)
85
+ r = "%04x" % [rand(0x0100000)]
86
+ dest_servicename = src_servicename.sub(src_appname,dest_appname).sub(/-\h{4,5}/,"-#{r}")
87
+ if src_servicename == dest_servicename
88
+ if dest_infra
89
+ dest_servicename = "#{dest_servicename}-#{dest_infra}"
90
+ else
91
+ dest_servicename = "#{dest_servicename}-#{r}"
92
+ end
93
+ end
94
+ dest_servicename
95
+ end
83
96
 
84
97
  def check_app_for_restart(appname)
85
98
  app = client.app_info(appname)
@@ -101,7 +101,10 @@ module VMC::Cli
101
101
  begin
102
102
  response = RestClient.get(tunnel_url(infra) + "/" + VMC::Client.path("services", service), "Auth-Token" => token)
103
103
  break
104
- rescue RestClient::Exception
104
+ rescue RestClient::Exception => e
105
+ puts "Error infra: #{infra}, url: #{tunnel_url(infra)}"
106
+ display tunnel_url(infra)
107
+ puts e.message.red
105
108
  sleep 1
106
109
  end
107
110
 
@@ -48,6 +48,7 @@ Currently available af commands are:
48
48
  stop <appname> Stop the application
49
49
  restart <appname> [--debug [MODE]] Restart the application
50
50
  delete <appname> Delete the application
51
+ clone <src-app> <dest-app> [infra] Clone the application and services
51
52
 
52
53
  Application Updates
53
54
  update <appname> [--path,--debug [MODE]] Update the application bits
@@ -66,6 +67,7 @@ Currently available af commands are:
66
67
 
67
68
  Application Download
68
69
  pull <appname> [path] Downloads last pushed source to <appname> or [path]
70
+ download <appname> [path] Downloads last pushed source to zipfile
69
71
 
70
72
  Application Environment
71
73
  env <appname> List application environment variables
@@ -75,13 +77,15 @@ Currently available af commands are:
75
77
  Services
76
78
  services Lists of services available and provisioned
77
79
  create-service <service> [--name,--bind] Create a provisioned service
78
- create-service <service> --infra Create a provisioned service on a specified infrastructure
80
+ create-service <service> --infra Create a provisioned service on a specified infrastructure
79
81
  create-service <service> <name> Create a provisioned service and assign it <name>
80
82
  create-service <service> <name> <app> Create a provisioned service and assign it <name>, and bind to <app>
81
83
  delete-service [servicename] Delete a provisioned service
82
84
  bind-service <servicename> <appname> Bind a service to an application
83
85
  unbind-service <servicename> <appname> Unbind service from the application
84
86
  clone-services <src-app> <dest-app> Clone service bindings from <src-app> application to <dest-app>
87
+ export-service <service> Export the data from a service
88
+ import-service <service> <url> Import data into a service
85
89
  tunnel <servicename> [--port] Create a local tunnel to a service
86
90
  tunnel <servicename> <clientcmd> Create a local tunnel to a service and start a local client
87
91
 
@@ -2,6 +2,6 @@ module VMC
2
2
  module Cli
3
3
  # This version number is used as the RubyGem release version.
4
4
  # The internal VMC version number is VMC::VERSION.
5
- VERSION = '0.3.18.4'
5
+ VERSION = '0.3.18.5'
6
6
  end
7
7
  end
@@ -159,11 +159,21 @@ class VMC::Client
159
159
  body
160
160
  end
161
161
 
162
+ def app_download(name,path)
163
+ check_login_status
164
+ url = path(VMC::APPS_PATH, name, "application")
165
+ status, body, headers = http_get(url,'application/octet-stream')
166
+ file = File.new(path,"wb")
167
+ file.write(body)
168
+ file.close
169
+ end
170
+
162
171
  def app_pull(name, dir)
163
172
  check_login_status
164
173
  url = path(VMC::APPS_PATH, name, "application")
165
174
  status, body, headers = http_get(url,'application/octet-stream')
166
175
  file = Tempfile.new(name)
176
+ file.binmode
167
177
  file.write(body)
168
178
  file.close
169
179
  ::VMC::Cli::ZipUtil.unpack(file.path, dir)
@@ -237,6 +247,14 @@ class VMC::Client
237
247
  app[:services] = services
238
248
  update_app(appname, app)
239
249
  end
250
+
251
+ def export_service(service)
252
+ json_get(path(VMC::SERVICE_EXPORT_PATH, service))
253
+ end
254
+
255
+ def import_service(service,uri)
256
+ json_post(path(VMC::SERVICE_IMPORT_PATH, service),{uri:uri})
257
+ end
240
258
 
241
259
  ######################################################
242
260
  # Resources
@@ -360,9 +378,14 @@ class VMC::Client
360
378
 
361
379
  def base_for_infra(name)
362
380
  info = infras.detect { |i| i[:infra] == name }
363
- info ? info[:base] : "aws.af.cm"
381
+ info ? info[:base] : default_base
364
382
  end
365
383
 
384
+ def default_base
385
+ return "vcap.me" if @target =~ /https?:\/\/api.vcap.me/
386
+ "aws.af.cm"
387
+ end
388
+
366
389
  def infra_valid?(name)
367
390
  infras.detect { |i| i[:infra] == name }
368
391
  end
@@ -19,5 +19,9 @@ module VMC
19
19
  APPS_PATH = 'apps'
20
20
  SERVICES_PATH = 'services'
21
21
  USERS_PATH = 'users'
22
+
23
+ # Service paths
24
+ SERVICE_EXPORT_PATH = ['services','export']
25
+ SERVICE_IMPORT_PATH = ['services','import']
22
26
 
23
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: af
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.18.4
4
+ version: 0.3.18.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-17 00:00:00.000000000 -07:00
13
- default_executable:
12
+ date: 2012-09-19 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: json_pure
17
- requirement: &2153196420 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
@@ -25,10 +24,18 @@ dependencies:
25
24
  version: 1.7.0
26
25
  type: :runtime
27
26
  prerelease: false
28
- version_requirements: *2153196420
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 1.5.1
33
+ - - <
34
+ - !ruby/object:Gem::Version
35
+ version: 1.7.0
29
36
  - !ruby/object:Gem::Dependency
30
37
  name: rubyzip
31
- requirement: &2153195620 !ruby/object:Gem::Requirement
38
+ requirement: !ruby/object:Gem::Requirement
32
39
  none: false
33
40
  requirements:
34
41
  - - ~>
@@ -36,10 +43,15 @@ dependencies:
36
43
  version: 0.9.4
37
44
  type: :runtime
38
45
  prerelease: false
39
- version_requirements: *2153195620
46
+ version_requirements: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ~>
50
+ - !ruby/object:Gem::Version
51
+ version: 0.9.4
40
52
  - !ruby/object:Gem::Dependency
41
53
  name: rest-client
42
- requirement: &2153195120 !ruby/object:Gem::Requirement
54
+ requirement: !ruby/object:Gem::Requirement
43
55
  none: false
44
56
  requirements:
45
57
  - - ! '>='
@@ -50,10 +62,18 @@ dependencies:
50
62
  version: 1.7.0
51
63
  type: :runtime
52
64
  prerelease: false
53
- version_requirements: *2153195120
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: 1.6.1
71
+ - - <
72
+ - !ruby/object:Gem::Version
73
+ version: 1.7.0
54
74
  - !ruby/object:Gem::Dependency
55
75
  name: terminal-table
56
- requirement: &2153194380 !ruby/object:Gem::Requirement
76
+ requirement: !ruby/object:Gem::Requirement
57
77
  none: false
58
78
  requirements:
59
79
  - - ~>
@@ -61,10 +81,15 @@ dependencies:
61
81
  version: 1.4.2
62
82
  type: :runtime
63
83
  prerelease: false
64
- version_requirements: *2153194380
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 1.4.2
65
90
  - !ruby/object:Gem::Dependency
66
91
  name: interact
67
- requirement: &2153193920 !ruby/object:Gem::Requirement
92
+ requirement: !ruby/object:Gem::Requirement
68
93
  none: false
69
94
  requirements:
70
95
  - - ~>
@@ -72,10 +97,15 @@ dependencies:
72
97
  version: 0.4.0
73
98
  type: :runtime
74
99
  prerelease: false
75
- version_requirements: *2153193920
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ~>
104
+ - !ruby/object:Gem::Version
105
+ version: 0.4.0
76
106
  - !ruby/object:Gem::Dependency
77
107
  name: addressable
78
- requirement: &2153193440 !ruby/object:Gem::Requirement
108
+ requirement: !ruby/object:Gem::Requirement
79
109
  none: false
80
110
  requirements:
81
111
  - - ~>
@@ -83,10 +113,15 @@ dependencies:
83
113
  version: 2.2.6
84
114
  type: :runtime
85
115
  prerelease: false
86
- version_requirements: *2153193440
116
+ version_requirements: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ~>
120
+ - !ruby/object:Gem::Version
121
+ version: 2.2.6
87
122
  - !ruby/object:Gem::Dependency
88
123
  name: uuidtools
89
- requirement: &2153192940 !ruby/object:Gem::Requirement
124
+ requirement: !ruby/object:Gem::Requirement
90
125
  none: false
91
126
  requirements:
92
127
  - - ~>
@@ -94,10 +129,15 @@ dependencies:
94
129
  version: 2.1.0
95
130
  type: :runtime
96
131
  prerelease: false
97
- version_requirements: *2153192940
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ~>
136
+ - !ruby/object:Gem::Version
137
+ version: 2.1.0
98
138
  - !ruby/object:Gem::Dependency
99
139
  name: rb-readline
100
- requirement: &2153192340 !ruby/object:Gem::Requirement
140
+ requirement: !ruby/object:Gem::Requirement
101
141
  none: false
102
142
  requirements:
103
143
  - - ~>
@@ -105,10 +145,15 @@ dependencies:
105
145
  version: 0.4.2
106
146
  type: :runtime
107
147
  prerelease: false
108
- version_requirements: *2153192340
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ~>
152
+ - !ruby/object:Gem::Version
153
+ version: 0.4.2
109
154
  - !ruby/object:Gem::Dependency
110
155
  name: rake
111
- requirement: &2153191840 !ruby/object:Gem::Requirement
156
+ requirement: !ruby/object:Gem::Requirement
112
157
  none: false
113
158
  requirements:
114
159
  - - ! '>='
@@ -116,10 +161,15 @@ dependencies:
116
161
  version: '0'
117
162
  type: :development
118
163
  prerelease: false
119
- version_requirements: *2153191840
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ none: false
166
+ requirements:
167
+ - - ! '>='
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
120
170
  - !ruby/object:Gem::Dependency
121
171
  name: rspec
122
- requirement: &2153191200 !ruby/object:Gem::Requirement
172
+ requirement: !ruby/object:Gem::Requirement
123
173
  none: false
124
174
  requirements:
125
175
  - - ~>
@@ -127,10 +177,15 @@ dependencies:
127
177
  version: 1.3.0
128
178
  type: :development
129
179
  prerelease: false
130
- version_requirements: *2153191200
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ none: false
182
+ requirements:
183
+ - - ~>
184
+ - !ruby/object:Gem::Version
185
+ version: 1.3.0
131
186
  - !ruby/object:Gem::Dependency
132
187
  name: webmock
133
- requirement: &2153190580 !ruby/object:Gem::Requirement
188
+ requirement: !ruby/object:Gem::Requirement
134
189
  none: false
135
190
  requirements:
136
191
  - - ~>
@@ -138,7 +193,12 @@ dependencies:
138
193
  version: 1.5.0
139
194
  type: :development
140
195
  prerelease: false
141
- version_requirements: *2153190580
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ none: false
198
+ requirements:
199
+ - - ~>
200
+ - !ruby/object:Gem::Version
201
+ version: 1.5.0
142
202
  description: AppFog.com CLI
143
203
  email: support@appfog.com
144
204
  executables:
@@ -190,7 +250,6 @@ files:
190
250
  - caldecott_helper/Gemfile.lock
191
251
  - caldecott_helper/server.rb
192
252
  - bin/af
193
- has_rdoc: true
194
253
  homepage: http://appfog.com
195
254
  licenses: []
196
255
  post_install_message:
@@ -211,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
211
270
  version: '0'
212
271
  requirements: []
213
272
  rubyforge_project:
214
- rubygems_version: 1.6.2
273
+ rubygems_version: 1.8.24
215
274
  signing_key:
216
275
  specification_version: 3
217
276
  summary: AppFog.com CLI