cloudflock 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +15 -0
  2. data/bin/cloudflock +7 -1
  3. data/bin/cloudflock-files +2 -14
  4. data/bin/cloudflock-profile +3 -15
  5. data/bin/cloudflock-servers +3 -22
  6. data/bin/cloudflock.default +3 -22
  7. data/lib/cloudflock/app/common/cleanup/unix.rb +23 -0
  8. data/lib/cloudflock/app/common/cleanup.rb +107 -0
  9. data/lib/cloudflock/app/common/exclusions/unix/centos.rb +18 -0
  10. data/lib/cloudflock/app/common/exclusions/unix/redhat.rb +18 -0
  11. data/lib/cloudflock/app/common/exclusions/unix.rb +58 -0
  12. data/lib/cloudflock/app/common/exclusions.rb +57 -0
  13. data/lib/cloudflock/app/common/platform_action.rb +59 -0
  14. data/lib/cloudflock/app/common/rackspace.rb +63 -0
  15. data/lib/cloudflock/app/common/servers.rb +673 -0
  16. data/lib/cloudflock/app/files-migrate.rb +246 -0
  17. data/lib/cloudflock/app/server-migrate.rb +327 -0
  18. data/lib/cloudflock/app/server-profile.rb +130 -0
  19. data/lib/cloudflock/app.rb +87 -0
  20. data/lib/cloudflock/error.rb +6 -19
  21. data/lib/cloudflock/errstr.rb +31 -0
  22. data/lib/cloudflock/remote/files.rb +82 -22
  23. data/lib/cloudflock/remote/ssh.rb +234 -278
  24. data/lib/cloudflock/target/servers/platform.rb +92 -115
  25. data/lib/cloudflock/target/servers/profile.rb +331 -340
  26. data/lib/cloudflock/task/server-profile.rb +651 -0
  27. data/lib/cloudflock.rb +6 -8
  28. metadata +49 -68
  29. data/lib/cloudflock/interface/cli/app/common/servers.rb +0 -128
  30. data/lib/cloudflock/interface/cli/app/files.rb +0 -179
  31. data/lib/cloudflock/interface/cli/app/servers/migrate.rb +0 -491
  32. data/lib/cloudflock/interface/cli/app/servers/profile.rb +0 -88
  33. data/lib/cloudflock/interface/cli/app/servers.rb +0 -2
  34. data/lib/cloudflock/interface/cli/console.rb +0 -213
  35. data/lib/cloudflock/interface/cli/opts/servers.rb +0 -20
  36. data/lib/cloudflock/interface/cli/opts.rb +0 -87
  37. data/lib/cloudflock/interface/cli.rb +0 -15
  38. data/lib/cloudflock/target/servers/data/exceptions/base.txt +0 -44
  39. data/lib/cloudflock/target/servers/data/exceptions/platform/amazon.txt +0 -10
  40. data/lib/cloudflock/target/servers/data/exceptions/platform/centos.txt +0 -7
  41. data/lib/cloudflock/target/servers/data/exceptions/platform/debian.txt +0 -0
  42. data/lib/cloudflock/target/servers/data/exceptions/platform/redhat.txt +0 -7
  43. data/lib/cloudflock/target/servers/data/exceptions/platform/suse.txt +0 -1
  44. data/lib/cloudflock/target/servers/data/post-migration/chroot/base.txt +0 -1
  45. data/lib/cloudflock/target/servers/data/post-migration/chroot/platform/amazon.txt +0 -19
  46. data/lib/cloudflock/target/servers/data/post-migration/pre/base.txt +0 -3
  47. data/lib/cloudflock/target/servers/data/post-migration/pre/platform/amazon.txt +0 -4
  48. data/lib/cloudflock/target/servers/migrate.rb +0 -466
  49. data/lib/cloudflock/target/servers/platform/v1.rb +0 -97
  50. data/lib/cloudflock/target/servers/platform/v2.rb +0 -93
  51. data/lib/cloudflock/target/servers.rb +0 -5
  52. data/lib/cloudflock/version.rb +0 -3
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NjNmYTg2NmMyOTExM2M1YjlkM2ExMjkzMDE0Yzc1ZjlhYzNmNGIyOQ==
5
+ data.tar.gz: !binary |-
6
+ N2Q2M2Y4ZjMyNmE2MDYzNTA3MjRmYTYyNTQ0OWRlNDIyYWY5ODdhOQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MTZlYTlmOWMwMTMwM2IxMTRjOWFjY2Y1OGNlMWQ4YjE2OGZkMDUyNjMxNDI1
10
+ NDU1OTczYTBhNzI3OTYzNjhlY2QwNDI5NTQ0NTE4MzExM2NiMjkwNWZmZWUy
11
+ Y2U1ZjJkZjgyZmJkMTViMzMzMTBlZjljMGUxNzRjN2IxMjM2YTg=
12
+ data.tar.gz: !binary |-
13
+ MWY2ZGYyMDUwYTFkYzZmZDhkMDZiMmQ5NDU1ZDA3Y2U0MzhiYWFjNDQ0NTc4
14
+ NDYyZjM4ZjNhMWVlZTU1OTUxNTk2MzhlODgyMDRhY2UxYjRlYjhjZjgwNzMw
15
+ NTlhYmFlMjQ5YzQ0NzY3ZjA3MmJmNzJkNWFjMDc1M2VjZTEyZTE=
data/bin/cloudflock CHANGED
@@ -1,8 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # Trap C-c to kill the application without a stack trace
4
+ trap 'INT' do
5
+ puts "\nCaught SIGINT, exiting..."
6
+ exit 1
7
+ end
8
+
3
9
  current_path = File.expand_path('../', __FILE__)
4
10
  function = ARGV.shift.to_s
5
- bin = File.basename($0, '.dev')
11
+ bin = File.basename($0)
6
12
 
7
13
  if function.match(/^[^-]/)
8
14
  target = "#{current_path}/#{bin}-#{function}"
data/bin/cloudflock-files CHANGED
@@ -1,18 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'cloudflock/app/files-migrate'
3
4
  $0 = 'cloudflock-files'
4
5
 
5
- require 'cloudflock/interface/cli/app/files'
6
- CLI = CloudFlock::Interface::CLI::Console
7
- Opts = CloudFlock::Interface::CLI::Opts
8
-
9
- # Trap C-c to kill the application in a friendly manner
10
- trap 'INT' do
11
- puts "\nCaught SIGINT, exiting..."
12
- exit 1
13
- end
14
-
15
- options = Opts.parse
16
- options[:config] = Opts.parse_config_file(options[:config_file])
17
-
18
- CloudFlock::Interface::CLI::App::Files.new(options)
6
+ CloudFlock::App::FilesMigrate.new
@@ -1,19 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $0 = 'cloudflock-profile'
4
-
5
- require 'cloudflock/interface/cli/app/servers/profile'
6
- CLI = CloudFlock::Interface::CLI::Console
7
- Opts = CloudFlock::Interface::CLI::Opts
3
+ require 'cloudflock/app/server-profile'
8
4
 
9
- # Trap C-c to kill the application in a friendly manner
10
- trap 'INT' do
11
- puts "\nCaught SIGINT, exiting..."
12
- exit 1
13
- end
14
-
15
- options = Opts.parse
16
- options[:function] = :profile
17
- options[:config] = Opts.parse_config_file(options[:config_file])
5
+ $0 = 'cloudflock-profile'
18
6
 
19
- CloudFlock::Interface::CLI::App::Servers::Profile.new(options)
7
+ CloudFlock::App::ServerProfile.new
@@ -1,26 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $0 = 'cloudflock-servers'
4
-
5
- require 'cloudflock/interface/cli/app/servers/migrate'
6
- CLI = CloudFlock::Interface::CLI::Console
7
- Opts = CloudFlock::Interface::CLI::Opts
8
-
9
- # Trap C-c to kill the application in a friendly manner
10
- trap 'INT' do
11
- puts "\nCaught SIGINT, exiting..."
12
- exit 1
13
- end
3
+ require 'cloudflock/app/server-migrate'
14
4
 
15
- options = Opts.parse(:servers)
16
- type_prompt = "Type of migration (servers, opencloud)?"
17
-
18
- if options[:function].nil?
19
- options[:function] = CLI.prompt(type_prompt, valid_answers:
20
- ["servers", "opencloud"],
21
- default_answer: "opencloud")
22
- end
23
- options[:function] = options[:function].to_sym
24
- options[:config] = Opts.parse_config_file(options[:config_file])
5
+ $0 = 'cloudflock-servers'
25
6
 
26
- CloudFlock::Interface::CLI::App::Servers::Migrate.new(options)
7
+ CloudFlock::App::ServerMigrate.new
@@ -1,26 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- $0 = 'cloudflock-servers'
4
-
5
- require 'cloudflock/interface/cli/app/servers/migrate'
6
- CLI = CloudFlock::Interface::CLI::Console
7
- Opts = CloudFlock::Interface::CLI::Opts
8
-
9
- # Trap C-c to kill the application in a friendly manner
10
- trap 'INT' do
11
- puts "\nCaught SIGINT, exiting..."
12
- exit 1
13
- end
3
+ require 'cloudflock/app/server-migrate'
14
4
 
15
- options = Opts.parse(:servers)
16
- type_prompt = "Type of migration (servers, opencloud)?"
17
-
18
- if options[:function].nil?
19
- options[:function] = CLI.prompt(type_prompt, valid_answers:
20
- ["servers", "opencloud"],
21
- default_answer: "opencloud")
22
- end
23
- options[:function] = options[:function].to_sym
24
- options[:config] = Opts.parse_config_file(options[:config_file])
5
+ $0 = 'cloudflock-servers'
25
6
 
26
- CloudFlock::Interface::CLI::App::Servers::Migrate.new(options)
7
+ CloudFlock::App::ServerMigrate.new
@@ -0,0 +1,23 @@
1
+ require 'cloudflock/app/common/servers'
2
+
3
+ module CloudFlock; module App; module Common; class Cleanup
4
+ # Public: The Unix module provides cleanup steps which are appropriate for
5
+ # all Unix-like hosts.
6
+ module Unix extend self
7
+ # Public: Define pre-, during-, and post-chroot steps which will be
8
+ # applicable to all Unix-like hosts.
9
+ #
10
+ # Returns nothing.
11
+ def unix_cleanup
12
+ pre_step 'mount proc -t proc /mnt/migration_target/proc'
13
+ pre_step 'mount /dev /mnt/migration_target/dev -o rbind'
14
+ pre_step 'mount /sys /mnt/migration_target/sys -o rbind'
15
+
16
+ chroot_step 'find /var/run -type f -exec rm {} \;'
17
+
18
+ post_step 'umount /mnt/migration_target/sys'
19
+ post_step 'umount /mnt/migration_target/dev'
20
+ post_step 'umount /mnt/migration_target/proc'
21
+ end
22
+ end
23
+ end; end; end; end
@@ -0,0 +1,107 @@
1
+ require 'cloudflock/app/common/platform_action'
2
+
3
+ module CloudFlock; module App; module Common
4
+ # Public: The Cleanup Class allows for building tasks leading up to, during
5
+ # and following chrooting into a staged post-migration environment to perform
6
+ # cleanup tasks.
7
+ class Cleanup < PlatformAction
8
+ # Public: Initialize the internal state, then find suitable tasks for the
9
+ # detected platform.
10
+ #
11
+ # cpe - CPE object.
12
+ def initialize(cpe)
13
+ super
14
+
15
+ define_steps
16
+ end
17
+
18
+ # Public: Define a step to be performed prior to chrooting.
19
+ #
20
+ # step - String containing a command to be performed.
21
+ #
22
+ # Returns nothing.
23
+ def pre_step(step)
24
+ pre << step
25
+ end
26
+
27
+ # Public: Define a step to be performed in a chroot environment.
28
+ #
29
+ # step - String containing a command to be performed.
30
+ #
31
+ # Returns nothing.
32
+ def chroot_step(step)
33
+ chroot << step
34
+ end
35
+
36
+ # Public: Define a step to be performed after leaving the chroot
37
+ # environment.
38
+ #
39
+ # step - String containing a command to be performed.
40
+ #
41
+ # Returns nothing.
42
+ def post_step(step)
43
+ post << step
44
+ end
45
+
46
+ # Public: Return all pre-chroot steps separated by newlines.
47
+ #
48
+ # Returns a String.
49
+ def pre_s
50
+ pre.join("\n")
51
+ end
52
+
53
+ # Public: Return all chroot steps separated by newlines.
54
+ #
55
+ # Returns a String.
56
+ def chroot_s
57
+ chroot.join("\n")
58
+ end
59
+
60
+ # Public: Return all post-chroot steps separated by newlines.
61
+ #
62
+ # Returns a String.
63
+ def post_s
64
+ post.join("\n")
65
+ end
66
+
67
+ private
68
+
69
+ # Internal: Gets the internal Array of pre-chroot steps. Initializes to an
70
+ # empy Array if it doesn't exist.
71
+ #
72
+ # Returns an Array.
73
+ def pre
74
+ @collection[:pre] ||= []
75
+ end
76
+
77
+ # Internal: Gets the internal Array of chroot environment steps.
78
+ # Initializes to an empy Array if it doesn't exist.
79
+ #
80
+ # Returns an Array.
81
+ def chroot
82
+ @collection[:chroot] ||= []
83
+ end
84
+
85
+ # Internal: Gets the internal Array of post-chroot steps. Initializes to
86
+ # an empy Array if it doesn't exist.
87
+ #
88
+ # Returns an Array.
89
+ def post
90
+ @collection[:post] ||= []
91
+ end
92
+
93
+ # Internal: Iterate through available modules for the current platform,
94
+ # calling all methods available which end in '_cleanup'.
95
+ #
96
+ # Returns nothing.
97
+ def define_steps
98
+ load_each do |mod|
99
+ extend mod
100
+
101
+ mod.public_methods.select { |m| /_cleanup$/.match m }.each do |m|
102
+ self.send(m)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end; end; end
@@ -0,0 +1,18 @@
1
+ module CloudFlock; module App; module Common; class Exclusions; module Unix
2
+ # Public: The Centos module provides exclusions which are expected to be
3
+ # appropriate for CentOS hosts.
4
+ module Centos extend self
5
+ # Public: Exclude paths which are expected to be appropriate for CentOS
6
+ # hosts.
7
+ #
8
+ # Returns nothing.
9
+ def centos_exclusions
10
+ exclude '/etc/yum.repos.d/'
11
+ exclude '/usr/lib/yum-plugins'
12
+ exclude '/etc/yum.conf'
13
+ exclude '/etc/yum'
14
+ exclude '/etc/yum.repos.d'
15
+ exclude '/etc/sysconfig/iptables'
16
+ end
17
+ end
18
+ end; end; end; end; end
@@ -0,0 +1,18 @@
1
+ module CloudFlock; module App; module Common; class Exclusions; module Unix
2
+ # Public: The Redhat module provides exclusions which are expected to be
3
+ # appropriate for Redhat hosts.
4
+ module Redhat extend self
5
+ # Public: Exclude paths which are expected to be appropriate for RedHat
6
+ # hosts.
7
+ #
8
+ # Returns nothing.
9
+ def redhat_exclusions
10
+ exclude '/etc/yum.repos.d/'
11
+ exclude '/usr/lib/yum-plugins'
12
+ exclude '/etc/yum.conf'
13
+ exclude '/etc/yum'
14
+ exclude '/etc/yum.repos.d'
15
+ exclude '/etc/sysconfig/iptables'
16
+ end
17
+ end
18
+ end; end; end; end; end
@@ -0,0 +1,58 @@
1
+ require 'cloudflock/app/common/servers'
2
+
3
+ module CloudFlock; module App; module Common; class Exclusions
4
+ # Public: The Unix module provides exclusions which are expected to be
5
+ # appropriate for all Unix-like hosts.
6
+ module Unix extend self
7
+ # Public: Exclude paths which are expected to be appropriate for all
8
+ # Unix-like hosts.
9
+ #
10
+ # Returns nothing.
11
+ def unix_exclusions
12
+ exclude '/boot'
13
+ exclude '/dev'
14
+ exclude '/etc/fstab'
15
+ exclude '/etc/hosts'
16
+ exclude '/etc/init.d/nova-agent*'
17
+ exclude '/etc/driveclient'
18
+ exclude '/etc/initramfs-tools'
19
+ exclude '/etc/issue'
20
+ exclude '/etc/issue.net'
21
+ exclude '/etc/lvm'
22
+ exclude '/etc/mdadm*'
23
+ exclude '/etc/mtab'
24
+ exclude '/etc/mod*'
25
+ exclude '/etc/network/'
26
+ exclude '/etc/network.d/*'
27
+ exclude '/etc/networks'
28
+ exclude '/etc/rc3.d/S99Galaxy'
29
+ exclude '/etc/resolv.conf'
30
+ exclude '/etc/sysconfig/network'
31
+ exclude '/etc/sysconfig/network-scripts/*'
32
+ exclude '/etc/system-release'
33
+ exclude '/etc/system-release-cpe'
34
+ exclude '/etc/udev'
35
+ exclude '/etc/prelink*'
36
+ exclude '/etc/rc.conf'
37
+ exclude '/etc/conf.d/net'
38
+ exclude '/lib/init/rw'
39
+ exclude '/lib/firmware'
40
+ exclude '/lib/modules'
41
+ exclude '/lib/udev'
42
+ exclude '/root/.rackspace'
43
+ exclude '/mnt'
44
+ exclude '/net'
45
+ exclude '/opt/galaxy/'
46
+ exclude '/proc'
47
+ exclude '/sys'
48
+ exclude '/tmp'
49
+ exclude '/usr/sbin/nova-agent*'
50
+ exclude '/usr/share/initramfs-tools'
51
+ exclude '/usr/share/nova-agent*'
52
+ exclude '/var/cache/yum/*'
53
+ exclude '/var/lib/initramfs-tools'
54
+ exclude '/var/lock'
55
+ exclude '/var/log'
56
+ end
57
+ end
58
+ end; end; end; end
@@ -0,0 +1,57 @@
1
+ require 'cloudflock/app/common/platform_action'
2
+
3
+ module CloudFlock; module App; module Common
4
+ # Public: The Exclusions Class allows for building exclusions lists suitable
5
+ # for migrating live hosts based upon the detected platform.
6
+ class Exclusions < PlatformAction
7
+ # Public: Initialize the internal state, then find suitable exclusions for
8
+ # the detected platform.
9
+ #
10
+ # cpe - CPE object.
11
+ def initialize(cpe)
12
+ super
13
+
14
+ find_exclusions
15
+ end
16
+
17
+ # Public: Add a location to the list of paths to exclude from a migration.
18
+ #
19
+ # location - String containing a path.
20
+ #
21
+ # Returns nothing.
22
+ def exclude(location)
23
+ exclusions << location
24
+ end
25
+
26
+ # Public: Return all exclusions separated by newlines.
27
+ #
28
+ # Returns a String.
29
+ def to_s
30
+ exclusions.join("\n")
31
+ end
32
+
33
+ private
34
+
35
+ # Internal: Gets the internal Array of exclusions. Initializes to an empy
36
+ # Array if it doesn't exist.
37
+ #
38
+ # Returns an Array.
39
+ def exclusions
40
+ @collection[:exclude] ||= []
41
+ end
42
+
43
+ # Internal: Iterate through available modules for the current platform,
44
+ # calling all methods available which end in '_exclusions'.
45
+ #
46
+ # Returns nothing.
47
+ def find_exclusions
48
+ load_each do |mod|
49
+ extend mod
50
+
51
+ mod.public_methods.select { |m| /_exclusions$/.match m }.each do |m|
52
+ self.send(m)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end; end; end
@@ -0,0 +1,59 @@
1
+ module CloudFlock; module App; module Common
2
+ # Public: The PlatformAction Class provides the template for actions to be
3
+ # taken dependant upon the platform targeted.
4
+ class PlatformAction
5
+ # Public: Gets the Array containing the platform details.
6
+ attr_reader :platform
7
+
8
+ # Public: Gets the path prefix for including any applicable files.
9
+ attr_reader :prefix
10
+
11
+ # Public: Set internal parameters and initialize an empty Hash to be used
12
+ # as a collection.
13
+ #
14
+ # cpe - CPE object containing information off of which the platform
15
+ # parameters will be based.
16
+ def initialize(cpe)
17
+ classname = self.class.name.downcase.split(/::/).last
18
+ @prefix = "cloudflock/app/common/#{classname}/"
19
+ @platform = ['unix', cpe.vendor, cpe.product + cpe.version]
20
+ @collection = {}
21
+ end
22
+
23
+ # Public: Map a block to the platform Array.
24
+ #
25
+ # Yields each item in platform (per map).
26
+ def map_platforms(&block)
27
+ platform.map(&block)
28
+ end
29
+
30
+ # Public: Applies a block to each item in the platform Array.
31
+ #
32
+ # Yields each item in platform (per each).
33
+ def each_platform(&block)
34
+ platform.each(&block)
35
+ end
36
+
37
+ # Public: Loads each available file corresponding to a given platform in
38
+ # order of ascending specificity, then passes the Module to the block
39
+ # passed.
40
+ #
41
+ # Yields each Module.
42
+ def load_each(&block)
43
+ platforms = map_platforms { |name| name.gsub(/[^a-zA-Z0-9]/, '_') }
44
+
45
+ paths = (0...platforms.length).map { |i| platforms[(0...i)].join('/') }
46
+ mods = (0...platforms.length).map do |i|
47
+ platforms[(0...i)].map(&:capitalize)
48
+ end
49
+
50
+ (0...paths.length).each do |index|
51
+ begin
52
+ require prefix + paths[index]
53
+ block.call(mods[index].reduce(self.class) { |c,e| c.const_get(e) })
54
+ rescue LoadError
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end; end; end
@@ -0,0 +1,63 @@
1
+ require 'fog'
2
+ require 'console-glitter'
3
+ require 'cloudflock/app'
4
+
5
+ module CloudFlock; module App
6
+ # Public: The Rackspace module provides common methods for CLI interaction
7
+ # pertaining to interaction with the Rackspace API.
8
+ module Rackspace
9
+ include ConsoleGlitter
10
+ # Public: Gather information necessary to manage Rackspace cloud assets via
11
+ # API.
12
+ #
13
+ # Returns a Hash containing information necessary to establish an API
14
+ # session.
15
+ def define_rackspace_api
16
+ api = { provider: 'rackspace' }
17
+
18
+ api[:rackspace_username] = UI.prompt('Rackspace Cloud Username')
19
+ api[:rackspace_api_key] = UI.prompt('Rackspace Cloud API key')
20
+
21
+ region = UI.prompt('Account Region (us, uk)',
22
+ valid_answers: [/^u[sk]$/i])
23
+ region.gsub!(/$/, '_AUTH_ENDPOINT')
24
+ api[:rackspace_region] = Fog::Rackspace.const_get(region.upcase)
25
+
26
+ api
27
+ end
28
+
29
+ # Public: Wrap define_rackspace_service_region, specifying
30
+ # 'cloudServersOpenStack' as the service type.
31
+ #
32
+ # api - Authenticated Fog API instance.
33
+ def define_rackspace_cloudservers_region(api)
34
+ api.merge(define_rackspace_service_region(api, 'cloudServersOpenStack'))
35
+ end
36
+
37
+ # Public: Wrap define_rackspace_service_region, specifying 'cloudFiles' as
38
+ # the service type.
39
+ #
40
+ # api - Authenticated Fog API instance.
41
+ def define_rackspace_files_region(api)
42
+ api.merge(define_rackspace_service_region(api, 'cloudFiles'))
43
+ end
44
+
45
+ # Public: Have the user select from a list of regions available to their
46
+ # Rackspace account.
47
+ #
48
+ # api - Authenticated Fog API instance.
49
+ # service - String describing the service to be used (e.g. 'cloudFiles',
50
+ # 'cloudServersOpenStack').
51
+ #
52
+ # Returns a Hash containing a :rackspace_region => String mapping.
53
+ def define_rackspace_service_region(api, service)
54
+ identity = Fog::Identity.new(api)
55
+ regions = identity.service_catalog.display_service_regions(service)
56
+ regions = regions.split(', ').map { |e| e.gsub(/^:/, '') }
57
+
58
+ region = UI.prompt("Target Region (#{regions.join(', ')})",
59
+ valid_answers: regions)
60
+ { rackspace_region: region }
61
+ end
62
+ end
63
+ end; end