forj 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +7 -0
  3. data/.gitreview +4 -0
  4. data/Gemfile +21 -19
  5. data/Gemfile.lock +71 -0
  6. data/bin/forj +126 -83
  7. data/forj.gemspec +64 -0
  8. data/{lib → forj}/defaults.yaml +23 -1
  9. data/lib/appinit.rb +5 -5
  10. data/lib/build_tmpl/build-env.py +293 -0
  11. data/lib/cloud_test.rb +121 -0
  12. data/lib/forj-settings.rb +52 -39
  13. data/lib/forj/ForjCli.rb +11 -10
  14. data/lib/forj/ForjCore.rb +8 -6
  15. data/lib/forj/process/ForjProcess.rb +345 -82
  16. data/lib/ssh.rb +81 -20
  17. metadata +110 -80
  18. data/lib/compute.rb +0 -36
  19. data/lib/connection.rb +0 -144
  20. data/lib/down.rb +0 -60
  21. data/lib/forj-account.rb +0 -294
  22. data/lib/forj-config.rb +0 -522
  23. data/lib/helpers.rb +0 -56
  24. data/lib/lib-forj/lib/core/core.rb +0 -1740
  25. data/lib/lib-forj/lib/core/definition.rb +0 -441
  26. data/lib/lib-forj/lib/core/definition_internal.rb +0 -306
  27. data/lib/lib-forj/lib/core_process/CloudProcess.rb +0 -334
  28. data/lib/lib-forj/lib/core_process/global_process.rb +0 -406
  29. data/lib/lib-forj/lib/core_process/network_process.rb +0 -603
  30. data/lib/lib-forj/lib/lib-forj.rb +0 -37
  31. data/lib/lib-forj/lib/providers/hpcloud/Hpcloud.rb +0 -419
  32. data/lib/lib-forj/lib/providers/hpcloud/compute.rb +0 -108
  33. data/lib/lib-forj/lib/providers/hpcloud/network.rb +0 -117
  34. data/lib/lib-forj/lib/providers/hpcloud/security_groups.rb +0 -67
  35. data/lib/lib-forj/lib/providers/templates/compute.rb +0 -42
  36. data/lib/lib-forj/lib/providers/templates/core.rb +0 -61
  37. data/lib/lib-forj/lib/providers/templates/network.rb +0 -33
  38. data/lib/log.rb +0 -162
  39. data/lib/network.rb +0 -365
  40. data/lib/repositories.rb +0 -222
  41. data/lib/security.rb +0 -207
  42. data/lib/ssh.sh +0 -185
  43. data/spec/connection_spec.rb +0 -52
  44. data/spec/forj-config_spec.rb +0 -237
  45. data/spec/repositories_spec.rb +0 -50
data/forj.gemspec ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ Gem::Specification.new do |s|
19
+ s.name = 'forj'
20
+ s.homepage = 'https://www.forj.io'
21
+
22
+ s.version = '1.0.2'
23
+ s.date = '2014-12-18'
24
+ s.summary = 'forj command line'
25
+ s.description = 'forj cli - See https://www.forj.io for documentation/information'
26
+
27
+ s.authors = ['forj team']
28
+ s.email = %w(forj@forj.io)
29
+
30
+ s.files = `git ls-files -z`.split("\x0")
31
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
32
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
33
+ s.require_paths = ["lib"]
34
+
35
+ s.homepage = 'https://forj.io'
36
+ s.license = 'Apache License, Version 2.0.'
37
+ s.post_install_message = 'Go to docs.forj.io for more information on how to use forj cli'
38
+ s.required_ruby_version = '>= 1.8.5'
39
+
40
+ s.bindir = 'bin'
41
+
42
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
43
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
44
+ s.require_paths = %w[lib]
45
+
46
+ s.add_runtime_dependency 'thor', '>=0.16.0'
47
+ s.add_runtime_dependency 'fog', '1.19.0'
48
+ s.add_runtime_dependency 'git', '>=1.2.7'
49
+ s.add_runtime_dependency 'highline', '>= 1.6.21'
50
+ s.add_runtime_dependency 'ansi', '>= 1.4.3'
51
+ s.add_runtime_dependency 'encryptor', '>=1.3.0'
52
+ s.add_runtime_dependency 'json', '1.7.5'
53
+ s.add_runtime_dependency 'bundler'
54
+ s.add_runtime_dependency 'nokogiri','1.5.11'
55
+ s.add_runtime_dependency 'lorj', '~> 0.2.0'
56
+
57
+ s.add_development_dependency "bundler"
58
+ s.add_development_dependency "rake", "~> 10.0"
59
+ s.add_development_dependency "rspec", "~> 3.1.0"
60
+ s.rdoc_options << '--title' << 'Lorj - The Process Controllers framework system' <<
61
+ '--main' << 'README.md'
62
+
63
+
64
+ end
@@ -37,6 +37,9 @@
37
37
  # Network: If network doesn't exist, forj cli will try to create it, and attach it a router.
38
38
  :network: forj
39
39
 
40
+ # Users: Default user for ssh connection, if user doesn't exits, forj cli will try to get the user from the server image on it's name attribute
41
+ :users: ['ubuntu', 'fedora', 'cloud-user', 'cirros', 'centos', 'cloud', 'root']
42
+
40
43
  # build.sh internal variables.
41
44
  :build_config: box
42
45
  :branch: master
@@ -78,6 +81,7 @@
78
81
  - :desc: "Maestro and blueprint configuration:"
79
82
  :add:
80
83
  - :keypair_files
84
+ - :ssh_user
81
85
  - :desc: "DNS Configuration for Maestro:"
82
86
  :sections:
83
87
  # This section define updatable data available from config.yaml. But will never be added in an account file.
@@ -121,7 +125,7 @@
121
125
  The public key is used to configure your server to authorize you to access the box with your private key.
122
126
  This keypair files will be copied to '$HOME/.forj/keypairs/ under <keypair_name> files for 'forj' needs.
123
127
 
124
- If the keypair does exists locally, it will be created for you.
128
+ If the keypair doesn't exist locally, it will be created for you.
125
129
  :desc: "Base keypair file name"
126
130
  :default_value: "~/.ssh/id_rsa-forj"
127
131
  :validate_function: :forj_check_keypairs_files
@@ -252,6 +256,24 @@
252
256
  :value: :name
253
257
  :validate: :list_strict
254
258
  :ask_step: 2
259
+ :ssh_user:
260
+ :desc: "User name for ssh connection of your selected image."
261
+ :explanation: |-
262
+ The image name you have selected has a unique SSH Account access.
263
+
264
+ Thanks to the name of the image, setup assume the account name to use.
265
+ If this name is incoherent with the image you choosed, please update it.
266
+
267
+ Checking image '<%= config[:image_name] %>'...
268
+ :account: true
269
+ :ask_step: 2
270
+ :list_values:
271
+ :query_type: :process_call # Will execute a query on image and return the list of images.
272
+ :query_call: :setup_ssh_user
273
+ :query_params:
274
+ :image_name: lorj::config[:image_name]
275
+ :object: :image
276
+ :value: :name
255
277
  :ports:
256
278
  :desc: "List of security group rules (1 port or range of ports) to open to the external network."
257
279
  :branch:
data/lib/appinit.rb CHANGED
@@ -15,11 +15,11 @@
15
15
  # limitations under the License.
16
16
 
17
17
 
18
+ require 'lorj'
18
19
 
19
- # Base Logging system started and loaded.
20
- require 'log.rb' # Load default loggers
21
- include Logging
22
-
20
+ # Module to initialize the application
21
+ # TODO: Cleanup about Global variables used. Should be replaced by PrcLib
22
+ # or other kind of setting.
23
23
  module AppInit
24
24
 
25
25
  def AppInit.forj_initialize()
@@ -45,7 +45,7 @@ module AppInit
45
45
  end
46
46
 
47
47
  def AppInit.ensure_dir_exists(path)
48
- if not dir_exists?(path)
48
+ if not PrcLib.dir_exists?(path)
49
49
  FileUtils.mkpath(path) if not File.directory?(path)
50
50
  end
51
51
  end
@@ -0,0 +1,293 @@
1
+ #!/bin/env python
2
+ #
3
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # This script is used to create a env file used by build.sh.
18
+ # It is based on Maestro/templates/infra/maestro.box.GITBRANCH.env.tmpl
19
+
20
+ # This script detects few tags, and ask to enter the appropriate vallue,
21
+ # then save the result to a directory given by the user.
22
+
23
+ # As this script is very early in the boot process, we are running on end user worstation.
24
+ # We will avoid adding non default module like:
25
+ # - ptemplates, django for template interpreter. We use our own simple code to make it work with basics rules.
26
+ # It provides variable detection, with comments and default variables.
27
+
28
+ import sys
29
+ import getopt
30
+ #import urllib2
31
+ #from urlparse import urlparse,ParseResult
32
+ import re
33
+ import logging
34
+ import logging.handlers
35
+ import yaml
36
+ import os
37
+ #import subprocess
38
+ #import distutils.spawn
39
+ #import string
40
+ #from datetime import date,datetime
41
+ #import time
42
+ #import tempfile
43
+ import readline
44
+
45
+ # Defining defaults
46
+
47
+ GITBRANCH='master'
48
+ MAESTRO_RPATH_TMPL="templates/infra/"
49
+ MAESTRO_TMPL_FILE="maestro.box.GITBRANCH.env.tmpl"
50
+ MAESTRO_TMPL_PROVIDER='hpcloud'
51
+
52
+ #
53
+ #
54
+
55
+ ##############################
56
+ def help(sMsg):
57
+ print 'build-env.py [-h|--help] --maestro-repo MaestroPath --env-path BuildEnvPath [--gitbranch BranchName] [-d|--debug] [-v|--verbose]'
58
+
59
+ # TODO Support for re-build it.
60
+
61
+ ##############################
62
+ # TODO: split this function in 3, for code readibility
63
+
64
+ def BuildEnv(EnvPath, MaestroFile, MaestroPath, GitBranch):
65
+ """Build env file if doesn't exist."""
66
+
67
+ global MAESTRO_TMPL_FILE
68
+ oLogging=logging.getLogger('build-env')
69
+
70
+ # -----------------------------------------------
71
+ # Check step ------------------------------------
72
+
73
+ if not os.path.exists(EnvPath):
74
+ oLogging.error("'%s' do not exist. This directory is required. (--env-path)", EnvPath)
75
+ sys.exit(1)
76
+
77
+ if not os.path.isdir(EnvPath):
78
+ oLogging.error("'%s' is not a valid directory (--env_path)", EnvPath)
79
+ sys.exit(1)
80
+
81
+ if not os.path.isdir(MaestroPath):
82
+ oLogging.error("'%s' is not a valid directory. Should refer to Maestro repository root dir.(--maestro-path)", MaestroPath)
83
+ sys.exit(1)
84
+
85
+
86
+ sInputFile=os.path.join(MaestroPath, MaestroFile)
87
+ if not os.path.exists(sInputFile):
88
+ oLogging.error("Unable to find template '%s' from '%s'. Are you sure about Maestro Repository root path given? Check and retry.", MaestroPath, MaestroFile)
89
+ sys.exit(1)
90
+
91
+ # Replace GITBRANCH Name by real git branch value.
92
+ sOutputFile=os.path.join(EnvPath,re.sub('GITBRANCH',GITBRANCH,MAESTRO_TMPL_FILE))
93
+ sOutputFile=re.sub('.tmpl$','',sOutputFile)
94
+
95
+ if os.path.exists(sOutputFile):
96
+ # TODO Support for re-build it.
97
+ oLogging.info("'%s' exists. If you want to rewrite it, remove the file before.", sOutputFile)
98
+ sys.exit(0)
99
+
100
+ # Load template variables and build list of variable to query
101
+ oLogging.debug("Opening template '%s'",sInputFile)
102
+ try:
103
+ fTmpl=open(sInputFile)
104
+ except IOError as e:
105
+ oLogging.error("Unable to open '%s'. Errno: %s (%s)", sInputFile, e.errno, e.strerror)
106
+ sys.exit(2)
107
+
108
+ # -----------------------------------------------
109
+ # Reading template ------------------------------
110
+
111
+ print("Reading template '{0}'".format(sInputFile))
112
+ oComments={}
113
+ oVars={}
114
+
115
+ # Search for Variable. If the variable name ends with '!', this value could not be null.
116
+ reVar=re.compile('[^$]{([A-Z_-]+)(!)?(:.*?)?}')
117
+ # 1: Variable Name
118
+ # 2: Required if = '!'
119
+ # 3: Default
120
+
121
+
122
+ # Search for comment
123
+ reComment=re.compile('^ *# +([A-Z_-]+): (.*)$')
124
+
125
+ for line in fTmpl:
126
+
127
+ # Detecting comment
128
+ oComment=reComment.search(line)
129
+ if oComment <> None:
130
+ oLogging.debug('Found "%s" = "%s"', oComment.group(1), oComment.group(2))
131
+ if oVars.has_key(oComment.group(1)):
132
+ oComments[oComment.group(1)]=oVars[oVar.group(1)]['comments']+'\n# '+oComment.group(2)
133
+ elif oComments.has_key(oComment.group(1)):
134
+ oComments[oComment.group(1)]=oComments[oComment.group(1)]+'\n# '+ oComment.group(2)
135
+ else:
136
+ oComments[oComment.group(1)]='# '+oComment.group(2)
137
+
138
+ oVar=reVar.search(line)
139
+ if oVar <> None:
140
+ oLogging.debug('Found var "%s" from "%s"',oVar.group(1),line)
141
+
142
+ sComment=''
143
+ if oComments.has_key(oVar.group(1)):
144
+ sComment=oComments[oVar.group(1)]
145
+ else:
146
+ oComments.remove(oVar.group(1))
147
+
148
+ sDefault=''
149
+ bRequired=False
150
+ if oVar.group(2) <> None :
151
+ bRequired=True
152
+ oLogging.debug("'%s' is required",oVar.group(1))
153
+ if oVar.group(3) <> None:
154
+ sDefault=oVar.group(3)[1:]
155
+ oLogging.debug("'%s' default value is '%s'",oVar.group(1),sDefault)
156
+
157
+
158
+ oVars[oVar.group(1)]={ 'comments': sComment,
159
+ 'required': bRequired,
160
+ 'default': sDefault }
161
+
162
+ oLogging.debug('template loaded.')
163
+
164
+ # -----------------------------------------------
165
+ # Ask section -----------------------------------
166
+
167
+ print "We need some information from you. Please ask the following question:\n"
168
+ # Time to ask information to the user.
169
+
170
+ for sElem in oVars:
171
+ print '{0}'.format(oVars[sElem]['comments'])
172
+ sPar="# "
173
+ if oVars[sElem]['default'] <> '':
174
+ sPar+='Default is "'+oVars[sElem]['default']+'".'
175
+ if oVars[sElem]['required'] :
176
+ if sPar <> "# " :
177
+ sPar+=' Required.'
178
+ else:
179
+ sPar='# Required.'
180
+
181
+ if sPar <> "":
182
+ print sPar
183
+ sValue=""
184
+
185
+ while sValue == "":
186
+ sValue=raw_input(sElem+'=')
187
+
188
+ if sValue == "":
189
+ sValue=oVars[sElem]['default']
190
+
191
+ if oVars[sElem]['required']:
192
+ if sValue == "":
193
+ print "Value required. Please enter a value."
194
+ else:
195
+ break
196
+
197
+ oVars[sElem]['value']=sValue
198
+ print '{0}="{1}"\n'.format(sElem,sValue)
199
+
200
+
201
+ fTmpl.seek(0) # Read the file again to replace data
202
+ try:
203
+ fOutputFile=open(sOutputFile,"w+")
204
+ except IOError as e:
205
+ oLogging.error("Unable to open '%s' for write. Errno: %s (%s)", sOutputFile, e.errno, e.strerror)
206
+ sys.exit(2)
207
+
208
+ print "--------------------------------\nThank you\nWriting '{0}'".format(sOutputFile)
209
+
210
+ # -----------------------------------------------
211
+ # Time to save the template. --------------------
212
+
213
+ reReplaced=re.compile('([^$])({([A-Z_-]+)(!)?(:.*?)?})')
214
+ for line in fTmpl:
215
+ oVar=reReplaced.search(line)
216
+
217
+ if oVar <> None:
218
+
219
+ if oVar.group(1) <> None:
220
+ sValue=oVar.group(1)+oVars[oVar.group(3)]['value']
221
+ else:
222
+ sValue=oVars[oVar.group(3)]['value']
223
+ sNewLine=reReplaced.sub(sValue,line)
224
+ else:
225
+ sNewLine=line
226
+
227
+ sys.stdout.flush()
228
+ fOutputFile.write(sNewLine)
229
+
230
+ fOutputFile.close()
231
+ fTmpl.close()
232
+ print 'Done'
233
+
234
+
235
+
236
+ ##############################
237
+ def main(argv):
238
+ """Main function"""
239
+
240
+ global GITBRANCH
241
+ global MAESTRO_TMPL_PROVIDER
242
+ global MAESTRO_RPATH_TMPL
243
+
244
+ oLogging=logging.getLogger('build-env')
245
+ oLogging.setLevel(20)
246
+
247
+ try:
248
+ opts,args = getopt.getopt(argv,"hp:vd:r:P:", ["help", "--for-provider=", "env-path=" , "maestro-path=" ,"debug" ,"verbose" ])
249
+ except getopt.GetoptError, e:
250
+ oLogging.error('Error: '+e.msg)
251
+ help()
252
+ sys.exit(2)
253
+
254
+ for opt, arg in opts:
255
+ if opt in ('-h', '--help'):
256
+ help()
257
+ sys.exit()
258
+ elif opt in ('-v','--verbose'):
259
+ if oLogging.level >20:
260
+ oLogging.setLevel(oLogging.level-10)
261
+ elif opt in ('--debug','-d'):
262
+ logging.getLogger().setLevel(logging.DEBUG)
263
+ logging.debug("Setting debug mode")
264
+ oLogging.setLevel(logging.DEBUG)
265
+ elif opt in ('-p', '--env-path'):
266
+ ENV_PATH=arg
267
+ elif opt in ('--gitbranch'):
268
+ GITBRANCH=arg
269
+ elif opt in ('-r','--maestro-path'):
270
+ MAESTRO_PATH=arg
271
+ elif opt in ('-P','--for-provider'):
272
+ TMPL_PROVIDER=arg
273
+
274
+ # Start Main tasks - Testing required variables.
275
+ if not 'ENV_PATH' in locals() or not 'MAESTRO_PATH' in locals():
276
+ oLogging.error("--env-path or --maestro-path values missing. Please check command flags.")
277
+ sys.exit(1)
278
+
279
+
280
+ global MAESTRO_TMPL_FILE # template file to use.
281
+
282
+ sMaestroFile=os.path.join(MAESTRO_RPATH_TMPL, MAESTRO_TMPL_PROVIDER+'-'+MAESTRO_TMPL_FILE)
283
+ BuildEnv(ENV_PATH, sMaestroFile, MAESTRO_PATH, GITBRANCH)
284
+
285
+ sys.exit(0)
286
+
287
+ #####################################
288
+ logging.basicConfig(format='%(asctime)s: %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
289
+
290
+ if __name__ == "__main__":
291
+ main(sys.argv[1:])
292
+
293
+
data/lib/cloud_test.rb ADDED
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #require 'byebug'
4
+
5
+ $APP_PATH = File.dirname(__FILE__)
6
+ $LIB_PATH = File.expand_path(File.join(File.dirname($APP_PATH),'lib'))
7
+
8
+ $LOAD_PATH << $LIB_PATH
9
+
10
+ $LOAD_PATH << File.join($LIB_PATH, 'lib-forj', 'lib')
11
+
12
+ require 'appinit.rb'
13
+
14
+ # Initialize forj paths
15
+ AppInit::forj_initialize()
16
+
17
+ # Initialize global Log object
18
+ $FORJ_LOGGER=ForjLog.new()
19
+
20
+ require 'lib-forj.rb'
21
+
22
+ Logging.set_level(Logger::DEBUG)
23
+
24
+ # Load global Config
25
+ oConfig = ForjConfig.new()
26
+
27
+ aProcesses = []
28
+
29
+ # Defines how to manage Maestro and forges
30
+ # create a maestro box. Identify a forge instance, delete it,...
31
+ aProcesses << File.join($LIB_PATH, 'forj', 'ForjCore.rb')
32
+
33
+ # Defines how cli will control FORJ features
34
+ # boot/down/ssh/...
35
+ aProcesses << File.join($LIB_PATH, 'forj', 'ForjCli.rb')
36
+
37
+ $LIB_FORJ_DEBUG = 3 # verbose
38
+
39
+ infra_dir = File.expand_path(oConfig.get(:infra_repo))
40
+
41
+ # Ask information if needed.
42
+ if not Dir.exist?(File.expand_path(infra_dir))
43
+ Logging.warning(<<-END
44
+ Your infra workspace directory is missing.
45
+
46
+ Forj uses an infra workspace directory to store any kind of data that are private to you.
47
+ We provides ways to send those data securily to your new Forge instance, as metadata.
48
+ In production case, we suggest you to keep it safe in your SCM preferred database.
49
+
50
+ If you already have an existing infra workspace, use 'forj set infra_repo=<PathToYourRepo>' to set it and restart.
51
+
52
+ Otherwise, we will build a new one with some predefined data, you can review and update later.
53
+ END
54
+ )
55
+ sAsk = "Do you want to create a new one from Maestro (yes/no)?" % [infra_dir]
56
+ bBuildInfra=agree(sAsk)
57
+ if not bBuildInfra
58
+ puts 'Process aborted on your demand.'
59
+ exit 0
60
+ end
61
+ end
62
+
63
+ oCloud = ForjCloud.new(oConfig, 'hpcloud', aProcesses)
64
+
65
+ #oConfig.set(:instance_name, "test")
66
+ #oCloud.Create(:metadata)
67
+ #oCloud.Create(:infra_repository)
68
+ #oCloud.Create(:userdata)
69
+
70
+
71
+ #oCloud.Setup(:server, 'hpcloud')
72
+ #oCloud.Setup(:forge, 'hpcloud')
73
+
74
+ #oCloud.Create(:forge)
75
+
76
+ #oConfig.set(:instance_name, 'servertestluis')
77
+ #oCloud.Create(:forge)
78
+
79
+ oForge = oCloud.Get(:forge, "luistest")
80
+
81
+ #Ask the user to get server(s) to destroy
82
+ server_id_length = 0
83
+ server_name_length = 0
84
+
85
+ oForge[:server].each{ |server|
86
+ if server[:id].length() > server_id_length
87
+ server_id_length = server[:id].length()
88
+ end
89
+
90
+ if server[:name].length() > server_name_length
91
+ server_name_length = server[:name].length()
92
+ end
93
+ }
94
+
95
+ server_index = 1
96
+ #Display headers
97
+ puts "|%s |%s |%s |" % ["Index ".ljust(6), "Name".ljust(server_name_length), "ID".ljust(server_id_length) ]
98
+ #puts "|%s |%s |%s |" % ["0", "all".ljust(server_name_length), " ".ljust(server_id_length) ]
99
+ #Display Forge servers detail
100
+ oForge[:server].each{ |server|
101
+ puts "|%s |%s |%s |" % [server_index.to_s().ljust(6), server[:name].to_s().ljust(server_name_length), server[:id].to_s().ljust(server_id_length) ]
102
+ server_index = server_index + 1
103
+ }
104
+
105
+ oHighLine = HighLine.new()
106
+
107
+ index = oHighLine.ask("Select the index of the server to create the ssh connection", Integer)do |q|
108
+ q.below=oForge[:server].count + 1
109
+ q.above=0
110
+ end
111
+
112
+
113
+ oConfig.set(:instance_name, 'luistest')
114
+ oConfig.set(:forge_server, oForge[:server][index - 1][:id])
115
+ oConfig.set(:server_name, oForge[:server][index - 1][:name])
116
+ #oConfig.set(:box, 'maestro')
117
+ #oConfig.set(:instance_name, 'luistest')
118
+ #oConfig.Create(:server)
119
+ oCloud.Create(:ssh)
120
+
121
+ #oCloud.Query(:server, 'maestro')