forj 0.0.36 → 0.0.37

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.
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