kubectl cp in kubernetes python client - python

I have been trying to convert kubectl cp command to it's equivalent kubernetes python client program. I have following code for that:
from kubernetes import client, config
from kubernetes.stream import stream
import tarfile
from tempfile import TemporaryFile
# create an instance of the API class
config.load_kube_config()
api_instance = client.CoreV1Api()
exec_command = ['tar', 'xvf', '-', '-C', '/']
resp = stream(api_instance.connect_get_namespaced_pod_exec, "nginx-deployment-6bb6554bf-9sdtr", 'default',
command=exec_command,
stderr=True, stdin=True,
stdout=True, tty=False,
_preload_content=False)
source_file = '/tmp/abc.txt'
with TemporaryFile() as tar_buffer:
with tarfile.open(fileobj=tar_buffer, mode='w') as tar:
tar.add(source_file)
tar_buffer.seek(0)
commands = []
commands.append(tar_buffer.read())
while resp.is_open():
resp.update(timeout=1)
if resp.peek_stdout():
print("STDOUT: %s" % resp.read_stdout())
if resp.peek_stderr():
print("STDERR: %s" % resp.read_stderr())
if commands:
c = commands.pop(0)
# print("Running command... %s\n" % c)
resp.write_stdin(c)
else:
break
resp.close()
The above code gives me following error:
/home/velotio/venv/bin/python /home/velotio/PycharmProjects/k8sClient/testing.py
Traceback (most recent call last):
File "/home/velotio/PycharmProjects/k8sClient/testing.py", line 38, in <module>
resp.write_stdin(c)
File "/usr/local/lib/python3.6/site-packages/kubernetes/stream/ws_client.py", line 160, in write_stdin
self.write_channel(STDIN_CHANNEL, data)
File "/usr/local/lib/python3.6/site-packages/kubernetes/stream/ws_client.py", line 114, in write_channel
self.sock.send(chr(channel) + data)
TypeError: must be str, not bytes
I am using Python 3.6.3 and on kubernetes 1.13 version.

You have to convert bytes back to string which is what write_stdin method is expecting to get.
for example:
resp.write_stdin(c.decode())
Another example:
# Array with two byte objects
In [1]: a = [b'1234', b'3455']
# Pop one of them
In [2]: c = a.pop(0)
# it is of byte type
In [3]: c
Out[3]: b'1234'
# wrapping in str won't help if you don't provide decoding
In [4]: str(c)
Out[4]: "b'1234'"
# With decoding
In [5]: str(c, 'utf-8')
Out[5]: '1234'
# Or simply use the decode str method
In [6]: c.decode()
Out[6]: '1234'
More on byte to string conversion here:
Convert bytes to a string?

Related

TypeError in Python3.10 script

I am trying to do network automation task using python but ran with type error while running the below given script.
I AM STUCK AT SAME KIND OF ERROR, CAN YOU GUYS PLEASE HELP ME OUT HOW TO FIX THIS ?*
durai#durai-virtual-machine:~/Network Automation$ python3 session_details.py
devices list: ['1.1.1.1', '2.2.2.2', '6.6.6.6', '7.7.7.7', '', '']
establishing telnet session: 1.1.1.1 cisco cisco
--- connected to: 1.1.1.1
--- getting version information
Traceback (most recent call last):
File "/home/durai/Network Automation/session_details.py", line 82, in <module>
device_version = get_version_info(session)
File "/home/durai/Network Automation/session_details.py", line 65, in get_version_info
version_output_parts = version_output_lines[1].split(',')
**TypeError: a bytes-like object is required, not 'str'**
durai#durai-virtual-machine:~/Network Automation$
THE BELOW IS THE BLOCK OF CODE WHERE I AM GETTING ERROR !
#-----------------------------------------------------------------------
def get_version_info(session):
print ('--- getting version information')
session.sendline('show version | include Version')
result = session.expect(['>', pexpect.TIMEOUT])
# Extract the 'version' part of the output
version_output_lines = session.before.splitlines()
version_output_parts = version_output_lines[1].split(',')
version = version_output_parts[2].strip()
print ('--- got version: ', version)
return version
#-----------------------------------------------------------------------
FULL CODE FOR YOUR REFERENCE:
#!/usr/bin/python
import re
import pexpect
#-----------------------------------------------------------------------
def get_devices_list():
devices_list = []
file = open('devices', 'r')
for line in file:
devices_list.append( line.rstrip() )
file.close()
print ('devices list:', devices_list)
return devices_list
#-----------------------------------------------------------------------
def connect(ip_address, username, password):
print ('establishing telnet session:', ip_address, username, password)
telnet_command = 'telnet ' + ip_address
# Connect via telnet to device
session = pexpect.spawn('telnet ' + ip_address, timeout=20)
result = session.expect(['Username:', pexpect.TIMEOUT])
# Check for error, if so then print error and exit
if result != 0:
print ('!!! TELNET failed creating session for: ', ip_address)
exit()
# Enter the username, expect password prompt afterwards
session.sendline(username)
result = session.expect(['Password:', pexpect.TIMEOUT])
# Check for error, if so then print error and exit
if result != 0:
print ('!!! Username failed: ', username)
exit()
session.sendline(password)
result = session.expect(['>', pexpect.TIMEOUT])
# Check for error, if so then print error and exit
if result != 0:
print ('!!! Password failed: ', password)
exit()
print ('--- connected to: ', ip_address)
return session
#-----------------------------------------------------------------------
def get_version_info(session):
print ('--- getting version information')
session.sendline('show version | include Version')
result = session.expect(['>', pexpect.TIMEOUT])
# Extract the 'version' part of the output
version_output_lines = session.before.splitlines()
version_output_parts = version_output_lines[1].split(',')
version = version_output_parts[2].strip()
print ('--- got version: ', version)
return version
#-----------------------------------------------------------------------
devices_list = get_devices_list() # Get list of devices
version_file_out = open('version-info-out', 'w')
# Loop through all the devices in the devices list
for ip_address in devices_list:
# Connect to the device via CLI and get version information
session = connect(ip_address, 'cisco', 'cisco')
device_version = get_version_info(session)
session.close() # Close the session
version_file_out.write('IP: '+ip_address+' Version: '+device_version+'\n')
# Done with all devices and writing the file, so close
version_file_out.close()
Python has two different kinds of strings. Normal strings are Unicode, where the individual characters are several bytes long, to handle Unicode characters. Many activities (like networking) need to use byte strings, which are written b"abc".
That's the problem here. The pexpect module is returning a byte string. So, in this line:
version_output_parts = version_output_lines[1].split(',')
version_output_parts is a byte string, but ',' is a Unicode string, and you can't mix them. So, you can either keep it bytes and do this:
version_output_parts = version_output_lines[1].split(b',')
or you can convert it to a Unicode string:
version_output_parts = version_output_parts.decode('utf-8')
version_output_parts = version_output_lines[1].split(b',')
It depends on how much you need to do with the parts.
It's the part where you extract the version that is bugged.
Try using print statements as demonstrated below to check the data types of your variables at each step.
This error suggests that you are using a method that is not available for the given data type e.g. calling a string method on an array or so on.
def get_version_info(session):
print ('--- getting version information')
session.sendline('show version | include Version')
result = session.expect(['>', pexpect.TIMEOUT])
# Extract the 'version' part of the output
version_output_lines = session.before.splitlines()
# print(version_output_lines)
version_output_parts = version_output_lines[1].split(',')
# print(version_output_parts)
version = version_output_parts[2].strip()
# print(version)
print ('--- got version: ', version)
return version

How to save <class "ctypes.c_char_Array> with pickle

I'm doing research on palmprint recognition. for that I use the edcc library for the introduction of the palmprint. but i have problem in saving the encoding result from palm. I want to save the encoding result into a file, but I get an error like below
Traceback (most recent call last):
File "/home/pi/Coba/PalmDetection/PalmRecognition.py", line 18, in <module>
pickle.dump(one_palmprint_code, config_dictionary_file)
_pickle.PicklingError: Can't pickle <class 'ctypes.c_char_Array_849'>: attribute lookup c_char_Array_849 on ctypes failed
My code like this :
import os
import edcc
import cv2
import pickle
TEST_PALMPRINT_DATA_DIR = "/home/pi/Coba/PalmDetection/Data"
TEST_A_01_PALMPRINT_IMAGE = os.path.join(TEST_PALMPRINT_DATA_DIR, "Palm1.jpeg")
#TEST_A_02_PALMPRINT_IMAGE = os.path.join(TEST_PALMPRINT_DATA_DIR, "a_02.bmp")
TEST_B_01_PALMPRINT_IMAGE = os.path.join(TEST_PALMPRINT_DATA_DIR, "palme.jpeg")
#TEST_B_02_PALMPRINT_IMAGE = os.path.join(TEST_PALMPRINT_DATA_DIR, "b_02.bmp")
if __name__ == "__main__":
config = edcc.EncoderConfig(29, 5, 5, 10)
encoder = edcc.create_encoder(config)
one_palmprint_code = encoder.encode_using_file(TEST_A_01_PALMPRINT_IMAGE)
with open('encode.encode', 'wb') as config_dictionary_file:
pickle.dump(one_palmprint_code, config_dictionary_file)
another_palmprint_code = encoder.encode_using_file(TEST_B_01_PALMPRINT_IMAGE)
similarity_score = one_palmprint_code.compare_to(another_palmprint_code)
print(
"{} <-> {} similarity score:{}".format(
TEST_A_01_PALMPRINT_IMAGE, TEST_B_01_PALMPRINT_IMAGE, similarity_score
)
)
What should i do?
The edcc module must use ctypes internally, but really should hide that fact instead of returning a ctypes-wrapped object. A ctypes.c_char_Array_849 is just a C-compatible wrapper around an array of bytes. You can access the equivalent Python bytes object via the .raw property (what edcc should return instead) and write that to the file:
import ctypes
import pickle
one_palmprint_code = (ctypes.c_char * 849)()
with open('encode.encode', 'wb') as config_dictionary_file:
#pickle.dump(one_palmprint_code, config_dictionary_file) # reproduces error
config_dictionary_file.write(one_palmprint_code.raw)

PyCryptoDome Version 3.6.6 raises an TypeError: Object type <class 'str'> cannot be passed to C code

A couple o' years ago i created a cryptograph module in python with PyCryptoDome Version 2.6.1.
Now with the new PyCryptoDome Version 3.6.6 and Python 3.6 i got a TypeError with the same code. The error is thrown in the "_init_crypter" - method:
File "/usr/local/lib/python3.6/dist-packages/Crypto/Cipher/AES.py", line 206, in new
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/Crypto/Cipher/__init__.py", line 79, in _create_cipher
return modes[mode](factory, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/Crypto/Cipher/_mode_cbc.py", line 253, in _create_cbc_cipher
return CbcMode(cipher_state, iv)
File "/usr/local/lib/python3.6/dist-packages/Crypto/Cipher/_mode_cbc.py", line 96, in __init__
c_uint8_ptr(iv),
File "/usr/local/lib/python3.6/dist-packages/Crypto/Util/_raw_api.py", line 196, in c_uint8_ptr
raise TypeError("Object type %s cannot be passed to C code" % type(data))
TypeError: Object type <class 'str'> cannot be passed to C code
How can i fix this!
My Code for both versions:
import os
from base64 import b64encode, b64decode
import hashlib
from Crypto.Cipher import Blowfish, AES
class Crypt:
fileextension = ".enc"
def __init__(self, crypter, key="", encoding="utf-8"):
self._mode = -1
self._encoding = encoding
self._crypter = Blowfish
self._blocksize = 8
self._key_32byte = ""
self._cryptographer = None
self.set_crypter(crypter)
if key:
self.set_key(key)
def _init_crypter(self):
# self._key_32byte <- set in set_key-method
# self._mode = AES.MODE_CBC <- set in set_crypter-method
# self._blocksize = 16 <- set in set_crypter-method
self._cryptographer = self._crypter.new(
self._key_32byte,
self._mode,
IV=self._blocksize * '\x00'
)
# and further code ...
The key and IV parameter must be a binary type (bytes) and not a text type (str).
If you're loading your key from a file, be sure to open it in binary mode:
with open('keyfile', 'rb') as f:
...
If your key is a literal in code, make sure it is a binary literal:
key = b'badbadbadkey'
And last, to construct your IV parameter, it must be a sequence of bytes.
For example:
>>> Blowfish.new(b'badbadbadkey', 2, IV=8 * b'\x00')
<Crypto.Cipher._mode_cbc.CbcMode object at 0x7f434187b8d0>
Ok - after hours i got it! Only one letter solves the problem:
'\x00' must be b'\x00':
def _init_crypter(self):
self._cryptographer = self._crypter.new(
self._key_32byte,
self._mode,
IV=self._blocksize * b'\x00'
)

decode binary from xmlrpc python

I'm new to python and xml-rpc , and I'm stuck with decoding binary data coming from a public service :
the service request response with this code is :
from xmlrpc.client import Server
import xmlrpc.client
from pprint import pprint
DEV_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'
logFile = open('stat.txt', 'w')
s1 = Server('http://muovi.roma.it/ws/xml/autenticazione/1')
s2 = Server('http://muovi.roma.it/ws/xml/paline/7')
token = s1.autenticazione.Accedi(DEV_KEY, '')
res = s2.paline.GetStatPassaggi(token)
pprint(res, logFile)
response :
{'id_richiesta': '257a369dbf46e41ba275f8c821c7e1e0',
'risposta': {'periodi_aggregazione': <xmlrpc.client.Binary object at 0x0000027B7D6E2588>,
'tempi_attesa_percorsi': <xmlrpc.client.Binary object at 0x0000027B7D9276D8>}}
I need to decode these two binary objects , and I'm stuck with this code :
from xmlrpc.client import Server
import xmlrpc.client
from pprint import pprint
DEV_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxx'
logFile = open('stat.txt', 'w')
s1 = Server('http://muovi.roma.it/ws/xml/autenticazione/1')
s2 = Server('http://muovi.roma.it/ws/xml/paline/7')
token = s1.autenticazione.Accedi(DEV_KEY, '')
res = s2.paline.GetStatPassaggi(token)
dat = xmlrpc.client.Binary(res)
out = xmlrpc.client.Binary.decode(dat)
pprint(out, logFile)
that ends in :
Traceback (most recent call last): File "stat.py", line 18, in
dat = xmlrpc.client.Binary(res) File "C:\Users\Leonardo\AppData\Local\Programs\Python\Python35\lib\xmlrpc\client.py",
line 389, in init
data.class.name) TypeError: expected bytes or bytearray, not dict
The only doc I found for xmlrpc.client is the one at docs.python.org , but I can't figure out how I could decode these binaries
If the content of res variable (what you get from the 2nd (s2) server) is the response you pasted into the question, then you should modify the last 3 lines of your 2nd snippet to (as you already have 2 Binary objects in the res dictionary):
# ... Existing code
res = s2.paline.GetStatPassaggi(token)
answer = res.get("risposta", dict())
aggregation_periods = answer.get("periodi_aggregazione", xmlrpc.client.Binary())
timeout_paths = answer.get("tempi_attesa_percorsi", xmlrpc.client.Binary())
print(aggregation_periods.data)
print(timeout_paths.data)
Notes:
According to [Python.Docs]: xmlrpc.client - Binary Objects (emphasis is mine):
Binary objects have the following methods, supported mainly for internal use by the marshalling/unmarshalling code:
I wasn't able to connect (and this test the solution), since DEV_KEY is (obviously) fake

Python 3.5 BytesIO error

I am making a project all in python 2.7 but it started to give some errors to me on the final parts since the documentation is in python 3.5. So i am changing everything to python 3.5, but it is giving me a error because of bytesIO. Can you help me to understand why, and what should i do? The error is coming from def repr on string_dinamica.write('P3\n'). I left all the code in case that it´s needed. Thanks for the help. NOTE: Just to confirm this works on python 2.7 but not in 3.5
from io import BytesIO
from cor_rgb_42347 import CorRGB
class Imagem:
def __init__(self, numero_linhas, numero_colunas):
self.numero_linhas = numero_linhas
self.numero_colunas = numero_colunas
self.linhas = []
for n in range(numero_linhas):
linha = []
for m in range(numero_colunas):
linha.append(CorRGB(0.0, 0.0, 0.0))
self.linhas.append(linha)
def __repr__(self):
string_dinamica = BytesIO()
string_dinamica.write('P3\n')
string_dinamica.write("#mcg#leim#isel 2015/16\n")
string_dinamica.write(str(self.numero_colunas) + " " \
+ str(self.numero_linhas) + "\n")
string_dinamica.write("255\n")
for linha in range(self.numero_linhas):
for coluna in range(self.numero_colunas):
string_dinamica.write(str(self.linhas[linha][coluna])+ " ")
string_dinamica.write("\n")
resultado = string_dinamica.getvalue()
string_dinamica.close()
return resultado
def set_cor(self, linha, coluna, cor_rgb):
"""Permite especificar a cor RGB do pixel na linha "linha",
coluna "coluna".
"""
self.linhas[linha-1][coluna-1] = cor_rgb
def get_cor(self, linha, coluna):
"""Permite obter a cor RGB do pixel na linha "linha",
coluna "coluna".
"""
return self.linhas[linha-1][coluna-1]
def guardar_como_ppm(self, nome_ficheiro):
"""Permite guardar a imagem em formato PPM ASCII num ficheiro.
"""
ficheiro = open(nome_ficheiro, 'w')
ficheiro.write(str(self))
ficheiro.close()
if __name__ == "__main__":
imagem1 = Imagem(5,5)
print(imagem1)
Traceback (most recent call last):
File "C:\Users\Utilizador\Desktop\Projectos Finais\Projecto_42347\imagem_42347.py", line 60, in <module>
print(imagem1)
File "C:\Users\Utilizador\Desktop\Projectos Finais\Projecto_42347\imagem_42347.py", line 19, in __repr__
string_dinamica.write('P3\n')
TypeError: a bytes-like object is required, not 'str'
For Python 3, just change BytesIO to StringIO. Python 3 strings are Unicode strings instead of byte strings, and __repr__ should return a Unicode string in Python 3.
If you try to return a bytes object like some other answers suggest, you will get:
TypeError: __repr__ returned non-string (type bytes)
As I mentioned on my comment, BytesIO requires byte-like object.
Demo:
>>> from io import BytesIO
>>>
>>> b = BytesIO()
>>>
>>> b.write('TEST\n')
Traceback (most recent call last):
File "<pyshell#97>", line 1, in <module>
b.write('TEST\n')
TypeError: 'str' does not support the buffer interface
>>>
>>>
>>> b.write(b'TEST\n')
5
>>> v = b.getbuffer()
>>>
>>> v[2:4]=b'56'
>>>
>>> b.getvalue()
b'TE56\n'
So add to the beginning of your the param. in you pass to write method, b(for binary).

Categories

Resources