vagrant ansible sys.stdout.enconding is None

Estoy desplegando una máquina con vagrant y ansible en la que use vars_promt, mi intención es hacer una serie de preguntas previas al despliegue de una máquina y llevaba un buen rato pegándome con un error, concretamente este :

Traceback (most recent call last):
  File "/usr/bin/ansible-playbook", line 309, in <module>
    sys.exit(main(sys.argv[1:]))
  File "/usr/bin/ansible-playbook", line 249, in main
    pb.run()
  File "/usr/lib/python2.7/dist-packages/ansible/playbook/__init__.py", line 305, in run
    play = Play(self, play_ds, play_basedir, vault_password=self.vault_password)
  File "/usr/lib/python2.7/dist-packages/ansible/playbook/play.py", line 65, in __init__
    self.vars             = self._get_vars()
  File "/usr/lib/python2.7/dist-packages/ansible/playbook/play.py", line 672, in _get_vars
    vname, private, prompt, encrypt, confirm, salt_size, salt, default
  File "/usr/lib/python2.7/dist-packages/ansible/callbacks.py", line 662, in on_vars_prompt
    result = prompt(msg, private)
  File "/usr/lib/python2.7/dist-packages/ansible/callbacks.py", line 648, in prompt
    msg = prompt.encode(sys.stdout.encoding)
TypeError: encode() argument 1 must be string, not None
Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.

Leer el traceback de python al principio es un poco ruidoso, pero hay que leer detenidamente la traza y veremos claramente el problema. Yo al principio no lo he hecho y eso me ha llevado a dedicarle más tiempo 😀

Existe un problema documentado en ansible que genera este error cuando no es capaz de generar la codificación de salida, no se si es exactamente un bug de python2.x o es de ansible, por que en algunos casos recomiendan directamente migrar a python3 aunque ansible está desarrollado con python2.7.

Si queréis entreneros veréis que efectivamente sys.stdout.enconding devuelve None y de ahí la execepción que genera ansible.

Ahora bien,¿ como lo solucionamos ? forzando un tipo de codificacion con la variable de entorno PYTHONIOENCODING

export PYTHONIOENCODING='utf-8'

De esta manera ya podemos lanzar el provisionamiento de la máquina

vagrant provision

Esto está bien, pero no es práctico, ya que lo que queremos es olvidarnos de tener que hacer cosas manualmente, por eso automatizamos. Pues bien, hay una forma de agregar esto, y dejar nuestro Vagrantfile más o menos así:

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|

  config.vm.box = "debian/jessie64"

  #Force sys.stdout.encoding to utf8
  ENV['PYTHONIOENCODING'] = "utf-8"

  config.vm.provision "ansible" do |ansible|
      ansible.verbose = "v"
      ansible.playbook = "ansible/playbook.yml"
  end

end

Evidentemente esto es un fichero muy sencillo, lo importante es declarar la variable de entorno

 

  ENV['PYTHONIOENCODING'] = "utf-8"

Este fallo está documentado en una issue de github https://github.com/ansible/ansible/issues/8644 aunque su resolución está prevista en una versión ‘mayor’ con lo que supongo que estará corregido en la rama 1.8.x mientras que en Debian stable estamos en la versión 1.7.2 a diciembre de 2015. Otra alternativa sería crear un virtual environment de python e instalar la versión que queramos, no lo he probado pero seguro que es posible.

 

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.