2017-08-15 5 views
2

J'ai un docker-compose.yml assez standard et j'ai besoin de modifier le mot de passe de la base de données par programme.Édition docker-compose.yml avec PyYAML

Depuis son fichier YAML, j'ai pensé qu'il serait simple d'éditer et de vider le contenu. Jusqu'ici, j'ai essayé le PYYAML et il ne fait que gâcher le fichier docker-composer et je ne sais pas pourquoi.

Chargement et vidage du même contenu, cela casse la structure.

Contenu du docker-compose.yml:

version: '2' 
services: 
    web: 
    container_name: xxx 
    ports: 
    - "80:80" 
    volumes: 
     - .:/xxx 
    depends_on: 
     - mysql 
    build: . 
    mysql: 
    ports: 
    - "32768:32768" 
    - "3306:3306" 
    container_name: xxx-mysql 
    restart: always 
    image: mariadb:latest 
    environment: 
     MYSQL_ROOT_PASSWORD: 'thiswillbechangeonsetupscript' 
     MYSQL_DATABASE: 'xxxdb' 
    volumes: 
    - ./database:/var/lib/mysql 
    ports: 
     - "3306:3306" 

Voici comment je charge le dumping et le contenu:

import yaml 

with open("docker-compose.yml", 'r') as ymlfile: 
    docker_config = yaml.load(ymlfile) 

with open("docker-compose.yml", 'w') as newconf: 
    yaml.dump(docker_config, newconf) 

Et voici comment le fichier est enregistré.

services: 
    mysql: 
    container_name: xxx-mysql 
    environment: {MYSQL_DATABASE: xxxdb, MYSQL_ROOT_PASSWORD: thiswillbechangeonsetupscript} 
    image: mariadb:latest 
    ports: ['3306:3306'] 
    restart: always 
    volumes: ['./database:/var/lib/mysql'] 
    web: 
    build: . 
    container_name: xxx 
    depends_on: [mysql] 
    ports: ['80:80'] 
    volumes: ['.:/xxx'] 
version: '2' 

Y a-t-il une meilleure façon de procéder ?! Qu'est-ce qui me manque?

Répondre

1

Vous devez ajouter default_flow_style=False lorsque vous écrivez le YAML:

import yaml 

with open("docker-compose.yml", 'r') as ymlfile: 
    docker_config = yaml.load(ymlfile) 

with open("docker-compose_new.yml", 'w') as newconf: 
    yaml.dump(docker_config, newconf, default_flow_style=False) 

vous obtiendrez ce qui suit comme sortie qui, à l'exception en utilisant l'ordre alphabétique pour écrire les lignes, est similaire à votre entrée:

services: 
    mysql: 
    container_name: xxx-mysql 
    environment: 
     MYSQL_DATABASE: xxxdb 
     MYSQL_ROOT_PASSWORD: thiswillbechangeonsetupscript 
    image: mariadb:latest 
    ports: 
    - 3306:3306 
    restart: always 
    volumes: 
    - ./database:/var/lib/mysql 
    web: 
    build: . 
    container_name: xxx 
    depends_on: 
    - mysql 
    ports: 
    - 80:80 
    volumes: 
    - .:/xxx 
version: '2' 

Veuillez noter que, dans votre docker-compose.yaml d'origine, vous déclarez la variable ports deux fois, de sorte que yaml parser considère uniquement la dernière variable. Pour résoudre ce problème, supprimez les lignes suivantes:

ports: 
    - "3306:3306" 

Ensuite, l'exécution de l'opération d'écriture comme expliqué ci-dessus donne la ouput suivante:

services: 
    mysql: 
    container_name: xxx-mysql 
    environment: 
     MYSQL_DATABASE: xxxdb 
     MYSQL_ROOT_PASSWORD: thiswillbechangeonsetupscript 
    image: mariadb:latest 
    ports: 
    - 32768:32768 
    - 3306:3306 
    restart: always 
    volumes: 
    - ./database:/var/lib/mysql 
    web: 
    build: . 
    container_name: xxx 
    depends_on: 
    - mysql 
    ports: 
    - 80:80 
    volumes: 
    - .:/xxx 
version: '2' 
+0

Il est similaire, mais pas identique. Le mappage de port "32768: 32768" est manquant dans le vidage en raison des clés dupliquées que PyYAML ignore par erreur. – Anthon

+0

Oui. j'ai vu les 2 ports ... merci –

1

Le vidage par défaut pour PyYAML est d'utiliser le style de flux pour les noeuds de feuilles ([....] pour les séquences, {...} pour les correspondances), de sorte que le minimum que vous devez faire est de spécifier yaml.dump(....., default_flow_style=False)

Ensuite, les spécifications YAML indiquent que l'ordre des clés est pas garantie, et ce que vous voir est que PyYAML les dumps dans l'ordre trié.

Je peux recommander d'utiliser ruamel.yaml (avertissement: je suis l'auteur de ce paquet), qui avait pour objectif spécifique de permettre ce genre de déclenchement avec un minimum, des changements par rapport à l'entrée, souvent pas du tout. Y compris la commande clé, flux vs style bloc, citations sur les chaînes etc.

Il y a une autre raison d'utiliser ruamel.yaml: si vous exécutez ce programme sur votre entrée:

import sys 
import ruamel.yaml 

yaml = ruamel.yaml.YAML() 
yaml.preserve_quotes = True 
yaml.indent(sequence=3, offset=1) 

with open("docker-compose.yml", 'r') as ymlfile: 
    data = yaml.load(ymlfile) 
yaml.dump(data, sys.stdout) 

vous obtiendrez un DuplicateKeyError :

ruamel.yaml.constructor.DuplicateKeyError: while constructing a mapping 
    in "docker-compose.yml", line 13, column 5 
found duplicate key "ports" with value "[]" (original value: "[]") 
    in "docker-compose.yml", line 24, column 5 

car ports se produit deux fois plus important dans la mise en correspondance qui est la valeur de la clé mysql.Ceci n'est pas autorisé selon les spécifications de YAML (l'ancien 1.1 que PyYAML jette et le plus récent 1.2), mais PyYAML dispose silencieusement de la première paire clé-valeur, laissant le port 32768 non mappé.

Après avoir supprimé les deux dernières lignes de votre entrée, la sortie du programme est:

version: '2' 
services: 
    web: 
    container_name: xxx 
    ports: 
    - "80:80" 
    volumes: 
    - .:/xxx 
    depends_on: 
    - mysql 
    build: . 
    mysql: 
    ports: 
    - "32768:32768" 
    - "3306:3306" 
    container_name: xxx-mysql 
    restart: always 
    image: mariadb:latest 
    environment: 
     MYSQL_ROOT_PASSWORD: 'thiswillbechangeonsetupscript' 
     MYSQL_DATABASE: 'xxxdb' 
    volumes: 
    - ./database:/var/lib/mysql 

qui est assez proche, espérons pour votre usage prévu.

S'il vous plaît noter que PyYAML supprimer les citations dans - "80:80", ce qui est bien parce que 80:80 ne peut pas être interprété à tort comme sexagésimal, mais si vous faites quelque chose avec le port 25 en train de changer - 80:80-- 25:25 est très différent lorsque vous utilisez un analyseur YAML 1.1 comme PyYAML (comme docker-compose DOE) de - "25:25" (the former equalling - 1525`)

sur la base de ce que j'ai fait un utilitaire ruamel.dcw, qui utilise cette fonctionnalité pour prétraiter docker compose des fichiers, ce qui permet par défaut pour les variables d'environnement (au cas où ils ne sont pas définies) et quelques autres astuces, écrit un fichier temporaire, puis appelle docker-compose -f tmpfile, vous devriez utiliser une technique similaire , disposer de votre fichier temporaire après la course.