質問編集履歴

3

脱字修正

2020/04/25 04:40

投稿

Yuta_for
Yuta_for

スコア21

test CHANGED
File without changes
test CHANGED
@@ -362,6 +362,8 @@
362
362
 
363
363
 
364
364
 
365
+ 2020/4/25(土)追記
366
+
365
367
  頂いた回答を基に修正したコードです。
366
368
 
367
369
  ```Python

2

回答後の修正

2020/04/25 04:40

投稿

Yuta_for
Yuta_for

スコア21

test CHANGED
File without changes
test CHANGED
@@ -34,112 +34,408 @@
34
34
 
35
35
 
36
36
 
37
+ import sys
38
+
39
+ import os.path
40
+
41
+ import subprocess
42
+
43
+ import re
44
+
45
+ from paramiko import SSHConfig
46
+
47
+ from io import StringIO
48
+
49
+ from optparse import OptionParser
50
+
51
+ from collections import defaultdict
52
+
53
+ try:
54
+
55
+ import json
56
+
57
+ except:
58
+
59
+ import simplejson as json
60
+
61
+
62
+
63
+ _group = 'vagrant' # a default group
64
+
37
- # Copyright (C) 2013 Mark Mandel <mark@compoundtheory.com>
65
+ _ssh_to_ansible = [('user', 'ansible_ssh_user'),
66
+
38
-
67
+ ('hostname', 'ansible_ssh_host'),
68
+
69
+ ('identityfile', 'ansible_ssh_private_key_file'),
70
+
71
+ ('port', 'ansible_ssh_port')]
72
+
73
+
74
+
75
+ # Options
76
+
77
+ # ------------------------------
78
+
79
+
80
+
39
- # 2015 Igor Khomyakov <homyakov@gmail.com>
81
+ parser = OptionParser(usage="%prog [options] --list | --host <machine>")
82
+
83
+ parser.add_option('--list', default=False, dest="list", action="store_true",
84
+
85
+ help="Produce a JSON consumable grouping of Vagrant servers for Ansible")
86
+
87
+ parser.add_option('--host', default=None, dest="host",
88
+
89
+ help="Generate additional host specific details for given host for Ansible")
90
+
91
+ (options, args) = parser.parse_args()
92
+
93
+
40
94
 
41
95
  #
42
96
 
43
- # This program is free software: you can redistribute it and/or modify
44
-
45
- # it under the terms of the GNU General Public License as published by
46
-
47
- # the Free Software Foundation, either version 3 of the License, or
48
-
49
- # (at your option) any later version.
97
+ # helper functions
50
98
 
51
99
  #
52
100
 
101
+
102
+
103
+
104
+
105
+ # get all the ssh configs for all boxes in an array of dictionaries.
106
+
107
+ def get_ssh_config():
108
+
109
+ return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
110
+
111
+
112
+
113
+
114
+
115
+ # list all the running boxes
116
+
117
+ def list_running_boxes():
118
+
119
+ output = subprocess.check_output(["vagrant", "status"]).split('\n')
120
+
121
+
122
+
123
+ boxes = []
124
+
125
+
126
+
127
+ for line in output:
128
+
129
+ matcher = re.search("([^\s]+)[\s]+running (.+", line)
130
+
131
+ if matcher:
132
+
133
+ boxes.append(matcher.group(1))
134
+
135
+
136
+
137
+ return boxes
138
+
139
+
140
+
141
+
142
+
143
+ # get the ssh config for a single box
144
+
145
+ def get_a_ssh_config(box_name):
146
+
147
+ """Gives back a map of all the machine's ssh configurations"""
148
+
149
+
150
+
151
+ output = subprocess.check_output(["vagrant", "ssh-config", box_name])
152
+
153
+ config = SSHConfig()
154
+
155
+ config.parse(StringIO(output))
156
+
157
+ host_config = config.lookup(box_name)
158
+
159
+
160
+
161
+ # man 5 ssh_config:
162
+
53
- # This program is distributed in the hope that it will be useful,
163
+ # > It is possible to have multiple identity files ...
54
-
164
+
55
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
165
+ # > all these identities will be tried in sequence.
166
+
56
-
167
+ for id in host_config['identityfile']:
168
+
169
+ if os.path.isfile(id):
170
+
171
+ host_config['identityfile'] = id
172
+
173
+
174
+
57
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175
+ return dict((v, host_config[k]) for k, v in _ssh_to_ansible)
176
+
177
+
178
+
58
-
179
+ # List out servers that vagrant has running
180
+
181
+ # ------------------------------
182
+
183
+ if options.list:
184
+
185
+ ssh_config = get_ssh_config()
186
+
187
+ meta = defaultdict(dict)
188
+
189
+
190
+
191
+ for host in ssh_config:
192
+
193
+ meta['hostvars'][host] = ssh_config[host]
194
+
195
+
196
+
197
+ print((json.dumps({_group: list(ssh_config.keys()), '_meta': meta})))
198
+
199
+ sys.exit(0)
200
+
201
+
202
+
59
- # GNU General Public License for more details.
203
+ # Get out the host details
204
+
205
+ # ------------------------------
206
+
207
+ elif options.host:
208
+
209
+ print((json.dumps(get_a_ssh_config(options.host))))
210
+
211
+ sys.exit(0)
212
+
213
+
214
+
215
+ # Print out help
216
+
217
+ # ------------------------------
218
+
219
+ else:
220
+
221
+ parser.print_help()
222
+
223
+ sys.exit(0)
224
+
225
+
226
+
227
+ 実行結果
228
+
229
+ yuta@yuta-PC:~/Desktop/work/ansible/ansible-tutorial$ ./vagrant.py --list
230
+
231
+ Traceback (most recent call last):
232
+
233
+ File "./vagrant.py", line 108, in <module>
234
+
235
+ ssh_config = get_ssh_config()
236
+
237
+ File "./vagrant.py", line 70, in get_ssh_config
238
+
239
+ return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
240
+
241
+ File "./vagrant.py", line 75, in list_running_boxes
242
+
243
+ output = subprocess.check_output(["vagrant", "status"]).split('\n')
244
+
245
+ TypeError: a bytes-like object is required, not 'str'
246
+
247
+ ```
248
+
249
+
250
+
251
+ 書籍の想定出力ですと以下のようになるみたいです。
252
+
253
+ ```Python
254
+
255
+ {
256
+
257
+ "vagrant": [
258
+
259
+ "default"
260
+
261
+ ],
262
+
263
+ "_meta": {
264
+
265
+ "hostvars": {
266
+
267
+ "default": {
268
+
269
+ "ansible_ssh_host": "127.0.0.1",
270
+
271
+ "ansible_ssh_port": "2222",
272
+
273
+ "ansible_ssh_user": "vagrant",
274
+
275
+ "ansible_ssh_private_key_file": "Users/username/ansible-tutorial/.vagrant/machines/default/virtualbox/private_key"
276
+
277
+ }
278
+
279
+ }
280
+
281
+ }
282
+
283
+ }
284
+
285
+ ```
286
+
287
+
288
+
289
+ もともとPython2系で書かれていたみたいで、2to3ツールで3に変換した上で実行したのですが、エラーが発生しました。
290
+
291
+ 以前も[同じようなエラーが出た時に質問した](https://teratail.com/questions/253116)のですが、
292
+
293
+ TypeError: a bytes-like object is required, not 'str' 左記のエラーから文字コードを指定してバイト型に変換する必要があるとのことで、
294
+
295
+ output = subprocess.check_output([**b**"vagrant", **b**"status"]).split('\n')
296
+
297
+ 上記のようにバイト変換をしましたが、結果は変わりませんでした。
298
+
299
+ 前提条件となるVagrantの起動は完了しております。
300
+
301
+ 他にどうすればよいのか分からなくてわかる人がいましたらご教授お願いいたします。
302
+
303
+
304
+
305
+ 追記
306
+
307
+ レシーバにdecode()を修正して実行しましたが、別エラーが発生しました。
308
+
309
+ ```Python
310
+
311
+ # list all the running boxes
312
+
313
+ def list_running_boxes():
314
+
315
+ output = subprocess.check_output(["vagrant", "status"]).decode().split('\n')
316
+
317
+
318
+
319
+ boxes = []
320
+
321
+
322
+
323
+ for line in output:
324
+
325
+ matcher = re.search("([^\s]+)[\s]+running (.+", line)
326
+
327
+ if matcher:
328
+
329
+ boxes.append(matcher.group(1))
330
+
331
+
332
+
333
+ return boxes
334
+
335
+
336
+
337
+ 実行結果
338
+
339
+ yuta@yuta-PC:~/Desktop/work/ansible/ansible-tutorial$ ./vagrant.py --list
340
+
341
+ Traceback (most recent call last):
342
+
343
+ File "./vagrant.py", line 108, in <module>
344
+
345
+ ssh_config = get_ssh_config()
346
+
347
+ File "./vagrant.py", line 70, in get_ssh_config
348
+
349
+ return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
350
+
351
+ File "./vagrant.py", line 70, in <genexpr>
352
+
353
+ return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
354
+
355
+ File "./vagrant.py", line 93, in get_a_ssh_config
356
+
357
+ config.parse(StringIO(output))
358
+
359
+ TypeError: initial_value must be str or None, not bytes
360
+
361
+ ```
362
+
363
+
364
+
365
+ 頂いた回答を基に修正したコードです。
366
+
367
+ ```Python
368
+
369
+
370
+
371
+ #!/usr/bin/env python
372
+
373
+
374
+
375
+ import sys
376
+
377
+ import os.path
378
+
379
+ import subprocess
380
+
381
+ import re
382
+
383
+ from paramiko import SSHConfig
384
+
385
+ from io import BytesIO
386
+
387
+ from optparse import OptionParser
388
+
389
+ from collections import defaultdict
390
+
391
+ try:
392
+
393
+ import json
394
+
395
+ except:
396
+
397
+ import simplejson as json
398
+
399
+
400
+
401
+ _group = 'vagrant' # a default group
402
+
403
+ _ssh_to_ansible = [('user', 'ansible_ssh_user'),
404
+
405
+ ('hostname', 'ansible_ssh_host'),
406
+
407
+ ('identityfile', 'ansible_ssh_private_key_file'),
408
+
409
+ ('port', 'ansible_ssh_port')]
410
+
411
+
412
+
413
+ # Options
414
+
415
+ # ------------------------------
416
+
417
+
418
+
419
+ parser = OptionParser(usage="%prog [options] --list | --host <machine>")
420
+
421
+ parser.add_option('--list', default=False, dest="list", action="store_true",
422
+
423
+ help="Produce a JSON consumable grouping of Vagrant servers for Ansible")
424
+
425
+ parser.add_option('--host', default=None, dest="host",
426
+
427
+ help="Generate additional host specific details for given host for Ansible")
428
+
429
+ (options, args) = parser.parse_args()
430
+
431
+
60
432
 
61
433
  #
62
434
 
63
- # You should have received a copy of the GNU General Public License
435
+ # helper functions
64
-
65
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
66
-
67
-
68
436
 
69
437
  #
70
438
 
71
- # Thanks to the spacewalk.py inventory script for giving me the basic structure
72
-
73
- # of this.
74
-
75
- #
76
-
77
-
78
-
79
- import sys
80
-
81
- import os.path
82
-
83
- import subprocess
84
-
85
- import re
86
-
87
- from paramiko import SSHConfig
88
-
89
- from io import StringIO
90
-
91
- from optparse import OptionParser
92
-
93
- from collections import defaultdict
94
-
95
- try:
96
-
97
- import json
98
-
99
- except:
100
-
101
- import simplejson as json
102
-
103
-
104
-
105
- _group = 'vagrant' # a default group
106
-
107
- _ssh_to_ansible = [('user', 'ansible_ssh_user'),
108
-
109
- ('hostname', 'ansible_ssh_host'),
110
-
111
- ('identityfile', 'ansible_ssh_private_key_file'),
112
-
113
- ('port', 'ansible_ssh_port')]
114
-
115
-
116
-
117
- # Options
118
-
119
- # ------------------------------
120
-
121
-
122
-
123
- parser = OptionParser(usage="%prog [options] --list | --host <machine>")
124
-
125
- parser.add_option('--list', default=False, dest="list", action="store_true",
126
-
127
- help="Produce a JSON consumable grouping of Vagrant servers for Ansible")
128
-
129
- parser.add_option('--host', default=None, dest="host",
130
-
131
- help="Generate additional host specific details for given host for Ansible")
132
-
133
- (options, args) = parser.parse_args()
134
-
135
-
136
-
137
- #
138
-
139
- # helper functions
140
-
141
- #
142
-
143
439
 
144
440
 
145
441
 
@@ -158,7 +454,7 @@
158
454
 
159
455
  def list_running_boxes():
160
456
 
161
- output = subprocess.check_output(["vagrant", "status"]).split('\n')
457
+ output = subprocess.check_output([b"vagrant", b"status"]).split(b'\n') #bを追加してbyte変換
162
458
 
163
459
 
164
460
 
@@ -168,7 +464,7 @@
168
464
 
169
465
  for line in output:
170
466
 
171
- matcher = re.search("([^\s]+)[\s]+running (.+", line)
467
+ matcher = re.search(b"([^\s]+)[\s]+running (.+", line) #bを追加してbyte変換
172
468
 
173
469
  if matcher:
174
470
 
@@ -194,7 +490,7 @@
194
490
 
195
491
  config = SSHConfig()
196
492
 
197
- config.parse(StringIO(output))
493
+ config.parse(BytesIO(output))
198
494
 
199
495
  host_config = config.lookup(box_name)
200
496
 
@@ -266,138 +562,42 @@
266
562
 
267
563
 
268
564
 
269
- 実行結果
565
+ 実行
270
-
566
+
271
- yuta@yuta-PC:~/Desktop/work/ansible/ansible-tutorial$ ./vagrant.py --list
567
+ python vagrant.py --list
272
568
 
273
569
  Traceback (most recent call last):
274
570
 
275
- File "./vagrant.py", line 108, in <module>
571
+ File "vagrant.py", line 108, in <module>
276
572
 
277
573
  ssh_config = get_ssh_config()
278
574
 
279
- File "./vagrant.py", line 70, in get_ssh_config
575
+ File "vagrant.py", line 70, in get_ssh_config
280
576
 
281
577
  return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
282
578
 
579
+ File "vagrant.py", line 70, in <genexpr>
580
+
581
+ return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
582
+
283
- File "./vagrant.py", line 75, in list_running_boxes
583
+ File "vagrant.py", line 93, in get_a_ssh_config
584
+
284
-
585
+ config.parse(BytesIO(output))
586
+
587
+ File "/home/yuta/.pyenv/versions/3.8.2/lib/python3.8/site-packages/paramiko/config.py", line 136, in parse
588
+
285
- output = subprocess.check_output(["vagrant", "status"]).split('\n')
589
+ if not line or line.startswith("#"):
286
-
590
+
287
- TypeError: a bytes-like object is required, not 'str'
591
+ TypeError: startswith first arg must be bytes or a tuple of bytes, not str
592
+
593
+
594
+
595
+
288
596
 
289
597
  ```
290
598
 
291
599
 
292
600
 
293
- 書籍の想定出力ですと以下のようになるみたいです。
294
-
295
- ```Python
296
-
297
- {
298
-
299
- "vagrant": [
300
-
301
- "default"
302
-
303
- ],
304
-
305
- "_meta": {
306
-
307
- "hostvars": {
308
-
309
- "default": {
310
-
311
- "ansible_ssh_host": "127.0.0.1",
312
-
313
- "ansible_ssh_port": "2222",
314
-
315
- "ansible_ssh_user": "vagrant",
316
-
317
- "ansible_ssh_private_key_file": "Users/username/ansible-tutorial/.vagrant/machines/default/virtualbox/private_key"
318
-
319
- }
320
-
321
- }
322
-
323
- }
324
-
325
- }
326
-
327
- ```
328
-
329
-
330
-
331
- もともとPython2系で書かれていたみたいで、2to3ツールで3に変換した上で実行したのですが、エラーが発生しました。
332
-
333
- 以前も[同じようなエラーが出た時に質問した](https://teratail.com/questions/253116)のですが、
601
+ エラーの内容から最初の引数をバイトにしいといけないと出力されていますが、エラーがpyenv以下のparamikoパッケージコンフィグファイルあり、この部分を修正るということでしょうか?
334
-
335
- TypeError: a bytes-like object is required, not 'str' 左記のエラーから文字コードを指定してバイト型に変換する必要があるとのことで、
602
+
336
-
337
- output = subprocess.check_output([**b**"vagrant", **b**"status"]).split('\n')
338
-
339
- 上記のようにバイト変換をしましたが、結果は変わりませんでした。
340
-
341
- 前提条件となるVagrantの起動は完了しております。
342
-
343
- どうればよいのか分からなくてわかる人がいましたらご教授お願いいたします。
603
+ pip でインストールしたモジュールのコンフィグファイルを変更すること少し不安感を覚えるのでがこの考えは間違ってないのかご教授お願いいたします。
344
-
345
-
346
-
347
- 追記
348
-
349
- レシーバにdecode()を修正して実行しましたが、別エラーが発生しました。
350
-
351
- ```Python
352
-
353
- # list all the running boxes
354
-
355
- def list_running_boxes():
356
-
357
- output = subprocess.check_output(["vagrant", "status"]).decode().split('\n')
358
-
359
-
360
-
361
- boxes = []
362
-
363
-
364
-
365
- for line in output:
366
-
367
- matcher = re.search("([^\s]+)[\s]+running (.+", line)
368
-
369
- if matcher:
370
-
371
- boxes.append(matcher.group(1))
372
-
373
-
374
-
375
- return boxes
376
-
377
-
378
-
379
- 実行結果
380
-
381
- yuta@yuta-PC:~/Desktop/work/ansible/ansible-tutorial$ ./vagrant.py --list
382
-
383
- Traceback (most recent call last):
384
-
385
- File "./vagrant.py", line 108, in <module>
386
-
387
- ssh_config = get_ssh_config()
388
-
389
- File "./vagrant.py", line 70, in get_ssh_config
390
-
391
- return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
392
-
393
- File "./vagrant.py", line 70, in <genexpr>
394
-
395
- return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
396
-
397
- File "./vagrant.py", line 93, in get_a_ssh_config
398
-
399
- config.parse(StringIO(output))
400
-
401
- TypeError: initial_value must be str or None, not bytes
402
-
403
- ```

1

追記分の追加

2020/04/25 04:39

投稿

Yuta_for
Yuta_for

スコア21

test CHANGED
File without changes
test CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ##エラーの詳細
8
8
 
9
- Ansibleの勉強のために以下の技術書に記載されているDynamic Inventoryスクリプトを起動しましたが型エラーでつまずいてしまいました。
9
+ Ansibleの勉強のために以下の[技術書](https://www.amazon.co.jp/Ansible%E5%BE%B9%E5%BA%95%E5%85%A5%E9%96%80-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E6%99%82%E4%BB%A3%E3%81%AE%E6%96%B0%E3%81%97%E3%81%84%E6%A7%8B%E6%88%90%E7%AE%A1%E7%90%86%E3%81%AE%E5%AE%9F%E7%8F%BE-%E5%BB%A3%E5%B7%9D-%E8%8B%B1%E5%AF%BF/dp/4798149942)に記載されているDynamic Inventoryスクリプトを起動しましたが型エラーでつまずいてしまいました。
10
10
 
11
11
  ```Python
12
12
 
@@ -341,3 +341,63 @@
341
341
  前提条件となるVagrantの起動は完了しております。
342
342
 
343
343
  他にどうすればよいのか分からなくてわかる人がいましたらご教授お願いいたします。
344
+
345
+
346
+
347
+ 追記
348
+
349
+ レシーバにdecode()を修正して実行しましたが、別エラーが発生しました。
350
+
351
+ ```Python
352
+
353
+ # list all the running boxes
354
+
355
+ def list_running_boxes():
356
+
357
+ output = subprocess.check_output(["vagrant", "status"]).decode().split('\n')
358
+
359
+
360
+
361
+ boxes = []
362
+
363
+
364
+
365
+ for line in output:
366
+
367
+ matcher = re.search("([^\s]+)[\s]+running (.+", line)
368
+
369
+ if matcher:
370
+
371
+ boxes.append(matcher.group(1))
372
+
373
+
374
+
375
+ return boxes
376
+
377
+
378
+
379
+ 実行結果
380
+
381
+ yuta@yuta-PC:~/Desktop/work/ansible/ansible-tutorial$ ./vagrant.py --list
382
+
383
+ Traceback (most recent call last):
384
+
385
+ File "./vagrant.py", line 108, in <module>
386
+
387
+ ssh_config = get_ssh_config()
388
+
389
+ File "./vagrant.py", line 70, in get_ssh_config
390
+
391
+ return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
392
+
393
+ File "./vagrant.py", line 70, in <genexpr>
394
+
395
+ return dict((k, get_a_ssh_config(k)) for k in list_running_boxes())
396
+
397
+ File "./vagrant.py", line 93, in get_a_ssh_config
398
+
399
+ config.parse(StringIO(output))
400
+
401
+ TypeError: initial_value must be str or None, not bytes
402
+
403
+ ```