Il comportamento che morde qui è specificato, non accidentale: il Specifica YAML 1.2 definisce come uno scalare non quotato viene risolto in un tipo.
Una volta ho spedito una distribuzione che ha bloccato un servizio alla versione 1.1 Quando il file di configurazione ha detto chiaramente 1.10. non un errore di battitura. Non è un male trovare e sostituire. Il file yaml, che avevo letto quattro volte, diceva questo:
image_tag: 1.10
e il parser ha consegnato il numero al mio script di distribuzione 1.1. perché 1.10 isn't una stringa di versione per YAML - it's a Galleggiante letterale, e i galleggianti non continuano a non continuare a zeri. Dieci diventa un punto-uno. Il file era yaml valido al 100%. Il linter era felice. CI era verde. Il contenitore sbagliato è uscito.
Questa è la cosa che nessuno ti dice sulla convalida dello yaml: "Valido" non è uguale a "corretto". Un controllo sintattico che risponde solo sì/no è rispondere alla domanda facile La domanda difficile - quella che effettivamente si rompe si distribuisce - è In cosa si è trasformato il mio yaml? Poiché YAML non è un formato di configurazione, è un motore di inferenza di tipo che indossa abiti di un formato di configurazione e prende decisioni sui tuoi dati che non gli hai mai chiesto di prendere.
la Condivisore di yam su Toolz.dev risponde a entrambe le domande Ti dice se il documento viene analizzato, e poi ti mostra il risultato analizzato come JSON - la struttura dati effettiva che riceverà il tuo tooling Quella seconda metà è ciò che mi avrebbe salvato. "image_tag": 1.1 Nel riquadro di output è impossibile leggere erroneamente.
tl; dr: Incolla il tuo Yaml nel Condivisore di yam e leggi il Uscita JSON, non solo il segno di spunta verde. Ecco dove si mostra la coercizione di tipo:
1.10→1.1,0123→123, valori non virgoletta diventano silenziosamente numeri, booleani o null. Funziona su JS-YAML (YAML 1.2) interamente nel tuo browser, quindi i segreti di Kubernetes e le credenziali del database non lasciano mai la tua macchina. Cita tutto ciò che deve rimanere una stringa. Se hai bisogno di confrontare il risultato con una configurazione JSON, il Formattatore JSON e JSON DIFF Raccogli da lì.
Cosa controlla effettivamente un validatore YAML?
Due cose diverse, e vale la pena separarle perché falliscono in modo diverso.
Convalida della sintassi chiede: questo testo può essere analizzato? Schede a cui appartengono gli spazi, uno spazio mancante dopo i due punti, uno scalare di blocco il cui corpo non è rientrato, una citazione non chiusa. Questi sono alto fallimenti. Il tuo parser lancia, la tua pipeline diventa rossa, lo risolvi in due minuti. fastidioso, non pericoloso.
ispezione semantica chiede: cosa ha analizzato dentro? È qui che vivono i tranquilli fallimenti. Il documento è valido. La pipeline è verde. Il valore semplicemente non è quello che pensavi di aver scritto. Nessuno lo scopre finché la produzione non si comporta in modo strano, e per allora nessuno sta guardando il file di configurazione, perché il file di configurazione è "fine."
La maggior parte dei controllori YAML online esegue solo il primo Il validatore Toolz.dev fa il primo e poi ti consegna il secondo - il documento analizzato, reso come JSON, proprio accanto al tuo input Prendi l'abitudine di leggere quel riquadro It's la differenza tra & quot; il file è ben formato" e & quot; il file significa ciò che intendevo."
Quali errori di yaml rompono effettivamente le build?
Ecco cosa si presenta davvero, classificato in base a quanto mi è costata la vita. Ogni comportamento al di sotto ho verificato JS-YAM 4, che è il parser che viene eseguito il validatore Toolz.dev e che implementa il YAML 1.2 spec.
1. Schede. Sempre schede.
YAML vieta i caratteri di scheda per il rientro. Non & quot;discourages" - proibisce. Le specifiche sono esplicite e il messaggio di errore è piacevolmente diretto:
tab characters must not be used in indentation
Il motivo per cui ciò continua a accadere è che le schede sono invisibili. Il tuo editor ti mostra un file ben allineato; il parser vede un carattere di controllo. Risolvilo alla fonte: imposta il tuo editor per inserire spazi e attiva "rendering whitespace" per i file yaml. Due spazi per livello, che è la convenzione su cui si è stabilito ogni importante ecosistema di YAML.
2. Chiavi duplicate
database:
host: localhost
port: 5432
host: production-db.example.com
host appare due volte. Cosa succede? Dipende interamente dal tuo parser, che è una frase orribile da scrivere su un formato di configurazione.
JS-Yam getto: duplicated mapping key. Bene. Quello' è il comportamento che desideri, e it' è ciò che ti mostrerà il validatore Toolz.dev. Ma PyYAML - che è ciò su cui siede Ansible, e molti strumenti Python - prende silenziosamente il ultimo valore e va avanti. Nessun avviso. Il tuo host di database è ora qualunque cosa abbia detto l'ultimo duplicato, che in un file lungo che hai fuso male potrebbe essere a trecento righe da dove stai guardando.
Questo è l'unico miglior argomento per eseguire le configurazioni tramite un validatore rigoroso anche quando le tue strumenti di produzione le accettano. un validatore che è più rigoroso THE TURE RUNTIME è un validatore che trova bug.
3. Coercizione del tipo: quella che mi ha preso
YAML deduce i tipi da scalari non virgolettati. È molto fiducioso e spesso è sbagliato sul tuo intento:
| hai scritto | intendevi | YAML 1.2 ti dà |
|---|---|---|
version: 1.10 |
la stringa "1.10" | il galleggiante 1.1 |
pin: 0123 |
la stringa "0123" | l'intero 123 |
port: "8080" |
il numero 8080 | la stringa "8080" |
enabled: true |
booleano | booleano true - corretto |
value: |
Stringa vuota, forse? | null |
value: ~ |
una tilde | null |
la quale 0123 row è il tatuaggio I' d sulle persone Codici postali, PIN, numeri di conto, ID imbottiti a zero: ogni zero iniziale che hai scritto per un motivo viene mangiato Citali.
La regola che non mi ha mai deluso: Se il valore è un identificatore, una versione, un codice o qualsiasi cosa su cui non fai mai aritmetica, mettilo tra virgolette. I conteggi di porte e repliche possono rimanere nudi. tutto ciò che semplicemente aspetto Il numerico dovrebbe essere "quoted".
4. I booleani dipendenti dalla versione (aka il problema della Norvegia)
Questo è veramente famigerato e i dettagli contano più del meme.
per YAML 1.1, il tipo booleano accetta yes, no, on, off, y, n, e le loro maiuscole, oltre a true e false. di sì country: NO - Norvegia's Codice paese ISO - analizza come booleano falsificato. per YAML 1.2, che ha ripulito questo, solo true e false sono booleani; NO è solo la stringa "NO".
che significa lo stesso file significa cose diverse in strumenti diversi:
country: NO
feature_flag: on
- JS-YAML 4 (YAML 1.2 e cosa utilizza questo validatore):
{"country": "NO", "feature_flag": "on"}- corde. - Pyyam (Yaml 1.1):
{"country": False, "feature_flag": True}- booleani.
Stessi byte. dati diversi. Se il tuo CI esegue un linter Python su una configurazione che un servizio di nodo consuma, hai due parser in disaccordo sul tuo file e nessuno dei due è sbagliato.
Questa è anche l'origine delle azioni di GitHub' strano strano: il on: chiave con cui ogni flusso di lavoro inizia è a booleano a un parser yaml 1.1, quindi gli script che i file del flusso di lavoro di lint in Python trovano una chiave chiamata True invece di on. citando ("on":) è legale e lo risolve.
La mossa difensiva è la stessa di prima: Citalo. country: "NO" mezzi "NO" In ogni parser che sia mai esistito.
5. Blocca la rientranza scalare
description: |
This is not indented
la | (letterale) e > Gli scalari a blocchi (piegati) necessitano del loro contenuto rientrato rispetto alla chiave. Il contenuto non rientrato termina immediatamente il blocco e il parser inizia a leggere la tua prosa come chiavi Yaml, che produce messaggi di errore che sembrano non avere nulla a che fare con l'errore vero e proprio.
Vale la pena conoscere gli indicatori di masticazione mentre sei qui: | mantiene una sola nuova riga finale, |- lo spoglia, |+ li tiene tutti. Se stai incorporando una chiave privata o uno script e qualcosa a valle si lamenta di una nuova riga in traino, questa è la tua manopola.
6. Caratteri speciali non quotati
Uno spazio per due punti all'interno di un valore non quotato termina il valore e avvia una nuova chiave. Questo morde in messaggi di errore e URL:
message: Error: file not found # parse error
regex: [a-z]+ # parsed as a LIST, not a string
time: "22:22" # quote it — in YAML 1.1 this was base-60!
[, {, #, &, *, !, |, >, %, @ All'inizio di uno scalare significano tutto qualcosa. Cita Prima, fai domande dopo.
Come posso convalidare YAML su Toolz.dev?
- Apri il Condivisore di yam. Nessun account, nessun caricamento.
- Incolla il tuo documento. Un file di valori Helm, una composizione docker, un flusso di lavoro - qualunque cosa' si comporta male.
- Premi convalida. Gli errori tornano con l'esatto linea e colonna dal parser, più la stringa di ragione del parser (
bad indentation of a mapping entry,duplicated mapping key, e così via). - Leggere il riquadro di uscita JSON. Questo è il passo che le persone saltano ed è quello che conta. Scansionalo per i valori a cui tieni. è
image_tagUna stringa o un numero? Quella porta è citata? È diventato un valore vuotonull? - Risolvi, riconvalida. Gli errori possono mascherarsi a vicenda: il parser si ferma al primo da cui può't recuperare, quindi aggiustarne uno a volte ne rivela altri due. Quello' è normale, non è un segno che le cose stanno peggiorando.
una limitazione nota, dichiarata chiaramente
Il validatore attualmente analizza a singolo documento Yaml. Se incolli un file multi-documento - diversi manifesti Kubernetes separati da --- in un file, che è uno schema estremamente comune, riporterà:
expected a single document in the stream, but found more
Questo è il parser corretto, non il file che viene rotto. La soluzione alternativa oggi è convalidare ogni documento separatamente: incollare tutto al di sopra del ---, controllalo, quindi incolla il pezzo successivo. Il supporto multidocumento è nella mia lista proprio perché gli utenti di Kubernetes lo colpiscono immediatamente e preferirei parlarti del divario piuttosto che farti scoprire a metà incidente.
YAML vs JSON: Quando dovrei usare quale?
YAML 1.2 è un superset rigoroso di JSON: ogni documento JSON valido è YAML valido, motivo per cui il validatore può fornirti l'output JSON. Ma i formati hanno personalità opposte.
| igname | json | |
|---|---|---|
| struttura definita da | Rientro (spazi bianchi) | Bretelle e parentesi (esplicito) |
| commentario | si (#) |
no |
| Tipo Descrizione | Aggressivo - deduce numeri, booleani, null, date | Nessuno: le virgolette significano stringa, sempre |
| Documento multiplo | si (--- separatore) |
no |
| riutilizzazione | ancore (&), alias (*), unione chiavi (<<) |
nessuno |
| Modalità di fallimento | Interpretazione errata silenziosa | Errore di analisi ad alto volume |
| Il migliore a | File Gli esseri umani scrivono e modificano | Si scambiano macchine dati |
Il commercio è reale e va in entrambe le direzioni. YAML's leggibilità e commenti sono esattamente il motivo per cui la configurazione dell'infrastruttura vive lì: nessuno vuole mantenere un manifesto Kubernetes di 400 righe in JSON senza commenti. JSON's totale mancanza di intelligenza è esattamente il motivo per cui le API lo utilizzano: "1.10" è "1.10" E non c'è niente da discutere.
la mia regola: YAML per i file che le persone modificano, JSON per macchine dati passano. E quando un file YAML viene generato da un programma anziché digitato da una persona, quel & #39;s un odore - configurazione generata dalla macchina non ottiene nulla di YAML's benefici e tutti i suoi rischi.
Se ti muovi tra i due, il Convertitore JSON a YAML gestisce la trasformazione e il Formattatore JSON Riordina l'altro lato.
Cosa sono le ancore e gli alias e dovrei usarli?
Yaml ti consente di definire un blocco una volta e riutilizzarlo. ancorare con &, riferimento con *, unisciti in una mappa con <<:
defaults: &defaults
adapter: postgres
host: localhost
port: 5432
development:
<<: *defaults
database: myapp_dev
test:
<<: *defaults
database: myapp_test
ambo development e test esci con l'adattatore, l'host e la porta uniti in It' è davvero utile e js-yaml lo gestisce: ho verificato che l'unione si risolve correttamente.
Due avvertimenti, però.
prima, Le chiavi di unione sono un'estensione YAML 1.1, non fa parte del core YAML 1.2 Il supporto è diffuso ma non universale, e - quello che cattura le persone - GitHub Actions non li supporta. Gli ancoraggi in un file del flusso di lavoro non faranno quello che vuoi. Controlla il tuo consumatore prima di appoggiarti a questo.
In secondo luogo, gli ancoraggi rendono un file più difficile da leggere per la persona successiva, e in configurazione la persona successiva di solito sei tu alle 2 del mattino. Li uso per blocchi veramente ripetuti e mai per intelligenza.
Mentre siamo sul lato pericoloso di Yaml: il formato supporta tag personalizzati che alcuni parser usano per costruire oggetti arbitrari. yaml.load() era notoriamente sfruttabile in questo modo, ecco perché yaml.safe_load() esiste e perché dovresti usarlo - sempre - su qualsiasi YAML proveniente dall'esterno della tua squadra. js-yaml's load() In v4 è sicuro per impostazione predefinita (non ha mai creato tipi arbitrari), che è una cosa in meno di cui preoccuparsi qui.
Come faccio a smettere di scrivere yaml rotto in primo luogo?
Prevention batte la convalida e la maggior parte è la configurazione dell'editor:
- Due spazi, mai schede. Impostalo per tipo di file in modo da non dimenticare.
- Attiva il rendering degli spazi bianchi per
.yml/.yaml. Se riesci a vedere la scheda, non hai vinto la scheda. - Installare un server di lingua yaml. La convalida dello schema in tempo reale contro gli schemi Kubernetes, GitHub e Docker-Compose rileva un'intera classe di errori che la convalida della sintassi non può: YAM valida con una chiave scritta errata.
- Citazione per impostazione predefinita in caso di dubbio. Il costo di un preventivo non necessario è zero. Il costo di uno mancante è una distribuzione.
- Convalida prima di spingere, non dopo che CI fallisce. Incollare in una scheda del browser richiede otto secondi; una pipeline fallita richiede otto minuti.
- Per Kubernetes, sovrapponi i controlli. La convalida della sintassi cattura la struttura;
kubectl apply --dry-run=clientprende lo schema. Trovano bug diversi e tu vuoi entrambi.
E l'abitudine che ha effettivamente cambiato le cose per me: quando una distribuzione basata sulla configurazione fa qualcosa di inspiegabile, Guarda l'output analizzato prima di guardare qualsiasi altra cosa. non il file. l'output analizzato. Il file è una storia su cosa intendevi. L'output analizzato è ciò che è effettivamente accaduto.
questo è lo stesso istinto che governa tutto nel mio Flusso di lavoro di debug dell'API - leggi i dati, non il codice - e si applica altrettanto bene alle configurazioni quanto alle risposte Se vuoi il tour più ampio di cos'altro vive in quella cassetta degli attrezzi, il Guida agli strumenti di codifica lo copre.
Domande frequenti
Perché il mio yaml viene convalidato ma interrompe la mia distribuzione?
Perché la validità della sintassi e la correttezza semantica sono cose diverse. YAML deduce i tipi da valori non virgolettati, quindi 1.10 diventa il galleggiante 1.1, 0123 diventa l'intero 123, e un valore vuoto diventa null - il tutto in un documento perfettamente valido Leggi l'output JSON analizzato, non solo il risultato di passaggio/fallimento, e cita qualsiasi valore che deve rimanere una stringa.
Perché YAML trasforma il mio numero di versione in un numero diverso?
1.10 è un float letterale a yaml e i float non preservano gli zeri finali, quindi si risolve 1.1. Qualsiasi versione, numero di build o identificatore imbottito zero deve essere citato: version: "1.10". Questo è uno degli errori YAML più costosi perché il file sembra giusto e l'analisi riesce.
Qual è il problema della Norvegia in yaml?
In YAML 1.1, i valori no, NO, off, e yes sono booleani, quindi il prefisso internazionale della Norvegia NO Analisi come false. YAML 1.2 ha risolto questo problema - solo true e false sono booleani - ma molti strumenti (in particolare PyYAML, che Ansible utilizza) implementano ancora 1.1. lo stesso file può quindi significare cose diverse in strumenti diversi Citando il valore (country: "NO") lo rende una stringa ovunque.
Posso usare le schede per il rientro in YAML?
No. La specifica YAML vieta i caratteri di tabulazione nel rientro e i parser li rifiutano con un errore come & quot; i caratteri di tabulazione non devono essere utilizzati nel rientro.& quot; Configura il tuo editor per inserire spazi per i file YAML: due spazi per livello sono la convenzione standard.
Il validatore yaml Toolz.dev supporta file multidocumento?
non attualmente. convalida un singolo documento, quindi un file contenente diversi manifesti Kubernetes separati da --- Restituisce "Atteso un singolo documento nel flusso.” Convalida ogni documento separatamente come soluzione alternativa. È previsto un supporto multidocumento.
Le chiavi duplicate sono consentite in YAML?
La specifica dice che le chiavi di mappatura devono essere uniche, ma i parser non sono d'accordo nella pratica. js-yaml - che questo validatore usa - lancia un & quot; mapping key& quot duplicato; errore PyYAML mantiene silenziosamente l'ultimo valore, il che significa che un duplicato può sovrascrivere silenziosamente la tua configurazione senza alcun avviso. L'esecuzione della configurazione tramite un rigoroso validatore lo cattura prima che il runtime lo accetti silenziosamente.
È sicuro convalidare online i segreti e le credenziali di Kubernetes?
Con il validatore Toolz.dev, sì - l'analisi avviene interamente nel tuo browser tramite JavaScript e non viene trasmesso nulla a nessun server Puoi confermarlo tu stesso aprendo la scheda Rete del tuo browser' mentre convalidi e osservando che non viene effettuata alcuna richiesta Applica lo stesso controllo a qualsiasi strumento online prima di incollarvi la configurazione dell'infrastruttura.
Qual è la differenza tra .yml e .yam?
Niente di funzionale: entrambe le estensioni sono riconosciute da ogni parser YAML. La raccomandazione ufficiale è .yaml; .yml Sopravvive all'era delle estensioni a tre caratteri e rimane estremamente comune (le azioni Docker Compose e GitHub sono entrambe predefinite). Scegline uno e rimani coerente all'interno di un progetto.
Come faccio a convertire YAML in JSON?
Incolla lo YAML nel validatore e leggi il riquadro di output: rende il documento analizzato come JSON, che è la conversione. Poiché YAML 1.2 è un superset di JSON, ogni documento YAML valido ha un equivalente JSON, ma prima viene applicata l'inferenza del tipo, quindi un non quotato 1.10 arriva come 1.1 e 0123 tanto 123. Cita prima quei valori se ne hai bisogno conservati come stringhe.
Come posso convalidare lo yaml contro uno schema?
Questo validatore controlla la sintassi e mostra il risultato analizzato, ma non si convalida rispetto a uno schema - ovvero un controllo separato che conferma che le chiavi e i tipi di valore corrispondono a quanto si aspetta uno strumento come Kubernetes o GitHub Actions Per la convalida dello schema, utilizzare un server del linguaggio YAML nel proprio editor o una CLI compatibile con lo schema come kubeconform per Kubernetes o kubectl apply --dry-run=client. La convalida della sintassi e dello schema rileva diversi bug, quindi esegui entrambi.



