forj 0.0.36 → 0.0.37

Sign up to get free protection for your applications and to get access to all the features.
data/lib/setup.rb CHANGED
@@ -24,59 +24,187 @@ include YamlParse
24
24
  require_relative 'helpers.rb'
25
25
  include Helpers
26
26
 
27
+ require 'encryptor' # gem install encryptor
28
+ require 'base64'
29
+
30
+ # TODO: To move to a specific module driven by providers.
31
+ require 'hpcloud/version'
32
+ require 'hpcloud/config'
33
+ require 'hpcloud/accounts'
34
+ require 'hpcloud/connection'
35
+ include HP::Cloud
36
+
27
37
  #
28
38
  # Setup module call the hpcloud functions
29
39
  #
30
40
  module Setup
31
- def setup(sProvider, oConfig, options )
32
- begin
41
+ def setup(oConfig, options )
33
42
 
34
- Logging.fatal(1, 'No provider specified.') if not sProvider
43
+ # TODO: Provide a way to re-edit all or partially elements set up by this function.
44
+ begin
45
+ Logging.fatal(1, 'No provider specified.') if not oConfig.exist?('provider')
35
46
 
36
- sAccountName = sProvider # By default, the account name uses the same provider name.
37
- sAccountName = options[:account_name] if options[:account_name]
47
+ sProvider = oConfig.get('provider')
48
+ sAccountName = sProvider # By default, the account name uses the same provider name.
49
+ sAccountName = options[:account_name] if options[:account_name]
38
50
 
39
- if sProvider != 'hpcloud'
40
- Logging.fatal(1, "forj setup support only hpcloud. '%s' is currently not supported." % sProvider)
41
- end
51
+ if sProvider != 'hpcloud'
52
+ Logging.fatal(1, "forj setup support only hpcloud. '%s' is currently not supported." % sProvider)
53
+ end
42
54
 
43
- # TODO: Support of multiple providers thanks to fog.
44
- # TODO: Replace this code by our own forj account setup, inspired/derived from hpcloud account::setup
55
+ # setting up provider account - Required, while calling external provider tool, like hpcloud.
56
+ setup_provider_account(oConfig, sAccountName)
45
57
 
46
- # delegate the initial configuration to hpcloud (unix_cli)
47
- hpcloud_data=File.expand_path('~/.hpcloud/accounts')
48
- if File.exists?(File.join(hpcloud_data, 'hp')) and not File.exists?(File.join(hpcloud_data, sAccountName)) and sAccountName != 'hp'
49
- Logging.info("hpcloud: Copying 'hp' account setup to '%s'" % sAccountName)
50
- Kernel.system('hpcloud account:copy hp %s' % [sAccountName])
51
- end
58
+ # Implementation of simple credential encoding for build.sh/maestro
59
+ save_maestro_creds(oConfig, sAccountName)
60
+
61
+ # DNS Setting for Gardener
62
+ setup_dns(oConfig, sAccountName)
63
+
64
+ # Check/create keypair
65
+ keypair_setup(oConfig)
66
+
67
+ # Checking cloud connection
68
+ Logging.message("Checking cloud connection")
69
+ oFC=ForjConnection.new(oConfig)
52
70
 
53
- Logging.info("Configuring hpcloud account '%s'" % [sAccountName] )
54
- command = 'hpcloud account:setup %s' % [sAccountName]
55
- Logging.debug("Executing : '%s'" % command)
56
- case Kernel.system(command)
57
- when false
58
- Logging.fatal(1, "Unable to setup your hpcloud account")
59
- when nil
60
- Logging.fatal(1, "Unable to execute 'hpcloud' cli. Please check hpcloud installation.")
71
+ Logging.message("Setup '%s' done. Thank you." % sAccountName)
72
+
73
+ rescue RuntimeError => e
74
+ Logging.fatal(1,e.message)
75
+ rescue => e
76
+ Logging.fatal(1,"%s\n%s" % [e.message,e.backtrace.join("\n")])
61
77
  end
78
+ end
79
+ end
62
80
 
63
- if not oConfig.yConfig['default'].has_key?('account')
64
- oConfig.LocalSet('account',sAccountName)
65
- oConfig.SaveConfig
81
+ def setup_tenant_name(oConfig, sAccountName)
82
+ # Maestro uses fog/openstack to connect to the cloud. It needs Tenant name instead of tenant ID.
83
+ # Getting it from Compute connection and set it
84
+
85
+ oSSLError=SSLErrorMgt.new # Retry object
86
+ Logging.debug("Getting tenants from hpcloud cli libraries")
87
+ begin
88
+ tenants = Connection.instance.tenants(sAccountName)
89
+ rescue => e
90
+ if not oSSLError.ErrorDetected(e.message,e.backtrace)
91
+ retry
66
92
  end
93
+ Logging.fatal(1, 'Network: Unable to connect.')
94
+ end
95
+ tenant_id = rhGet(oConfig.ExtraGet(:hpc_accounts, sAccountName, :credentials), :tenant_id)
96
+ tenant_name = nil
97
+ tenants.each { |elem| tenant_name = elem['name'] if elem['id'] == tenant_id }
98
+ if tenant_name
99
+ Logging.debug("Tenant ID '%s': '%s' found." % [tenant_id, tenant_name])
100
+ hCompute = { :tenant_name => tenant_name }
101
+ oConfig.ExtraSet(:forj_accounts, sAccountName, :compute, hCompute)
102
+ else
103
+ Logging.error("Unable to found the tenant Name for '%s' ID." % tenant_id)
104
+ end
105
+ oConfig.set('tenants', tenants)
106
+ end
107
+
108
+ def setup_provider_account(oConfig, sAccountName)
109
+ # TODO: Support of multiple providers thanks to fog.
110
+ # TODO: Replace this code by our own forj account setup, inspired/derived from hpcloud account::setup
111
+
112
+ # delegate the initial configuration to hpcloud (unix_cli)
113
+ if File.exists?(File.join($HPC_ACCOUNTS, 'hp')) and not File.exists?(File.join($HPC_ACCOUNTS, sAccountName)) and sAccountName != 'hp'
114
+ Logging.info("hpcloud: Copying 'hp' account setup to '%s'" % sAccountName)
115
+ Kernel.system('hpcloud account:copy hp %s' % [sAccountName])
116
+ end
117
+
118
+ Logging.info("Configuring hpcloud account '%s'" % [sAccountName] )
119
+ command = 'hpcloud account:setup %s' % [sAccountName]
120
+ Logging.debug("Executing : '%s'" % command)
121
+ case Kernel.system(command)
122
+ when false
123
+ Logging.fatal(1, "Unable to setup your hpcloud account")
124
+ when nil
125
+ Logging.fatal(1, "Unable to execute 'hpcloud' cli. Please check hpcloud installation.")
126
+ end
127
+
128
+ if not oConfig.yConfig['default'].has_key?('account')
129
+ oConfig.LocalSet('account',sAccountName)
130
+ oConfig.SaveConfig
131
+ end
132
+
133
+ # Loading HPCloud account setting in Config.
134
+ hpc_account_file = File.join($HPC_ACCOUNTS, sAccountName)
135
+
136
+ # Maestro compute use openstack. It requires meta tenant_name (not ID). Need to query HPC to get the Project Name from the ID.
137
+ oConfig.ExtraLoad(hpc_account_file, :hpc_accounts, sAccountName)
67
138
 
68
- # Implementation of simple credential encoding for build.sh/maestro
69
- save_maestro_creds(sAccountName)
139
+ setup_tenant_name(oConfig, sAccountName)
140
+ end
141
+
142
+ def setup_dns(oConfig, sAccountName)
143
+ sAsk = "Optionally, you can ask Maestro to manage a Domain name. It requires your DNS cloud service to be enabled.\nDo you want to configure it?"
144
+ if agree(sAsk)
145
+ # Get HPCloud account definition
146
+ yHPC = oConfig.ExtraGet(:hpc_accounts, sAccountName)
147
+
148
+ # Get Forj account definition
149
+ yDNS = oConfig.ExtraGet(:forj_accounts, sAccountName, :dns)
150
+ yDNS = {} if not yDNS
70
151
 
71
- # Check/create keypair
72
- keypair_setup(oConfig)
152
+ # Getting tenants
153
+ tenants = oConfig.get('tenants')
154
+
155
+ # Question about DNS Tenant ID
156
+ # In HPCloud : credentials/tenant_id
157
+ aDNS_TenantIDs = []
158
+ sDNS_TenantIDs = rhGet(yDNS, :tenant_id)
159
+ sDNS_TenantIDs = rhGet(yHPC, :credentials, :tenant_id) if not sDNS_TenantIDs and rhExist?(yHPC, :credentials, :tenant_id) > 0
160
+
161
+ Logging.message("Following are the list of know project attached to your credentials:")
162
+ tenants.each do | elem |
163
+ aDNS_TenantIDs.push(elem['id'])
164
+ if sDNS_TenantIDs and elem['id'] == sDNS_TenantIDs
165
+ Logging.message("%s - %s" % [ANSI.bold+elem['id']+ANSI.reset, elem['name']])
166
+ else
167
+ Logging.message("%s - %s" % [elem['id'], elem['name']])
168
+ end
169
+ end
170
+
171
+ sOption = ' [%s]' % aDNS_TenantIDs.join(', ') if aDNS_TenantIDs.length() == 2
172
+ sDNS_TenantID = ask('Enter DNS Tenant ID:%s' % sOption) do |q|
173
+ q.default = sDNS_TenantIDs
174
+ q.validate = /[\w\d]+/
175
+ end
176
+ yDNS[:tenant_id] = sDNS_TenantID.to_s
177
+
178
+ # Question about DNS Service
179
+ # In HPCloud : regions/dns
180
+ if sDNS_TenantID == rhGet(yHPC, :credentials, :tenant_id)
181
+ sDNS_Service = rhGet(yHPC, :regions, :dns)
182
+ else
183
+ aDNS_Services = []
184
+ aDNS_Services.push(rhGet(yDNS, :service)) if rhExist?(yDNS, :service) > 0
73
185
 
74
- rescue RuntimeError => e
75
- Logging.fatal(1,e.message)
76
- rescue => e
77
- Logging.fatal(1,"%s\n%s" % [e.message,e.backtrace.join("\n")])
78
- end
79
- end
186
+ sDNS_Service = ask("Enter DNS Service for the Tenant ID '%s' (ex: region-a.geo-1): " % sDNS_TenantID) do |q|
187
+ q.validate = /[\w.-]+/
188
+ end
189
+ end
190
+ yDNS[:service] = sDNS_Service.to_s
191
+
192
+ else
193
+ yDNS = {} # Any information about DNS setting is removed.
194
+ Logging.message("Maestro won't manage any Domain.")
195
+ end
196
+ # Question about Domain name
197
+ previousDomainName = rhGet(yDNS, :domain_name) if rhExist?(yDNS, :domain_name) > 0
198
+
199
+ sDNS_DomainName = ask('Enter Domain name (puppet requirement) (ex: dev.forj.io):') do |q|
200
+ q.default = previousDomainName if previousDomainName
201
+ q.validate = /[\w._]+/
202
+ end
203
+ yDNS[:domain_name] = sDNS_DomainName.to_s
204
+
205
+ oConfig.ExtraSet(:forj_accounts, sAccountName, :dns, yDNS)
206
+ forjAccountFile = File.join($FORJ_ACCOUNTS_PATH, sAccountName)
207
+ oConfig.ExtraSave(forjAccountFile, :forj_accounts, sAccountName)
80
208
  end
81
209
 
82
210
  def ensure_forj_dirs_exists()
@@ -84,19 +212,20 @@ def ensure_forj_dirs_exists()
84
212
 
85
213
  # Defining Global variables
86
214
  $FORJ_DATA_PATH = File.expand_path(File.join('~', '.forj'))
87
- $FORJ_ACCOUNT_PATH = File.join($FORJ_DATA_PATH, 'account') # Not currently used...
215
+ $FORJ_ACCOUNTS_PATH = File.join($FORJ_DATA_PATH, 'accounts')
88
216
  $FORJ_KEYPAIRS_PATH = File.join($FORJ_DATA_PATH, 'keypairs')
89
217
  $FORJ_CREDS_PATH = File.expand_path(File.join('~', '.cache', 'forj'))
90
-
218
+
91
219
  # TODO: To move to an hpcloud object.
92
220
  $HPC_KEYPAIRS = File.expand_path(File.join('~', '.hpcloud', 'keypairs'))
221
+ $HPC_ACCOUNTS = File.expand_path(File.join('~', '.hpcloud', 'accounts'))
93
222
 
94
223
  Helpers.ensure_dir_exists($FORJ_DATA_PATH)
95
- Helpers.ensure_dir_exists($FORJ_ACCOUNT_PATH)
224
+ Helpers.ensure_dir_exists($FORJ_ACCOUNTS_PATH)
96
225
  Helpers.ensure_dir_exists($FORJ_KEYPAIRS_PATH)
97
226
  Helpers.ensure_dir_exists($FORJ_CREDS_PATH)
98
227
  end
99
-
228
+
100
229
  def keypair_setup(oConfig)
101
230
 
102
231
  key_path = oConfig.get('keypair_path')
@@ -122,59 +251,77 @@ def keypair_setup(oConfig)
122
251
  Logging.debug("Saving forj keypair '%s' as default." % [real_key_path] )
123
252
  oConfig.LocalSet('keypair_path', real_key_path)
124
253
  oConfig.SaveConfig()
125
- end
254
+ end
126
255
  end
127
256
  end
128
257
  end
129
258
 
130
259
 
131
- def save_maestro_creds(sAccountName)
132
- # Check required global data
133
- if not $FORJ_CREDS_PATH
134
- Logging.fatal(1, "Internal error: '$FORJ_CREDS_PATH' missing.")
135
- end
136
- if not Helpers.dir_exists?($FORJ_CREDS_PATH)
137
- Logging.fatal(1, "Internal error: '%s' doesn't exist." % $FORJ_CREDS_PATH)
138
- end
260
+ def save_maestro_creds(oConfig, sAccountName)
261
+ # Check required global data
262
+ if not $FORJ_CREDS_PATH
263
+ Logging.fatal(1, "Internal error: '$FORJ_CREDS_PATH' missing.")
264
+ end
265
+ if not Helpers.dir_exists?($FORJ_CREDS_PATH)
266
+ Logging.fatal(1, "Internal error: '%s' doesn't exist." % $FORJ_CREDS_PATH)
267
+ end
139
268
 
140
- Logging.info("Completing hpcloud account '%s' information." % [sAccountName] )
269
+ Logging.info("Completing hpcloud account '%s' information." % [sAccountName] )
141
270
 
142
- # TODO Be able to load the previous username if the g64 file exists.
143
- hpcloud_os_user = ask('Enter hpcloud username: ') do |q|
144
- q.validate = /\w+/
145
- q.default = ''
146
- end
271
+ forjAccountFile = File.join($FORJ_ACCOUNTS_PATH, sAccountName)
272
+ oConfig.ExtraLoad(forjAccountFile, :forj_accounts, sAccountName)
147
273
 
148
- hpcloud_os_key = ask('Enter hpcloud password: ') do |q|
149
- q.echo = '*'
150
- q.validate = /.+/
151
- end
274
+ forj_user = rhGet(oConfig.ExtraGet(:forj_accounts, sAccountName, :credentials), :os_user)
152
275
 
153
- add_creds = {:credentials => {:hpcloud_os_user=> hpcloud_os_user, :hpcloud_os_key=> hpcloud_os_key}}
276
+ hpcloud_os_user = ask('Enter hpcloud username: ') do |q|
277
+ q.validate = /\w+/
278
+ q.default = forj_user if forj_user
279
+ end
280
+
281
+ hpcloud_os_key = ask("Enter hpcloud password for '%s': " % hpcloud_os_user) do |q|
282
+ q.echo = '*'
283
+ q.validate = /.+/
284
+ end
154
285
 
155
- cloud_fog = File.join($FORJ_CREDS_PATH, sAccountName+'.g64')
286
+ # Checking key file used to encrypt/decrypt passwords
287
+ key_file = File.join($FORJ_CREDS_PATH, '.key')
288
+ if not File.exists?(key_file)
289
+ # Need to create a random key.
290
+ entr = { :key => rand(36**10).to_s(36), :salt => Time.now.to_i.to_s, :iv => OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv}
291
+
292
+ Logging.debug("Writing '%s' key file" % key_file)
293
+ File.open(key_file, 'w') do |out|
294
+ out.write(Base64::encode64(entr.to_yaml))
295
+ end
296
+ else
297
+ Logging.debug("Loading '%s' key file" % key_file)
298
+ encoded_key = IO.read(key_file)
299
+ entr = YAML.load(Base64::decode64(encoded_key))
300
+ end
301
+ enc_hpcloud_os_key = Base64::strict_encode64(Encryptor.encrypt(:value => hpcloud_os_key, :key => entr[:key], :iv => entr[:iv], :salt => entr[:salt]))
156
302
 
157
- # Security fix: Remove old temp file with clear password.
158
- old_file = '%s/master.forj-13.5' % [$FORJ_CREDS_PATH]
159
- File.delete(old_file) if File.exists?(old_file)
160
- old_file = '%s/creds' % [$FORJ_CREDS_PATH]
161
- File.delete(old_file) if File.exists?(old_file)
303
+ cloud_fog = File.join($FORJ_CREDS_PATH, sAccountName+'.g64')
162
304
 
163
- hpcloud_creds = File.expand_path('~/.hpcloud/accounts/%s' % [sAccountName])
164
- creds = YAML.load_file(hpcloud_creds)
305
+ # Security fix: Remove old temp file with clear password.
306
+ old_file = '%s/master.forj-13.5' % [$FORJ_CREDS_PATH]
307
+ File.delete(old_file) if File.exists?(old_file)
308
+ old_file = '%s/creds' % [$FORJ_CREDS_PATH]
309
+ File.delete(old_file) if File.exists?(old_file)
165
310
 
166
- access_key = creds[:credentials][:account_id]
167
- secret_key = creds[:credentials][:secret_key]
311
+ hpc_creds = oConfig.ExtraGet(:hpc_accounts, sAccountName, :credentials)
168
312
 
169
- os_user = add_creds[:credentials][:hpcloud_os_user]
170
- os_key = add_creds[:credentials][:hpcloud_os_key]
313
+ forj_creds = { :os_user => hpcloud_os_user.to_s,
314
+ :os_enckey => enc_hpcloud_os_key
315
+ }
316
+ oConfig.ExtraSet(:forj_accounts, sAccountName, :credentials, forj_creds)
317
+ oConfig.ExtraSave(forjAccountFile, :forj_accounts, sAccountName)
171
318
 
172
- IO.popen('gzip -c | base64 -w0 > %s' % [cloud_fog], 'r+') {|pipe|
173
- pipe.puts('HPCLOUD_OS_USER=%s' % [os_user] )
174
- pipe.puts('HPCLOUD_OS_KEY=%s' % [os_key] )
175
- pipe.puts('DNS_KEY=%s' % [access_key] )
176
- pipe.puts('DNS_SECRET=%s' % [secret_key])
177
- pipe.close_write
178
- }
179
- Logging.info("'%s' written." % cloud_fog)
319
+ IO.popen('gzip -c | base64 -w0 > %s' % [cloud_fog], 'r+') {|pipe|
320
+ pipe.puts('HPCLOUD_OS_USER=%s' % [hpcloud_os_user] )
321
+ pipe.puts('HPCLOUD_OS_KEY=%s' % [hpcloud_os_key] )
322
+ pipe.puts('DNS_KEY=%s' % [hpc_creds[:account_id]] )
323
+ pipe.puts('DNS_SECRET=%s' % [hpc_creds[:secret_key]])
324
+ pipe.close_write
325
+ }
326
+ Logging.info("'%s' written." % cloud_fog)
180
327
  end
data/lib/ssh.sh CHANGED
@@ -19,7 +19,7 @@ GRE="\e[92m"
19
19
  # See the License for the specific language governing permissions and
20
20
  # limitations under the License.
21
21
 
22
- OW=`date +%Y-%m-%d.%H%M%S`
22
+ NOW=$(date +%Y-%m-%d.%H%M%S)
23
23
  logpath=~/.ssh/
24
24
  DB=~/hosts
25
25
  #key_path=~/.ssh/
@@ -140,7 +140,7 @@ else
140
140
  echo -e "${RED}Error, the kit ${GRE}$node${RED} with id ${GRE}$id${RED} was not found.${RST}"
141
141
  exit 1
142
142
  fi
143
- key=$(cat $DB | grep -iE "$ip" | awk '{print $4}' | tr -d ' ')
143
+ key=$(cat $DB | grep -iEw "$ip" | awk '{print $4}' | tr -d ' ')
144
144
  message="$node.$id"
145
145
  extended="($ip)"
146
146
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forj
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.36
4
+ version: 0.0.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - forj team
@@ -14,14 +14,14 @@ dependencies:
14
14
  name: thor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.16.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.16.0
27
27
  - !ruby/object:Gem::Dependency
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 2.0.8
61
+ version: 2.0.9
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
- version: 2.0.8
68
+ version: 2.0.9
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: git
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -145,7 +145,6 @@ files:
145
145
  - lib/ssh.sh
146
146
  - lib/log.rb
147
147
  - lib/helpers.rb
148
- - lib/build_tmpl/build-env.py
149
148
  - lib/forj-config.rb
150
149
  - spec/boot_spec.rb
151
150
  - spec/connection_spec.rb