Validador YAML

Analisado no seu navegador e nunca transmitido - manifestos costumam carregar segredos, registries e nomes de host internos. Chaves duplicadas e indentacao com tab sao rejeitadas em vez de aceitas em silencio, e um fluxo com varios documentos vira um array JSON.

Nada do que você digita aqui é armazenado, registrado ou compartilhado.

Cole seu YAML para verifica-lo e converter para JSON, ou inverta a direcao para transformar JSON de volta em YAML. Os erros informam a linha e a coluna exatas. Tudo e analisado no seu navegador, entao manifestos com segredos nunca sao enviados.

Como usar

  1. Cole seu YAML no campo de entrada.
  2. Leia o resultado abaixo: valido, ou o motivo com linha e coluna.
  3. Copie o JSON, ou mude para JSON para YAML na direcao inversa.

Por que YAML é mais difícil do que parece

O atrativo do YAML é que um documento simples quase não precisa de sintaxe. O preço é que o parser precisa inferir muita coisa, e a maioria dos problemas com YAML vem dele inferir algo diferente do que você quis dizer.

Indentação é estrutura, e precisa ser feita com espaços - tabs nunca foram permitidos, e é por isso que um editor configurado para inseri-los produz erros que parecem não ter motivo. A indentação também é relativa, não fixa, então um bloco indentado com quatro espaços ao lado de um irmão indentado com dois é um erro de verdade, e não só uma inconsistência de estilo.

Além disso, os mesmos dados podem ser escritos de várias formas: estilo de bloco e estilo de fluxo, escalares com e sem aspas, três jeitos de escrever null. Nada disso importa até que um valor caia no vão entre elas - e aí importa muito.

As armadilhas da tipagem implícita

Um escalar sem aspas é tipado pela sua forma, e essas formas coincidem com coisas que as pessoas escrevem como texto.

Números de versão são o caso clássico. 1.10 sem aspas é um float, e floats não têm zero à direita, então vira 1.1 e a versão fixada da sua dependência passa a apontar para outro lugar sem aviso. Qualquer coisa com zero à esquerda tem o problema inverso: no YAML 1.2, 0755 é o número 755, não uma permissão de arquivo em octal, e você precisa escrever 0o755. Sequências longas de dígitos - telefones, números de conta, IDs - perdem os zeros à esquerda e, acima de dezesseis dígitos, a precisão.

Os booleanos são o caso famoso. O YAML 1.1 tratava yes, no, on, off, y e n como booleanos, e daí vem o "problema da Noruega": uma lista de países com NO vira uma lista com false. O core do YAML 1.2 restringiu isso a true e false, que é o que esta ferramenta segue, mas muito software por aí ainda usa parsers 1.1 - o Psych do Ruby e versões antigas do PyYAML, entre outros -, então o hábito seguro é colocar entre aspas tudo o que você quer como texto.

Também vale saber: null pode ser escrito como null, ~ ou simplesmente nada, então uma chave com valor vazio é null, e não uma string vazia. E no YAML 1.1, 22:22 é interpretado como número sexagesimal, não como horário.

Strings de várias linhas

Dois indicadores de escalar de bloco cobrem quase todos os casos, e escolher o errado é uma causa comum de configuração quebrada.

O pipe (|) mantém as quebras de linha exatamente como foram escritas. É o que você quer para um script de shell, um certificado, um arquivo de configuração embutido ou qualquer coisa em que a estrutura das linhas tenha significado. O sinal de maior (>) dobra o texto: quebras simples viram espaços e linhas em branco viram quebras, o que é certo para um parágrafo longo que você quer quebrar no código-fonte sem quebrar no valor.

Ambos aceitam um indicador de chomping que controla a quebra de linha final. Sem nada, mantém exatamente uma; o sinal de menos (-) remove todas; o de mais (+) mantém todas. O menos importa quando uma quebra final estragaria o que consome o valor - um token, uma chave, um argumento -, e o mais quando você precisa preservar os espaços exatamente.

O conteúdo é indentado em relação à chave, e essa indentação é removida do valor. Uma linha indentada além das demais mantém os espaços extras, e é assim que um script dentro de um manifesto preserva a própria estrutura.

Âncoras, aliases e merge keys

Uma âncora marca um nó com & e um alias se refere a ele com *, permitindo que o documento reutilize um valor definido antes. Numa configuração de CI ou num arquivo compose, é isso que elimina a repetição entre jobs ou serviços quase idênticos, e é um dos bons motivos reais para escrever em YAML e não em JSON.

A merge key, escrita <<: *base, vai além e incorpora as chaves de um mapeamento ancorado ao mapeamento atual, para que você sobrescreva só algumas. Vale saber que ela não faz parte do core do YAML 1.2 - é uma especificação separada que a maioria dos parsers implementa e alguns não, então não é universalmente segura.

Tudo isso desaparece, necessariamente, na conversão para JSON. Os aliases são resolvidos em valores reais antes da conversão, então uma âncora referenciada três vezes vira três cópias dos dados, e não três referências. Os comentários também somem, já que JSON não tem comentários. Converter uma configuração cheia de âncoras para JSON e de volta dá um documento com o mesmo significado e muito mais longo - em termos de legibilidade, é uma viagem só de ida.

Aspas: quando importam e qual usar

Um escalar sem aspas tem o tipo definido pelo formato, então usar aspas é a maneira de dizer que aquilo é texto. Aspas simples são literais, com a única exceção de que duas aspas simples seguidas representam um apóstrofo: nenhum escape é processado, então 'C:\path\to' é exatamente essa string. Aspas duplas processam escapes, então \n vira uma quebra de linha e uma barra invertida literal precisa ser duplicada.

A regra que evita a maior parte dos problemas: use aspas simples por padrão, aspas duplas apenas quando precisar de uma sequência de escape, e coloque entre aspas tudo que possa ser lido como outro tipo. Isso cobre números de versão, valores compostos apenas por dígitos, qualquer coisa que comece com zero e as palavras yes, no, on e off.

Alguns caracteres obrigam o uso de aspas onde quer que apareçam em um valor: dois-pontos seguidos de espaço, cerquilha precedida de espaço e um &, *, !, %, @ ou crase no início. Um valor que começa com chave ou colchete inicia o estilo de fluxo, então um template Jinja ou Helm como {{ .Values.name }} precisa estar entre aspas, caso contrário o parser o lê como um mapeamento aninhado.

Os erros que quebram arquivos de Kubernetes e de CI

A indentação dos itens de lista é o primeiro. Uma sequência sob uma chave pode ser indentada ou alinhada com a chave, e as duas formas são válidas, mas os itens de uma mesma sequência precisam concordar entre si. Misturar as duas dentro de um arquivo editado por várias pessoas produz um erro cuja linha reportada quase sempre fica em outro lugar.

Arquivos com múltiplos documentos são o segundo. Três traços separam documentos, e uma ferramenta que lê apenas o primeiro ignora silenciosamente tudo depois do separador - é assim que um manifesto do Kubernetes aplica o Deployment e não o Service. O kubectl lida com múltiplos documentos; muitos scripts que usam a função de carregamento padrão da linguagem não lidam, e precisam da variante load-all.

O terceiro é o valor vazio. Uma chave sem nada depois dos dois-pontos é null, não uma string vazia nem um mapa vazio, então um bloco de configuração comentado mas com a chave ainda presente é lido como um null onde o consumidor esperava um objeto. Nulls e strings vazias se comportam de maneiras diferentes em todo sistema de templates construído sobre YAML.

Validando YAML contra um esquema

Um parser diz que o arquivo é sintaticamente válido. Um esquema diz que o conteúdo faz sentido e, para qualquer coisa operacional, essa é a verificação mais útil. Como o YAML se mapeia para o mesmo modelo de dados do JSON, o JSON Schema funciona diretamente sobre ele, e é isso que a maioria dos editores usa para oferecer autocompletar e erros em linha num manifesto do Kubernetes ou num arquivo do GitHub Actions.

Em um pipeline, validadores especializados vão além de um esquema genérico: o kubeconform confere manifestos contra os esquemas da API do Kubernetes de uma versão alvo, o yamllint impõe estilo e pega problemas de indentação e chaves duplicadas, e a maioria dos sistemas de CI permite validar localmente o próprio arquivo de configuração antes de você fazer o push.

Chaves duplicadas merecem menção à parte. A maioria dos parsers as aceita e fica com a última, descartando a primeira em silêncio - então um valor definido duas vezes em um arquivo longo parece simplesmente ter sido ignorado. Os linters sinalizam isso; o runtime da linguagem, em geral, não.

Templates sobre YAML, e por que isso dói

Helm, Ansible e a maioria dos sistemas de CI geram YAML a partir de templates, o que significa uma linguagem de template textual produzindo um formato sensível a espaços em branco. Os resultados são previsíveis: um valor inserido na indentação errada, uma string de múltiplas linhas que achata um bloco, um condicional que remove uma linha e deixa uma chave solta.

Dois hábitos reduzem a dor. Renderize antes de aplicar - helm template, ou o dry run equivalente - e leia a saída como YAML em vez de confiar no template. E use os auxiliares de indentação que a ferramenta oferece, como o nindent do Helm, em vez de contar espaços à mão dentro do template.

A alternativa mais profunda é gerar YAML a partir de dados, e não de texto: produza uma estrutura em uma linguagem de verdade e serialize-a, para que a indentação seja problema do serializador. É exatamente para isso que existem o CDK8s, o Pulumi e várias linguagens de configuração como CUE e Dhall, e isso elimina uma categoria inteira de falhas.

Segredos, comentários e o que sobrevive à conversão

Arquivos de configuração YAML são onde os segredos mais costumam acabar parando em um repositório, em geral como um valor que alguém pretendia remover antes de commitar. Mantê-los fora é uma decisão de fluxo de trabalho - variáveis de ambiente, um gerenciador de segredos, ou arquivos criptografados com SOPS ou sealed secrets - e vale escanear o repositório uma vez para ver o que já está lá, lembrando que o histórico guarda tudo que um dia foi commitado.

Os comentários são a outra coisa que vale proteger. Eles são a única documentação que muitos arquivos de configuração têm, e não sobrevivem a uma conversão para JSON nem a uma ida e volta por um programa que carrega e reserializa o arquivo. Existem ferramentas que editam YAML no lugar preservando comentários - ruamel.yaml em Python, yq para edições de linha de comando - e são a escolha certa para mudanças automatizadas em um arquivo que pessoas mantêm.

O mesmo vale para as âncoras. Converter para JSON expande cada alias em uma cópia, então uma configuração construída em torno de blocos compartilhados volta bem mais longa e sem a estrutura que a tornava fácil de manter. Para a máquina significa a mesma coisa; para a próxima pessoa que for editá-la, significa bem menos.

Perguntas frequentes

E seguro colar um manifesto do Kubernetes aqui?
Sim. O parser roda no seu navegador e o documento nunca e enviado a lugar nenhum, que e exatamente o motivo desta ferramenta existir em vez de apontar voce para uma que processa no servidor. Manifestos costumam carregar registries de imagem, nomes de host internos e segredos em base64, e nada disso sai da sua maquina - nem para este site, nem para uma IA.
Por que meu numero de versao mudou de 1.10 para 1.1?
Porque 1.10 sem aspas e um float, e floats nao tem zero a direita. Essa e a pegadinha de YAML mais comum na pratica e a ferramenta nao a esconde: escreva "1.10" entre aspas para manter uma string. O mesmo vale para tudo que parece numero sem ser: numeros de build, telefones e identificadores com zero a esquerda.
NO ainda vira false, como no problema da Noruega?
Nao. Isso era YAML 1.1, onde NO, yes, on e off eram todos booleanos. Esta ferramenta segue o YAML 1.2 core, entao eles continuam strings. Zeros a esquerda tambem mudaram: 0755 agora e o numero decimal 755, nao octal - escreva 0o755 se queria um modo de arquivo.
O que acontece com um arquivo de varios documentos?
Um fluxo separado por --- vira um array JSON, um elemento por documento, que e a unica forma honesta de representar varios documentos raiz em JSON. Um --- final sem nada depois e ignorado em vez de virar um item null, ja que quase todo gerador de manifesto emite um.
Por que ele rejeita chaves duplicadas se meu editor nao rejeita?
Porque um validador que as aceita nao esta validando. YAML proibe chaves duplicadas em mapeamentos, mas muitos parsers silenciosamente ficam com a ultima, e o primeiro valor desaparece sem aviso - que e exatamente o bug que voce veio procurar aqui. Indentacao com tab e rejeitada pelo mesmo motivo: YAML nunca permitiu.
Converter para JSON perde alguma coisa?
Comentarios e ancoras, necessariamente - JSON nao tem nenhum dos dois. Ancoras e aliases sao resolvidos em valores reais antes da conversao, entao &base e *base viram duas copias dos mesmos dados. No sentido inverso, valores repetidos sao escritos por extenso em vez de virarem aliases, e strings longas nunca sao quebradas em varias linhas.

Última atualização:

Relatar um problema

Inclua os passos, o resultado esperado e o resultado real. Remova segredos e dados pessoais.

Ferramentas relacionadas