af 0.3.18.4 → 0.3.18.5

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