+
+ def ExecuteCommandInPod(self, pod, cmd, strip_newlines=True, namespace=None):
+ # near as i can tell, the python k8s client doesn't implement
+ # 'kubectl exec'. this is near enough for our purposes.
+ # 'cmd' is an argv list.
+ channels={1: 'stdout', 2: 'stderr', 3: 'k8s'}
+ output={'stdout': [], 'stderr': [], 'k8s': []}
+ path='/api/v1/namespaces/%s/pods/%s/exec?%s&stdin=false&stderr=true&stdout=true&tty=false' % \
+ (namespace or self._ns, pod, urllib.parse.urlencode({'command': cmd}, doseq=True))
+ # we could probably cache and reuse the sslcontext, but meh, we're not
+ # after performance here.
+ ctx=ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+ c = client.Configuration()
+
+ async def ExecCoroutine():
+ # base64.channel.k8s.io is also a valid subprotocol, but i don't see any
+ # reason to support it.
+ async with websockets.connect(uri,\
+ ssl=ctx,\
+ subprotocols=["channel.k8s.io"],\
+ extra_headers=c.api_key) as ws:
+ async for message in ws:
+ if message[0] in channels and (not strip_newlines or len(message) > 1):
+ # we probably should throw up if we get an unrecognized channel, but
+ # i really don't want to be bothered with asyncio exception handling
+ # for that vanishingly improbable case.
+ output[channels[message[0]]].extend(message[1:-1].decode('utf-8').split('\n'))
+
+ ctx.load_verify_locations(c.ssl_ca_cert)
+ if(c.cert_file and c.key_file):
+ ctx.load_cert_chain(c.cert_file, c.key_file)
+ uri = 'wss://%s%s' % (c.host.lstrip('https://'), path)
+
+ asyncio.get_event_loop().run_until_complete(ExecCoroutine())
+
+ return(output)