μ΅μ ν¨λΈλ¦ λ²μ μ λν λ³λ ¬ μ€νμ λν λ¬Έμλ₯Ό μ°Ύμ μ μμμ΅λλ€. python 2 λ²μ κ³Ό λμΌν©λκΉ, μλλ©΄ μμ μ€μ λκΉ?
κ°μ¬ ν΄μ!
μ, κ·Έλ¬λ μ€λ λ© κ·Έλ£Ήμ νΉν ꡬμ±μ μ§μνμ§ μμ΅λλ€.
config = Config(overrides={'sudo':{'password': 'changeme'}})
c = ThreadingGroup("[email protected]", "[email protected]", connect_kwargs={"password": "changeme"}, config=config)
c.run("whoami")
c.sudo("whoami") #Throws AttributeError: 'ThreadingGroup' object has no attribute 'sudo'
ThreadingGroupμ μ€ν λͺ
λ Ήλ§ νμ©νμ΅λλ€.
https://github.com/fabric/fabric/issues/1899#issue -377714688
λͺ λ Ή μ§μμ λ€μ μμ±νκ³ μΆκ°ν μ μμ΅λλ€.
SerialGroup λ° ThreadingGroupμμ sudoλ₯Ό νμ±ννλ λ€μ ν¨μΉμ λν΄ μ΄λ»κ² μκ°νμλκΉ?
(ν¨λΈλ¦ 2.4μ μ μ© λ° ν
μ€νΈ)
--- fabric-orig/group.py 2018-10-30 14:35:22.000000000 +0100
+++ fabric-patched/group.py 2019-02-18 10:16:29.186000000 +0100
@@ -183,12 +183,28 @@
raise GroupException(results)
return results
+ def sudo(self, *args, **kwargs):
+ results = GroupResult()
+ excepted = False
+ for cxn in self:
+ try:
+ results[cxn] = cxn.sudo(*args, **kwargs)
+ except Exception as e:
+ results[cxn] = e
+ excepted = True
+ if excepted:
+ raise GroupException(results)
+ return results
def thread_worker(cxn, queue, args, kwargs):
result = cxn.run(*args, **kwargs)
# TODO: namedtuple or attrs object?
queue.put((cxn, result))
+def thread_worker_sudo(cxn, queue, args, kwargs):
+ result = cxn.sudo(*args, **kwargs)
+ # TODO: namedtuple or attrs object?
+ queue.put((cxn, result))
class ThreadingGroup(Group):
"""
@@ -208,6 +224,49 @@
)
threads.append(thread)
for thread in threads:
+ thread.start()
+ for thread in threads:
+ # TODO: configurable join timeout
+ # TODO: (in sudo's version) configurability around interactive
+ # prompting resulting in an exception instead, as in v1
+ thread.join()
+ # Get non-exception results from queue
+ while not queue.empty():
+ # TODO: io-sleep? shouldn't matter if all threads are now joined
+ cxn, result = queue.get(block=False)
+ # TODO: outstanding musings about how exactly aggregate results
+ # ought to ideally operate...heterogenous obj like this, multiple
+ # objs, ??
+ results[cxn] = result
+ # Get exceptions from the threads themselves.
+ # TODO: in a non-thread setup, this would differ, e.g.:
+ # - a queue if using multiprocessing
+ # - some other state-passing mechanism if using e.g. coroutines
+ # - ???
+ excepted = False
+ for thread in threads:
+ wrapper = thread.exception()
+ if wrapper is not None:
+ # Outer kwargs is Thread instantiation kwargs, inner is kwargs
+ # passed to thread target/body.
+ cxn = wrapper.kwargs["kwargs"]["cxn"]
+ results[cxn] = wrapper.value
+ excepted = True
+ if excepted:
+ raise GroupException(results)
+ return results
+
+ def sudo(self, *args, **kwargs):
+ results = GroupResult()
+ queue = Queue()
+ threads = []
+ for cxn in self:
+ my_kwargs = dict(cxn=cxn, queue=queue, args=args, kwargs=kwargs)
+ thread = ExceptionHandlingThread(
+ target=thread_worker_sudo, kwargs=my_kwargs
+ )
+ threads.append(thread)
+ for thread in threads:
thread.start()
for thread in threads:
# TODO: configurable join timeout
μ λ§ λλ¨νκ² λ€μ @akiuni
execute() κΈ°λ₯μ Fabric2μ© ThreadingGroupμΌλ‘ λ€μ κ°μ Έμ€λ κ²μ΄ μ’μ΅λλ€.
@akiuni μ΄μ λν νλ³΄κ° μμ΅λκΉ? https://github.com/fabric/fabric/issues/1912#issuecomment -464652728
@akiuni μ΄μ λν νλ³΄κ° μμ΅λκΉ? #1912(λκΈ)
μλ νμΈμ..κ·Έλ κ² μκ°μ΄ μλμ.. μμ§ν νμΈ λ°©λ²μ μκ² λλ° μ΄λ»κ² μ λ° μμ μ μΆμ ν΄μΌν μ§ λͺ¨λ₯΄κ² λ€μ...
μ΄κ²μ Fabricμ μ΅λν 빨리 λ³ν©ν΄μΌ ν©λλ€.
mm v 2.5.0μ νμ¬ μ½λλ₯Ό λ³΄κ³ μμ΅λλ€.
https://github.com/fabric/fabric/blob/2.5.0/fabric/group.py#L127 μ΄ μ½λλ λ μ΄μ μ΅μ μ½λκ° μλλ©° μμ±μκ° μ΄λ₯Ό ꡬννλ κ°μ₯ μ’μ λ°©λ²μ λν΄ μκ°νκ³ μμμ μ μ μμ΅λλ€. λν PRμ΄ μμΌλ©΄ μ½λκ° λμ
νλ λ³κ²½ μ¬νμ λ
Όμν νλ«νΌμ΄ μμ΅λλ€. μ΄κ±° λ³΄κ³ μλλ° νμ΄μ¬ μ λ¬Έ μ½λλ μλμ§λ§ ν보μ©μΌλ‘ νλ² ν΄λ³Όκ»μ
μ¬κΈ°μμ ν보: https://github.com/fabric/fabric/pull/2052
μλ νμΈμ, μ λ git developmentpemenμ μ΅μνμ§ μμ΅λλ€(PRμ μ μκ² μ΄μν λ¨μ΄μ λλ€). μ κ° λμΈ μ μμΌλ©΄ μΈμ λ μ§ λ§μν΄ μ£Όμμμ€.
μλ
νμΈμ @akiuni
PRμ λμ΄μ€κΈ° μμ²(Pull Request)μ μ½μμ΄λ©°, λ³κ²½νλ €λ κ²½μ° λμ΄μ€κΈ° μμ²μ ν΅ν΄ ν΄λΉ λ³κ²½ μ¬νμ μμ€ μ½λλ‘ κ°μ Έμ¨ λ€μ μΉμΈλ λκΉμ§ λνλ‘ μ²λ¦¬λκ³ κ²ν λ μ μμμ μλ―Έν©λλ€. μΉμΈλλ©΄ μ¬κΈ°μμ μνν κ²μ²λΌ PRμ΄ λμ
ν λ³κ²½ μ¬νμ 컀λ°μΌλ‘ λ€μ μΆμ ν μ μμ΅λλ€. #2052
μ리ν νΈλ¦μ https://patch-diff.githubusercontent.com/raw/fabric/fabric/pull/2052.patch μ κ°μ΄ pull μμ²(PR)μ ".patch"λ₯Ό μΆκ°νλ κ²μ
λλ€. κ·Έλ¬λ©΄ diffκ° μ 곡λ©λλ€. λ³κ²½ μ¬ν(μ΄μ μ견μμ μ 곡ν λλ‘)μ΄μ§λ§ μ΄μ μ΄μ μ μμμ μΈκΈν λλ‘ λν/κ²ν /λ³κ²½ μ¬νμ λ¨μΌ μ§μ μ
λλ€. νμ§λ§ μ΄μ λν ν¨μΉλ₯Ό μ²μμΌλ‘ μ μ©ν΄ μ£Όμ
μ κ°μ¬ν©λλ€. λ΄κ° PRμ λ§λλ λμ
Sudoλ μ§κΈ κ·Έλ£Ήμ μΆκ°λκ³ μμ΅λλ€! #1999 μ°Έμ‘°
κ°μ₯ μ μ©ν λκΈ
μλ νμΈμ..κ·Έλ κ² μκ°μ΄ μλμ.. μμ§ν νμΈ λ°©λ²μ μκ² λλ° μ΄λ»κ² μ λ° μμ μ μΆμ ν΄μΌν μ§ λͺ¨λ₯΄κ² λ€μ...