<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[AUTONETOPS]]></title><description><![CDATA[AUTONETOPS]]></description><link>https://autonetops.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1730066554884/d9dec3fc-d265-41c2-b27a-38885cc2f523.png</url><title>AUTONETOPS</title><link>https://autonetops.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 17 Mar 2026 03:03:01 GMT</lastBuildDate><atom:link href="https://autonetops.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><atom:link rel="first" href="https://autonetops.com/rss.xml"/><atom:link rel="next" href="https://autonetops.com/rss.xml?after=NjgyYzQ4MWY5ZGRjOTY4ZDRmYWJjM2ZmXzIwMjUtMDUtMjBUMDk6MTU6MTEuMTAxWg=="/><item><title><![CDATA[HTTP (SSE)]]></title><description><![CDATA[<p>No cenrio em evoluo da comunicao web em tempo real, os <strong>Server-Sent Events (SSE)</strong> surgiram como um padro para enviar dados de servidores para clientes. Embora tecnologias como WebSockets frequentemente dominem a conversa sobre interatividade em tempo real, o SSE oferece um conjunto de vantagens, particularmente no contexto do <strong>Model Context Protocol (MCP)</strong>. Este artigo explora a mecnica do SSE, suas diferenas fundamentais em relao ao HTTP tradicional e seu papel crtico como mecanismo de transporte para servidores MCP.</p>
<h2>O que so Eventos Enviados pelo Servidor HTTP (SSE)?</h2>
<p>Server-Sent Events (SSE)  um padro que permite que um servidor envie dados para uma pgina web ou cliente por meio de uma nica conexo HTTP de longa durao. Ao contrrio das requisies web tradicionais, onde o cliente deve solicitar explicitamente os dados, o SSE permite um fluxo unidirecional de informaes. Uma vez estabelecida a conexo, o servidor pode enviar atualizaes sempre que novos dados estiverem disponveis, sem interveno adicional do cliente.</p>
<blockquote>
<p><strong>Definio:</strong> Server-Sent Events (SSE)  uma tecnologia onde um navegador recebe atualizaes automticas de um servidor via uma conexo HTTP. Faz parte da especificao HTML5 e  projetado para ser uma alternativa mais simples aos WebSockets para comunicao servidor-para-cliente.</p>
</blockquote>
<h2>A Diferena Fundamental: HTTP Simples vs. SSE</h2>
<p>Para entender o valor do SSE,  essencial compar-lo com o modelo padro de requisio-resposta HTTP que governa a maioria das interaes web.</p>
<table>
<thead>
<tr>
<th>Caracterstica</th>
<th>HTTP Simples (Requisio-Resposta)</th>
<th>Server-Sent Events (SSE)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Modelo de Comunicao</strong></td>
<td>Iniciado pelo cliente; requisio seguida por resposta.</td>
<td>Iniciado pelo servidor (aps o handshake inicial do cliente).</td>
</tr>
<tr>
<td><strong>Ciclo de Vida da Conexo</strong></td>
<td>Geralmente de curta durao; fechada aps a entrega da resposta.</td>
<td>De longa durao; permanece aberta para um fluxo contnuo de dados.</td>
</tr>
<tr>
<td><strong>Fluxo de Dados</strong></td>
<td>Bidirecional, mas sequencial (Requisio -&gt; Resposta).</td>
<td>Unidirecional (Servidor -&gt; Cliente) aps a requisio inicial.</td>
</tr>
<tr>
<td><strong>Sobrecarga</strong></td>
<td>Alta para atualizaes frequentes (novos cabealhos para cada requisio).</td>
<td>Baixa; os cabealhos so enviados uma vez no incio da conexo.</td>
</tr>
<tr>
<td><strong>Latncia</strong></td>
<td>Maior para dados em tempo real devido a polling ou restabelecimento.</td>
<td>Extremamente baixa; os dados so enviados assim que disponveis.</td>
</tr>
</tbody></table>
<p>Em um cenrio de <strong>HTTP simples</strong>, se um cliente precisa saber quando um arquivo foi atualizado em um servidor, ele deve fazer polling repetidamente no servidor ou esperar por uma ao especfica do usurio. Isso leva a trfego de rede desnecessrio e maior latncia. O <strong>SSE</strong> resolve isso mantendo o canal de comunicao aberto, permitindo que o servidor "envie" a atualizao no momento em que ela ocorre.</p>
<h2>Como o SSE Funciona: Por Trs dos Panos</h2>
<p>O SSE opera sobre HTTP padro e usa um tipo MIME especfico: <code>text/event-stream</code>. O processo comea com uma requisio HTTP GET padro do cliente, incluindo um cabealho indicando que ele deseja aceitar um fluxo de eventos.</p>
<ol>
<li><p><strong>Handshake:</strong> O cliente envia uma requisio com o cabealho <code>Accept: text/event-stream</code>.</p>
</li>
<li><p><strong>Resposta:</strong> O servidor responde com <code>Content-Type: text/event-stream</code> e mantm a conexo aberta.</p>
</li>
<li><p><strong>Transmisso de Dados:</strong> O servidor envia dados em um formato de texto especfico, geralmente prefixado com <code>data:</code>. Por exemplo:</p>
<pre><code class="language-text">event: update
data: {"status": "processing", "progress": 45}

event: result
data: {"message": "Task completed successfully"}
</code></pre>
</li>
<li><p><strong>Reconexo Automtica:</strong> Uma das caractersticas mais poderosas do SSE  seu suporte integrado para reconexo. Se a conexo for perdida, o cliente (geralmente o navegador) tentar automaticamente se reconectar aps um curto atraso.</p>
</li>
</ol>
<h2>SSE no Contexto dos Servidores MCP</h2>
<p>O <strong>Model Context Protocol (MCP)</strong>  um padro aberto que permite que modelos de IA interajam com ferramentas externas e fontes de dados. O MCP suporta mltiplos mecanismos de transporte, sendo o <strong>SSE a escolha principal para implementaes de servidor remoto baseadas na web (frequentemente referidas como "Streamable HTTP").</strong></p>
<h3>Por que o MCP Usa SSE</h3>
<p>Servidores MCP frequentemente precisam fornecer feedback em tempo real para agentes de IA, como transmitir a sada de uma ferramenta de longa execuo ou fornecer atualizaes de status durante a recuperao de dados complexos. O SSE  ideal para isso por vrias razes:</p>
<ul>
<li><p><strong>Streaming em Tempo Real:</strong> Modelos de IA geram texto e dados incrementalmente. O SSE permite que os servidores MCP transmitam esses resultados de volta ao cliente  medida que so produzidos, em vez de esperar que todo o processo termine.</p>
</li>
<li><p><strong>Compatibilidade com Firewall e Proxy:</strong> Como o SSE  apenas HTTP padro, ele atravessa facilmente firewalls, proxies e balanceadores de carga que poderiam bloquear protocolos no padronizados como WebSockets.</p>
</li>
<li><p><strong>Simplicidade e Eficincia:</strong> Para muitas tarefas orientadas por IA, a comunicao  principalmente do servidor (a ferramenta/fonte de dados) para o cliente (o agente de IA). O SSE fornece a capacidade de tempo real necessria sem a complexidade de gerenciar conexes WebSocket full-duplex.</p>
</li>
</ul>
<h3>A Arquitetura de Transporte MCP</h3>
<p>Em uma implementao MCP SSE, a comunicao  estruturada para lidar com a natureza unidirecional do SSE, mantendo a capacidade do cliente de enviar comandos:</p>
<ol>
<li><p><strong>O Endpoint SSE (GET):</strong> O cliente estabelece uma conexo de longa durao para receber mensagens, eventos e sadas de ferramentas do servidor MCP.</p>
</li>
<li><p><strong>O Endpoint de Comando (POST):</strong> Quando o cliente precisa enviar uma requisio ao servidor (por exemplo, "executar esta ferramenta"), ele envia uma requisio HTTP POST padro. O servidor ento processa a requisio e envia os resultados de volta atravs do fluxo SSE estabelecido.</p>
</li>
</ol>
<h2>Casos de Uso para SSE no MCP</h2>
<p>A integrao de SSE e MCP permite uma variedade de casos de uso poderosos no ecossistema de IA:</p>
<ol>
<li><p><strong>Monitoramento de Logs ao Vivo:</strong> Um agente de IA pode se conectar a um servidor MCP que monitora logs do servidor. Usando SSE, o agente recebe um fluxo ao vivo de entradas de log, permitindo detectar e reagir a erros em tempo real.</p>
</li>
<li><p><strong>Visualizao Dinmica de Dados:</strong> Quando um agente de IA realiza anlise de dados via uma ferramenta MCP, o servidor pode usar SSE para enviar atualizaes incrementais para um painel, mostrando o progresso da anlise ou grficos intermedirios.</p>
</li>
<li><p><strong>Fluxos de Trabalho Colaborativos de IA:</strong> Mltiplos agentes podem se inscrever no mesmo fluxo SSE de um servidor MCP, permitindo que eles permaneam sincronizados sobre o estado de uma tarefa compartilhada ou fonte de dados.</p>
</li>
</ol>
]]></description><link>https://autonetops.com/http-sse</link><guid isPermaLink="true">https://autonetops.com/http-sse</guid><category><![CDATA[pt-br]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Desmistificando o Async em Python: Um Guia para Automação de Redes]]></title><description><![CDATA[<p>A programao assncrona (<code>async/await</code>) em Python  uma das funcionalidades mais poderosas e, ao mesmo tempo, mais mal compreendidas. Para engenheiros de automao de redes, cujas tarefas so dominadas por esperas: esperar por uma conexo SSH, pela resposta de uma API, pelo output de um comando, o <code>async</code>  uma necessidade. Ele promete executar dezenas de tarefas de rede no tempo que levaria para fazer apenas uma.</p>
<p>No entanto, entrar no mundo <code>async</code> pode ser confuso. O que  uma corrotina? Eu preciso mesmo do <code>asyncio</code>? E, a pergunta mais crtica de todas: <strong>o que acontece se eu misturar cdigo sncrono e assncrono?</strong></p>
<h2 id="heading-o-basico-funcoes-sincronas-vs-assincronas">O Bsico: Funes Sncronas vs. Assncronas</h2>
<ul>
<li><p><strong>Funo Sncrona (normal):</strong> Quando voc a chama, ela executa do incio ao fim sem interrupo. Se ela precisa esperar por algo (como uma resposta de rede), todo o seu programa para e espera junto.  como um telefonema: voc fica na linha at a conversa acabar.</p>
</li>
<li><p><strong>Funo Assncrona (Corrotina):</strong>  uma funo que pode ser <strong>pausada</strong> e <strong>retomada</strong>. Quando ela encontra uma operao de espera (marcada com <code>await</code>), ela diz ao Python: "Ei, isso vai demorar. Pode ir fazendo outra coisa enquanto eu espero".  como enviar uma mensagem de texto: voc envia e pode fazer outras coisas at a resposta chegar.</p>
</li>
</ul>
<h2 id="heading-as-pecas-do-quebra-cabeca-async">As Peas do Quebra-Cabea Async</h2>
<p>Para o <code>async</code> funcionar, precisamos de trs componentes principais:</p>
<ol>
<li><p><strong>Corrotinas (</strong><code>async def</code>): So as funes "pausveis". Voc as define com <code>async def</code>.</p>
</li>
<li><p><code>await</code>: A palavra-chave que de fato pausa a corrotina e devolve o controle, dizendo "estou esperando por este resultado". Voc s pode usar <code>await</code> dentro de uma <code>async def</code>.</p>
</li>
<li><p><strong>O Event Loop:</strong>  o maestro que orquestra tudo. Ele mantm uma lista de tarefas e executa uma de cada vez. Quando uma tarefa  pausada com <code>await</code>, o event loop imediatamente pega a prxima tarefa da lista e a executa. Ele  o corao do <code>asyncio</code>.</p>
</li>
</ol>
<h2 id="heading-eu-preciso-do-asyncio">Eu Preciso do <code>asyncio</code>?</h2>
<p>Sim e no.</p>
<ul>
<li><p><strong>No,</strong> voc no precisa importar e interagir com todas as partes complexas do <code>asyncio</code> o tempo todo.</p>
</li>
<li><p><strong>Sim,</strong> voc precisa de <em>algo</em> para rodar o event loop e gerenciar as corrotinas. O <code>asyncio</code>  a biblioteca padro do Python para isso.</p>
</li>
</ul>
<p>Na prtica, seu uso do <code>asyncio</code> pode ser to simples quanto:</p>
<ul>
<li><p><code>asyncio.run(main())</code>: O ponto de entrada que inicia o event loop e executa sua corrotina principal <code>main</code>.</p>
</li>
<li><p><code>asyncio.gather(*tasks)</code>: Uma forma de executar uma lista de corrotinas concorrentemente e esperar que todas terminem.</p>
</li>
</ul>
<p>Voc no precisa construir o event loop manualmente; o <code>asyncio</code> cuida da parte difcil para voc.</p>
<h2 id="heading-o-pecado-capital-chamar-codigo-bloqueante-em-uma-corrotina">O Pecado Capital: Chamar Cdigo Bloqueante em uma Corrotina</h2>
<p>Esta  a regra mais importante da programao assncrona: <strong>nunca, jamais, chame uma funo sncrona e bloqueante dentro de uma corrotina.</strong></p>
<p>Funes bloqueantes so aquelas que fazem o programa esperar, como:</p>
<ul>
<li><p><code>time.sleep(5)</code></p>
</li>
<li><p><code>requests.get(url)</code></p>
</li>
<li><p>Uma chamada de uma biblioteca de rede que no  <code>async</code>, como <code>netmiko.ConnectHandler(...)</code></p>
</li>
</ul>
<p><strong>O que acontece quando voc faz isso?</strong></p>
<p>Voc congela o chef de cozinha. A funo bloqueante toma controle total do processo e no o devolve at que ela termine. O event loop fica paralisado, incapaz de trocar de tarefa. Todas as outras corrotinas que estavam prontas para rodar ficam esperando, famintas. Todo o benefcio da concorrncia  perdido.</p>
<pre><code class="lang-mermaid">sequenceDiagram
    participant EventLoop
    participant CorrotinaA
    participant CorrotinaB
    participant FuncaoSincrona

    EventLoop-&gt;&gt;CorrotinaA: Executar
    CorrotinaA-&gt;&gt;FuncaoSincrona: Chamar time.sleep(5)
    Note over EventLoop,FuncaoSincrona: O EVENT LOOP EST BLOQUEADO!
    Note over CorrotinaB: Esperando para executar...
    FuncaoSincrona--&gt;&gt;CorrotinaA: Retorna aps 5s
    CorrotinaA--&gt;&gt;EventLoop: Finaliza
    EventLoop-&gt;&gt;CorrotinaB: Finalmente executa
</code></pre>
<p>No diagrama acima, a <code>CorrotinaB</code> s pde executar depois que a <code>FuncaoSincrona</code> (o <code>time.sleep(5)</code>) liberou o processo, 5 segundos depois. A concorrncia foi destruda.</p>
<h2 id="heading-a-solucao-asynciotothread">A Soluo: <code>asyncio.to_thread()</code></h2>
<p>Ento, como usamos bibliotecas sncronas e bloqueantes (como a <code>netmiko</code>, que  essencial para muitos de ns) em um cdigo <code>async</code>?</p>
<p>A resposta  delegar o trabalho bloqueante para um <em>thread</em> separado, liberando o event loop para continuar seu trabalho. Desde o Python 3.9, o <code>asyncio</code> tornou isso incrivelmente fcil com <code>asyncio.to_thread()</code>.</p>
<p><code>asyncio.to_thread(func, *args)</code> pega uma funo sncrona <code>func</code> e seus argumentos <code>*args</code>, a executa em um thread separado e retorna um objeto "aguardvel" (<code>awaitable</code>). O event loop pode "esperar" por esse objeto sem ser bloqueado.</p>
<h3 id="heading-caso-pratico-netmiko-sincrono-httpx-assincrono">Caso Prtico: Netmiko (Sncrono) + HTTPX (Assncrono)</h3>
<p>Vamos criar um script que, concorrentemente, busca a configurao de um roteador usando <code>netmiko</code> e busca dados de uma API usando <code>httpx</code>.</p>
<p><strong>O jeito ERRADO (bloqueante):</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">import</span> httpx
<span class="hljs-keyword">from</span> netmiko <span class="hljs-keyword">import</span> ConnectHandler

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_config_bloqueante</span>(<span class="hljs-params">device</span>):</span> <span class="hljs-comment"># RUIM!</span>
    print(<span class="hljs-string">'Iniciando conexo Netmiko...'</span>)
    <span class="hljs-keyword">with</span> ConnectHandler(**device) <span class="hljs-keyword">as</span> conn:
        output = conn.send_command(<span class="hljs-string">'show run'</span>)
    print(<span class="hljs-string">'Conexo Netmiko finalizada.'</span>)
    <span class="hljs-keyword">return</span> output

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_api_data</span>():</span>
    print(<span class="hljs-string">'Iniciando chamada de API...'</span>)
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> httpx.AsyncClient() <span class="hljs-keyword">as</span> client:
        <span class="hljs-keyword">await</span> client.get(<span class="hljs-string">'https://httpbin.org/delay/2'</span>) <span class="hljs-comment"># Simula espera de 2s</span>
    print(<span class="hljs-string">'Chamada de API finalizada.'</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    <span class="hljs-comment"># ... (definio do dispositivo) ...</span>
    <span class="hljs-keyword">await</span> asyncio.gather(
        get_config_bloqueante(device), <span class="hljs-comment"># Esta chamada ir bloquear tudo!</span>
        get_api_data()
    )

<span class="hljs-comment"># Se a conexo Netmiko levar 5s, a chamada de API s comear depois disso.</span>
</code></pre>
<p><strong>O jeito CERTO (com</strong> <code>to_thread</code>):</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">import</span> httpx
<span class="hljs-keyword">from</span> netmiko <span class="hljs-keyword">import</span> ConnectHandler

<span class="hljs-comment"># Funo sncrona e bloqueante, como deve ser</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_config_sincrono</span>(<span class="hljs-params">device</span>):</span>
    print(<span class="hljs-string">'Iniciando conexo Netmiko em um thread...'</span>)
    <span class="hljs-keyword">with</span> ConnectHandler(**device) <span class="hljs-keyword">as</span> conn:
        output = conn.send_command(<span class="hljs-string">'show run'</span>)
    print(<span class="hljs-string">'Conexo Netmiko finalizada.'</span>)
    <span class="hljs-keyword">return</span> output

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_api_data</span>():</span>
    print(<span class="hljs-string">'Iniciando chamada de API...'</span>)
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> httpx.AsyncClient() <span class="hljs-keyword">as</span> client:
        <span class="hljs-keyword">await</span> client.get(<span class="hljs-string">'https://httpbin.org/delay/2'</span>)
    print(<span class="hljs-string">'Chamada de API finalizada.'</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    device = {
    <span class="hljs-comment"># dados do router</span>
    }

    <span class="hljs-comment"># Delega a funo bloqueante para um thread separado</span>
    netmiko_task = asyncio.to_thread(get_config_sincrono, device)
    api_task = get_api_data()

    <span class="hljs-keyword">await</span> asyncio.gather(netmiko_task, api_task)

asyncio.run(main())
</code></pre>
<p>Nesta verso, enquanto <code>get_config_sincrono</code> est rodando em seu prprio thread, o event loop est livre para executar <code>get_api_data</code> concorrentemente. As duas tarefas progridem ao mesmo tempo.</p>
<h2 id="heading-conclusao">Concluso</h2>
<p>Entender <code>async</code>  entender a arte de no esperar. Para automao de redes, onde o tempo de espera  o maior inimigo, isso  transformador.</p>
<p><strong>Lembre-se das regras de ouro:</strong></p>
<ol>
<li><p><strong>Use</strong> <code>async/await</code> para tarefas I/O-bound: Interaes com rede (APIs, SSH) so o caso de uso perfeito.</p>
</li>
<li><p><strong>Nunca bloqueie o Event Loop:</strong> Uma nica chamada sncrona bloqueante em uma corrotina destri toda a vantagem do <code>async</code>.</p>
</li>
<li><p><strong>Use</strong> <code>asyncio.to_thread()</code>:  a sua ponte segura para integrar bibliotecas sncronas e legadas em um mundo assncrono moderno.</p>
</li>
</ol>
<p>Ao dominar esses conceitos, voc estar equipado para escrever automaes de rede drasticamente mais rpidas, eficientes e escalveis.</p>
<hr />
<p><strong>Referncias:</strong></p>
<ol>
<li><p><a target="_blank" href="https://realpython.com/async-io-python/">RealPython - Async IO in Python: A Complete Walkthrough</a></p>
</li>
<li><p><a target="_blank" href="https://docs.python.org/3/library/asyncio.html">Documentao Oficial do <code>asyncio</code></a></p>
</li>
<li><p><a target="_blank" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.to_thread">Documentao do</a> <code>asyncio.to_thread</code></p>
</li>
</ol>
]]></description><link>https://autonetops.com/desmistificando-o-async-em-python-um-guia-para-automacao-de-redes</link><guid isPermaLink="true">https://autonetops.com/desmistificando-o-async-em-python-um-guia-para-automacao-de-redes</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Network Automation]]></category><category><![CDATA[Python 3]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[HTTPX: O Sucessor do Requests]]></title><description><![CDATA[<p>A biblioteca <code>requests</code> tem sido indiscutivelmente a ferramenta das requisies HTTP em Python. Sua API tornou a interao com APIs uma tarefa trivial, e ela se tornou a base de incontveis scripts de automao de redes. No entanto, o mundo da programao e das redes evoluiu. Aplicaes modernas exigem alta concorrncia e eficincia, e  aqui que o <code>requests</code>, com sua natureza puramente sncrona, comea a mostrar sua idade.</p>
<p> nesse cenrio que surge o <strong>HTTPX</strong>, uma biblioteca de cliente HTTP de nova gerao para Python. O HTTPX oferece uma API amplamente compatvel, o que torna a migrao quase indolor, mas adiciona superpoderes que so cruciais para a automao de redes moderna: <strong>suporte nativo a</strong> <code>async/await</code> e <strong>HTTP/2</strong></p>
<p>Vamos focar nas vantagens do <code>httpx</code> e mostrar por que ele deve se tornar a sua nova ferramenta padro para interagir com APIs de rede.</p>
<h2 id="heading-requests-vs-httpx-uma-comparacao-direta">Requests vs. HTTPX: Uma Comparao Direta</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Caracterstica</strong></td><td><code>requests</code></td><td><code>httpx</code></td></tr>
</thead>
<tbody>
<tr>
<td><strong>API</strong></td><td>Sncrona</td><td>Sncrona <strong>e</strong> Assncrona</td></tr>
<tr>
<td><strong>Protocolo HTTP</strong></td><td>HTTP/1.1</td><td>HTTP/1.1 <strong>e</strong> HTTP/2</td></tr>
<tr>
<td><strong>Performance</strong></td><td>Excelente para tarefas sequenciais.</td><td>Superior para tarefas concorrentes (I/O-bound).</td></tr>
<tr>
<td><strong>Dependncias</strong></td><td>Nenhuma para funcionalidades bsicas.</td><td><code>httpcore</code>, <code>sniffio</code>, <code>anyio</code> (para async).</td></tr>
<tr>
<td><strong>Compatibilidade</strong></td><td>Padro de fato, enorme ecossistema.</td><td>API quase 100% compatvel com <code>requests</code>.</td></tr>
<tr>
<td><strong>Uso</strong></td><td>Menos ideal para frameworks web assncronos.</td><td>Ideal para FastAPI, Starlette</td></tr>
</tbody>
</table>
</div><h2 id="heading-vantagem-1-programacao-assincrona-asyncawait">Vantagem 1: Programao Assncrona (<code>async/await</code>)</h2>
<p>A maior limitao do <code>requests</code>  que ele  <strong>sncrono</strong>. Quando voc faz uma requisio, seu cdigo para e espera a resposta do servidor antes de continuar. Em automao de redes, isso  um gargalo fatal. Imagine precisar consultar a API de 100 switches para obter o status de suas interfaces. Com <code>requests</code>, voc faria isso em srie:</p>
<pre><code class="lang-mermaid">sequenceDiagram
    participant Script
    participant Switch1
    participant Switch2
    participant Switch100

    Script-&gt;&gt;Switch1: GET /api/interfaces
    Note right of Script: Espera...
    Switch1--&gt;&gt;Script: Resposta
    Script-&gt;&gt;Switch2: GET /api/interfaces
    Note right of Script: Espera...
    Switch2--&gt;&gt;Script: Resposta
    Note over Script: ...continua sequencialmente...
    Script-&gt;&gt;Switch100: GET /api/interfaces
    Note right of Script: Espera...
    Switch100--&gt;&gt;Script: Resposta
</code></pre>
<p>Se cada requisio levar 1 segundo, o processo todo levar 100 segundos. A maior parte desse tempo  gasta esperando a rede e o servidor (I/O-bound).</p>
<p>O <strong>HTTPX com</strong> <code>async</code> resolve isso. Ele permite que voc dispare todas as 100 requisies de uma vez e espere pelas respostas concorrentemente. Enquanto uma requisio est esperando pela rede, o programa pode trabalhar em outra.</p>
<pre><code class="lang-mermaid">sequenceDiagram
    participant Script
    participant Switch1
    participant Switch2
    participant Switch100

    Script-&gt;&gt;Switch1: GET /api/interfaces
    Script-&gt;&gt;Switch2: GET /api/interfaces
    Script-&gt;&gt;Switch100: GET /api/interfaces
    Note right of Script: Dispara todas as requisies

    Switch1--&gt;&gt;Script: Resposta
    Switch2--&gt;&gt;Script: Resposta
    Switch100--&gt;&gt;Script: Resposta
    Note right of Script: Processa as respostas  medida que chegam
</code></pre>
<p>Com <code>async</code>, o tempo total ser prximo ao da requisio mais longa, talvez pouco mais de 1 segundo, em vez de 100 segundos. Uma melhoria de performance de quase 100x.</p>
<h3 id="heading-caso-pratico-consultando-multiplos-dispositivos-no-netbox">Caso Prtico: Consultando Mltiplos Dispositivos no NetBox</h3>
<p>Vamos buscar os detalhes de 3 dispositivos diferentes no NetBox, primeiro com <code>requests</code> e depois com <code>httpx</code>.</p>
<p><strong>Com</strong> <code>requests</code> (Sequencial):</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> time

NETBOX_URL = <span class="hljs-string">"https://demo.netbox.dev/api"</span>
DEVICE_IDS = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_devices_sync</span>():</span>
    start_time = time.time()
    <span class="hljs-keyword">for</span> device_id <span class="hljs-keyword">in</span> DEVICE_IDS:
        response = requests.get(<span class="hljs-string">f"<span class="hljs-subst">{NETBOX_URL}</span>/dcim/devices/<span class="hljs-subst">{device_id}</span>/"</span>)
        print(<span class="hljs-string">f"Dispositivo <span class="hljs-subst">{device_id}</span>: <span class="hljs-subst">{response.json()[<span class="hljs-string">"name"</span>]}</span>"</span>)
    duration = time.time() - start_time
    print(<span class="hljs-string">f"\nVerso sncrona levou: <span class="hljs-subst">{duration:<span class="hljs-number">.2</span>f}</span> segundos"</span>)

fetch_devices_sync()
</code></pre>
<p><strong>Com</strong> <code>httpx</code> (Concorrente):</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> httpx
<span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">import</span> time

NETBOX_URL = <span class="hljs-string">"https://demo.netbox.dev/api"</span>
DEVICE_IDS = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_device</span>(<span class="hljs-params">client, device_id</span>):</span>
    response = <span class="hljs-keyword">await</span> client.get(<span class="hljs-string">f"<span class="hljs-subst">{NETBOX_URL}</span>/dcim/devices/<span class="hljs-subst">{device_id}</span>/"</span>)
    print(<span class="hljs-string">f"Dispositivo <span class="hljs-subst">{device_id}</span>: <span class="hljs-subst">{response.json()[<span class="hljs-string">"name"</span>]}</span>"</span>)

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fetch_devices_async</span>():</span>
    start_time = time.time()
    <span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> httpx.AsyncClient() <span class="hljs-keyword">as</span> client:
        tasks = [fetch_device(client, device_id) <span class="hljs-keyword">for</span> device_id <span class="hljs-keyword">in</span> DEVICE_IDS]
        <span class="hljs-keyword">await</span> asyncio.gather(*tasks)
    duration = time.time() - start_time
    print(<span class="hljs-string">f"\nVerso assncrona levou: <span class="hljs-subst">{duration:<span class="hljs-number">.2</span>f}</span> segundos"</span>)

asyncio.run(fetch_devices_async())
</code></pre>
<p>Embora para 3 dispositivos a diferena possa ser pequena, para 100 ou 1000, a verso assncrona ser ordens de magnitude mais rpida.</p>
<h2 id="heading-vantagem-2-suporte-a-http2">Vantagem 2: Suporte a HTTP/2</h2>
<p>O HTTP/2  uma reviso majoritria do protocolo HTTP que traz melhorias significativas de performance, especialmente o <strong>multiplexing</strong>. Com HTTP/1.1, se voc precisa de 5 recursos de um mesmo servidor, o navegador (ou seu cliente HTTP) abre mltiplas conexes TCP, o que  custoso. Com HTTP/2, todas essas requisies podem ser enviadas concorrentemente sobre uma nica conexo TCP</p>
<p>Para APIs modernas que so servidas sobre HTTP/2 (como muitas APIs gRPC-web e de provedores de nuvem), usar um cliente que suporte o protocolo pode reduzir a latncia e o consumo de recursos.</p>
<p>Com <code>httpx</code>, habilitar HTTP/2  trivial:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> httpx

<span class="hljs-comment"># O cliente tentar negociar HTTP/2 com o servidor</span>
<span class="hljs-keyword">with</span> httpx.Client(http2=<span class="hljs-literal">True</span>) <span class="hljs-keyword">as</span> client:
    response = client.get(<span class="hljs-string">"https://http2.pro/api/v1"</span>)
    print(response.http_version)
    <span class="hljs-comment"># Output: "HTTP/2"</span>
</code></pre>
<p>A biblioteca <code>requests</code> no possui suporte nativo a HTTP/2.</p>
<h2 id="heading-migrando-de-requests-para-httpx-um-cheatsheet">Migrando de <code>requests</code> para <code>httpx</code>: Um Cheatsheet</h2>
<p>A beleza do <code>httpx</code>  que sua API sncrona  um substituto quase direto para o <code>requests</code>. A migrao  incrivelmente fcil.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><code>requests</code></td><td><code>httpx</code> (Sncrono)</td><td><code>httpx</code> (Assncrono)</td></tr>
</thead>
<tbody>
<tr>
<td><code>import requests</code></td><td><code>import httpx</code></td><td><code>import httpx</code> &amp; <code>import asyncio</code></td></tr>
<tr>
<td><code>requests.get(url)</code></td><td><code>httpx.get(url)</code></td><td><code>await client.get(url)</code></td></tr>
<tr>
<td><code>requests.post(url, json=data)</code></td><td><code>httpx.post(url, json=data)</code></td><td><code>await client.post(url, json=data)</code></td></tr>
<tr>
<td><code>response.json()</code></td><td><code>response.json()</code></td><td><code>response.json()</code></td></tr>
<tr>
<td><code>response.status_code</code></td><td><code>response.status_code</code></td><td><code>response.status_code</code></td></tr>
<tr>
<td><code>response.text</code></td><td><code>response.text</code></td><td><code>response.text</code></td></tr>
<tr>
<td><code>requests.Session()</code></td><td><code>httpx.Client()</code></td><td><code>httpx.AsyncClient()</code></td></tr>
<tr>
<td><code>with requests.Session() as s:</code></td><td><code>with httpx.Client() as c:</code></td><td><code>async with httpx.AsyncClient() as c:</code></td></tr>
</tbody>
</table>
</div><p><strong>Passo 1: Migrao Sncrona</strong></p>
<p>Na maioria dos casos, voc pode simplesmente substituir <code>import requests</code> por <code>import httpx</code> e seu cdigo continuar funcionando.</p>
<p><strong>Passo 2: Adotando o Async (Onde faz sentido)</strong></p>
<p>Para as partes do seu cdigo que fazem mltiplas chamadas de API, refatore-as para usar <code>async def</code>, <code>httpx.AsyncClient</code>, e <code>asyncio.gather</code> para obter os ganhos de performance.</p>
<h2 id="heading-conclusao-por-que-o-httpx-e-o-futuro-para-netdevops">Concluso: Por que o HTTPX  o Futuro para NetDevOps</h2>
<p>O <code>requests</code>  uma biblioteca fantstica e serviu  comunidade Python por muitos anos. Ela no est "morta" e ainda  perfeitamente adequada para scripts simples e sequenciais. No entanto, a automao de redes moderna  inerentemente concorrente. Precisamos interagir com dezenas, centenas ou milhares de dispositivos e APIs o mais rpido possvel.</p>
<p>O <strong>HTTPX</strong> no  apenas uma alternativa;  a evoluo natural. Ele nos d:</p>
<ul>
<li><p><strong>Performance:</strong> A capacidade de executar operaes de I/O em paralelo com <code>async</code>.</p>
</li>
<li><p><strong>Eficincia:</strong> Suporte a HTTP/2 para interaes mais rpidas com APIs modernas.</p>
</li>
<li><p><strong>Flexibilidade:</strong> Uma nica biblioteca que pode operar tanto de forma sncrona quanto assncrona.</p>
</li>
<li><p><strong>Familiaridade:</strong> Uma API que se sente em casa para qualquer um que j usou <code>requests</code>.</p>
</li>
</ul>
<p>Para qualquer novo projeto de automao de redes que envolva interao com APIs, o <code>httpx</code> deveria ser sua escolha padro. Comece usando sua API sncrona para uma transio fcil e, em seguida, adote o <code>async</code> nas partes do seu cdigo que mais se beneficiaro da concorrncia. Sua automao agradecer pela velocidade.</p>
<p><strong>Referncias:</strong></p>
<ol>
<li><p><a target="_blank" href="https://www.python-httpx.org/">HTTPX Official Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/HTTP_2">MDN Web Docs - HTTP/2</a></p>
</li>
<li><p><a target="_blank" href="https://scrapingant.com/blog/requests-vs-httpx">ScrapingAnt - Requests vs. HTTPX - A Detailed Comparison</a></p>
</li>
</ol>
]]></description><link>https://autonetops.com/httpx-o-sucessor-do-requests</link><guid isPermaLink="true">https://autonetops.com/httpx-o-sucessor-do-requests</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Network Automation]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Operador Walrus (:=) em Python]]></title><description><![CDATA[<p>O operador "Walrus" (<code>:=</code>), introduzido no Python 3.8,  uma ferramenta que nos ajuda a escrever cdigo mais limpo, eficiente e legvel (. mais ou menos, mais ou menos). Oficialmente chamado de "expresso de atribuio", ele permite que voc atribua um valor a uma varivel como parte de uma expresso maior.</p>
<p>Bora dar uma olhada!</p>
<h2 id="heading-o-que-e-o-operador-walrus-e-a-problematica">O Que  o Operador Walrus e a problemtica</h2>
<p>Em essncia, o operador walrus combina duas aes em uma: <strong>atribuir um valor</strong> a uma varivel e <strong>retornar esse mesmo valor</strong> para ser usado imediatamente.</p>
<p><strong>O Problema:</strong> Muitas vezes, precisamos obter um valor, checar se ele  vlido e, se for, us-lo. Isso geralmente resulta em cdigo repetitivo ou menos legvel.</p>
<p><strong>A Soluo (</strong><code>:=</code>): Ele elimina essa redundncia, tornando o cdigo mais conciso e direto ao ponto.</p>
<hr />
<h2 id="heading-exemplos-antes-e-depois">Exemplos: Antes e Depois</h2>
<h3 id="heading-exemplo-1-parsing-de-saida-de-comandos">Exemplo 1: Parsing de Sada de Comandos</h3>
<p>Um dos usos mais comuns na automao de redes  executar um comando, procurar por um padro com expresses regulares (regex) e, se encontrar, usar o valor encontrado.</p>
<p><strong>Cenrio:</strong> Encontrar todas as interfaces que esto administrativamente desativadas (<code>administratively down</code>) na sada de um <code>show interface</code>.</p>
<p><strong>Sem o Operador Walrus 🙁</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> re

<span class="hljs-comment"># Simulao da sada de um comando</span>
show_interface_output = <span class="hljs-string">"""
GigabitEthernet1 is up, line protocol is up
GigabitEthernet2 is administratively down, line protocol is down
TenGigabitEthernet3/1 is up, line protocol is up
GigabitEthernet4 is administratively down, line protocol is down
"""</span>

down_interfaces = []
<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> show_interface_output.splitlines():
    <span class="hljs-comment"># Procuramos pelo padro</span>
    match = re.search(<span class="hljs-string">r"^(.*) is administratively down"</span>, line)
    <span class="hljs-comment"># Checamos se o padro foi encontrado</span>
    <span class="hljs-keyword">if</span> match:
        <span class="hljs-comment"># Se sim, usamos o valor capturado</span>
        interface_name = match.group(<span class="hljs-number">1</span>)
        down_interfaces.append(interface_name)

print(<span class="hljs-string">f"Interfaces desativadas: <span class="hljs-subst">{down_interfaces}</span>"</span>)
<span class="hljs-comment"># Sada: Interfaces desativadas: [\"GigabitEthernet2\", \"GigabitEthernet4\"]</span>
</code></pre>
<p><strong>Com o Operador Walrus 🙂</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> re

show_interface_output = <span class="hljs-string">"""mesma do exemplo anterior"""</span>

down_interfaces = []
<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> show_interface_output.splitlines():
    <span class="hljs-comment"># 1. Procuramos, atribumos e checamos TUDO EM UMA LINHA</span>
    <span class="hljs-keyword">if</span> match := re.search(<span class="hljs-string">r"^(.*) is administratively down"</span>, line):
        <span class="hljs-comment"># 2. Se o padro foi encontrado, a varivel \"match\" j est pronta para uso</span>
        down_interfaces.append(match.group(<span class="hljs-number">1</span>))

print(<span class="hljs-string">f"Interfaces desativadas: <span class="hljs-subst">{down_interfaces}</span>"</span>)
<span class="hljs-comment"># Sada: Interfaces desativadas: [\"GigabitEthernet2\", \"GigabitEthernet4\"]</span>
</code></pre>
<p>A verificao e a atribuio acontecem no mesmo lugar, reduzindo a complexidade visual.</p>
<h3 id="heading-exemplo-2-loops-interativos-cliente-ollama">Exemplo 2: Loops Interativos (Cliente Ollama)</h3>
<p>O operador walrus brilha em loops <code>while</code> onde voc precisa obter uma entrada do usurio e verificar se ela atende a uma condio de sada.</p>
<p><strong>Cenrio:</strong> Criar um loop simples que l a entrada do usurio, envia para uma funo (simulando o cliente Ollama) e para quando o usurio digita "sair".</p>
<p><strong>Sem o Operador Walrus 🙁</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">processar_prompt</span>(<span class="hljs-params">prompt</span>):</span>
    print(<span class="hljs-string">f"🤖 Processando: <span class="hljs-subst">{prompt}</span>"</span>)
    <span class="hljs-comment"># Aqui iria a chamada real para o cliente Ollama</span>
    <span class="hljs-comment"># client.chat(model="llama3", messages=[...])</span>

<span class="hljs-comment"># Precisamos ler a entrada uma vez fora do loop</span>
prompt = input(<span class="hljs-string">"Voc: "</span>)

<span class="hljs-comment">#  Checamos a condio</span>
<span class="hljs-keyword">while</span> prompt.lower() != <span class="hljs-string">"sair"</span>:
    processar_prompt(prompt)
    <span class="hljs-comment"># 3. E precisamos ler a entrada novamente dentro do loop</span>
    prompt = input(<span class="hljs-string">"Voc: "</span>)

print(<span class="hljs-string">"At logo!"</span>)
</code></pre>
<p><strong>Com o Operador Walrus 🙂</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">processar_prompt</span>(<span class="hljs-params">prompt</span>):</span>
    print(<span class="hljs-string">f"🤖 Processando: <span class="hljs-subst">{prompt}</span>"</span>)

<span class="hljs-comment"># 1. Lemos, atribumos e checamos TUDO NA CONDIO DO WHILE</span>
<span class="hljs-keyword">while</span> (prompt := input(<span class="hljs-string">"Voc: "</span>)).lower() != <span class="hljs-string">"sair"</span>:
    processar_prompt(prompt)

print(<span class="hljs-string">"At logo!"</span>)
</code></pre>
<ol>
<li><p><strong>Elimina a Duplicao:</strong> No precisamos mais da linha <code>prompt = input("Voc: ")</code> em dois lugares diferentes.</p>
</li>
<li><p><strong>Lgica Centralizada:</strong> A lgica de controle do loop (obter entrada e verificar a condio de parada) est toda concentrada na declarao <code>while</code>, tornando o cdigo mais fcil de entender.</p>
</li>
</ol>
<h2 id="heading-quando-usar-e-quando-evitar">Quando Usar e Quando Evitar</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Use o Operador Walrus (</strong><code>:=</code><strong>)</strong></td><td><strong>Evite o Operador Walrus (</strong><code>:=</code><strong>)</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Em condies <code>if</code> e <code>while</code> para evitar repetio.</td><td>Em expresses simples onde uma atribuio normal (<code>=</code>)  mais clara.</td></tr>
<tr>
<td>Quando o valor atribudo  usado imediatamente no mesmo contexto.</td><td>No nvel superior de um mdulo. Ele foi feito para ser usado dentro de expresses.</td></tr>
</tbody>
</table>
</div><blockquote>
<p><strong>Regra:</strong> Se o operador walrus torna seu cdigo mais limpo e fcil de entender, use-o. Se ele o torna mais crptico, prefira a forma tradicional.</p>
</blockquote>
]]></description><link>https://autonetops.com/operador-walrus-em-python</link><guid isPermaLink="true">https://autonetops.com/operador-walrus-em-python</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Git Pt.2]]></title><description><![CDATA[<h2 id="heading-comandos-avancados-quando-as-coisas-ficam-complicadas">Comandos Avanados: Quando as Coisas Ficam Complicadas</h2>
<p>O bsico (<code>add</code>, <code>commit</code>, <code>push</code>, <code>pull</code>) resolve 90% dos casos. Mas os outros 10% so onde os problemas crticos acontecem. Dominar os comandos a seguir  o que diferencia um usurio iniciante de um expert.</p>
<h3 id="heading-git-stash-salvando-seu-trabalho-temporariamente"><code>git stash</code><strong>: Salvando seu Trabalho Temporariamente</strong></h3>
<p><strong>Cenrio:</strong> Voc est no meio da configurao de uma nova poltica de BGP (<code>feature/bgp-policy</code>), mas um incidente urgente acontece e voc precisa verificar o estado de uma configurao no branch <code>main</code> imediatamente. Seu trabalho est incompleto e voc no quer fazer um commit "WIP" (Work in Progress).</p>
<p>O <code>git stash</code> salva suas modificaes no commitadas em uma "pilha" temporria e limpa seu diretrio de trabalho, deixando-o no estado do ltimo commit (<code>HEAD</code>).</p>
<pre><code class="lang-mermaid">graph TD
    A[Diretrio de Trabalho com Mudanas] -- git stash --&gt; B(Pilha de Stash);
    B -- git stash pop --&gt; C[Diretrio de Trabalho Restaurado];
</code></pre>
<p><strong>Cheatsheet do</strong> <code>stash</code>:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Comando</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>git stash</code></td><td>Salva as mudanas atuais na pilha de stash.</td></tr>
<tr>
<td><code>git stash list</code></td><td>Lista todos os stashes salvos.</td></tr>
<tr>
<td><code>git stash pop</code></td><td>Aplica o stash mais recente e o remove da pilha.</td></tr>
<tr>
<td><code>git stash apply</code></td><td>Aplica o stash mais recente, mas o mantm na pilha.</td></tr>
<tr>
<td><code>git stash drop</code></td><td>Descarta o stash mais recente.</td></tr>
</tbody>
</table>
</div><p><strong>Exemplo de fluxo:</strong></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Voc est no branch 'feature/bgp-policy' com trabalho no salvo</span>
git status <span class="hljs-comment"># Mostra arquivos modificados</span>

<span class="hljs-comment"># Salva o trabalho para atender a uma emergncia</span>
git stash

<span class="hljs-comment"># Muda para o branch principal para investigar</span>
git checkout main
<span class="hljs-comment"># ... faz a investigao ...</span>

<span class="hljs-comment"># Volta para seu branch de feature</span>
git checkout feature/bgp-policy

<span class="hljs-comment"># Restaura seu trabalho no salvo</span>
git stash pop

git status <span class="hljs-comment"># Seus arquivos modificados esto de volta!</span>
</code></pre>
<h3 id="heading-git-revert-vs-git-reset-a-batalha-pela-historia-do-git"><code>git revert</code> <strong>vs</strong> <code>git reset</code><strong>: A Batalha pela Histria do Git</strong></h3>
<p>Ambos os comandos desfazem mudanas, mas de maneiras fundamentalmente diferentes. A escolha errada aqui pode causar grandes problemas para sua equipe.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Caracterstica</strong></td><td><code>git revert &lt;commit&gt;</code></td><td><code>git reset --hard &lt;commit&gt;</code></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Ao</strong></td><td>Cria um <strong>novo commit</strong> que  o inverso do commit especificado.</td><td><strong>Move o ponteiro</strong> do branch para um commit anterior, descartando todos os commits posteriores.</td></tr>
<tr>
<td><strong>Histrico</strong></td><td><strong>No reescreve o histrico.</strong> Adiciona ao histrico.  seguro.</td><td><strong>Reescreve (destri) o histrico.</strong>  perigoso.</td></tr>
<tr>
<td><strong>Uso Principal</strong></td><td>Reverter um commit que <strong>j foi compartilhado</strong> com a equipe (ex: j est no <code>main</code>).</td><td>Desfazer commits <strong>locais</strong> que ainda no foram compartilhados.</td></tr>
<tr>
<td><strong>Colaborao</strong></td><td><strong>Seguro para branches compartilhados.</strong></td><td><strong>NUNCA use em branches compartilhados</strong> (como <code>main</code>).</td></tr>
</tbody>
</table>
</div><p><strong>Visualizando</strong> <code>git revert</code>:</p>
<p>Imagine que o commit <code>C</code> introduziu um bug em produo.</p>
<pre><code class="lang-mermaid">gitGraph
    commit id: "A"
    commit id: "B"
    commit id: "C" type: HIGHLIGHT
    commit id: "D"
    commit id: "C'" type: REVERSE msg: "Revert feat: Adiciona bug"
</code></pre>
<p>O <code>git revert C</code> cria um novo commit <code>C'</code> que desfaz as mudanas de <code>C</code>. O histrico  preservado e a mudana  transparente para todos.</p>
<p><strong>Visualizando</strong> <code>git reset</code>:</p>
<p>Agora, imagine que <code>C</code> e <code>D</code> so commits ruins que voc fez localmente e ainda no compartilhou.</p>
<pre><code class="lang-mermaid">gitGraph
    commit id: "A"
    commit id: "B"
    commit id: "C"
    commit id: "D"
</code></pre>
<p>Executar <code>git reset --hard B</code> mover o <code>HEAD</code> do <code>main</code> de volta para <code>B</code>, e os commits <code>C</code> e <code>D</code> sero perdidos (ou, mais precisamente, se tornaro rfos, aguardando para serem limpos pelo garbage collector do Git).</p>
<pre><code class="lang-mermaid">gitGraph
    commit id: "A"
    commit id: "B"
</code></pre>
<p><strong>Regra de ouro:</strong> Se o commit est no repositrio remoto (GitHub/GitLab), use <code>git revert</code>. Se o commit s existe na sua mquina local, <code>git reset</code>  uma opo.</p>
<h3 id="heading-git-rebase-reescrevendo-a-historia-para-um-futuro-mais-limpo"><code>git rebase</code>: Reescrevendo a Histria para um Futuro Mais Limpo</h3>
<p><strong>Cenrio:</strong> Voc criou seu branch <code>feature/nova-firewall-policy</code> a partir do <code>main</code>. Enquanto voc trabalhava, outros engenheiros mesclaram vrias outras mudanas no <code>main</code>. Seu branch de feature agora est desatualizado, e um <code>git merge main</code> criaria um "merge commit" que polui o histrico.</p>
<p>O <code>git rebase</code> resolve isso. Ele pega todos os commits do seu branch e os reaplica "em cima" do estado mais recente do branch alvo (<code>main</code>).</p>
<pre><code class="lang-mermaid">graph TD
    subgraph "Antes do Rebase"
        A((A)) --&gt; B((B)) --&gt; C((C&lt;br&gt;main))
        B --&gt; D((D)) --&gt; E((E&lt;br&gt;feature))
    end
    subgraph "Depois de 'git rebase main'"
        A2((A)) --&gt; B2((B)) --&gt; C2((C&lt;br&gt;main)) --&gt; D2((D')) --&gt; E2((E'&lt;br&gt;feature))
    end
    style C fill:#f9f,stroke:#333
    style E fill:#f9f,stroke:#333
    style C2 fill:#f9f,stroke:#333
    style E2 fill:#f9f,stroke:#333
</code></pre>
<p><strong>Fluxo de trabalho com</strong> <code>rebase</code>:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># No seu branch de feature</span>
git checkout feature/nova-firewall-policy

<span class="hljs-comment"># Busca as ltimas mudanas do remoto</span>
git fetch origin

<span class="hljs-comment"># Rebase do seu branch em cima do 'main' mais recente</span>
git rebase origin/main

<span class="hljs-comment"># Agora seu branch est atualizado e pronto para um merge limpo (fast-forward)</span>
</code></pre>
<blockquote>
<p><strong>Aviso:</strong> Assim como o <code>reset</code>, o <code>rebase</code> reescreve o histrico (os hashes dos commits <code>D</code> e <code>E</code> mudam para <code>D'</code> e <code>E'</code>). <strong>Nunca faa rebase de um branch que  compartilhado e usado por mltiplos desenvolvedores</strong> (como o <code>main</code>).  seguro para seus prprios branches de feature antes de abrir um PR.</p>
</blockquote>
<h3 id="heading-git-reflog-e-git-bisect-as-ferramentas-do-detetive"><code>git reflog</code> e <code>git bisect</code>: As Ferramentas do Detetive</h3>
<ul>
<li><p><code>git reflog</code> (Reference Log): Seu salva-vidas. O Git mantm um registro de quase tudo que voc faz (commits, resets, checkouts). Se voc usou <code>git reset</code> e acha que perdeu um commit para sempre, o <code>git reflog</code> mostrar o hash daquele commit perdido, e voc pode recuper-lo com <code>git checkout &lt;hash&gt;</code> ou <code>git cherry-pick &lt;hash&gt;</code>.  a sua rede de segurana pessoal.</p>
</li>
<li><p><code>git bisect</code>: O caador de bugs. Se voc sabe que um bug foi introduzido em algum momento nos ltimos 100 commits, mas no sabe onde, o <code>git bisect</code> automatiza a busca. Voc informa um commit "bom" (onde o bug no existia) e um commit "ruim" (onde o bug existe). O Git ento faz uma busca binria, fazendo checkout de commits no meio do caminho e perguntando a voc se o bug est presente. Em poucos passos, ele aponta o commit exato que introduziu a regresso. Isso  incrvel para encontrar qual mudana de configurao quebrou a conectividade.</p>
</li>
</ul>
]]></description><link>https://autonetops.com/git-pt2</link><guid isPermaLink="true">https://autonetops.com/git-pt2</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Git]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Git Workflows para NetDevOps: Um Cheatsheet Prático para gerenciar infraestrutura como Código]]></title><description><![CDATA[<p> medida que a automao de redes amadurece, passamos a tratar nossas configuraes, scripts e playbooks como o que realmente so: <strong>cdigo</strong>. E se estamos lidando com cdigo, precisamos de uma ferramenta para gerenciar seu ciclo de vida, controlar verses, facilitar a colaborao e garantir a integridade. Essa ferramenta  o <strong>Git</strong>. Para um engenheiro de redes, dominar o Git  to fundamental quanto entender os protocolos de roteamento</p>
<p>Adotar o Git como a <strong>fonte de versionamento</strong> para a configurao da sua rede transforma a maneira como voc opera. Mudanas deixam de ser comandos ad-hoc digitados em uma sesso SSH  meia-noite e passam a ser commits rastreveis, revisveis e, o mais importante, reversveis. O Git no  apenas um sistema de backup;  a base para uma operao de rede moderna, habilitando prticas como reviso por pares (code review), testes automatizados (CI/CD) e auditoria.</p>
<p>Este guia  um cheatsheet focado nos comandos que mais utilizo no Git e que vez ou outra preciso de um refresh.</p>
<h2 id="heading-por-que-git-para-redes-o-modelo-de-iac">Por que Git para Redes? O Modelo de IaC</h2>
<p>Infraestrutura como Cdigo (IaC)  a prtica de gerenciar e provisionar infraestrutura atravs de arquivos de definio legveis por mquina, em vez de configurao manual. O Git  o pilar que sustenta essa prtica.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Benefcio do Git para NetDevOps</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Controle de Verso</strong></td><td>Cada mudana na configurao da rede  um <code>commit</code>. Voc sabe quem mudou, o que mudou, por que mudou e quando mudou.</td></tr>
<tr>
<td><strong>Reversibilidade</strong></td><td>Uma mudana causou um problema? <code>git revert</code> permite reverter um commit especfico de forma segura, sem adivinhaes.</td></tr>
<tr>
<td><strong>Colaborao e Reviso</strong></td><td>O fluxo de Pull/Merge Request permite que as mudanas sejam revisadas por outros membros da equipe antes de serem aplicadas, reduzindo erros.</td></tr>
<tr>
<td><strong>Branching (Ramificao)</strong></td><td>Trabalhe em novas features (como a configurao de um novo datacenter) em um branch isolado, sem impactar a configurao de produo.</td></tr>
<tr>
<td><strong>Automao (GitOps)</strong></td><td>O repositrio Git se torna o gatilho para pipelines de CI/CD. Um <code>merge</code> no branch principal pode disparar um playbook Ansible para aplicar a configurao.</td></tr>
</tbody>
</table>
</div><h2 id="heading-git-cheatsheet-basico-para-o-dia-a-dia">Git Cheatsheet Bsico para o Dia a Dia</h2>
<p>Estes so os comandos que voc usar 90% do tempo. Mantenha esta lista por perto.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Comando</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>git status</code></td><td>Mostra o estado do seu diretrio de trabalho: arquivos modificados, novos, etc.</td></tr>
<tr>
<td><code>git add &lt;arquivo&gt;</code></td><td>Adiciona um arquivo modificado  rea de preparao (staging area).</td></tr>
<tr>
<td><code>git commit -m "msg"</code></td><td>Salva as mudanas da staging area no histrico do repositrio com uma mensagem.</td></tr>
<tr>
<td><code>git push</code></td><td>Envia seus commits locais para o repositrio remoto.</td></tr>
<tr>
<td><code>git pull</code></td><td>Baixa as mudanas do repositrio remoto e as mescla com seu branch local.</td></tr>
<tr>
<td><code>git checkout -b &lt;nome&gt;</code></td><td>Cria um novo branch e muda para ele. <strong>Sempre trabalhe em um branch!</strong></td></tr>
<tr>
<td><code>git checkout &lt;nome&gt;</code></td><td>Muda para um branch existente.</td></tr>
<tr>
<td><code>git merge &lt;branch&gt;</code></td><td>Mescla as mudanas de outro branch no seu branch atual.</td></tr>
<tr>
<td><code>git log --oneline</code></td><td>Mostra um histrico de commits de forma concisa.</td></tr>
<tr>
<td><code>git diff</code></td><td>Mostra as diferenas entre o seu diretrio de trabalho e o ltimo commit.</td></tr>
</tbody>
</table>
</div><h2 id="heading-o-workflow-de-feature-branch-um-padrao-para-netdevops">O Workflow de Feature Branch: Um Padro para NetDevOps</h2>
<p>Nunca, jamais, faa commit diretamente no branch <code>main</code> (ou <code>master</code>). O branch <code>main</code> deve sempre refletir o estado desejado da sua produo. Todas as mudanas devem seguir o <strong>Feature Branch Workflow</strong>.</p>
<pre><code class="lang-mermaid">sequenceDiagram
    participant Dev as Engenheiro
    participant Local as Repositrio Local
    participant Remote as Repositrio Remoto (GitHub)
    participant CI_CD as Pipeline CI/CD

    Dev-&gt;&gt;Local: git checkout main
    Dev-&gt;&gt;Local: git pull origin main
    Dev-&gt;&gt;Local: git checkout -b feature/nova-vlan
    Note over Dev,Local: Trabalha na nova feature
    Dev-&gt;&gt;Local: git add .
    Dev-&gt;&gt;Local: git commit -m "feat: Adiciona VLAN 100"
    Dev-&gt;&gt;Remote: git push origin feature/nova-vlan
    Dev-&gt;&gt;Remote: Abre Pull Request (PR)
    Remote-&gt;&gt;CI_CD: Dispara pipeline de CI (testes)
    CI_CD--&gt;&gt;Remote: Testes passaram
    Note over Remote: Outro engenheiro revisa e aprova o PR
    Remote-&gt;&gt;Local: Engenheiro mescla o PR no branch 'main'
    Remote-&gt;&gt;CI_CD: Dispara pipeline de CD (deploy)
    CI_CD--&gt;&gt;Remote: Deploy concludo com sucesso
</code></pre>
<p><strong>Cenrio:</strong> Voc precisa adicionar uma nova VLAN de voz (VLAN 100) em todos os switches de acesso.</p>
<p><strong>Passo a Passo do Workflow:</strong></p>
<ol>
<li><p><strong>Sincronize seu Repositrio Local:</strong> Antes de comear, garanta que seu branch <code>main</code> local est atualizado com o remoto.</p>
<pre><code class="lang-bash"> git checkout main
 git pull origin main
</code></pre>
</li>
<li><p><strong>Crie um Novo Branch para sua Mudana:</strong> O nome do branch deve ser descritivo.</p>
<pre><code class="lang-bash"> git checkout -b feature/add-voice-vlan-100
</code></pre>
</li>
<li><p><strong>Faa as Mudanas Necessrias:</strong> Modifique os arquivos de configurao, templates Jinja2, ou variveis do inventrio Ansible para adicionar a VLAN 100.</p>
<pre><code class="lang-bash"> <span class="hljs-comment"># Exemplo: editando um arquivo de variveis</span>
 <span class="hljs-comment"># vim group_vars/access_switches.yml</span>
</code></pre>
</li>
<li><p><strong>Teste suas Mudanas Localmente:</strong> Use ferramentas como <code>ansible-lint</code>, <code>pytest</code>, ou um laboratrio virtual (EVE-NG, GNS3) para validar que sua mudana funciona como esperado e no quebra nada.</p>
</li>
<li><p><strong>Faa o Commit das suas Mudanas:</strong> Adicione os arquivos modificados e faa o commit com uma mensagem clara, seguindo um padro como o <a target="_blank" href="https://www.conventionalcommits.org/">Conventional Commits</a>.</p>
<pre><code class="lang-bash"> git add group_vars/access_switches.yml
 git commit -m <span class="hljs-string">"feat: Adiciona VLAN 100 para o servio de voz"</span>
</code></pre>
</li>
<li><p><strong>Envie seu Branch para o Repositrio Remoto:</strong></p>
<pre><code class="lang-bash"> git push origin feature/add-voice-vlan-100
</code></pre>
</li>
<li><p><strong>Abra um Pull Request (PR) ou Merge Request (MR):</strong> Na interface do seu provedor Git (GitHub, GitLab, Bitbucket), abra um PR do seu branch (<code>feature/add-voice-vlan-100</code>) para o branch <code>main</code>.</p>
<ul>
<li><p>Descreva o <em>propsito</em> da mudana.</p>
</li>
<li><p>Associe o PR a um ticket do Jira ou outra ferramenta de gerenciamento.</p>
</li>
</ul>
</li>
<li><p><strong>Reviso por Pares (Code Review) e CI:</strong></p>
<ul>
<li><p>Outro membro da equipe revisa suas mudanas, sugere melhorias e, finalmente, aprova.</p>
</li>
<li><p>Um pipeline de CI  disparado automaticamente, rodando testes (<code>pytest</code>, <code>ansible-lint</code>) contra o seu branch para uma validao final.</p>
</li>
</ul>
</li>
<li><p><strong>Merge:</strong> Aps a aprovao e o sucesso do pipeline de CI, o PR  mesclado no branch <code>main</code>.</p>
</li>
<li><p><strong>Deploy (Opcional, mas recomendado - GitOps):</strong> O merge no <code>main</code> pode disparar um pipeline de CD (Continuous Deployment) que executa um playbook Ansible em produo, aplicando a mudana na rede real.</p>
</li>
<li><p><strong>Limpeza:</strong> Aps o merge, voc pode deletar o branch local e remoto.</p>
<pre><code class="lang-bash">git checkout main
git branch -d feature/add-voice-vlan-100
git push origin --delete feature/add-voice-vlan-100
</code></pre>
</li>
</ol>
<h2 id="heading-comandos-avancados-uteis-quando-as-coisas-dao-errado">Comandos Avanados teis (Quando as Coisas do Errado)</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Comando</strong></td><td><strong>Descrio</strong></td><td><strong>Quando Usar</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>git revert &lt;commit&gt;</code></td><td>Cria um novo commit que desfaz as mudanas de um commit anterior. <strong>Seguro para o histrico compartilhado.</strong></td><td>Quando uma mudana j mesclada no <code>main</code> causou um problema em produo.</td></tr>
<tr>
<td><code>git reset --hard &lt;commit&gt;</code></td><td>Move o ponteiro do branch para um commit anterior, descartando todas as mudanas posteriores. <strong>Perigoso, reescreve o histrico.</strong></td><td>Apenas em branches locais, para descartar commits que voc ainda no compartilhou.</td></tr>
<tr>
<td><code>git stash</code></td><td>Salva temporariamente suas mudanas no commitadas para que voc possa trocar de branch.</td><td>Quando voc precisa mudar para outro branch urgentemente, mas no quer fazer commit do seu trabalho inacabado.</td></tr>
<tr>
<td><code>git cherry-pick &lt;commit&gt;</code></td><td>Aplica um commit especfico de outro branch no seu branch atual.</td><td>Quando voc precisa de uma correo de bug que est em outro branch, mas no quer mesclar o branch inteiro.</td></tr>
</tbody>
</table>
</div><p><strong>Referncias:</strong></p>
<ol>
<li><p><a target="_blank" href="https://www.atlassian.com/git/tutorials">Atlassian Git Tutorial</a></p>
</li>
<li><p><a target="_blank" href="https://www.conventionalcommits.org/">Conventional Commits Specification</a></p>
</li>
<li><p><a target="_blank" href="https://www.datascience-school.com/git-flow-vs-github-flow/">Git Flow vs. GitHub Flow</a></p>
</li>
</ol>
]]></description><link>https://autonetops.com/git-workflows-para-netdevops-um-cheatsheet-pratico-para-gerenciar-infraestrutura-como-codigo</link><guid isPermaLink="true">https://autonetops.com/git-workflows-para-netdevops-um-cheatsheet-pratico-para-gerenciar-infraestrutura-como-codigo</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Git]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Conheça o UV: Guia Rápido]]></title><description><![CDATA[<p>Se voc trabalha com Python, especialmente em reas como automao de redes, sabe que a velocidade e a eficincia na gesto de dependncias e ambientes virtuais so cruciais. Ferramentas como <code>pip</code> e <code>virtualenv</code> so o padro h anos, mas um novo competidor chamado <code>uv</code>.</p>
<p>Desenvolvido pela Astral, o <code>uv</code>  um gerenciador de pacotes e projetos Python escrito em Rust. Ele foi projetado para ser um substituto completo e veloz para os fluxos de trabalho de <code>pip</code>, <code>pip-tools</code>, <code>pipx</code> e <code>virtualenv</code>. A promessa  uma performance de <strong>10 a 100 vezes mais rpida</strong> que as ferramentas tradicionais</p>
<h2 id="heading-por-que-usar-o-uv">Por que usar o <code>uv</code>?</h2>
<p>Antes de entrarmos nos comandos, vale a pena entender os benefcios:</p>
<ul>
<li><p><strong>Velocidade Extrema:</strong> Graas ao Rust e a um resolvedor de dependncias avanado, o <code>uv</code> instala e atualiza pacotes em uma frao do tempo do <code>pip</code>.</p>
</li>
<li><p><strong>Tudo em Um:</strong> Ele unifica as funcionalidades de vrias ferramentas em um nico executvel. Chega de instalar <code>virtualenv</code>, <code>pip-tools</code> e outros pacotes separadamente.</p>
</li>
<li><p><strong>Cache Inteligente:</strong> O <code>uv</code> utiliza um cache global de pacotes, evitando downloads repetidos entre diferentes projetos.</p>
</li>
<li><p><strong>Compatibilidade:</strong>  um substituto direto do pip, o que significa que voc pode us-lo com seus arquivos <code>requirements.txt</code> existentes sem nenhuma modificao.</p>
</li>
</ul>
<h2 id="heading-instalacao">Instalao</h2>
<p>A instalao do <code>uv</code>  simples e no requer uma instalao prvia de Python.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Sistema Operacional</td><td>Comando</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Linux / macOS</strong></td><td>`curl -LsSf <a target="_blank" href="https://astral.sh/uv/install.sh">https://astral.sh/uv/install.sh</a></td></tr>
</tbody>
</table>
</div><p>Aps a instalao, verifique se tudo ocorreu bem com o comando:</p>
<pre><code class="lang-bash">uv --version
</code></pre>
<h2 id="heading-guia-de-comandos-do-uv">Guia de Comandos do <code>uv</code></h2>
<p>Vamos detalhar os comandos mais importantes para o seu fluxo de trabalho.</p>
<h3 id="heading-ambientes-virtuais">Ambientes Virtuais</h3>
<p>O <code>uv</code> gerencia ambientes virtuais de forma nativa.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Comando</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>uv venv</code></td><td>Cria um novo ambiente virtual no diretrio <code>.venv</code>.  o equivalente a <code>python -m venv .venv</code>.</td></tr>
<tr>
<td><code>uv venv --python &lt;versao&gt;</code></td><td>Cria um ambiente virtual com uma verso especfica do Python (ex: <code>uv venv --python 3.11</code>)</td></tr>
</tbody>
</table>
</div><p><strong>Uso:</strong></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Cria o ambiente</span>
uv venv

<span class="hljs-comment"># Ativa o ambiente (Linux/macOS)</span>
<span class="hljs-built_in">source</span> .venv/bin/activate

<span class="hljs-comment"># Ativa o ambiente (Windows)</span>
.venv\Scripts\activate
</code></pre>
<h2 id="heading-gerenciamento-de-pacotes">Gerenciamento de Pacotes</h2>
<p>Esta  a principal funcionalidade do <code>uv</code>. Os comandos so intuitivos e substituem diretamente o <code>pip</code></p>
<p>Basicamente, se voce sabia trabalhar com o pip, nao tera dificuldades aqui.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Comando</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>uv pip install &lt;pacote&gt;</code></td><td>Instala um ou mais pacotes</td></tr>
<tr>
<td><code>uv pip install -r reqs.txt</code></td><td>Instala pacotes a partir de um arquivo de requerimentos.</td></tr>
<tr>
<td><code>uv pip uninstall &lt;pacote&gt;</code></td><td>Remove um pacote.</td></tr>
<tr>
<td><code>uv pip list</code></td><td>Lista os pacotes instalados no ambiente.</td></tr>
<tr>
<td><code>uv pip freeze &gt; reqs.txt</code></td><td>Gera um arquivo <code>requirements.txt</code> com os pacotes instalados.</td></tr>
</tbody>
</table>
</div><p><strong>Exemplo para Automao de Redes:</strong></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Instala as bibliotecas essenciais para automao</span>
uv pip install netmiko napalm nornir

<span class="hljs-comment"># Verifica os pacotes instalados</span>
uv pip list
</code></pre>
<h2 id="heading-sincronizacao-de-dependencias-estilo-pip-tools">Sincronizao de Dependncias (Estilo <code>pip-tools</code>)</h2>
<p>Para projetos mais robustos,  uma boa prtica fixar as verses das dependncias para garantir a reprodutibilidade. O <code>uv</code> simplifica isso.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Comando</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>uv add &lt;pacote&gt;</code></td><td>Adiciona um pacote ao seu <code>pyproject.toml</code> ou <code>requirements.txt</code> e o instala</td></tr>
<tr>
<td><code>uv sync</code></td><td>Instala as dependncias de um arquivo de lock (<code>requirements.lock</code> ou <code>pyproject.toml</code>).</td></tr>
<tr>
<td><code>uv pip compile pyproject.toml -o requirements.txt</code></td><td>Gera um arquivo <code>requirements.txt</code> a partir das dependncias de alto nvel do seu projeto.</td></tr>
</tbody>
</table>
</div><h2 id="heading-executando-comandos-e-ferramentas">Executando Comandos e Ferramentas</h2>
<p>O <code>uv</code> tambm substitui o <code>pipx</code>, permitindo executar ferramentas de linha de comando sem poluir seu ambiente global.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Comando</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>uv run &lt;comando&gt;</code></td><td>Executa um comando dentro do ambiente virtual do projeto (ex: <code>uv run python script.py</code>)</td></tr>
<tr>
<td><code>uvx &lt;comando&gt;</code></td><td>Executa um comando em um ambiente efmero, instalando as dependncias necessrias temporariamente.</td></tr>
</tbody>
</table>
</div><p><strong>Exemplo Prtico com</strong> <code>uvx</code>:</p>
<p>Imagine que voc quer formatar seu cdigo com o <code>black</code> sem instal-lo no seu projeto.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Formata todos os arquivos .py no diretrio atual</span>
uvx black .
</code></pre>
<blockquote>
<p>O <code>uv</code> baixar o <code>black</code> em um ambiente temporrio, o executar e depois o descartar. Simples assim!</p>
</blockquote>
<h2 id="heading-caso-de-uso-projeto-de-automacao-de-rede">Caso de Uso: Projeto de Automao de Rede</h2>
<p>Vamos simular o incio de um novo projeto para automatizar a coleta de fatos de dispositivos de rede usando <code>nornir</code>.</p>
<ol>
<li><p><strong>Crie o diretrio do projeto e inicialize o ambiente:</strong></p>
<pre><code class="lang-bash"> mkdir projeto-nornir
 <span class="hljs-built_in">cd</span> projeto-nornir
 uv venv
 <span class="hljs-built_in">source</span> .venv/bin/activate
</code></pre>
</li>
<li><p><strong>Instale as dependncias:</strong></p>
<p> O <code>nornir</code> precisa de plugins para se conectar aos dispositivos. Vamos instalar o <code>nornir</code> e o plugin para <code>netmiko</code>.</p>
<pre><code class="lang-bash"> uv pip install nornir nornir-netmiko
</code></pre>
<p> A instalao ser notavelmente mais rpida do que com o <code>pip</code>.</p>
</li>
<li><p><strong>Crie seu script de automao (</strong><code>coleta_fatos.py</code>):</p>
<pre><code class="lang-python"> <span class="hljs-keyword">from</span> nornir <span class="hljs-keyword">import</span> InitNornir
 <span class="hljs-keyword">from</span> nornir_netmiko <span class="hljs-keyword">import</span> netmiko_send_command
 <span class="hljs-keyword">from</span> nornir_utils.plugins.functions <span class="hljs-keyword">import</span> print_result

 nr = InitNornir(config_file=<span class="hljs-string">"config.yaml"</span>)

 result = nr.run(task=netmiko_send_command, command_string=<span class="hljs-string">"show version"</span>)

 print_result(result)
</code></pre>
</li>
<li><p><strong>Execute o script com</strong> <code>uv run</code>:</p>
<pre><code class="lang-bash"> uv run python coleta_fatos.py
</code></pre>
</li>
<li><p><strong>Gere o arquivo de requerimentos para compartilhar o projeto:</strong></p>
<pre><code class="lang-bash"> uv pip freeze &gt; requirements.txt
</code></pre>
</li>
</ol>
<p>Agora, qualquer colega de equipe pode recriar seu ambiente de forma rpida e determinstica com <code>uv venv</code> e <code>uv pip install -r requirements.txt</code>.</p>
<h2 id="heading-conclusao">Concluso</h2>
<p>O <code>uv</code>  uma melhoria na qualidade de vida para desenvolvedores Python ao unificar vrias funcionalidades em uma nica interface. Ele simplifica o fluxo de trabalho, reduz a complexidade e acelera o ciclo de desenvolvimento.</p>
<p>Para quem trabalha com automao de redes, onde a agilidade para testar scripts e gerenciar dependncias  fundamental, adotar o <code>uv</code>  um passo natural.</p>
<p><strong>Referncias:</strong></p>
<ol>
<li><a target="_blank" href="https://docs.astral.sh/uv/">Astral, <code>uv</code> - Documentao Oficial</a></li>
</ol>
]]></description><link>https://autonetops.com/conheca-o-uv-guia-rapido</link><guid isPermaLink="true">https://autonetops.com/conheca-o-uv-guia-rapido</guid><category><![CDATA[UV ]]></category><category><![CDATA[Python]]></category><category><![CDATA[pt-br]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Tutorial: Gerar Diagramas de Banco de Dados NetBox com SchemaSpy]]></title><description><![CDATA[<p>Enquanto tentava entender melhor alguns relacionamentos do banco de dados do <a target="_blank" href="https://netbox.readthedocs.io/"><strong>NetBox</strong></a>, senti falta de um diagrama de esquema. Aps procurar na documentao e no <a target="_blank" href="https://github.com/netbox-community/netbox">repositrio do cdigo</a>, no encontrei nada. Precisava de uma ferramenta que gerasse automaticamente diagramas a partir de um banco de dados existente.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730820986887/6836e7fe-364f-4c25-b52d-ef7900daeb60.png" alt class="image--center mx-auto" /></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Instalar Netbox com Docker <a target="_self" href="https://autonetops.com/how-to-set-up-netbox-with-docker">aqui</a></div>
</div>

<p>Uma pesquisa rpida me levou a algumas opes interessantes:</p>
<h3 id="heading-schemaspyhttpsschemaspyorg"><strong></strong> <a target="_blank" href="https://schemaspy.org/"><strong>SchemaSpy</strong></a></h3>
<p>Ferramenta open source baseada em Java que analisa os metadados do banco de dados e gera diagramas interativos em HTML, alm de relatrios detalhados.</p>
<p><strong>Ideal para:</strong> Gerar automaticamente relatrios e diagramas completos a partir de um banco de dados existente.</p>
<h3 id="heading-dbeaver"><strong> DBeaver</strong></h3>
<p>Ferramenta universal de gerenciamento de bancos de dados, compatvel com diversos sistemas (MySQL, PostgreSQL, Oracle, etc.). Permite gerar diagramas de esquemas a partir de um banco existente.</p>
<p><strong>Ideal para:</strong> Administrar mltiplos sistemas de banco e visualizar esquemas complexos.</p>
<h3 id="heading-dbschema"><strong> DbSchema</strong></h3>
<p>Ferramenta universal de banco de dados que pode realizar engenharia reversa p criar um diagrama visual, alm de permitir desenhar esquemas e export-los como SQL.</p>
<p><strong>Ideal para:</strong> Usurios que precisam de uma representao visual e tambm da funcionalidade de exportao em SQL.</p>
<h2 id="heading-schemaspy"><strong>SchemaSpy</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730821041481/e6e74dac-5984-4afd-8d17-75ae7255d582.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://schemaspy.readthedocs.io/en/latest/">Documentacao</a></p>
<p>Fiz uma nova instalao do NetBox via Docker e baixei o <strong>SchemaSpy</strong> a partir do <a target="_blank" href="https://hub.docker.com/r/schemaspy/schemaspy/">repositrio Docker Hub</a> junto com suas dependncias.</p>
<h3 id="heading-criando-o-diretorio-de-saida">Criando o diretrio de sada</h3>
<pre><code class="lang-bash">mkdir schemaspy
<span class="hljs-built_in">cd</span> schemaspy
</code></pre>
<h3 id="heading-criando-o-arquivo-de-configuracao-do-banco-de-dados">Criando o arquivo de configurao do banco de dados</h3>
<p>As informaes do banco de dados do NetBox esto no arquivo <code>/env/postgres.env</code>:</p>
<pre><code class="lang-python">POSTGRES_DB=netbox
POSTGRES_PASSWORD=FAKE_PASSWORD
POSTGRES_USER=netbox
</code></pre>
<p>Para entender os valores que podemos definir no arquivo de configurao, <a target="_blank" href="https://schemaspy.readthedocs.io/en/latest/configuration/databaseType.html#included">consulte</a></p>
<p>Crie um arquivo chamado <a target="_blank" href="http://postgresdb.properties"><code>postgresdb.properties</code></a> com o seguinte contedo:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Tipo de banco de dados. Execute com -dbhelp para mais detalhes</span>
schemaspy.t=pgsql11
<span class="hljs-comment"># Propriedades do banco: host, porta, nome, usurio e senha</span>
schemaspy.host=postgres
schemaspy.port=<span class="hljs-number">5432</span>
schemaspy.db=netbox
schemaspy.u=netbox
schemaspy.p=FAKE_PASSWORD
</code></pre>
<h3 id="heading-executando">Executando</h3>
<p>A documentao lista todas as opes necessrias.<br />Basta informar o caminho de sada, as credenciais do banco e o formato desejado.<br />O comando abaixo executa o container e gera o relatrio da estrutura do banco:</p>
<pre><code class="lang-bash">docker run \
    -v <span class="hljs-string">"<span class="hljs-variable">$PWD</span>/output:/output"</span> \
    --network netbox-docker_default \
    -v <span class="hljs-string">"./postgresdb.properties:/schemaspy.properties"</span> \
    schemaspy/schemaspy:latest
</code></pre>
<h3 id="heading-saida">Sada</h3>
<p>O SchemaSpy gera um <strong>relatrio navegvel em HTML</strong> dentro do diretrio <code>output</code>, repleto de informaes interessantes sobre o banco de dados.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730819151752/986e6efb-2845-4a1f-8cfa-b1da3afe3536.png" alt class="image--center mx-auto" /></p>
<p>Ao acessar a aba <strong>Relationships</strong>, voc ver um diagrama das tabelas e seus relacionamentos  exatamente o que eu estava procurando!</p>
<h3 id="heading-resultado">Resultado</h3>
<p>O SchemaSpy gera dois diagramas:</p>
<ul>
<li><p>Um <strong>compacto</strong></p>
</li>
<li><p>E outro <strong>amplo</strong>, localizado em <code>/diagrams/summary</code></p>
</li>
</ul>
<p>A verso do NetBox utilizada neste teste foi <strong>NetBox Community v4.1.6</strong>.</p>
<h3 id="heading-revisao">Reviso</h3>
<p>Os diagramas so bem detalhados, mas h <strong>muitas intersees de setas</strong>, o que pode dificultar a leitura.<br />Como o arquivo  exportado em <strong>HTML</strong>, <strong>no  possvel arrastar ou reorganizar as tabelas</strong>.</p>
<p>Abaixo est um exemplo da tabela <code>dcim_device</code>.  possvel perceber que, com o aumento de relacionamentos, o diagrama se torna mais denso:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730820180096/f23b5ecd-5b4a-4d19-b014-bc6e23441b58.png" alt class="image--center mx-auto" /></p>
<p>O <strong>SchemaSpy</strong>  uma ferramenta extremamente til para quem deseja compreender a estrutura de bancos de dados complexos como o do NetBox.</p>
]]></description><link>https://autonetops.com/tutorial-gerar-diagramas-de-banco-de-dados-netbox-com-schemaspy</link><guid isPermaLink="true">https://autonetops.com/tutorial-gerar-diagramas-de-banco-de-dados-netbox-com-schemaspy</guid><category><![CDATA[pt-br]]></category><category><![CDATA[netbox]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[O que é Automação de Redes e por que é Essencial para sua Carreira?]]></title><description><![CDATA[<h2 id="heading-introducao-a-revolucao-silenciosa-na-engenharia-de-redes">Introduo: A Revoluo Silenciosa na Engenharia de Redes</h2>
<p>Se voc trabalha com infraestrutura de TI, provavelmente j ouviu o termo "automao de redes" (ou <em>network automation</em>). Longe de ser apenas mais um <em>buzzword</em>, a automao de redes representa uma mudana fundamental na forma como projetamos, gerenciamos e operamos as redes. Para o profissional de redes no Brasil, entender e dominar essa disciplina no  mais um diferencial, mas uma necessidade para se manter relevante e competitivo no mercado.</p>
<h2 id="heading-a-realidade-da-gestao-de-redes-tradicional">A Realidade da Gesto de Redes Tradicional</h2>
<p>Vamos ser honestos: a maneira como gerenciamos redes por dcadas est se tornando insustentvel. O mtodo tradicional, baseado em acesso manual via CLI para configurar roteadores, switches e firewalls, um de cada vez, apresenta desafios significativos:</p>
<ul>
<li><p><strong>Erros Humanos:</strong> Uma simples digitao errada pode causar uma interrupo de servio ou uma falha de segurana. (E convenhamos que fazer uma change na madrugada aumenta nossas chances)</p>
</li>
<li><p><strong>Lentido:</strong> Implementar uma mudana em dezenas ou centenas de dispositivos manualmente  um processo lento, tedioso e que no escala.</p>
</li>
<li><p><strong>Inconsistncia:</strong> Garantir que todos os dispositivos tenham uma configurao padronizada  quase impossvel manualmente, levando a uma "deriva de configurao"</p>
</li>
<li><p><strong>Falta de Visibilidade:</strong> Obter uma viso completa do estado da rede muitas vezes requer a execuo de mltiplos comandos em diversos equipamentos, consolidando os dados manualmente.</p>
</li>
</ul>
<blockquote>
<p>"A complexidade das redes modernas, impulsionada pela nuvem, virtualizao e IoT, tornou a gesto manual uma barreira para a agilidade dos negcios." </p>
</blockquote>
<h2 id="heading-o-que-e-automacao-de-redes-afinal">O que  Automao de Redes, Afinal?</h2>
<p>A automao de redes  a prtica de usar software para automatizar o processo de configurao, gerenciamento, teste, implantao e operao de dispositivos de rede. Em vez de um engenheiro se conectar manualmente a um switch para configurar uma VLAN, ele escreve um script ou usa uma ferramenta que faz isso por ele de forma programtica.</p>
<p>Isso  possvel atravs de APIs, que permitem que softwares conversem com os equipamentos de rede e de ferramentas de automao que orquestram essas interaes em larga escala.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Tarefa Manual</strong></td><td><strong>Tarefa Automatizada</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Acessar 100 switches via SSH e configurar uma nova VLAN</td><td>Executar um <em>playbook</em> Ansible que configura a VLAN nos 100 switches em minutos</td></tr>
<tr>
<td>Coletar a verso do software de todos os roteadores da rede</td><td>Rodar um script Python com Netmiko para gerar um relatrio completo</td></tr>
<tr>
<td>Validar se as configuraes de BGP esto corretas em todos os peers</td><td>Usar testes automatizados para garantir a conformidade da configurao com um padro definido</td></tr>
</tbody>
</table>
</div><h2 id="heading-por-que-a-automacao-de-redes-e-importante">Por que a Automao de Redes  Importante?</h2>
<p>A automao no  sobre substituir engenheiros de rede, mas sim sobre <strong>potencializ-los</strong>. Ao automatizar tarefas repetitivas e de baixo valor, os engenheiros podem focar em atividades mais estratgicas, como o design da arquitetura da rede, planejamento de capacidade e inovao.</p>
<h3 id="heading-principais-beneficios">Principais Benefcios:</h3>
<ol>
<li><p><strong>Agilidade e Velocidade:</strong> Implemente mudanas e novos servios em minutos, no em semanas. A automao permite que a infraestrutura de rede acompanhe a velocidade do desenvolvimento de software e das necessidades do negcio.</p>
</li>
<li><p><strong>Reduo de Erros:</strong> Scripts e ferramentas executam tarefas de forma consistente e previsvel, eliminando os erros humanos que so a principal causa de interrupes de servio [2].</p>
</li>
<li><p><strong>Padronizao e Conformidade:</strong> Garanta que todos os dispositivos sigam uma configurao padro (golden configuration), facilitando a gesto e auditorias de segurana.</p>
</li>
<li><p><strong>Escalabilidade:</strong> Gerenciar 1.000 dispositivos se torna to simples quanto gerenciar 10. A automao permite que as equipes de rede gerenciem ambientes muito maiores e mais complexos com os mesmos recursos.</p>
</li>
<li><p><strong>Valorizao Profissional:</strong> Profissionais com habilidades em automao de redes so mais valorizados no mercado, com salrios significativamente maiores e acesso a melhores oportunidades de carreira.</p>
</li>
</ol>
<h2 id="heading-ferramentas-essenciais-para-comecar">Ferramentas Essenciais para Comear</h2>
<p>O universo da automao de redes  vasto, mas algumas ferramentas se destacam como fundamentais para quem est comeando:</p>
<ul>
<li><p><strong>Ansible:</strong> Uma ferramenta de automao de TI extremamente popular por sua simplicidade. Usa arquivos YAML, que so fceis de ler e escrever e no requer a instalao de agentes nos dispositivos de rede.</p>
</li>
<li><p><strong>Python:</strong> A linguagem de programao de fato para automao de redes. Sintaxe simples e um ecossistema de bibliotecas amplo a tornam uma escolha popular.</p>
</li>
<li><p><strong>Netmiko e Scrapli:</strong> Bibliotecas Python que simplificam a conexo via SSH com dispositivos de rede, permitindo enviar comandos e extrair informaes de forma estruturada.</p>
</li>
<li><p><strong>Git:</strong> Um sistema de controle de verso essencial para gerenciar seus scripts e playbooks. Tratar sua configurao de rede como cdigo (<em>Infrastructure as Code</em>)  um dos pilares da automao.</p>
</li>
</ul>
<h2 id="heading-como-comecar-sua-jornada-em-automacao-de-redes">Como Comear sua Jornada em Automao de Redes?</h2>
<p>A transio para a automao pode parecer intimidante, mas pode ser feita de forma gradual.</p>
<ol>
<li><p><strong>Comece com a Mentalidade Certa:</strong> Entenda que automao  uma jornada, no um destino. Comece pequeno, automatizando tarefas simples que voc realiza repetidamente.</p>
</li>
<li><p><strong>Aprenda os Fundamentos:</strong> Invista tempo para aprender os conceitos bsicos de Python e os princpios de funcionamento do Ansible. No  preciso ser um desenvolvedor, mas  crucial entender a lgica da programao.</p>
</li>
<li><p><strong>Pratique em Laboratrios:</strong> Crie um ambiente de laboratrio para testar seus scripts sem arriscar a rede de produo.</p>
</li>
<li><p><strong>Busque Conhecimento Estruturado:</strong> <a target="_blank" href="https://autonetops.com/courses/">Cursos especializados</a> podem acelerar drasticamente sua curva de aprendizado. Eles fornecem um caminho claro, exemplos prticos e o suporte de instrutores experientes.</p>
</li>
</ol>
<h2 id="heading-conclusao-o-futuro-da-engenharia-de-redes-e-automatizado">Concluso: O Futuro da Engenharia de Redes  Automatizado</h2>
<p>A automao de redes no  mais uma opo, mas uma evoluo natural da profisso de engenheiro de redes. Abraar essa mudana significa se tornar um profissional mais eficiente, estratgico e valorizado. As empresas no Brasil esto cada vez mais buscando talentos que possam construir e gerenciar redes modernas, geis e seguras.</p>
<p>Se voc est pronto para dar o prximo passo na sua carreira e se tornar um protagonista nesta transformao, a <strong>AutoNetOps</strong> est aqui para te ajudar. Somos a primeira comunidade do Brasil 100% focada em automao de redes, com cursos prticos e mentoria para te guiar nesta jornada.</p>
<p><strong>Explore nossos cursos de</strong> <a target="_blank" href="https://autonetops.com/courses/ansible"><strong>Ansible</strong></a><strong>, Python e</strong> <a target="_blank" href="https://autonetops.com/courses/netmiko-scrapli-napalm/"><strong>Netmiko</strong></a> <strong>e comece a automatizar hoje mesmo!</strong></p>
]]></description><link>https://autonetops.com/o-que-e-automacao-de-redes-e-por-que-e-essencial-para-sua-carreira</link><guid isPermaLink="true">https://autonetops.com/o-que-e-automacao-de-redes-e-por-que-e-essencial-para-sua-carreira</guid><category><![CDATA[automacao de redes]]></category><category><![CDATA[Network Automation]]></category><category><![CDATA[pt-br]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Além do Dictionary get(): Um método mais simples]]></title><description><![CDATA[<h2 id="heading-a-armadilha-sutil-do-dictget"><strong>A Armadilha Sutil do</strong> <code>dict.get()</code></h2>
<p>Se voc trabalha com automao de redes em Python,  provvel que tenha usado o mtodo <code>dict.get()</code> muitas vezes. Ele  extremamente til para evitar excees do tipo <code>KeyError</code> ao acessar configuraes de dispositivos ou dados de rede:</p>
<pre><code class="lang-python">network_config = {<span class="hljs-string">"ip"</span>: <span class="hljs-string">"192.168.1.1"</span>}
port = network_config.get(<span class="hljs-string">"port"</span>, <span class="hljs-number">80</span>)  <span class="hljs-comment"># defaults 80 se "port" estiver faltando</span>
</code></pre>
<p>Simples, n? Sem erros, sem travamentos, apenas um valor padro.</p>
<p>Mas aqui est o problema: embora o <code>dict.get()</code> seja prtico, ele  frequentemente <strong>superutilizado</strong> e, em alguns casos, <strong>no  a maneira mais clara ou legvel</strong> de lidar com chaves ausentes em configuraes de rede.</p>
<p>Neste artigo, vou mostrar <strong>abordagens mais limpas e Pythonicas</strong> que tornam seu cdigo mais seguro, legvel e fcil de manter.</p>
<h2 id="heading-por-que-o-dictget-nem-sempre-e-a-melhor-escolha"><strong>Por que o</strong> <code>dict.get()</code> <strong>Nem Sempre  a Melhor Escolha</strong></h2>
<p>O <code>dict.get()</code> parece inofensivo  primeira vista, mas vamos analisar as desvantagens no contexto de automao de redes:</p>
<blockquote>
<p><strong><em>Lgica</em></strong>*: Quando o valor default  dinmico (como uma porta padro calculada ou um endereo de gateway), a linha pode ficar poluda ou repetitiva.*</p>
<p><strong><em>Flexibilidade limitada</em></strong>*: Muitas vezes voc precisa retornar um valor padro e tambm armazen-lo no dicionrio para uso futuro  o* <code>dict.get()</code> <em>no faz isso automaticamente.</em></p>
</blockquote>
<p>Imagine que voc est lidando com configuraes de um roteador:</p>
<pre><code class="lang-python">mtu = device.get(<span class="hljs-string">"mtu"</span>, <span class="hljs-number">1500</span>)
</code></pre>
<p>Se voc precisar <strong>armazenar</strong> esse valor padro de volta no dicionrio <code>device</code>, pode acabar escrevendo:</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> <span class="hljs-string">"mtu"</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> device:
    device[<span class="hljs-string">"mtu"</span>] = <span class="hljs-number">1500</span>
mtu = device[<span class="hljs-string">"mtu"</span>]
</code></pre>
<p>Isso  verboso e propenso a erros. O Python oferece uma ferramenta melhor para esses casos.</p>
<h2 id="heading-conheca-o-setdefault-a-alternativa-mais-limpa"><strong>Conhea o</strong> <code>setdefault()</code>  <strong>A Alternativa Mais Limpa</strong></h2>
<p>Em vez de usar <code>get()</code> e atribuies manuais, o mtodo <code>setdefault()</code>  perfeito para automao de redes:</p>
<pre><code class="lang-python">mtu = device.setdefault(<span class="hljs-string">"mtu"</span>, <span class="hljs-number">1500</span>)
</code></pre>
<p>O que isso faz:</p>
<blockquote>
<p><em>Se</em> <code>"mtu"</code> <em>existe no dicionrio, retorna seu valor.</em></p>
<p><em>Se no existe, insere o valor padro (</em><code>1500</code><em>) no dicionrio e o retorna.</em></p>
</blockquote>
<p>Simples, conciso e explcito.</p>
<p>Vamos comparar:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Using get()</span>
mtu = device.get(<span class="hljs-string">"mtu"</span>, <span class="hljs-number">1500</span>)
<span class="hljs-keyword">if</span> <span class="hljs-string">"mtu"</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> device:
    device[<span class="hljs-string">"mtu"</span>] = <span class="hljs-number">1500</span>

<span class="hljs-comment"># Using setdefault()</span>
mtu = device.setdefault(<span class="hljs-string">"mtu"</span>, <span class="hljs-number">1500</span>)
</code></pre>
<p>A verso com <code>setdefault()</code>  mais curta, clara e garante que o dicionrio seja atualizado com o valor padro.</p>
<h2 id="heading-quando-preferir-o-setdefault-ao-inves-do-get"><strong>Quando Preferir o</strong> <code>setdefault()</code> <strong>ao invs do</strong> <code>get()</code></h2>
<p>Use o <code>setdefault()</code> quando:</p>
<blockquote>
<p><em>Voc precisa</em> <strong><em>buscar e inicializar</em></strong> <em>um valor de configurao ausente, como portas, IPs ou MTUs.</em></p>
<p><em>Voc trabalha com</em> <strong><em>dicionrios aninhados</em></strong> <em>(como configuraes de VLANs ou interfaces).</em></p>
<p><em>Voc quer</em> <strong><em>reduzir cdigo repetitivo</em></strong> <em>e manter a clareza em scripts de automao.</em></p>
</blockquote>
<p>Por exemplo, ao processar configuraes de interfaces de rede:</p>
<pre><code class="lang-python">interfaces = [<span class="hljs-string">"eth0"</span>, <span class="hljs-string">"eth1"</span>, <span class="hljs-string">"eth0"</span>, <span class="hljs-string">"eth2"</span>, <span class="hljs-string">"eth1"</span>]

interface_status = {}
<span class="hljs-keyword">for</span> interface <span class="hljs-keyword">in</span> interfaces:
    interface_status.setdefault(interface, {<span class="hljs-string">"status"</span>: <span class="hljs-string">"down"</span>, <span class="hljs-string">"vlans"</span>: []})[<span class="hljs-string">"vlans"</span>].append(<span class="hljs-number">10</span>)

print(interface_status)
<span class="hljs-comment"># {</span>
<span class="hljs-comment"># 'eth0': {'status': 'down', 'vlans': [10, 10]},</span>
<span class="hljs-comment"># 'eth1': {'status': 'down', 'vlans': [10, 10]},</span>
<span class="hljs-comment"># 'eth2': {'status': 'down', 'vlans': [10]}</span>
<span class="hljs-comment">#}</span>
</code></pre>
<p>Sem o <code>setdefault()</code>, voc precisaria verificar a existncia de cada chave antes de atualizar, adicionando linhas desnecessrias.</p>
<h2 id="heading-uma-abordagem-ainda-mais-limpa-o-defaultdict"><strong>Uma Abordagem Ainda Mais Limpa: O</strong> <code>defaultdict</code></h2>
<p>O mdulo <code>collections</code> do Python oferece o <code>defaultdict</code>, que  ideal para automao de redes:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> defaultdict

interface_status = defaultdict(<span class="hljs-keyword">lambda</span>: {<span class="hljs-string">"status"</span>: <span class="hljs-string">"down"</span>, <span class="hljs-string">"vlans"</span>: []})
<span class="hljs-keyword">for</span> interface <span class="hljs-keyword">in</span> interfaces:
    interface_status[interface][<span class="hljs-string">"vlans"</span>].append(<span class="hljs-number">10</span>)

print(dict(interface_status))
<span class="hljs-comment">#{</span>
<span class="hljs-comment"># 'eth0': {'status': 'down', 'vlans': [10, 10]},</span>
<span class="hljs-comment"># 'eth1': {'status': 'down', 'vlans': [10, 10]},</span>
<span class="hljs-comment"># 'eth2': {'status': 'down', 'vlans': [10]}</span>
}
</code></pre>
<p>Por que o <code>defaultdict</code> muitas vezes supera tanto o <code>get()</code> quanto o <code>setdefault()</code>:</p>
<blockquote>
<p><em>Inicializa chaves ausentes automaticamente.</em></p>
<p><em>Mantm seu cdigo mnimo.</em></p>
<p><em>Deixa a inteno cristalina: Quero um dicionrio que padro para configuraes de interface.</em></p>
</blockquote>
<p>Pense nele como um dicionrio mais inteligente que elimina verificaes repetitivas.</p>
<h2 id="heading-comparando-as-tres-abordagens"><strong>Comparando as Trs Abordagens</strong></h2>
<p>Vamos resumir com uma tabela de referncia rpida:</p>
<blockquote>
<p><code>dict.get(key, default)</code><em>: Retorna um valor com segurana ou um padro.</em></p>
</blockquote>
<p>Use quando <em>no precisa</em> armazenar o padro de volta no dicionrio.</p>
<blockquote>
<p><code>dict.setdefault(key, default)</code><em>: Retorna um valor se presente; caso contrrio, define e retorna o padro.</em></p>
</blockquote>
<p>Use quando precisa <em>buscar e inicializar</em>.</p>
<blockquote>
<p><code>collections.defaultdict</code><em>: Inicializa padres automaticamente para chaves ausentes.</em></p>
</blockquote>
<p>Use quando trabalha com <em>colees de configuraes</em> ou quando chaves ausentes so frequentes.</p>
<h2 id="heading-exemplo-do-mundo-real-gerenciamento-de-configuracoes-de-rede"><strong>Exemplo do Mundo Real: Gerenciamento de Configuraes de Rede</strong></h2>
<p>Imagine que voc est construindo um script para gerenciar configuraes de rede:</p>
<pre><code class="lang-python">device = {<span class="hljs-string">"hostname"</span>: <span class="hljs-string">"router1"</span>}

mtu = device.get(<span class="hljs-string">"mtu"</span>, <span class="hljs-number">1500</span>)  <span class="hljs-comment">#  Funciona, mas nao atualiza o device</span>
</code></pre>
<p>Mais tarde, algum inspeciona <code>device</code> e no v <code>"mtu"</code>. Confuso, n?</p>
<p>Em vez disso:</p>
<pre><code class="lang-python">mtu = device.setdefault(<span class="hljs-string">"mtu"</span>, <span class="hljs-number">1500</span>)
<span class="hljs-comment"># device = {"hostname": "router1", "mtu": 1500}</span>
</code></pre>
<p>Ou, se voc tem mltiplos padres:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> defaultdict

device = defaultdict(<span class="hljs-keyword">lambda</span>: <span class="hljs-string">"N/A"</span>)
device.update({<span class="hljs-string">"hostname"</span>: <span class="hljs-string">"router1"</span>})

print(device[<span class="hljs-string">"mtu"</span>])  <span class="hljs-comment"># N/A</span>
</code></pre>
<p>Agora seu dicionrio lida com chaves ausentes de forma elegante, e seu cdigo  mais previsvel.</p>
<h2 id="heading-o-custo-oculto-de-usar-get-demais"><strong>O Custo Oculto de Usar</strong> <code>get()</code> <strong>Demais</strong></h2>
<p>Depender muito do <code>get()</code> pode introduzir bugs sutis em scripts de automao:</p>
<blockquote>
<p><em>Voc pode esquecer de atualizar o dicionrio com os padres.</em></p>
<p><em>Seu cdigo pode esconder o fato de que algumas configuraes esto faltando.</em></p>
<p><em>Futuros mantenedores (ou o futuro voc) podem se perguntar por que alguns padres no foram persistidos.</em></p>
</blockquote>
<p>Sim, o <code>get()</code> tem seu lugar. Mas, muitas vezes, o <code>setdefault()</code> ou o <code>defaultdict</code> comunicam sua inteno de forma mais clara  e cdigo que comunica inteno  <em>sempre</em> mais limpo.</p>
<h2 id="heading-conclusao-escreva-codigo-que-seu-futuro-eu-agradecera"><strong>Concluso: Escreva Cdigo que seu Futuro Eu Agradecer</strong></h2>
<p>O Python nos oferece vrias ferramentas para lidar com chaves de dicionrio ausentes em automao de redes. Embora o <code>dict.get()</code> seja conveniente, nem sempre  a melhor escolha a longo prazo.</p>
<blockquote>
<p><em>Use o</em> <code>get()</code> <em>quando precisar apenas de um fallback rpido e somente leitura.</em></p>
<p><em>Use o</em> <code>setdefault()</code> <em>quando quiser buscar</em> <strong><em>e</em></strong> <em>inicializar em uma nica operao.</em></p>
<p><em>Adote o</em> <code>defaultdict</code> <em>quando lidar com colees de configuraes e chaves ausentes frequentes.</em></p>
</blockquote>
<p>Cdigo mais limpo no  apenas sobre menos linhas.  sobre clareza, manutenibilidade e expresso de inteno. Na prxima vez que voc instintivamente alcanar o <code>get()</code>, pare por um momento e pergunte a si mesmo: <em>Existe uma maneira mais limpa?</em></p>
]]></description><link>https://autonetops.com/alem-do-dictionary-get-um-metodo-mais-simples</link><guid isPermaLink="true">https://autonetops.com/alem-do-dictionary-get-um-metodo-mais-simples</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Como Usar Filtros Jinja: Exemplos Simples]]></title><description><![CDATA[<h1 id="heading-filtros-jinja2-guia-completo-com-exemplos-praticos">Filtros Jinja2: Guia Completo com Exemplos Prticos</h1>
<p>O Jinja2  uma poderosa biblioteca de templates para Python, amplamente utilizada para manipular dados diretamente em templates. Seus filtros embutidos permitem transformar e formatar dados de maneira eficiente. Este guia explora os filtros mais usados, com explicaes detalhadas, exemplos prticos e casos de uso reais, ajudando voc a aplicar o Jinja2 em projetos de automao, gerao de relatrios ou configuraes de rede.</p>
<h2 id="heading-agrupando-dados-com-o-filtro-batch"><strong>Agrupando Dados com o Filtro</strong> <code>batch</code></h2>
<h3 id="heading-proposito"><strong>Propsito</strong></h3>
<p>O filtro <code>batch</code> divide uma sequncia em sublistas (ou "lotes") com um nmero fixo de elementos.  ideal para organizar dados em grupos para exibio ou processamento em blocos.</p>
<h3 id="heading-sintaxe"><strong>Sintaxe</strong></h3>
<p><code>batch(value, linecount, fill_with=None)</code></p>
<ul>
<li><p><code>value</code>: Sequncia a ser agrupada.</p>
</li>
<li><p><code>linecount</code>: Nmero mximo de elementos por grupo.</p>
</li>
<li><p><code>fill_with</code> (opcional): Valor para preencher grupos incompletos.</p>
</li>
</ul>
<h3 id="heading-caso-de-uso"><strong>Caso de Uso</strong></h3>
<p>Organizar endereos IP em grupos para exibio em interfaces de usurio ou para processamento em lotes, como em scripts de automao de rede.</p>
<h3 id="heading-exemplo-1-agrupando-enderecos-ip"><strong>Exemplo 1: Agrupando Endereos IP</strong></h3>
<pre><code class="lang-yaml">{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">grupo</span> <span class="hljs-string">in</span> <span class="hljs-string">sflow_boxes|batch(2)</span> <span class="hljs-string">%</span>}  
<span class="hljs-string">Grupo</span> <span class="hljs-string">Sflow</span> {{ <span class="hljs-string">loop.index</span> }}<span class="hljs-string">:</span> {{ <span class="hljs-string">grupo</span> <span class="hljs-string">|</span> <span class="hljs-string">join("</span>, <span class="hljs-string">") }}  
{% endfor %}</span>
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">sflow_boxes:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.2</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.3</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.4</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.5</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">Grupo Sflow 1:</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span><span class="hljs-string">,</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.2</span>  
<span class="hljs-attr">Grupo Sflow 2:</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.3</span><span class="hljs-string">,</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.4</span>  
<span class="hljs-attr">Grupo Sflow 3:</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.5</span>
</code></pre>
<h3 id="heading-exemplo-2-preenchendo-grupos-incompletos"><strong>Exemplo 2: Preenchendo Grupos Incompletos</strong></h3>
<pre><code class="lang-yaml">{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">grupo</span> <span class="hljs-string">in</span> <span class="hljs-string">sflow_boxes|batch(3</span>, <span class="hljs-string">fill_with='N/A')</span> <span class="hljs-string">%</span>}  
<span class="hljs-string">Grupo</span> <span class="hljs-string">Sflow</span> {{ <span class="hljs-string">loop.index</span> }}<span class="hljs-string">:</span> {{ <span class="hljs-string">grupo</span> <span class="hljs-string">|</span> <span class="hljs-string">join("</span>, <span class="hljs-string">") }}  
{% endfor %}</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">Grupo Sflow 1:</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span><span class="hljs-string">,</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.2</span><span class="hljs-string">,</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.3</span>  
<span class="hljs-attr">Grupo Sflow 2:</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.4</span><span class="hljs-string">,</span> <span class="hljs-number">10.180</span><span class="hljs-number">.0</span><span class="hljs-number">.5</span><span class="hljs-string">,</span> <span class="hljs-string">N/A</span>
</code></pre>
<h2 id="heading-definindo-valores-padrao-com-o-filtro-default"><strong>Definindo Valores Padro com o Filtro</strong> <code>default</code></h2>
<h3 id="heading-proposito-1"><strong>Propsito</strong></h3>
<p>O filtro <code>default</code> retorna um valor padro quando a varivel est indefinida ou  avaliada como falsa (como <code>None</code>, <code>0</code>, <code>False</code> ou string vazia).  til para evitar erros em templates com dados ausentes.</p>
<h3 id="heading-sintaxe-1"><strong>Sintaxe</strong></h3>
<p><code>default(value, default_value='', boolean=False)</code></p>
<ul>
<li><p><code>value</code>: Varivel a ser verificada.</p>
</li>
<li><p><code>default_value</code>: Valor retornado se <code>value</code> for indefinido ou falso.</p>
</li>
<li><p><code>boolean</code> (opcional): Se <code>True</code>, considera valores falsos como indefinidos.</p>
</li>
</ul>
<h3 id="heading-caso-de-uso-1"><strong>Caso de Uso</strong></h3>
<p>Atribuir uma VLAN padro a interfaces de rede quando nenhuma VLAN  especificada.</p>
<h3 id="heading-exemplo"><strong>Exemplo</strong></h3>
<pre><code class="lang-yaml">{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">intf</span> <span class="hljs-string">in</span> <span class="hljs-string">interfaces</span> <span class="hljs-string">%</span>}  
<span class="hljs-string">interface</span> {{ <span class="hljs-string">intf.name</span> }}  
  <span class="hljs-string">switchport</span> <span class="hljs-string">mode</span> <span class="hljs-string">access</span>  
  <span class="hljs-string">switchport</span> <span class="hljs-string">access</span> <span class="hljs-string">vlan</span> {{ <span class="hljs-string">intf.vlan</span> <span class="hljs-string">|</span> <span class="hljs-string">default('10')</span> }}  
{<span class="hljs-string">%</span> <span class="hljs-string">endfor</span> <span class="hljs-string">%</span>}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">interfaces:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet1</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">50</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet2</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet3</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">60</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">interface</span> <span class="hljs-string">Ethernet1</span>  
  <span class="hljs-string">switchport</span> <span class="hljs-string">mode</span> <span class="hljs-string">access</span>  
  <span class="hljs-string">switchport</span> <span class="hljs-string">access</span> <span class="hljs-string">vlan</span> <span class="hljs-number">50</span>  
<span class="hljs-string">interface</span> <span class="hljs-string">Ethernet2</span>  
  <span class="hljs-string">switchport</span> <span class="hljs-string">mode</span> <span class="hljs-string">access</span>  
  <span class="hljs-string">switchport</span> <span class="hljs-string">access</span> <span class="hljs-string">vlan</span> <span class="hljs-number">10</span>  
<span class="hljs-string">interface</span> <span class="hljs-string">Ethernet3</span>  
  <span class="hljs-string">switchport</span> <span class="hljs-string">mode</span> <span class="hljs-string">access</span>  
  <span class="hljs-string">switchport</span> <span class="hljs-string">access</span> <span class="hljs-string">vlan</span> <span class="hljs-number">60</span>
</code></pre>
<h2 id="heading-ordenando-dicionarios-com-o-filtro-dictsort"><strong>Ordenando Dicionrios com o Filtro</strong> <code>dictsort</code></h2>
<h3 id="heading-proposito-2"><strong>Propsito</strong></h3>
<p>O filtro <code>dictsort</code> ordena dicionrios por chave ou valor, em ordem crescente ou decrescente, permitindo organizar dados no ordenados por padro no Python.</p>
<h3 id="heading-sintaxe-2"><strong>Sintaxe</strong></h3>
<p><code>dictsort(value, case_sensitive=False, by='key', reverse=False)</code></p>
<ul>
<li><p><code>value</code>: Dicionrio a ser ordenado.</p>
</li>
<li><p><code>case_sensitive</code>: Se <code>True</code>, diferencia maisculas de minsculas.</p>
</li>
<li><p><code>by</code>: Ordenar por <code>'key'</code> (padro) ou <code>'value'</code>.</p>
</li>
<li><p><code>reverse</code>: Se <code>True</code>, ordena em ordem decrescente.</p>
</li>
</ul>
<h3 id="heading-caso-de-uso-2"><strong>Caso de Uso</strong></h3>
<p>Organizar prefixos de rede por nome ou pares BGP por prioridade.</p>
<h3 id="heading-exemplo-1-ordenando-por-chave"><strong>Exemplo 1: Ordenando por Chave</strong></h3>
<pre><code class="lang-yaml">{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">pl_name</span>, <span class="hljs-string">pl_lines</span> <span class="hljs-string">in</span> <span class="hljs-string">prefix_lists</span> <span class="hljs-string">|</span> <span class="hljs-string">dictsort</span> <span class="hljs-string">%</span>}  
<span class="hljs-string">ip</span> <span class="hljs-string">prefix-list</span> {{ <span class="hljs-string">pl_name</span> }}  
  {{ <span class="hljs-string">pl_lines</span> <span class="hljs-string">|</span> <span class="hljs-string">join('\n</span>  <span class="hljs-string">') }}  
{% endfor %}</span>
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">prefix_lists:</span>  
  <span class="hljs-attr">pl-ntt-out:</span>  
    <span class="hljs-bullet">-</span> <span class="hljs-string">permit</span> <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-string">/23</span>  
  <span class="hljs-attr">pl-zayo-out:</span>  
    <span class="hljs-bullet">-</span> <span class="hljs-string">permit</span> <span class="hljs-number">10.0</span><span class="hljs-number">.1</span><span class="hljs-number">.0</span><span class="hljs-string">/24</span>  
  <span class="hljs-attr">pl-cogent-out:</span>  
    <span class="hljs-bullet">-</span> <span class="hljs-string">permit</span> <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-string">/24</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">ip</span> <span class="hljs-string">prefix-list</span> <span class="hljs-string">pl-cogent-out</span>  
  <span class="hljs-string">permit</span> <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-string">/24</span>  
<span class="hljs-string">ip</span> <span class="hljs-string">prefix-list</span> <span class="hljs-string">pl-ntt-out</span>  
  <span class="hljs-string">permit</span> <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-string">/23</span>  
<span class="hljs-string">ip</span> <span class="hljs-string">prefix-list</span> <span class="hljs-string">pl-zayo-out</span>  
  <span class="hljs-string">permit</span> <span class="hljs-number">10.0</span><span class="hljs-number">.1</span><span class="hljs-number">.0</span><span class="hljs-string">/24</span>
</code></pre>
<h3 id="heading-exemplo-2-ordenando-por-valor-prioridade"><strong>Exemplo 2: Ordenando por Valor (Prioridade)</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-attr">Pares BGP por prioridade:</span>  
{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">peer</span>, <span class="hljs-string">priority</span> <span class="hljs-string">in</span> <span class="hljs-string">peer_priority</span> <span class="hljs-string">|</span> <span class="hljs-string">dictsort(by='value'</span>, <span class="hljs-string">reverse=true)</span> <span class="hljs-string">%</span>}  
  <span class="hljs-attr">Par:</span> {{ <span class="hljs-string">peer</span> }}<span class="hljs-string">;</span> <span class="hljs-attr">Prioridade:</span> {{ <span class="hljs-string">priority</span> }}  
{<span class="hljs-string">%</span> <span class="hljs-string">endfor</span> <span class="hljs-string">%</span>}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">peer_priority:</span>  
  <span class="hljs-attr">ntt:</span> <span class="hljs-number">200</span>  
  <span class="hljs-attr">zayo:</span> <span class="hljs-number">300</span>  
  <span class="hljs-attr">cogent:</span> <span class="hljs-number">100</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">Pares BGP por prioridade:</span>  
  <span class="hljs-attr">Par:</span> <span class="hljs-string">zayo;</span> <span class="hljs-attr">Prioridade:</span> <span class="hljs-number">300</span>  
  <span class="hljs-attr">Par:</span> <span class="hljs-string">ntt;</span> <span class="hljs-attr">Prioridade:</span> <span class="hljs-number">200</span>  
  <span class="hljs-attr">Par:</span> <span class="hljs-string">cogent;</span> <span class="hljs-attr">Prioridade:</span> <span class="hljs-number">100</span>
</code></pre>
<h2 id="heading-convertendo-para-numeros-com-os-filtros-float-e-int"><strong>Convertendo para Nmeros com os Filtros</strong> <code>float</code> e <code>int</code></h2>
<h3 id="heading-filtro-float"><strong>Filtro</strong> <code>float</code></h3>
<h4 id="heading-proposito-3"><strong>Propsito</strong></h4>
<p>Converte um valor em nmero de ponto flutuante, til para operaes numricas ou comparaes com strings numricas.</p>
<h4 id="heading-sintaxe-3"><strong>Sintaxe</strong></h4>
<p><code>float(value, default=0.0)</code></p>
<ul>
<li><p><code>value</code>: Valor a ser convertido.</p>
</li>
<li><p><code>default</code>: Valor retornado se a converso falhar.</p>
</li>
</ul>
<h4 id="heading-caso-de-uso-3"><strong>Caso de Uso</strong></h4>
<p>Comparar verses de software representadas como strings.</p>
<h4 id="heading-exemplo-1"><strong>Exemplo</strong></h4>
<pre><code class="lang-yaml">{<span class="hljs-string">%</span> <span class="hljs-string">if</span> <span class="hljs-string">eos_ver</span> <span class="hljs-string">|</span> <span class="hljs-string">float</span> <span class="hljs-string">&gt;=</span> <span class="hljs-number">4.22</span> <span class="hljs-string">%</span>}  
<span class="hljs-string">Verso</span> <span class="hljs-string">EOS</span> {{ <span class="hljs-string">eos_ver</span> }}<span class="hljs-string">:</span> <span class="hljs-string">nova</span> <span class="hljs-string">sintaxe</span> <span class="hljs-string">de</span> <span class="hljs-string">comando.</span>  
{<span class="hljs-string">%</span> <span class="hljs-string">else</span> <span class="hljs-string">%</span>}  
<span class="hljs-string">Verso</span> <span class="hljs-string">EOS</span> {{ <span class="hljs-string">eos_ver</span> }}<span class="hljs-string">:</span> <span class="hljs-string">sintaxe</span> <span class="hljs-string">de</span> <span class="hljs-string">comando</span> <span class="hljs-string">antiga.</span>  
{<span class="hljs-string">%</span> <span class="hljs-string">endif</span> <span class="hljs-string">%</span>}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">eos_ver:</span> <span class="hljs-string">"4.10"</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">Verso</span> <span class="hljs-attr">EOS 4.10:</span> <span class="hljs-string">sintaxe</span> <span class="hljs-string">de</span> <span class="hljs-string">comando</span> <span class="hljs-string">antiga.</span>
</code></pre>
<h3 id="heading-filtro-int"><strong>Filtro</strong> <code>int</code></h3>
<h4 id="heading-proposito-4"><strong>Propsito</strong></h4>
<p>Converte um valor em nmero inteiro, com suporte para diferentes bases numricas (como hexadecimal).</p>
<h4 id="heading-sintaxe-4"><strong>Sintaxe</strong></h4>
<p><code>int(value, default=0, base=10)</code></p>
<ul>
<li><p><code>value</code>: Valor a ser convertido.</p>
</li>
<li><p><code>default</code>: Valor retornado se a converso falhar.</p>
</li>
<li><p><code>base</code>: Base numrica do valor (ex.: <code>16</code> para hexadecimal).</p>
</li>
</ul>
<h4 id="heading-caso-de-uso-4"><strong>Caso de Uso</strong></h4>
<p>Converter um Ethertype hexadecimal para decimal.</p>
<h4 id="heading-exemplo-2"><strong>Exemplo</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-string">Ethertype</span> <span class="hljs-string">LLDP</span>  
  <span class="hljs-attr">Hex:</span> {{ <span class="hljs-string">lldp_ethertype</span> }}  
  <span class="hljs-attr">Dec:</span> {{ <span class="hljs-string">lldp_ethertype</span> <span class="hljs-string">|</span> <span class="hljs-string">int(base=16)</span> }}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">lldp_ethertype:</span> <span class="hljs-string">88CC</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">Ethertype</span> <span class="hljs-string">LLDP</span>  
  <span class="hljs-attr">Hex:</span> <span class="hljs-string">88CC</span>  
  <span class="hljs-attr">Dec:</span> <span class="hljs-number">35020</span>
</code></pre>
<h2 id="heading-agrupando-por-atributo-com-o-filtro-groupby"><strong>Agrupando por Atributo com o Filtro</strong> <code>groupby</code></h2>
<h3 id="heading-proposito-5"><strong>Propsito</strong></h3>
<p>Agrupa objetos de uma sequncia com base em um atributo, ideal para relatrios ou organizao de dados.</p>
<h3 id="heading-sintaxe-5"><strong>Sintaxe</strong></h3>
<p><code>groupby(value, attribute)</code></p>
<ul>
<li><p><code>value</code>: Sequncia de objetos.</p>
</li>
<li><p><code>attribute</code>: Atributo para agrupamento (suporta notao de ponto, ex.: <code>interface.vlan</code>).</p>
</li>
</ul>
<h3 id="heading-caso-de-uso-5"><strong>Caso de Uso</strong></h3>
<p>Agrupar interfaces de rede por VLAN.</p>
<h3 id="heading-exemplo-3"><strong>Exemplo</strong></h3>
<pre><code class="lang-yaml">{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">vid</span>, <span class="hljs-string">members</span> <span class="hljs-string">in</span> <span class="hljs-string">interfaces</span> <span class="hljs-string">|</span> <span class="hljs-string">groupby('vlan')</span> <span class="hljs-string">%</span>}  
<span class="hljs-string">Interfaces</span> <span class="hljs-string">na</span> <span class="hljs-string">VLAN</span> {{ <span class="hljs-string">vid</span> }}<span class="hljs-string">:</span> {{ <span class="hljs-string">members</span> <span class="hljs-string">|</span> <span class="hljs-string">map(attribute='name')</span> <span class="hljs-string">|</span> <span class="hljs-string">join("</span>, <span class="hljs-string">") }}  
{% endfor %}</span>
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">interfaces:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet1</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">50</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet2</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">50</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet3</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">60</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">Interfaces na VLAN 50:</span> <span class="hljs-string">Ethernet1,</span> <span class="hljs-string">Ethernet2</span>  
<span class="hljs-attr">Interfaces na VLAN 60:</span> <span class="hljs-string">Ethernet3</span>
</code></pre>
<h2 id="heading-concatenando-listas-com-o-filtro-join"><strong><mark>Concatenando Listas com o Filtro </mark></strong> <code>join</code></h2>
<h3 id="heading-proposito-6"><strong>Propsito</strong></h3>
<p>Une elementos de uma sequncia em uma nica string, com um delimitador especificado.</p>
<h3 id="heading-sintaxe-6"><strong>Sintaxe</strong></h3>
<p><code>join(value, d='', attribute=None)</code></p>
<ul>
<li><p><code>value</code>: Sequncia a ser unida.</p>
</li>
<li><p><code>d</code>: Delimitador (padro: string vazia).</p>
</li>
<li><p><code>attribute</code>: Atributo a ser extrado, se os elementos forem objetos.</p>
</li>
</ul>
<h3 id="heading-caso-de-uso-6"><strong>Caso de Uso</strong></h3>
<p>Exibir servidores de nomes em uma nica linha.</p>
<h3 id="heading-exemplo-4"><strong>Exemplo</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-string">ip</span> <span class="hljs-string">name-server</span> {{ <span class="hljs-string">name_servers</span> <span class="hljs-string">|</span> <span class="hljs-string">join("</span> <span class="hljs-string">") }}</span>
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">name_servers:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">1.1</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">8.8</span><span class="hljs-number">.8</span><span class="hljs-number">.8</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">9.9</span><span class="hljs-number">.9</span><span class="hljs-number">.9</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">ip</span> <span class="hljs-string">name-server</span> <span class="hljs-number">1.1</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span> <span class="hljs-number">8.8</span><span class="hljs-number">.8</span><span class="hljs-number">.8</span> <span class="hljs-number">9.9</span><span class="hljs-number">.9</span><span class="hljs-number">.9</span>
</code></pre>
<h2 id="heading-transformando-dados-com-o-filtro-map"><strong><mark>Transformando Dados com o Filtro </mark></strong> <code>map</code></h2>
<h3 id="heading-proposito-7"><strong>Propsito</strong></h3>
<p>Aplica um filtro ou extrai um atributo de todos os elementos de uma sequncia.</p>
<h3 id="heading-sintaxe-7"><strong>Sintaxe</strong></h3>
<p><code>map(*args, **kwargs)</code></p>
<ul>
<li><code>*args</code>: Nome de um filtro (ex.: <code>"lower"</code>) ou atributo a extrair (ex.: <code>attribute='name'</code>).</li>
</ul>
<h3 id="heading-caso-de-uso-1-normalizando-nomes"><strong>Caso de Uso 1: Normalizando Nomes</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-attr">Dispositivos:</span>  
{{ <span class="hljs-string">devices</span> <span class="hljs-string">|</span> <span class="hljs-string">map('lower')</span> <span class="hljs-string">|</span> <span class="hljs-string">join('\n')</span> }}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">devices:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-string">Core-rtr-warsaw-01</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-string">DIST-Rtr-Prague-01</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">Dispositivos:</span>  
<span class="hljs-string">core-rtr-warsaw-01</span>  
<span class="hljs-string">dist-rtr-prague-01</span>
</code></pre>
<h3 id="heading-caso-de-uso-2-extraindo-atributos"><strong>Caso de Uso 2: Extraindo Atributos</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-attr">Interfaces:</span>  
{{ <span class="hljs-string">interfaces</span> <span class="hljs-string">|</span> <span class="hljs-string">map(attribute='name')</span> <span class="hljs-string">|</span> <span class="hljs-string">join('\n')</span> }}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">interfaces:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet1</span>  
    <span class="hljs-attr">mode:</span> <span class="hljs-string">switched</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet2</span>  
    <span class="hljs-attr">mode:</span> <span class="hljs-string">routed</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">Interfaces:</span>  
<span class="hljs-string">Ethernet1</span>  
<span class="hljs-string">Ethernet2</span>
</code></pre>
<h2 id="heading-filtrando-dados-com-os-filtros-select-e-reject"><strong>Filtrando Dados com os Filtros</strong> <code>select</code> e <code>reject</code></h2>
<h3 id="heading-filtro-select"><strong>Filtro</strong> <code>select</code></h3>
<h4 id="heading-proposito-8"><strong>Propsito</strong></h4>
<p>Mantm elementos de uma sequncia que passam em um teste Jinja2.</p>
<h4 id="heading-sintaxe-8"><strong>Sintaxe</strong></h4>
<p><code>select(*args, **kwargs)</code></p>
<ul>
<li><p><code>*args</code>: Nome do teste (ex.: <code>"gt"</code>).</p>
</li>
<li><p><code>**kwargs</code>: Argumentos adicionais para o teste.</p>
</li>
</ul>
<h4 id="heading-caso-de-uso-7"><strong>Caso de Uso</strong></h4>
<p>Listar apenas nmeros de AS BGP privados (&gt;64495).</p>
<h4 id="heading-exemplo-5"><strong>Exemplo</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-attr">AS BGP privados:</span>  
{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">as_no</span> <span class="hljs-string">in</span> <span class="hljs-string">as_numbers</span> <span class="hljs-string">|</span> <span class="hljs-string">select('gt'</span>, <span class="hljs-number">64495</span><span class="hljs-string">)</span> <span class="hljs-string">%</span>}  
{{ <span class="hljs-string">as_no</span> }}  
{<span class="hljs-string">%</span> <span class="hljs-string">endfor</span> <span class="hljs-string">%</span>}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">as_numbers:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">1794</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">65203</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-number">65099</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">AS BGP privados:</span>  
<span class="hljs-number">65203</span>  
<span class="hljs-number">65099</span>
</code></pre>
<h3 id="heading-filtro-reject"><strong>Filtro</strong> <code>reject</code></h3>
<h4 id="heading-proposito-9"><strong>Propsito</strong></h4>
<p>Remove elementos de uma sequncia que passam em um teste Jinja2.</p>
<h4 id="heading-caso-de-uso-8"><strong>Caso de Uso</strong></h4>
<p>Listar apenas nmeros de AS BGP pblicos (64495).</p>
<h4 id="heading-exemplo-6"><strong>Exemplo</strong></h4>
<pre><code class="lang-yaml"><span class="hljs-string">AS</span> <span class="hljs-string">BGP</span> <span class="hljs-string">pblicos:</span>  
{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">as_no</span> <span class="hljs-string">in</span> <span class="hljs-string">as_numbers</span> <span class="hljs-string">|</span> <span class="hljs-string">reject('gt'</span>, <span class="hljs-number">64495</span><span class="hljs-string">)</span> <span class="hljs-string">%</span>}  
{{ <span class="hljs-string">as_no</span> }}  
{<span class="hljs-string">%</span> <span class="hljs-string">endfor</span> <span class="hljs-string">%</span>}
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-string">AS</span> <span class="hljs-string">BGP</span> <span class="hljs-string">pblicos:</span>  
<span class="hljs-number">1794</span>
</code></pre>
<h2 id="heading-filtrando-atributos-com-o-filtro-rejectattr"><strong>Filtrando Atributos com o Filtro</strong> <code>rejectattr</code></h2>
<h3 id="heading-proposito-10"><strong>Propsito</strong></h3>
<p>Remove objetos de uma sequncia cujo atributo passa em um teste especfico.</p>
<h3 id="heading-sintaxe-9"><strong>Sintaxe</strong></h3>
<p><code>rejectattr(*args, **kwargs)</code></p>
<ul>
<li><p><code>*args</code>: Atributo e nome do teste (ex.: <code>"mode", "eq"</code>).</p>
</li>
<li><p><code>**kwargs</code>: Argumentos adicionais.</p>
</li>
</ul>
<h3 id="heading-caso-de-uso-9"><strong>Caso de Uso</strong></h3>
<p>Listar apenas interfaces roteadas, excluindo as no modo "switched".</p>
<h3 id="heading-exemplo-7"><strong>Exemplo</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-attr">Interfaces roteadas:</span>  
{<span class="hljs-string">%</span> <span class="hljs-string">for</span> <span class="hljs-string">intf</span> <span class="hljs-string">in</span> <span class="hljs-string">interfaces</span> <span class="hljs-string">|</span> <span class="hljs-string">rejectattr('mode'</span>, <span class="hljs-string">'eq'</span>, <span class="hljs-string">'switched'</span><span class="hljs-string">)</span> <span class="hljs-string">%</span>}  
{{ <span class="hljs-string">intf.name</span> }}  
{<span class="hljs-string">%</span> <span class="hljs-string">endfor</span> <span class="hljs-string">%</span>}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">interfaces:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet1</span>  
    <span class="hljs-attr">mode:</span> <span class="hljs-string">switched</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet2</span>  
    <span class="hljs-attr">mode:</span> <span class="hljs-string">routed</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">Interfaces roteadas:</span>  
<span class="hljs-string">Ethernet2</span>
</code></pre>
<h2 id="heading-convertendo-para-json-com-o-filtro-tojson"><strong>Convertendo para JSON com o Filtro</strong> <code>tojson</code></h2>
<h3 id="heading-proposito-11"><strong>Propsito</strong></h3>
<p>Converte uma estrutura de dados Python em uma string JSON, til para APIs ou depurao.</p>
<h3 id="heading-sintaxe-10"><strong>Sintaxe</strong></h3>
<p><code>tojson(value, indent=None)</code></p>
<ul>
<li><p><code>value</code>: Estrutura de dados a ser convertida.</p>
</li>
<li><p><code>indent</code>: Nmero de espaos para indentao.</p>
</li>
</ul>
<h3 id="heading-caso-de-uso-10"><strong>Caso de Uso</strong></h3>
<p>Gerar uma representao JSON de interfaces para uma API.</p>
<h3 id="heading-exemplo-8"><strong>Exemplo</strong></h3>
<pre><code class="lang-yaml">{{ <span class="hljs-string">interfaces</span> <span class="hljs-string">|</span> <span class="hljs-string">tojson(indent=2)</span> }}
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">interfaces:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet1</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">50</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet2</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">60</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml">[
  {
    <span class="hljs-attr">"name":</span> <span class="hljs-string">"Ethernet1"</span>,
    <span class="hljs-attr">"vlan":</span> <span class="hljs-number">50</span>
  },
  {
    <span class="hljs-attr">"name":</span> <span class="hljs-string">"Ethernet2"</span>,
    <span class="hljs-attr">"vlan":</span> <span class="hljs-number">60</span>
  }
]
</code></pre>
<h2 id="heading-extraindo-valores-unicos-com-o-filtro-unique"><strong>Extraindo Valores nicos com o Filtro</strong> <code>unique</code></h2>
<h3 id="heading-proposito-12"><strong>Propsito</strong></h3>
<p>Retorna valores nicos de uma coleo, frequentemente usado com <code>map</code> para extrair atributos distintos.</p>
<h3 id="heading-sintaxe-11"><strong>Sintaxe</strong></h3>
<p><code>unique(value, case_sensitive=False, attribute=None)</code></p>
<ul>
<li><p><code>value</code>: Coleo de dados.</p>
</li>
<li><p><code>case_sensitive</code>: Se <code>True</code>, diferencia maisculas de minsculas.</p>
</li>
<li><p><code>attribute</code>: Atributo para extrair valores nicos.</p>
</li>
</ul>
<h3 id="heading-caso-de-uso-11"><strong>Caso de Uso</strong></h3>
<p>Listar VLANs de acesso nicas em uso.</p>
<h3 id="heading-exemplo-9"><strong>Exemplo</strong></h3>
<pre><code class="lang-yaml"><span class="hljs-attr">VLANs em uso:</span> {{ <span class="hljs-string">interfaces</span> <span class="hljs-string">|</span> <span class="hljs-string">map(attribute='vlan')</span> <span class="hljs-string">|</span> <span class="hljs-string">unique</span> <span class="hljs-string">|</span> <span class="hljs-string">join("</span>, <span class="hljs-string">") }}</span>
</code></pre>
<p><strong>Dados:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">interfaces:</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet1</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">50</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet2</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">50</span>  
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Ethernet3</span>  
    <span class="hljs-attr">vlan:</span> <span class="hljs-number">60</span>
</code></pre>
<p><strong>Resultado:</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">VLANs em uso:</span> <span class="hljs-number">50</span><span class="hljs-string">,</span> <span class="hljs-number">60</span>
</code></pre>
<h2 id="heading-referencias"><strong>Referncias</strong></h2>
<ul>
<li><p><a target="_blank" href="https://jinja.palletsprojects.com/en/stable/">Documentao Oficial do Jinja</a></p>
</li>
<li><p><a target="_blank" href="https://realpython.com/primer-on-jinja-templating/">Primer on Jinja Templating - Real Python</a></p>
</li>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/python/best-practices-for-jinja-templating/">Best Practices for Jinja Templating - GeeksforGeeks</a></p>
</li>
<li><p><a target="_blank" href="https://community.dataops.live/guides-47/mastering-jinja2-templating-for-dataops-best-practices-and-pitfalls-150">Mastering Jinja2 Templating for DataOps - DataOps.live</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@mrinal.k.sardar/python-jinja-templating-library-use-cases-and-examples-bfac2002ffdf">Python Jinja Templating: Use Cases and Examples - Medium</a></p>
</li>
</ul>
]]></description><link>https://autonetops.com/como-usar-filtros-jinja-exemplos-simples</link><guid isPermaLink="true">https://autonetops.com/como-usar-filtros-jinja-exemplos-simples</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Jinja2]]></category><category><![CDATA[Jinja python]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Metodologias de Desenvolvimento: Ágil, Scrum, Lean e Cascata]]></title><description><![CDATA[<h2 id="heading-metodologia-agil-agile">Metodologia gil - AGILE</h2>
<p>A metodologia gil  uma abordagem flexvel para o desenvolvimento de software que valoriza a <mark>adaptao s mudanas</mark>, colaborao e entrega rpida de resultados. Ela surgiu com o <strong>Manifesto gil</strong>, um documento que define quatro valores principais:</p>
<ol>
<li><p><strong>Indivduos e interaes</strong> acima de processos e ferramentas.</p>
</li>
<li><p><strong>Software funcionando</strong> acima de documentao extensiva.</p>
</li>
<li><p><strong>Colaborao com o cliente</strong> acima de negociaes contratuais.</p>
</li>
<li><p><strong>Resposta s mudanas</strong> acima de seguir um plano rgido.</p>
</li>
</ol>
<p><strong>Explicao simplificada</strong>:<br />Imagine que voc est construindo uma casa. Em vez de planejar cada detalhe no incio e s mostrar o resultado final, a metodologia gil permite que voc mostre ao cliente uma parte funcional da casa a cada poucas semanas, ajustando o projeto conforme o feedback. Isso garante que o produto final atenda s necessidades reais.</p>
<h3 id="heading-principios-do-manifesto-agil">Princpios do Manifesto gil</h3>
<p>O Manifesto gil tambm lista 12 princpios que orientam como colocar esses valores em prtica:</p>
<ol>
<li><p><strong>Foco no cliente</strong>: Satisfazer o cliente com entregas contnuas e valiosas.</p>
</li>
<li><p><strong>Adaptao s mudanas</strong>: Aceitar alteraes nos requisitos, mesmo no final do projeto.</p>
</li>
<li><p><strong>Entregas frequentes</strong>: Entregar software funcional regularmente, preferencialmente a cada 2 a 4 semanas.</p>
</li>
<li><p><strong>Colaborao</strong>: Desenvolvedores e clientes devem trabalhar juntos diariamente.</p>
</li>
<li><p><strong>Equipes motivadas</strong>: Criar um ambiente que motive a equipe, dando confiana e autonomia.</p>
</li>
<li><p><strong>Comunicao direta</strong>: Preferir conversas presenciais ou videochamadas para alinhar ideias.</p>
</li>
<li><p><strong>Software funcional</strong>: A principal medida de progresso  o software que realmente funciona.</p>
</li>
<li><p><strong>Ritmo sustentvel</strong>: Promover um ritmo de trabalho que a equipe possa manter indefinidamente.</p>
</li>
<li><p><strong>Ambiente gil</strong>: Criar uma cultura que facilite mudanas rpidas e eficientes.</p>
</li>
<li><p><strong>Simplicidade</strong>: Fazer apenas o necessrio, evitando trabalho desnecessrio.</p>
</li>
<li><p><strong>Equipes auto-organizveis</strong>: Permitir que as equipes decidam como realizar o trabalho.</p>
</li>
<li><p><strong>Melhoria contnua</strong>: Refletir regularmente sobre como melhorar processos e resultados.</p>
</li>
</ol>
<p><strong>Exemplo prtico</strong>:<br />Uma equipe est desenvolvendo um aplicativo de delivery. Em vez de criar todo o app de uma vez, ela entrega primeiro a funcionalidade de busca de restaurantes. O cliente testa, d feedback, e a equipe ajusta antes de desenvolver o sistema de pedidos.</p>
<pre><code class="lang-mermaid">graph TD
    A[Planejamento] --&gt; B[Desenvolvimento]
    B --&gt; C[Testes]
    C --&gt; D[Entrega ao Cliente]
    D --&gt; E[Feedback]
    E --&gt; A
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C fill:#bfb,stroke:#333,stroke-width:2px
    style D fill:#fbf,stroke:#333,stroke-width:2px
    style E fill:#ffb,stroke:#333,stroke-width:2px
</code></pre>
<hr />
<h2 id="heading-scrum-uma-implementacao-do-agil">Scrum: Uma Implementao do gil</h2>
<p>O <strong>Scrum</strong>  uma das formas mais populares de aplicar a metodologia gil. Ele <mark>organiza </mark> o trabalho em equipes pequenas (geralmente de 5 a 10 pessoas) que trabalham em ciclos curtos chamados <strong>sprints</strong>.</p>
<h4 id="heading-componentes-do-scrum">Componentes do Scrum</h4>
<ol>
<li><p><strong>Histrias de Usurio</strong>: So pequenas tarefas que descrevem uma funcionalidade do ponto de vista do usurio. Exemplo: "Como cliente, quero buscar restaurantes por tipo de comida para escolher onde pedir."</p>
</li>
<li><p><strong>Backlog</strong>: Uma lista priorizada de todas as funcionalidades (histrias de usurio) que o projeto precisa. O <strong>Product Owner</strong> (representante do cliente) decide a ordem de prioridade.</p>
</li>
<li><p><strong>Sprints</strong>: Ciclos curtos onde a equipe desenvolve, testa e entrega uma ou mais histrias de usurio. No final de cada sprint, o software deve estar funcional.</p>
</li>
<li><p><strong>Reunies Dirias (Daily)</strong>: Reunies rpidas (menos de 15 minutos) onde cada membro da equipe responde:</p>
<ul>
<li><p>O que fiz ontem?</p>
</li>
<li><p>O que vou fazer hoje?</p>
</li>
<li><p>H algum obstculo?</p>
</li>
</ul>
</li>
<li><p><strong>Reviso do Sprint</strong>: No final do sprint, a equipe apresenta o software ao cliente para feedback.</p>
</li>
<li><p><strong>Retrospectiva</strong>: A equipe reflete sobre o que funcionou bem e o que pode melhorar no prximo sprint.</p>
</li>
</ol>
<p><strong>Exemplo prtico</strong>:<br />A equipe de desenvolvimento do app de delivery planeja um sprint de 2 semanas para criar a funcionalidade de busca de restaurantes. Durante o sprint, eles se renem diariamente para alinhar o progresso. No final, mostram a funcionalidade ao cliente, que sugere adicionar filtros por preo. A equipe ajusta o backlog para incluir essa mudana no prximo sprint.</p>
<pre><code class="lang-mermaid">graph TD
    A[Backlog] --&gt;|Planejamento do Sprint| B[Sprint 2-4 semanas]
    B --&gt; C[Desenvolvimento]
    C --&gt; D[Testes]
    D --&gt; E[Reviso do Sprint]
    E --&gt; F[Entrega do Incremento]
    F --&gt; G[Retrospectiva]
    G --&gt;|Feedback| A
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C fill:#bfb,stroke:#333,stroke-width:2px
    style D fill:#fbf,stroke:#333,stroke-width:2px
    style E fill:#ffb,stroke:#333,stroke-width:2px
    style F fill:#bff,stroke:#333,stroke-width:2px
    style G fill:#fbf,stroke:#333,stroke-width:2px
</code></pre>
<hr />
<h2 id="heading-lean-foco-em-valor-e-eficiencia">Lean: Foco em Valor e Eficincia</h2>
<p>A metodologia <strong>Lean</strong> foca em <strong><mark>minimizar desperdcios</mark></strong> enquanto <strong>maximiza o valor entregue ao cliente</strong>. Ela  frequentemente usada junto com o gil ou Scrum.</p>
<h3 id="heading-principios-do-lean">Princpios do Lean</h3>
<ol>
<li><p><strong>Eliminar desperdcios</strong>: Qualquer coisa que no agrega valor ao cliente  considerada desperdcio. Os sete tipos de desperdcio so:</p>
<ul>
<li><p>Trabalho incompleto (cdigo parcialmente desenvolvido)</p>
</li>
<li><p>Processos extras (reunies desnecessrias)</p>
</li>
<li><p>Funcionalidades extras (adicionar recursos que o cliente no pediu)</p>
</li>
<li><p>Troca de tarefas (multitarefa que reduz a produtividade)</p>
</li>
<li><p>Espera (aguardar aprovao ou recursos)</p>
</li>
<li><p>Movimentao (deslocamentos desnecessrios entre ferramentas ou equipes)</p>
</li>
<li><p>Defeitos (erros que exigem retrabalho)</p>
</li>
</ul>
</li>
<li><p><strong>Amplificar o aprendizado</strong>: Sprints curtos permitem que a equipe aprenda rapidamente com feedback do cliente, ajustando o produto para entregar mais valor.</p>
</li>
<li><p><strong>Decidir o mais tarde possvel</strong>: Evitar decises prematuras permite maior flexibilidade. Exemplo: No escolher uma tecnologia especfica at entender todas as necessidades do projeto.</p>
</li>
<li><p><strong>Entregar o mais rpido possvel</strong>: Entregas rpidas geram feedback imediato, reduzem desperdcios e garantem que o cliente receba o que precisa agora.</p>
</li>
<li><p><strong>Otimizar o todo</strong>: Cada membro da equipe deve entender o impacto de suas decises no projeto como um todo, evitando solues que beneficiem apenas uma parte.</p>
</li>
</ol>
<p><strong>Exemplo prtico</strong>:<br />No desenvolvimento do app de delivery, a equipe Lean percebe que adicionar um recurso de inteligncia artificial para recomendaes de restaurantes no foi solicitado pelo cliente. Eles removem essa ideia do backlog para evitar desperdcio de tempo e recursos.</p>
<pre><code class="lang-mermaid">graph TD
    A[Identificar Valor] --&gt; B[Mapear Fluxo de Valor]
    B --&gt; C[Eliminar Desperdcios]
    C --&gt; D[Entrega Rpida]
    D --&gt; E[Feedback do Cliente]
    E --&gt; F[Melhoria Contnua]
    F --&gt; A
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C fill:#bfb,stroke:#333,stroke-width:2px
    style D fill:#fbf,stroke:#333,stroke-width:2px
    style E fill:#ffb,stroke:#333,stroke-width:2px
    style F fill:#bff,stroke:#333,stroke-width:2px
</code></pre>
<p><strong>Explicao do diagrama</strong>:<br />O Lean comea identificando o que  valioso para o cliente, mapeia o processo para eliminar desperdcios, entrega rapidamente, coleta feedback e melhora continuamente.</p>
<hr />
<h2 id="heading-metodologia-cascata-waterfall">Metodologia Cascata (Waterfall)</h2>
<p>A metodologia <strong>Cascata</strong>  uma abordagem tradicional e linear, onde <mark>cada fase do projeto deve ser concluda antes de iniciar a prxima. No h como voltar s fases anteriores</mark>, exceto em casos excepcionais (como erros encontrados nos testes).</p>
<h3 id="heading-fases-da-metodologia-cascata">Fases da Metodologia Cascata</h3>
<ol>
<li><p><strong>Requisitos</strong>: Define o que o software deve fazer, documentado em um documento de requisitos. Exemplo: "O app deve permitir pedidos de comida online."</p>
</li>
<li><p><strong>Anlise</strong>: Analisa o sistema para criar modelos e lgica que sero usados no desenvolvimento.</p>
</li>
<li><p><strong>Design do Programa</strong>: Define detalhes tcnicos, como linguagem de programao, banco de dados e arquitetura.</p>
</li>
<li><p><strong>Codificao</strong>: Escreve o cdigo-fonte do software.</p>
</li>
<li><p><strong>Testes</strong>: Identifica e corrige erros. Se forem encontrados problemas graves, pode ser necessrio repetir a fase de codificao.</p>
</li>
<li><p><strong>Operaes</strong>: Inclui implantao, suporte e manuteno do software.</p>
</li>
</ol>
<p><strong>Exemplo prtico</strong>:<br />No desenvolvimento do app de delivery, a equipe Cascata passa meses definindo todos os requisitos antes de comear a codificar. S depois de terminar o cdigo completo  que o cliente v o produto final, o que pode levar a ajustes caros se houver mudanas.</p>
<pre><code class="lang-mermaid">graph TD
    A[Requisitos] --&gt; B[Anlise]
    B --&gt; C[Design]
    C --&gt; D[Codificao]
    D --&gt; E[Testes]
    E --&gt; F[Operaes]
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#bbf,stroke:#333,stroke-width:2px
    style C fill:#bfb,stroke:#333,stroke-width:2px
    style D fill:#fbf,stroke:#333,stroke-width:2px
    style E fill:#ffb,stroke:#333,stroke-width:2px
    style F fill:#bff,stroke:#333,stroke-width:2px
</code></pre>
<p><strong>Explicao do diagrama</strong>:<br />A Cascata  um processo linear. Cada fase  concluda antes da prxima, sem possibilidade de voltar, exceto em casos de erros nos testes.</p>
<hr />
<h2 id="heading-comparacao-entre-agil-lean-e-cascata">Comparao entre gil, Lean e Cascata</h2>
<p>Para facilitar a compreenso, aqui est uma tabela comparativa:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Caracterstica</strong></td><td><strong>gil (Scrum)</strong></td><td><strong>Lean</strong></td><td><strong>Cascata</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Flexibilidade</strong></td><td>Alta, adapta-se a mudanas</td><td>Alta, foca em eliminar desperdcios</td><td>Baixa, segue plano rgido</td></tr>
<tr>
<td><strong>Entregas</strong></td><td>Frequentes, a cada 2-4 semanas</td><td>Rpidas, conforme valor ao cliente</td><td>nica, no final do projeto</td></tr>
<tr>
<td><strong>Feedback do Cliente</strong></td><td>Contnuo, em cada sprint</td><td>Contnuo, para ajustar o valor</td><td>Tarde, apenas no final</td></tr>
<tr>
<td><strong>Tamanho da Equipe</strong></td><td>Pequena (5-10 pessoas)</td><td>Varivel</td><td>Pode ser grande, com papis definidos</td></tr>
<tr>
<td><strong>Exemplo de Uso</strong></td><td>Apps, startups, projetos dinmicos</td><td>Produtos com foco em eficincia</td><td>Projetos com requisitos fixos, como infraestrutura</td></tr>
</tbody>
</table>
</div>]]></description><link>https://autonetops.com/metodologias-de-desenvolvimento-agil-scrum-lean-e-cascata</link><guid isPermaLink="true">https://autonetops.com/metodologias-de-desenvolvimento-agil-scrum-lean-e-cascata</guid><category><![CDATA[pt-br]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Cheat Sheet de Automação de Rede: Ferramentas de Suporte]]></title><description><![CDATA[<p>Este <em>cheat sheet</em> oferece um guia conciso para ferramentas que me ajudam durante alguns cenarios pontuais de automao de rede antes de iniciar a criar cdigo, incluindo passos de instalao, exemplos de uso e referncias. Vamos comear!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729240573535/5a93cea4-c87a-479a-9508-3096e119bc7a.png" alt="Network Automation" class="image--center mx-auto" /></p>
<h2 id="heading-visao-geral-das-ferramentas">Viso Geral das Ferramentas</h2>
<p>As seguintes ferramentas so essenciais para automao de rede, abrangendo SSH, SNMP e protocolos baseados em YANG:</p>
<ul>
<li><p><strong>SSH</strong>: Para acesso seguro via linha de comando e operaes NETCONF.</p>
<ul>
<li><p><strong>NAPALM</strong>: Uma biblioteca Python para automao de rede multi-fornecedor.</p>
</li>
<li><p><strong>Netmiko</strong>: Uma biblioteca Python para automao de dispositivos via SSH.</p>
</li>
</ul>
</li>
<li><p><strong>SNMP</strong>: Para monitoramento e gerenciamento de dispositivos de rede.</p>
<ul>
<li><strong>NET-SNMP</strong>: Um conjunto de ferramentas para operaes SNMP.</li>
</ul>
</li>
<li><p><strong>YANG-based</strong>:</p>
<ul>
<li><p><strong>Cisco YANG Suite</strong>: Uma ferramenta para explorar e testar modelos YANG.</p>
</li>
<li><p><strong>GNMIc/Pygnmi</strong>: Ferramentas para interaes com o protocolo gNMI.</p>
</li>
<li><p><strong>SSH (NETCONF)</strong>: Para gerenciamento de dispositivos baseado em YANG via NETCONF.</p>
</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-napalm">NAPALM</h2>
<p>NAPALM simplifica o gerenciamento de dispositivos de rede por meio de uma API unificada. Pode ser usado via CLI ou integrado em scripts Python.</p>
<h3 id="heading-instalacao">Instalao</h3>
<p>Instale o NAPALM usando pip:</p>
<pre><code class="lang-bash">pip3 install napalm
</code></pre>
<h3 id="heading-referencia">Referncia</h3>
<ul>
<li><a target="_blank" href="https://napalm.readthedocs.io/en/latest/">NAPALM Documentation</a></li>
</ul>
<h3 id="heading-uso">Uso</h3>
<p>Execute o NAPALM via CLI para interagir com dispositivos:</p>
<pre><code class="lang-bash">napalm --user &lt;username&gt; --password &lt;password&gt; --vendor &lt;driver&gt; &lt;ip_address&gt; call &lt;getter&gt;
</code></pre>
<h4 id="heading-exemplo-getfacts">Exemplo: <code>get_facts</code></h4>
<p>Obtenha informaes do dispositivo, como hostname, modelo e verso do sistema operacional:</p>
<pre><code class="lang-bash">napalm --user admin --password admin --vendor ios 192.168.1.1 call get_facts
</code></pre>
<p><strong>Getters:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728940208781/b0e3e059-93b3-4d1c-b2ad-acc791c8b933.png" alt="NAPALM get_facts" class="image--center mx-auto" /></p>
<p><strong>Resultado</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728940174292/9f96f06f-78dc-4cec-8aec-f833e82fc7f4.png" alt="Resultado NAPALM" class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-gnmic">GNMIc</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749670273035/ba63eccc-6e0a-4452-a562-acdf55175cfd.png" alt="GNMIc" class="image--center mx-auto" /></p>
<p>GNMIc  uma ferramenta CLI poderosa para interagir com dispositivos de rede via protocolo gNMI (<em>gRPC Network Management Interface</em>), ideal para telemetria e configurao.</p>
<h3 id="heading-instalacao-1">Instalao</h3>
<p>Instale o GNMIc usando o script de instalao fornecido:</p>
<pre><code class="lang-bash">bash -c <span class="hljs-string">"<span class="hljs-subst">$(curl -sL https://get-gnmic.kmrd.dev)</span>"</span>
</code></pre>
<h3 id="heading-referencia-1">Referncia</h3>
<ul>
<li><a target="_blank" href="https://gnmic.openconfig.net/">GNMIc Documentation</a></li>
</ul>
<h3 id="heading-comandos-comuns">Comandos Comuns</h3>
<h4 id="heading-capabilities">CAPABILITIES</h4>
<p>Verifique as capacidades gNMI de um dispositivo:</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure capabilities
</code></pre>
<p><strong>Exemplo</strong>:</p>
<pre><code class="lang-bash">gnmic -a 10.80.255.30:6030 -u admin -p admin --insecure capabilities
</code></pre>
<h4 id="heading-get">GET</h4>
<p>Obtenha um instantneo de dados do dispositivo usando um caminho especfico:</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure get --path <span class="hljs-string">"/components/component/state/temperature"</span>
</code></pre>
<h4 id="heading-set">SET</h4>
<p>Modifique o estado do dispositivo (consulte a <a target="_blank" href="https://gnmic.openconfig.net/cmd/set/">Documentao de Set do GNMIc</a>):</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure <span class="hljs-built_in">set</span> --update-path <span class="hljs-string">"/interfaces/interface[name=Management1]/config/description"</span> --update-value <span class="hljs-string">"Atualizado via gNMI"</span>
</code></pre>
<h4 id="heading-subscribe">SUBSCRIBE</h4>
<p>Inscreva-se para receber dados de telemetria em tempo real:</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure subscribe --path <span class="hljs-string">"/interfaces/interface[name=Management1]/state/counters"</span>
</code></pre>
<h4 id="heading-gnmi-prompt">GNMI Prompt</h4>
<p>Inicie uma sesso interativa com credenciais pr-configuradas:</p>
<pre><code class="lang-bash">gnmic --insecure --username admin --password admin --address &lt;ip:port&gt; prompt
</code></pre>
<hr />
<h2 id="heading-net-snmp">NET-SNMP</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749670353681/a2ee3ee3-fc1e-4485-9c32-5d0ae5743eb1.png" alt="NET-SNMP" class="image--center mx-auto" /></p>
<p>NET-SNMP  um conjunto de ferramentas para interagir com dispositivos habilitados para SNMP, permitindo consultas e gerenciamento de estatsticas de rede.</p>
<h3 id="heading-instalacao-2">Instalao</h3>
<p>Siga o guia oficial para instalao:</p>
<ul>
<li><a target="_blank" href="http://www.net-snmp.org/wiki/index.php/Tutorials">NET-SNMP Tutorial</a></li>
</ul>
<h3 id="heading-oids-comuns-do-snmp">OIDs Comuns do SNMP</h3>
<p>Principais OIDs para estatsticas de interface (MIB-II, RFC 1213):</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Nome do OID</td><td>Valor do OID</td><td>Descrio</td></tr>
</thead>
<tbody>
<tr>
<td><code>ifInOctets</code></td><td><code>.1.3.6.1.2.1.2.2.1.10</code></td><td>Bytes recebidos em uma interface</td></tr>
<tr>
<td><code>ifOutOctets</code></td><td><code>.1.3.6.1.2.1.2.2.1.16</code></td><td>Bytes enviados por uma interface</td></tr>
<tr>
<td><code>ifInErrors</code></td><td><code>.1.3.6.1.2.1.2.2.1.14</code></td><td>Erros de entrada</td></tr>
<tr>
<td><code>ifOutErrors</code></td><td><code>.1.3.6.1.2.1.2.2.1.20</code></td><td>Erros de sada</td></tr>
</tbody>
</table>
</div><h3 id="heading-consultando-estatisticas-de-interface">Consultando Estatsticas de Interface</h3>
<p>Consulte dispositivos habilitados para SNMP (por exemplo, IP <code>192.168.1.1</code>, <em>community string</em> <code>public</code>). Substitua <code>IF_INDEX</code> pelo ndice da interface (descoberto via <code>ifDescr</code>).</p>
<h4 id="heading-exemplo-snmpv2c">Exemplo (SNMPv2c):</h4>
<pre><code class="lang-bash">snmpget -v2c -c public 192.168.1.1 .1.3.6.1.2.1.2.2.1.10.IF_INDEX .1.3.6.1.2.1.2.2.1.16.IF_INDEX
snmpget -v2c -c public 192.168.1.1 SNMPv2-MIB::sysUpTime.0 <span class="hljs-comment"># Tempo de atividade do sistema</span>
snmpbulkwalk -v2c -c public 192.168.1.1 .1.0.8802.1.1.2.1.4.1.1.9 <span class="hljs-comment"># Vizinhos LLDP</span>
</code></pre>
<h4 id="heading-exemplo-snmpv3">Exemplo (SNMPv3):</h4>
<p>Obtenha o nome do sistema com SNMPv3:</p>
<pre><code class="lang-bash">snmpget -v3 -u USERNAME -a SHA -x AES -l authPriv -A AUTHPASS -X PRIVPASS 192.168.1.1 .1.3.6.1.2.1.1.5.0
</code></pre>
<hr />
<h2 id="heading-cisco-yang-suite">Cisco YANG Suite</h2>
<p><img src="https://www.packetswitch.co.uk/content/images/2023/10/Screenshot-2023-10-18-at-13.46.09.png" alt="Cisco YANG Suite" /></p>
<p>O Cisco YANG Suite  uma ferramenta baseada em navegador para explorar e testar modelos YANG, ideal para operaes NETCONF e RESTCONF.</p>
<h3 id="heading-instalacao-3">Instalao</h3>
<p>Instale via Docker ou pip. Consulte o repositrio oficial:</p>
<ul>
<li><a target="_blank" href="https://github.com/CiscoDevNet/yangsuite">Cisco YANG Suite GitHub</a></li>
</ul>
<h3 id="heading-executando-o-yang-suite">Executando o YANG Suite</h3>
<p>Inicie o <em>suite</em>:</p>
<pre><code class="lang-bash">yangsuite
</code></pre>
<p>Acesse a interface web para explorar modelos YANG e executar operaes.</p>
<hr />
<h2 id="heading-ssh-netconf">SSH (NETCONF)</h2>
<p>O NETCONF sobre SSH permite o gerenciamento de dispositivos baseado em YANG.  til para obter esquemas e realizar operaes.</p>
<h3 id="heading-iniciando-uma-sessao-netconf">Iniciando uma Sesso NETCONF</h3>
<p>Inicie uma sesso NETCONF (porta padro 830):</p>
<pre><code class="lang-bash">ssh -s &lt;username&gt;@&lt;device-ip&gt; -p 830 netconf
</code></pre>
<p>Isso abre uma sesso interativa para operaes NETCONF, como obter esquemas YANG ou configurar dispositivos.</p>
<p><strong>Nota</strong>: Embora o NETCONF sobre SSH seja suportado, ferramentas como NAPALM ou GNMIc frequentemente oferecem fluxos de trabalho mais eficientes.</p>
]]></description><link>https://autonetops.com/cheat-sheet-de-automacao-de-rede-ferramentas-de-suporte</link><guid isPermaLink="true">https://autonetops.com/cheat-sheet-de-automacao-de-rede-ferramentas-de-suporte</guid><category><![CDATA[pt-br]]></category><category><![CDATA[networking]]></category><category><![CDATA[automation]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[A Network Engineer's Tale: Uncovering the Power of Pktmon on Windows]]></title><description><![CDATA[<p>It was a typical morning, and I, a network engineer, found myself staring at a users PC that was acting up. The network was sluggish, connections were dropping, and I needed to get to the bottom of itfast. My go-to tool, Wireshark, was nowhere to be found on this machine. Installing it wouldve meant jumping through hoops: change management approvals, security scans, and probably a coffee-fueled wait for IT to give the green light. In a quick research I stumbled upon a hidden gem tucked away in Windows<strong>Pktmon</strong></p>
<h3 id="heading-the-discovery-pktmon-to-the-rescue">The Discovery: Pktmon to the Rescue</h3>
<p>Picture this: youre deep in the trenches of troubleshooting, and you realize the system youre working on is bare-bones. No third-party tools, no fancy GUI sniffers. But then, like finding a forgotten tool in the back of a shed, I discovered <strong>Pktmon</strong>, a built-in packet sniffer introduced in Windows 10. Its not flashyno sleek interface like Wiresharkbut its powerful, lightweight, and, best of all, already there just waiting to be used.</p>
<p>I opened an elevated Command Prompt (because Pktmon demands admin privileges, naturally) and typed <code>pktmon help</code> to get the lay of the land. The help menu was like a treasure map, revealing commands for capturing packets, setting filters, and even converting logs for later analysis. I was ready to dive in.</p>
<h2 id="heading-step-1-setting-the-stage">Step 1: Setting the Stage</h2>
<p>First things first, I needed to know what network interfaces were available. I typed:</p>
<pre><code class="lang-ini">pktmon comp list
</code></pre>
<p>This command listed all the network adapters on the system, each with an ID. For example:</p>
<pre><code class="lang-ini">Network Adapters:
Id  MAC Address        Name
--  -----------        ----
9   00-50-56-BD-C1-83  Ethernet Adapter
12  E8-6A-64-44-7B-00  Wi-Fi Adapter
</code></pre>
<p>My target was the Ethernet adapter (ID 9). Knowing the interface ID is crucial if you want to focus your capture on a specific NIC to avoid drowning in irrelevant data.</p>
<h2 id="heading-step-2-crafting-filters-like-a-pro">Step 2: Crafting Filters Like a Pro</h2>
<p>Pktmons filtering capabilities are where it shines. I needed to zero in on specific trafficsay, HTTP traffic on port 80. To set this up, I added a filter:</p>
<pre><code class="lang-ini">pktmon filter add -p 80 -t tcp
</code></pre>
<p>This told Pktmon to capture TCP traffic on port 80. Want to capture ICMP pings instead? Easy:</p>
<pre><code class="lang-ini">pktmon filter add -t icmp
</code></pre>
<p>You can stack up to 32 filters to get granular. For instance, to monitor traffic to a specific IP (like 192.168.1.100):</p>
<pre><code class="lang-ini">pktmon filter add -i 192.168.1.100
</code></pre>
<p>To check your filters, run:</p>
<pre><code class="lang-ini">pktmon filter list
</code></pre>
<p>If you mess up, clear them with:</p>
<pre><code class="lang-ini">pktmon filter remove
</code></pre>
<p>Pro tip: Always set filters before capturing. Unfiltered captures are like trying to find a needle in a haystack of network traffic.</p>
<h2 id="heading-step-3-starting-the-capture">Step 3: Starting the Capture</h2>
<p>With filters in place, it was time to start capturing. I wanted to save the packets to a file for later analysis, so I ran:</p>
<pre><code class="lang-ini">pktmon start --etw --pkt-size 0 --file-name C:\Temp\traffic.etl --comp 9
</code></pre>
<p>Heres what each part does:</p>
<ul>
<li><p><code>--etw</code>: Enables Event Tracing for Windows, saving packets to an ETL file.</p>
</li>
<li><p><code>--pkt-size 0</code>: Captures full packets (default is just the first 128 bytes).</p>
</li>
<li><p><code>--file-name C:\Temp\traffic.etl</code>: Specifies the output file.</p>
</li>
<li><p><code>--comp 9</code>: Targets the Ethernet adapter (ID 9).</p>
</li>
</ul>
<p>The capture started, silently logging packets in the background. To monitor in real-time (available in Windows 10 version 2004 and later), I couldve added <code>-l real-time</code>, but I wanted a file for deeper analysis.</p>
<h2 id="heading-step-4-stopping-and-converting">Step 4: Stopping and Converting</h2>
<p>After reproducing the issue (a quick browser refresh to a problematic website), I stopped the capture:</p>
<pre><code class="lang-ini">pktmon stop
</code></pre>
<p>This saved the data to <code>C:\Temp\traffic.etl</code>. But ETL files arent exactly user-friendly. To make them compatible with Wireshark, I converted the file to PCAPNG format:</p>
<pre><code class="lang-ini">pktmon etl2pcap C:\Temp\traffic.etl --out C:\Temp\traffic.pcapng
</code></pre>
<p>Now I had a <code>traffic.pcapng</code> file I could transfer to my workstation, where Wireshark was ready to dissect it with all its graphical glory.</p>
<h2 id="heading-step-5-analyzing-the-results">Step 5: Analyzing the Results</h2>
<p>On my own machine, I opened <code>traffic.pcapng</code> in Wireshark. The HTTP traffic I filtered for was there, clear as day, helping me pinpoint a misconfigured server response causing the slowdown. Pktmons ability to identify packet drops (with reasons like MTU Mismatch or Filtered VLAN) also gave me clues about potential network issues.</p>
<h2 id="heading-bonus-real-time-monitoring">Bonus: Real-Time Monitoring</h2>
<p>For quick checks, Pktmons real-time mode is a lifesaver. Try:</p>
<pre><code class="lang-ini">pktmon start --etw -l real-time -p 0
</code></pre>
<p>This displays packets on the command line as theyre captured. Hit <code>Ctrl+C</code> to stop. Its not as pretty as Wireshark, but it gets the job done when youre in a bind.</p>
<h2 id="heading-why-pktmon-rocks">Why Pktmon Rocks</h2>
<ul>
<li><p><strong>No Installation Needed</strong>: Its built into Windows 10</p>
</li>
<li><p><strong>Lightweight</strong>: Perfect for servers where installing third-party tools is a no-go.</p>
</li>
<li><p><strong>Flexible Filters</strong>: Filter by IP, port, protocol, MAC, and more.</p>
</li>
<li><p><strong>Wireshark Compatibility</strong>: Convert to PCAPNG for detailed analysis.</p>
</li>
</ul>
<h2 id="heading-caveats">Caveats</h2>
<ul>
<li><p><strong>No GUI</strong>: Its command-line only, so expect to get cozy with CMD or PowerShell.</p>
</li>
<li><p><strong>Basic Analysis</strong>: For deep packet inspection, youll still want Wireshark or similar tools.</p>
</li>
<li><p><strong>Admin Privileges</strong>: You need elevated access to run Pktmon.</p>
</li>
</ul>
<hr />
<h3 id="heading-the-victory-lap">The Victory Lap</h3>
<p>Back to my story: with Pktmon, I captured the problematic traffic, converted it to PCAPNG, and analyzed it later on my own machine. The issue? An old DNS server that was taking forever to answer. Thanks to Pktmons filters, I isolated the culprit without sifting through gigabytes of data.</p>
<blockquote>
<p>It is a nice tool to have on the tool belt. Leaving here for further reference and for those who might also leverage it.</p>
</blockquote>
]]></description><link>https://autonetops.com/a-network-engineers-tale-uncovering-the-power-of-pktmon-on-windows</link><guid isPermaLink="true">https://autonetops.com/a-network-engineers-tale-uncovering-the-power-of-pktmon-on-windows</guid><category><![CDATA[en]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Um Conto de Engenheiro de Redes: Desvendando Pktmon no Windows]]></title><description><![CDATA[<p>Era uma manh tpica, e eu, um engenheiro de redes, me vi encarando o PC de um usurio reclamando que a rede estava lenta e eu precisava descobrir a causa. Minha ferramenta de confiana, o Wireshark, no estava instalada nesse computador. Instal-lo seria como pular obstculos: aprovaes de gerenciamento de mudanas, verificaes de segurana e, provavelmente, uma espera at o departamento responsavel liberar. Foi ento que, em uma pesquisa rpida, tropecei em uma joia escondida no Windows<strong>Pktmon</strong>.</p>
<h3 id="heading-a-descoberta-pktmon-ao-resgate">A Descoberta: Pktmon ao Resgate</h3>
<p>Em um ambiente limitado, sem ferramentas de terceiros nao autorizadas, sem sniffers com interface grfica sofisticada. Mas ento, como encontrar uma ferramenta esquecida no fundo de um galpo, descobri o <strong>Pktmon</strong>, um sniffer de pacotes embutido, introduzido no Windows 10. No  chamativosem uma interface elegante como o Wiresharkmas  suficiente para quebrar o galho, leve e, o melhor de tudo, j est ali, esperando para ser usado.</p>
<p>Abri um Prompt de Comando elevado (porque o Pktmon exige privilgios de administrador, claro) e digitei <code>pktmon help</code> para me orientar. O menu de ajuda era como um mapa do tesouro, revelando comandos para capturar pacotes, configurar filtros e at converter logs para anlise posterior.</p>
<h2 id="heading-passo-1-preparando-o-terreno">Passo 1: Preparando o Terreno</h2>
<p>Primeiro, eu precisava saber quais interfaces de rede estavam disponveis. Digitei:</p>
<pre><code class="lang-ini">pktmon comp list
</code></pre>
<p>Esse comando listou todos os adaptadores de rede do sistema, cada um com um ID. Por exemplo:</p>
<pre><code class="lang-ini">Adaptadores de Rede:
Id  Endereo MAC      Nome
--  -----------        ----
9   00-50-56-BD-C1-83  Adaptador Ethernet
12  E8-6A-64-44-7B-00  Adaptador Wi-Fi
</code></pre>
<p>Meu alvo era o adaptador Ethernet (ID 9). Saber o ID da interface  crucial se voc quer focar a captura em uma NIC especfica para evitar se afogar em dados irrelevantes.</p>
<h2 id="heading-passo-2-criando-filtros">Passo 2: Criando Filtros</h2>
<p>As capacidades de filtragem do Pktmon so onde ele brilha. Eu precisava focar em um trfego especficodigamos, trfego HTTP na porta 80. Para configurar isso, adicionei um filtro:</p>
<pre><code class="lang-ini">pktmon filter add -p 80 -t tcp
</code></pre>
<p>Isso instruiu o Pktmon a capturar trfego TCP na porta 80. Quer capturar pings ICMP em vez disso? Fcil:</p>
<pre><code class="lang-ini">pktmon filter add -t icmp
</code></pre>
<p>Voc pode empilhar at 32 filtros para ser bem especfico. Por exemplo, para monitorar trfego para um IP especfico (como 192.168.1.100):</p>
<pre><code class="lang-ini">pktmon filter add -i 192.168.1.100
</code></pre>
<p>Para verificar seus filtros, execute:</p>
<pre><code class="lang-ini">pktmon filter list
</code></pre>
<p>Se errar, limpe-os com:</p>
<pre><code class="lang-ini">pktmon filter remove
</code></pre>
<p>Dica de ouro: Sempre configure os filtros antes de capturar. Capturas sem filtro so como procurar uma agulha em um palheiro de trfego de rede.</p>
<h2 id="heading-passo-3-iniciando-a-captura">Passo 3: Iniciando a Captura</h2>
<p>Com os filtros configurados, era hora de comear a capturar. Eu queria salvar os pacotes em um arquivo para anlise posterior, ento executei:</p>
<pre><code class="lang-ini">pktmon start --etw --pkt-size 0 --file-name C:\Temp\traffic.etl --comp 9
</code></pre>
<p>Aqui est o que cada parte faz:</p>
<ul>
<li><p><code>--etw</code>: Ativa o Event Tracing for Windows, salvando pacotes em um arquivo ETL.</p>
</li>
<li><p><code>--pkt-size 0</code>: Captura pacotes completos (o padro  apenas os primeiros 128 bytes).</p>
</li>
<li><p><code>--file-name C:\Temp\traffic.etl</code>: Especifica o arquivo de sada.</p>
</li>
<li><p><code>--comp 9</code>: Foca no adaptador Ethernet (ID 9).</p>
</li>
</ul>
<p>A captura comeou, registrando pacotes silenciosamente em segundo plano. Para monitoramento em tempo real (disponvel no Windows 10 verso 2004 ou posterior), eu poderia ter adicionado <code>-l real-time</code>, mas queria um arquivo para uma anlise mais profunda.</p>
<h2 id="heading-passo-4-parando-e-convertendo">Passo 4: Parando e Convertendo</h2>
<p>Depois de reproduzir o problema (uma rpida atualizao no navegador para um site problemtico), parei a captura:</p>
<pre><code class="lang-ini">pktmon stop
</code></pre>
<p>Isso salvou os dados em <code>C:\Temp\traffic.etl</code>. Mas arquivos ETL no so exatamente amigveis. Para torn-los compatveis com o Wireshark, converti o arquivo para o formato PCAPNG:</p>
<pre><code class="lang-ini">pktmon etl2pcap C:\Temp\traffic.etl --out C:\Temp\traffic.pcapng
</code></pre>
<p>Agora eu tinha um arquivo <code>traffic.pcapng</code> que podia transferir para minha estao de trabalho, onde o Wireshark estava pronto para dissec-lo com toda sua glria grfica.</p>
<h2 id="heading-passo-5-analisando-os-resultados">Passo 5: Analisando os Resultados</h2>
<p>Na minha prpria mquina, abri o <code>traffic.pcapng</code> no Wireshark. O trfego HTTP que filtrei estava l, claro como o dia, me ajudando a identificar uma resposta de servidor mal configurada que causava a lentido. A capacidade do Pktmon de identificar quedas de pacotes (com motivos como MTU Mismatch ou Filtered VLAN) tambm me deu pistas sobre possveis problemas na rede.</p>
<h2 id="heading-bonus-monitoramento-em-tempo-real">Bnus: Monitoramento em Tempo Real</h2>
<p>Para verificaes rpidas, o modo em tempo real do Pktmon  um salva-vidas. Experimente:</p>
<pre><code class="lang-ini">pktmon start --etw -l real-time -p 0
</code></pre>
<p>Isso exibe os pacotes na linha de comando enquanto so capturados. Pressione <code>Ctrl+C</code> para parar. No  to bonito quanto o Wireshark, mas resolve quando voc est em apuros.</p>
<h2 id="heading-por-que-o-pktmon-e-incrivel">Por que o Pktmon  Incrvel</h2>
<ul>
<li><p><strong>Sem Instalao Necessria</strong>: Est embutido no Windows 10.</p>
</li>
<li><p><strong>Leve</strong>: Perfeito para servidores onde instalar ferramentas de terceiros  proibido.</p>
</li>
<li><p><strong>Filtros Flexveis</strong>: Filtre por IP, porta, protocolo, MAC e mais.</p>
</li>
<li><p><strong>Compatibilidade com Wireshark</strong>: Converta para PCAPNG para anlise detalhada.</p>
</li>
</ul>
<h2 id="heading-cuidados">Cuidados</h2>
<ul>
<li><p><strong>Sem Interface Grfica</strong>:  s linha de comando, ento prepare-se para se familiarizar com CMD ou PowerShell.</p>
</li>
<li><p><strong>Anlise Bsica</strong>: Para inspeo profunda de pacotes, voc ainda vai querer o Wireshark ou ferramentas similares.</p>
</li>
<li><p><strong>Privilgios de Administrador</strong>: Voc precisa de acesso elevado para rodar o Pktmon.</p>
</li>
</ul>
<h3 id="heading-a-volta-da-vitoria">A Volta da Vitria</h3>
<p>Voltando  minha histria: com o Pktmon, capturei o trfego problemtico, converti para PCAPNG e analisei depois na minha prpria mquina. O problema? Um servidor DNS antigo que demorava uma eternidade para responder. Graas aos filtros do Pktmon, isolei o culpado sem precisar vasculhar gigabytes de dados.</p>
<blockquote>
<p> uma ferramenta excelente para ter no cinto de utilidades. Deixo aqui para referncia futura e para quem tambm quiser aproveit-la.</p>
</blockquote>
]]></description><link>https://autonetops.com/desvendando-pktmon-no-windows</link><guid isPermaLink="true">https://autonetops.com/desvendando-pktmon-no-windows</guid><category><![CDATA[pt-br]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Helpful Tools for Network Automation: A Practical Cheat Sheet]]></title><description><![CDATA[<p>Hey there! Today we will be building a cheat sheet to facilitate using some very helpful tools for network automation. This helps us get some fast information on network devices and verify the information and formats beforehand and while debugging when scripting. Let's get to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729240573535/5a93cea4-c87a-479a-9508-3096e119bc7a.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-overview-of-tools">Overview of Tools</h2>
<p>The following tools are essential for network automation, covering SSH, SNMP, and YANG-based protocols:</p>
<ul>
<li><p><strong>SSH</strong>: For secure command-line access and NETCONF operations.</p>
<ul>
<li><p><strong>NAPALM</strong>: A Python library for multi-vendor network automation.</p>
</li>
<li><p><strong>Netmiko</strong></p>
</li>
</ul>
</li>
<li><p><strong>SNMP</strong>: For monitoring and managing network devices.</p>
<ul>
<li><strong>NET-SNMP</strong>: A suite of tools for SNMP operations.</li>
</ul>
</li>
<li><p><strong>YANG-based</strong>:</p>
<ul>
<li><p><strong>Cisco YANG Suite</strong>: A tool for exploring and testing YANG models.</p>
</li>
<li><p><strong>GNMIc/Pygnmi</strong>: Tools for gNMI protocol interactions.</p>
</li>
<li><p><strong>SSH (NETCONF)</strong>: For YANG-based device management via NETCONF.</p>
</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-napalm">NAPALM</h2>
<p>NAPALM (Network Automation and Programmability Abstraction Layer with Multivendor support) simplifies network device management through a unified API. It can be used via CLI or integrated into Python scripts.</p>
<h3 id="heading-installation">Installation</h3>
<p>Install NAPALM using pip:</p>
<pre><code class="lang-bash">pip3 install napalm
</code></pre>
<h3 id="heading-reference">Reference</h3>
<ul>
<li>NAPALM Documentation</li>
</ul>
<h3 id="heading-usage">Usage</h3>
<p>Run NAPALM from the CLI to interact with devices:</p>
<pre><code class="lang-bash">napalm --user &lt;username&gt; --password &lt;password&gt; --vendor &lt;driver&gt; &lt;ip_address&gt; call &lt;getter&gt;
</code></pre>
<h4 id="heading-example-getfacts">Example: get_facts</h4>
<p>Retrieve device facts such as hostname, model, and OS version:</p>
<pre><code class="lang-bash">napalm --user admin --password admin --vendor ios 192.168.1.1 call get_facts
</code></pre>
<p><strong>Example Output</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728940208781/b0e3e059-93b3-4d1c-b2ad-acc791c8b933.png" alt class="image--center mx-auto" /></p>
<p><strong>Result</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728940174292/9f96f06f-78dc-4cec-8aec-f833e82fc7f4.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-gnmic">GNMIc</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749670273035/ba63eccc-6e0a-4452-a562-acdf55175cfd.png" alt class="image--center mx-auto" /></p>
<p>GNMIc is a powerful CLI tool for interacting with network devices via the gNMI (gRPC Network Management Interface) protocol, ideal for telemetry and configuration.</p>
<h3 id="heading-installationhttpsgnmicopenconfignetinstallation"><a target="_blank" href="https://gnmic.openconfig.net/#installation">Installation</a></h3>
<p>Install GNMIc using the provided installation script:</p>
<pre><code class="lang-bash">bash -c <span class="hljs-string">"<span class="hljs-subst">$(curl -sL https://get-gnmic.kmrd.dev)</span>"</span>
</code></pre>
<h3 id="heading-reference-1">Reference</h3>
<ul>
<li><a target="_blank" href="https://gnmic.openconfig.net/">GNMIc Documentation</a></li>
</ul>
<h3 id="heading-common-commands">Common Commands</h3>
<h4 id="heading-capabilities">CAPABILITIES</h4>
<p>Check the gNMI capabilities of a device:</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure capabilities
</code></pre>
<p><strong>Example</strong>:</p>
<pre><code class="lang-bash">gnmic -a 10.80.255.30:6030 -u admin -p admin --insecure capabilities
</code></pre>
<h4 id="heading-get">GET</h4>
<p>Retrieve a snapshot of device data using a specific path:</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure get --path <span class="hljs-string">"/components/component/state/temperature"</span>
</code></pre>
<h4 id="heading-sethttpsgnmicopenconfignetcmdset"><a target="_blank" href="https://gnmic.openconfig.net/cmd/set/">SET</a></h4>
<p>Modify device state (refer to GNMIc Set Documentation):</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure <span class="hljs-built_in">set</span> --update-path <span class="hljs-string">"/interfaces/interface[name=Management1]/config/description"</span> --update-value <span class="hljs-string">"Updated via gNMI"</span>
</code></pre>
<h4 id="heading-subscribe">SUBSCRIBE</h4>
<p>Subscribe to real-time telemetry data:</p>
<pre><code class="lang-bash">gnmic -a &lt;ip:port&gt; --username &lt;user&gt; --password &lt;password&gt; --insecure subscribe --path <span class="hljs-string">"/interfaces/interface[name=Management1]/state/counters"</span>
</code></pre>
<h4 id="heading-gnmi-prompt">GNMI Prompt</h4>
<p>Start an interactive session with preconfigured credentials:</p>
<pre><code class="lang-bash">gnmic --insecure --username admin --password admin --address &lt;ip
</code></pre>
<hr />
<h2 id="heading-net-snmphttpsgnmicopenconfignetcmdset"><a target="_blank" href="https://gnmic.openconfig.net/cmd/set/">NET-SNMP</a></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749670353681/a2ee3ee3-fc1e-4485-9c32-5d0ae5743eb1.png" alt class="image--center mx-auto" /></p>
<p>NET-SNMP is a suite for interacting with SNMP-enabled devices, providing tools to query and manage network statistics.</p>
<h3 id="heading-installation-1">Installation</h3>
<p>Follow the official guide for installation:</p>
<ul>
<li><a target="_blank" href="http://www.net-snmp.org/wiki/index.php/Tutorials">NET-SNMP Tutorial</a></li>
</ul>
<h3 id="heading-common-snmp-oids">Common SNMP OIDs</h3>
<p>Key OIDs for interface statistics (MIB-II, RFC 1213):</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>OID Name</td><td>OID Value</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>ifInOctets</td><td>.1.3.6.1.2.1.2.2.1.10</td><td>Bytes received on an interface</td></tr>
<tr>
<td>ifOutOctets</td><td>.1.3.6.1.2.1.2.2.1.16</td><td>Bytes sent on an interface</td></tr>
<tr>
<td>ifInErrors</td><td>.1.3.6.1.2.1.2.2.1.14</td><td>Inbound errors</td></tr>
<tr>
<td>ifOutErrors</td><td>.1.3.6.1.2.1.2.2.1.20</td><td>Outbound errors</td></tr>
</tbody>
</table>
</div><h3 id="heading-querying-interface-statistics">Querying Interface Statistics</h3>
<p>Query SNMP-enabled devices (e.g., IP 192.168.1.1, community string public). Replace IF_INDEX with the interface index (discoverable via ifDescr).</p>
<h4 id="heading-example-snmpv2c">Example (SNMPv2c):</h4>
<pre><code class="lang-python">snmpget -v2c -c public <span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span> <span class="hljs-number">.1</span><span class="hljs-number">.3</span><span class="hljs-number">.6</span><span class="hljs-number">.1</span><span class="hljs-number">.2</span><span class="hljs-number">.1</span><span class="hljs-number">.2</span><span class="hljs-number">.2</span><span class="hljs-number">.1</span><span class="hljs-number">.10</span>.IF_INDEX <span class="hljs-number">.1</span><span class="hljs-number">.3</span><span class="hljs-number">.6</span><span class="hljs-number">.1</span><span class="hljs-number">.2</span><span class="hljs-number">.1</span><span class="hljs-number">.2</span><span class="hljs-number">.2</span><span class="hljs-number">.1</span><span class="hljs-number">.16</span>.IF_INDEX
snmpget -v2c -c public <span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span> SNMPv2-MIB::sysUpTime<span class="hljs-number">.0</span> <span class="hljs-comment"># SYS UPTIME</span>
snmpbulkwalk -v2c -c public <span class="hljs-number">192.168</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span> <span class="hljs-number">.1</span><span class="hljs-number">.0</span><span class="hljs-number">.8802</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span><span class="hljs-number">.2</span><span class="hljs-number">.1</span><span class="hljs-number">.4</span><span class="hljs-number">.1</span><span class="hljs-number">.1</span><span class="hljs-number">.9</span> <span class="hljs-comment">#LLDP NEIGHORS</span>
</code></pre>
<h4 id="heading-example-snmpv3">Example (SNMPv3):</h4>
<p>Retrieve system name with SNMPv3:</p>
<pre><code class="lang-plaintext">snmpget -v3 -u USERNAME -a SHA -x AES -l authPriv -A AUTHPASS -X PRIVPASS 192.168.1.1 .1.3.6.1.2.1.1.5.0
</code></pre>
<hr />
<h2 id="heading-cisco-yang-suite">Cisco YANG Suite</h2>
<p><img src="https://www.packetswitch.co.uk/content/images/2023/10/Screenshot-2023-10-18-at-13.46.09.png" alt /></p>
<p>YANG Suite is a valuable tool for working with YANG-based models.</p>
<h3 id="heading-installation-2">Installation</h3>
<p>You can install Cisco YANG Suite either via Docker or pip. Check the <a target="_blank" href="https://github.com/CiscoDevNet/yangsuite">GitHub Repository</a> for instructions.</p>
<h3 id="heading-running-yang-suite">Running YANG Suite</h3>
<p>Once installed, run the suite using:</p>
<pre><code class="lang-python">yangsuite
</code></pre>
<p>Access the web interface to explore YANG models and execute operations.</p>
<hr />
<h2 id="heading-ssh-netconf">SSH (NETCONF)</h2>
<p>NETCONF over SSH enables YANG-based device management. Its useful for retrieving schemas and performing operations.</p>
<h3 id="heading-starting-a-netconf-session">Starting a NETCONF Session</h3>
<p>Initiate a NETCONF session (default port 830):</p>
<pre><code class="lang-python">ssh -s &lt;username&gt;@&lt;device-ip&gt; -p <span class="hljs-number">830</span> netconf
</code></pre>
<p>This opens an interactive session for NETCONF operations, such as retrieving YANG schemas or configuring devices.</p>
<p><strong>Note</strong>: While NETCONF over SSH is supported, tools like NAPALM or GNMIc often provide more efficient workflows.</p>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>This cheat sheet consolidates essential tools for network automation, including NAPALM, GNMIc, NET-SNMP, Cisco YANG Suite, and NETCONF over SSH. These tools enable efficient device querying, configuration, and telemetry, streamlining network management tasks. Use this guide as a quick reference to enhance your automation workflows.</p>
]]></description><link>https://autonetops.com/helpful-tools-for-network-automation-a-practical-cheat-sheet</link><guid isPermaLink="true">https://autonetops.com/helpful-tools-for-network-automation-a-practical-cheat-sheet</guid><category><![CDATA[netconf]]></category><category><![CDATA[gnmi]]></category><category><![CDATA[napalm]]></category><category><![CDATA[yang]]></category><category><![CDATA[netsnmp]]></category><category><![CDATA[en]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Exploring Basic Search Algorithms Using Python]]></title><description><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>As network engineers, we often deal with large datasets like IP addresses or subnets. Efficiently searching through these datasets is critical for automation tasks, such as finding a specific subnet in a network inventory. In this article, well explore two fundamental search algorithmslinear search and binary searchusing Python and subnets from the 10.0.0.0/8 network</p>
<h2 id="heading-creating-the-data">Creating the Data</h2>
<p>To simulate a network inventory, well create a dataset of /24 subnets from the 10.0.0.0/8 range (e.g., 10.0.0.0, 10.0.1.0, ..., 10.255.255.0). The following Python script generates three files: an ordered list, a reversed list, and a random list of subnets.</p>
<pre><code class="lang-python"><span class="hljs-string">"""Generate subnet lists for testing search algorithms"""</span>
<span class="hljs-keyword">import</span> ipaddress
<span class="hljs-keyword">import</span> random

<span class="hljs-comment"># Generate all /24 subnets from 10.0.0.0/8</span>
subnets = list(ipaddress.ip_network(<span class="hljs-string">"10.0.0.0/8"</span>).subnets(new_prefix=<span class="hljs-number">24</span>))
networks = [str(n.network_address) <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> subnets]

<span class="hljs-comment"># Ordered subnets</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"ordered_ip.txt"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"\n"</span>.join(networks))

<span class="hljs-comment"># Reversed subnets</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"reverse_ip.txt"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"\n"</span>.join(reversed(networks)))

<span class="hljs-comment"># Random subnets</span>
random.shuffle(networks)
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"random_ip.txt"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"\n"</span>.join(networks))
</code></pre>
<p>This script produces:</p>
<ul>
<li><p>ordered_ip.txt: Subnets in ascending order (10.0.0.0, 10.0.1.0, ...).</p>
</li>
<li><p>reverse_ip.txt: Subnets in descending order (10.255.255.0, 10.255.254.0, ...).</p>
</li>
<li><p>random_ip.txt: Subnets in random order.</p>
</li>
</ul>
<p>Each file contains 65,536 subnets (256  256), perfect for testing search performance.</p>
<hr />
<h2 id="heading-linear-search-the-straightforward-approach">Linear Search: The Straightforward Approach</h2>
<p>Linear search is like checking each device in a rack one by one until you find the one youre looking for. It examines every element in a list until it finds a match or reaches the end.</p>
<h3 id="heading-how-it-works">How It Works</h3>
<p>Imagine searching for 10.0.5.0 in an ordered list:</p>
<pre><code class="lang-python">Subnets: <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.1</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.2</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.3</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.4</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.5</span><span class="hljs-number">.0</span>
Indices:    <span class="hljs-number">0</span>         <span class="hljs-number">1</span>         <span class="hljs-number">2</span>         <span class="hljs-number">3</span>         <span class="hljs-number">4</span>         <span class="hljs-number">5</span>
</code></pre>
<ul>
<li><p>Check 10.0.0.0  No match.</p>
</li>
<li><p>Check 10.0.1.0  No match.</p>
</li>
<li><p>Continue until 10.0.5.0 is found (6 steps).</p>
</li>
</ul>
<p><strong>Performance</strong>:</p>
<ul>
<li><p><strong>Best case</strong>: Target is at the start (1 step, (1)).</p>
</li>
<li><p><strong>Worst case</strong>: Target is at the end or absent (n steps, O(n), where n is the list size).</p>
</li>
<li><p>For 65,536 subnets, the worst case means checking all 65,536 entries!</p>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">from</span> ipaddress <span class="hljs-keyword">import</span> ip_address

<span class="hljs-comment"># Read subnets and convert to integers for comparison</span>
<span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">1</span>], <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> f:
    data = [str(ip_address(line.strip())) <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f]

<span class="hljs-comment"># Get target subnet from user</span>
target = str(ip_address(input(<span class="hljs-string">"Enter a /24 subnet (e.g., 10.80.40.0): "</span>)))

start_time = time.time()
<span class="hljs-keyword">for</span> prefix <span class="hljs-keyword">in</span> data:
    <span class="hljs-keyword">if</span> prefix == target:
        print(<span class="hljs-string">f"Found <span class="hljs-subst">{ip_address(target)}</span> with linear search"</span>)
        <span class="hljs-keyword">break</span>
print(<span class="hljs-string">f"Time: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> seconds"</span>)
</code></pre>
<hr />
<h2 id="heading-binary-search-the-efficient-divide-and-conquer">Binary Search: The Efficient Divide-and-Conquer</h2>
<p>Binary search is like troubleshooting a network by dividing the problem space in half repeatedly. It requires a sorted list but is significantly faster for large datasets.</p>
<h3 id="heading-how-it-works-1">How It Works</h3>
<p>For the same list, searching for 10.0.5.0:</p>
<pre><code class="lang-python">Subnets: <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.1</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.2</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.3</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.4</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.5</span><span class="hljs-number">.0</span>
Indices:    <span class="hljs-number">0</span>         <span class="hljs-number">1</span>         <span class="hljs-number">2</span>         <span class="hljs-number">3</span>         <span class="hljs-number">4</span>         <span class="hljs-number">5</span>
</code></pre>
<ol>
<li><p>Find the midpoint: (0 + 5) // 2 = 2 (10.0.2.0).</p>
</li>
<li><p>Compare: 10.0.2.0 &lt; 10.0.5.0, so ignore the left half (indices 02).</p>
</li>
<li><p>New list: 10.0.3.0, 10.0.4.0, 10.0.5.0.</p>
</li>
<li><p>New midpoint: (3 + 5) // 2 = 4 (10.0.4.0).</p>
</li>
<li><p>Compare: 10.0.4.0 &lt; 10.0.5.0, ignore index 4.</p>
</li>
<li><p>Check 10.0.5.0  Found in 3 steps!</p>
</li>
</ol>
<p><strong>Performance</strong>:</p>
<ul>
<li><p><strong>Best case</strong>: Target is at the midpoint (1 step, (1)).</p>
</li>
<li><p><strong>Worst case</strong>: O(log n), where n is the list size. For 65,536 subnets, it takes at most ~16 steps (log(65,536)  16).</p>
</li>
<li><p>Binary search is exponentially faster than linear search for large datasets.</p>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">from</span> ipaddress <span class="hljs-keyword">import</span> ip_address

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_search</span>(<span class="hljs-params">arr, target</span>):</span>
    arr = sorted(arr)  <span class="hljs-comment"># Ensure the list is sorted</span>
    start, end = <span class="hljs-number">0</span>, len(arr) - <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> start &lt;= end:
        mid = (start + end) // <span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> arr[mid] == target:
            <span class="hljs-keyword">return</span> mid
        <span class="hljs-keyword">elif</span> arr[mid] &lt; target:
            start = mid + <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            end = mid - <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

<span class="hljs-comment"># Read subnets and convert to integers</span>
<span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">1</span>], <span class="hljs-string">"r"</span>, encoding=<span class="hljs-string">"utf-8"</span>) <span class="hljs-keyword">as</span> f:
    data = [str(ip_address(line.strip())) <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f]

<span class="hljs-comment"># Get target subnet</span>
target = str(ip_address(input(<span class="hljs-string">"Enter a /24 subnet (e.g., 10.80.40.0): "</span>)))

start_time = time.time()
index = binary_search(data, target)
<span class="hljs-keyword">if</span> index != <span class="hljs-number">-1</span>:
    print(<span class="hljs-string">f"Found <span class="hljs-subst">{ip_address(target)}</span> with binary search"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">f"Subnet <span class="hljs-subst">{ip_address(target)}</span> not found"</span>)
print(<span class="hljs-string">f"Time: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> seconds"</span>)
</code></pre>
<h2 id="heading-performance-comparison">Performance Comparison</h2>
<p>To illustrate the difference, lets test both algorithms on our subnet datasets. Here are results for searching 10.255.255.0 (worst case for linear search in ordered_ip.txt):</p>
<ul>
<li><p><strong>Linear Search</strong>: ~0.008 seconds (65,536 checks).</p>
</li>
<li><p><strong>Binary Search</strong>: ~0.0001 seconds (~16 checks).</p>
</li>
</ul>
<p>For a random subnet like 10.80.40.0 in random_ip.txt:</p>
<ul>
<li><p><strong>Linear Search</strong>: ~0.004 seconds (average case).</p>
</li>
<li><p><strong>Binary Search</strong>: ~0.0001 seconds (sorting overhead included).</p>
</li>
</ul>
<p>The chart below visualizes the number of steps required as the dataset size grows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749465473657/50fcefda-bcd4-4379-824b-d1f27d6b57ef.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-practical-application-in-network-automation">Practical Application in Network Automation</h2>
<p>Imagine youre automating a task to find a specific subnet in a routing table or IPAM system. Linear search works for small lists but becomes impractical for thousands of subnets. Binary search, with its O(log n) efficiency, is ideal for large-scale network data, especially if the data is pre-sorted (common in databases or IPAM tools).</p>
<p><strong>Example Use Case</strong>: Youre validating whether a subnet exists in a networks inventory before assigning it to a new VLAN. Binary search ensures quick lookups, minimizing script runtime and improving automation efficiency.</p>
<h2 id="heading-interactive-challenge">Interactive Challenge</h2>
<p>Try this hands-on exercise to see the algorithms in action:</p>
<ol>
<li><p>Save the subnet generation script as <strong>subnets.py</strong> and run it to create the three files.</p>
</li>
<li><p>Combine the linear and binary search scripts into one file (search_subnets.py):</p>
</li>
</ol>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">from</span> ipaddress <span class="hljs-keyword">import</span> ip_address

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">linear_search</span>(<span class="hljs-params">arr, target</span>):</span>
    <span class="hljs-keyword">for</span> i, prefix <span class="hljs-keyword">in</span> enumerate(arr):
        <span class="hljs-keyword">if</span> prefix == target:
            <span class="hljs-keyword">return</span> i
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_search</span>(<span class="hljs-params">arr, target</span>):</span>
    arr = sorted(arr)
    start, end = <span class="hljs-number">0</span>, len(arr) - <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> start &lt;= end:
        mid = (start + end) // <span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> arr[mid] == target:
            <span class="hljs-keyword">return</span> mid
        <span class="hljs-keyword">elif</span> arr[mid] &lt; target:
            start = mid + <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            end = mid - <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

<span class="hljs-comment"># Read subnets</span>
<span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">1</span>], <span class="hljs-string">"r"</span>, encoding=<span class="hljs-string">"utf-8"</span>) <span class="hljs-keyword">as</span> f:
    data = [str(ip_address(line.strip())) <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f]

<span class="hljs-comment"># Get target subnet</span>
target = str(ip_address(input(<span class="hljs-string">"Enter a /24 subnet (e.g., 10.80.40.0): "</span>)))

<span class="hljs-comment"># Linear search</span>
start_time = time.time()
index = linear_search(data, target)
print(<span class="hljs-string">f"Linear Search: <span class="hljs-subst">{<span class="hljs-string">'Found'</span> <span class="hljs-keyword">if</span> index != <span class="hljs-number">-1</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'Not found'</span>}</span> <span class="hljs-subst">{ip_address(target)}</span>"</span>)
print(<span class="hljs-string">f"Time: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> seconds"</span>)

<span class="hljs-comment"># Binary search</span>
start_time = time.time()
index = binary_search(data, target)
print(<span class="hljs-string">f"Binary Search: <span class="hljs-subst">{<span class="hljs-string">'Found'</span> <span class="hljs-keyword">if</span> index != <span class="hljs-number">-1</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'Not found'</span>}</span> <span class="hljs-subst">{ip_address(target)}</span>"</span>)
print(<span class="hljs-string">f"Time: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> seconds"</span>)
</code></pre>
<p>Run the script with different files and subnets:</p>
<pre><code class="lang-python">python search_subnets.py ordered_ip.txt
</code></pre>
<p>Try searching for 10.0.0.0 (best case), 10.255.255.0 (worst case), and a random subnet like 10.80.40.0.</p>
<p><strong>Challenge</strong>: Modify the script to count the number of comparisons each algorithm makes and print them. This will help you see the efficiency gap firsthand!</p>
]]></description><link>https://autonetops.com/exploring-basic-search-algorithms-using-python</link><guid isPermaLink="true">https://autonetops.com/exploring-basic-search-algorithms-using-python</guid><category><![CDATA[en]]></category><category><![CDATA[Python]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Explorando Algoritmos de Busca para Engenheiros de Redes: Linear Search vs. Binary Search]]></title><description><![CDATA[<p>Como engenheiros de redes, frequentemente lidamos com grandes conjuntos de dados, como endereos IP ou sub-redes. Realizar buscas eficientes nesses conjuntos  crucial para tarefas de automao, como encontrar uma sub-rede especfica em um inventrio de rede. Neste artigo, exploraremos dois algoritmos de busca fundamentais  <strong>linear search</strong> e <strong>binary search</strong></p>
<hr />
<h2 id="heading-gerando-os-dados">Gerando os Dados</h2>
<p>Para simular um inventrio de rede, criaremos um conjunto de sub-redes <code>/24</code> no range<code>10.0.0.0/8</code> (por exemplo, <code>10.0.0.0</code>, <code>10.0.1.0</code>, ..., <code>10.255.255.0</code>). O script Python a seguir gera trs arquivos: uma lista ordenada, uma lista invertida e uma lista aleatria de sub-redes.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> ipaddress
<span class="hljs-keyword">import</span> random

<span class="hljs-comment"># Gera todas as sub-redes /24 de 10.0.0.0/8</span>
subnets = list(ipaddress.ip_network(<span class="hljs-string">"10.0.0.0/8"</span>).subnets(new_prefix=<span class="hljs-number">24</span>))
networks = [str(n.network_address) <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> subnets]

<span class="hljs-comment"># Sub-redes ordenadas</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"ordered_ip.txt"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"\n"</span>.join(networks))

<span class="hljs-comment"># Sub-redes invertidas</span>
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"reverse_ip.txt"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"\n"</span>.join(reversed(networks)))

<span class="hljs-comment"># Sub-redes aleatrias</span>
random.shuffle(networks)
<span class="hljs-keyword">with</span> open(<span class="hljs-string">"random_ip.txt"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> f:
    f.write(<span class="hljs-string">"\n"</span>.join(networks))
</code></pre>
<p>Este script produz:</p>
<ul>
<li><p><code>ordered_ip.txt</code>: Sub-redes em ordem crescente (<code>10.0.0.0</code>, <code>10.0.1.0</code>, ...).</p>
</li>
<li><p><code>reverse_ip.txt</code>: Sub-redes em ordem decrescente (<code>10.255.255.0</code>, <code>10.255.254.0</code>, ...).</p>
</li>
<li><p><code>random_ip.txt</code>: Sub-redes em ordem aleatria.</p>
</li>
</ul>
<p>Cada arquivo contm 65.536 sub-redes (256  256), ideal para testar o desempenho das buscas.</p>
<hr />
<h2 id="heading-linear-search-a-abordagem-direta">Linear Search: A Abordagem Direta</h2>
<p>O <strong>linear search</strong>  como verificar cada dispositivo em um rack, um a um, at encontrar o que voc procura. Ele examina cada elemento de uma lista at encontrar uma correspondncia ou chegar ao final.</p>
<h3 id="heading-como-funciona">Como Funciona</h3>
<p>Imagine procurar pela sub-rede <code>10.0.5.0</code> em uma lista ordenada:</p>
<pre><code class="lang-python">Sub-redes: <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.1</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.2</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.3</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.4</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.5</span><span class="hljs-number">.0</span>
ndices:      <span class="hljs-number">0</span>         <span class="hljs-number">1</span>         <span class="hljs-number">2</span>         <span class="hljs-number">3</span>         <span class="hljs-number">4</span>         <span class="hljs-number">5</span>
</code></pre>
<ul>
<li><p>Verifica <code>10.0.0.0</code>  Sem correspondncia.</p>
</li>
<li><p>Verifica <code>10.0.1.0</code>  Sem correspondncia.</p>
</li>
<li><p>Continua at encontrar <code>10.0.5.0</code> (6 passos).</p>
</li>
</ul>
<p><strong>Desempenho</strong>:</p>
<ul>
<li><p><strong>Melhor caso</strong>: O alvo est no incio (1 passo, O(1)).</p>
</li>
<li><p><strong>Pior caso</strong>: O alvo est no final ou ausente (n passos, O(n), onde n  o tamanho da lista).</p>
</li>
<li><p>Para 65.536 sub-redes, o pior caso significa verificar todas as 65.536 entradas</p>
</li>
</ul>
<h3 id="heading-codigo-do-linear-search">Cdigo do Linear Search</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">from</span> ipaddress <span class="hljs-keyword">import</span> ip_address

<span class="hljs-comment"># L as sub-redes e converte para inteiros para comparao</span>
<span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">1</span>], <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
    data = [str(ip_address(line.strip())) <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> file]

<span class="hljs-comment"># Obtm a sub-rede alvo do usurio</span>
target = str(ip_address(input(<span class="hljs-string">"Digite uma sub-rede /24 (ex., 10.80.40.0): "</span>)))

start_time = time.time()
<span class="hljs-keyword">for</span> prefix <span class="hljs-keyword">in</span> data:
    <span class="hljs-keyword">if</span> prefix == target:
        print(<span class="hljs-string">f"Encontrado <span class="hljs-subst">{ip_address(target)}</span> com linear search"</span>)
        <span class="hljs-keyword">break</span>
print(<span class="hljs-string">f"Tempo: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> segundos"</span>)
</code></pre>
<hr />
<h2 id="heading-binary-search-dividir-e-conquistar">Binary Search: Dividir e Conquistar</h2>
<p>O <strong>binary search</strong>  como solucionar um problema de rede dividindo o espao do problema ao meio repetidamente. Ele <strong>requer uma lista ordenada</strong>, mas  significativamente mais rpido para grandes conjuntos de dados.</p>
<h3 id="heading-como-funciona-1">Como Funciona</h3>
<p>Na mesma lista, procurando por <code>10.0.5.0</code>:</p>
<pre><code class="lang-python">Sub-redes: <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.1</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.2</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.3</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.4</span><span class="hljs-number">.0</span>  <span class="hljs-number">10.0</span><span class="hljs-number">.5</span><span class="hljs-number">.0</span>
ndices:      <span class="hljs-number">0</span>         <span class="hljs-number">1</span>         <span class="hljs-number">2</span>         <span class="hljs-number">3</span>         <span class="hljs-number">4</span>         <span class="hljs-number">5</span>
</code></pre>
<ol>
<li><p>Encontra o ponto mdio: <code>(0 + 5) // 2 = 2</code> (<code>10.0.2.0</code>).</p>
</li>
<li><p>Compara: <code>10.0.2.0</code> &lt; <code>10.0.5.0</code>, ento ignora a metade esquerda (ndices 02).</p>
</li>
<li><p>Nova lista: <code>10.0.3.0</code>, <code>10.0.4.0</code>, <code>10.0.5.0</code>.</p>
</li>
<li><p>Novo ponto mdio: <code>(3 + 5) // 2 = 4</code> (<code>10.0.4.0</code>).</p>
</li>
<li><p>Compara: <code>10.0.4.0</code> &lt; <code>10.0.5.0</code>, ignora o ndice 4.</p>
</li>
<li><p>Verifica <code>10.0.5.0</code>  Encontrado em 3 passos!</p>
</li>
</ol>
<p><strong>Desempenho</strong>:</p>
<ul>
<li><p><strong>Melhor caso</strong>: O alvo est no ponto mdio (1 passo, O(1)).</p>
</li>
<li><p><strong>Pior caso</strong>: O(log n), onde n  o tamanho da lista. Para 65.536 sub-redes, so necessrios no mximo ~16 passos (log(65.536)  16).</p>
</li>
<li><p>O <strong>binary search</strong>  exponencialmente mais rpido que o <strong>linear search</strong> para grandes conjuntos.</p>
</li>
</ul>
<h3 id="heading-codigo-do-binary-search">Cdigo do Binary Search</h3>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">from</span> ipaddress <span class="hljs-keyword">import</span> ip_address

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_search</span>(<span class="hljs-params">arr, target</span>):</span>
    arr = sorted(arr)  <span class="hljs-comment"># Garante que a lista est ordenada</span>
    start = <span class="hljs-number">0</span>
    end = len(arr) - <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> start &lt;= end:
        mid = (start + end) // <span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> arr[mid] == target:
            <span class="hljs-keyword">return</span> mid
        <span class="hljs-keyword">elif</span> arr[mid] &lt; target:
            start = mid + <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            end = mid - <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

<span class="hljs-comment"># L as sub-redes e converte para inteiros</span>
<span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">1</span>], <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> f:
    data = [str(ip_address(line.strip())) <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f]

<span class="hljs-comment"># Obtm a sub-rede alvo</span>
target = str(ip_address(input(<span class="hljs-string">"Digite uma sub-rede /24 (ex., 10.80.40.0): "</span>)))

start_time = time.time()
index = binary_search(data, target)
<span class="hljs-keyword">if</span> index != <span class="hljs-number">-1</span>:
    print(<span class="hljs-string">f"Encontrado <span class="hljs-subst">{ip_address(target)}</span> com binary search"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">f"Sub-rede <span class="hljs-subst">{ip_address(target)}</span> no encontrada"</span>)
print(<span class="hljs-string">f"Tempo: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> segundos"</span>)
</code></pre>
<hr />
<h2 id="heading-comparacao-de-desempenho">Comparao de Desempenho</h2>
<p>Para ilustrar a diferena, testamos ambos os algoritmos em nossos conjuntos de sub-redes. Resultados para a busca de <code>10.255.255.0</code> (pior caso para <strong>linear search</strong> em <code>ordered_ip.txt</code>):</p>
<ul>
<li><p><strong>Linear Search</strong>: ~0.008 segundos (65.536 verificaes).</p>
</li>
<li><p><strong>Binary Search</strong>: ~0.0001 segundos (~16 verificaes).</p>
</li>
</ul>
<p>Para uma sub-rede aleatria como <code>10.80.40.0</code> em <code>random_ip.txt</code>:</p>
<ul>
<li><p><strong>Linear Search</strong>: ~0.004 segundos (caso mdio).</p>
</li>
<li><p><strong>Binary Search</strong>: ~0.0001 segundos (incluindo a sobrecarga de ordenao).</p>
</li>
</ul>
<p>O grfico abaixo visualiza o nmero de passos necessrios conforme o tamanho do conjunto de dados aumenta:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749465881408/0123a0ef-bf01-46c0-8b37-367ac9557da2.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-aplicacao-pratica-em-automacao-de-redes">Aplicao Prtica em Automao de Redes</h2>
<p>Imagine que voc est automatizando uma tarefa para encontrar uma sub-rede especfica em uma tabela de roteamento ou sistema IPAM. O <strong>linear search</strong> funciona para listas pequenas, mas se torna impraticvel para milhares de sub-redes. O <strong>binary search</strong>, com sua eficincia O(log n),  ideal para dados de rede em grande escala, especialmente se os dados j estiverem ordenados (comum em bancos de dados ou ferramentas IPAM).</p>
<p><strong>Exemplo de Caso de Uso</strong>: Voc est validando se uma sub-rede existe no inventrio de uma rede antes de atribu-la a uma nova VLAN. O <strong>binary search</strong> garante buscas rpidas, minimizando o tempo de execuo do script e melhorando a eficincia da automao.</p>
<hr />
<h2 id="heading-desafio-interativo">Desafio Interativo</h2>
<p>Experimente este exerccio prtico para ver os algoritmos em ao:</p>
<ol>
<li><p>Salve o script de gerao de sub-redes como <strong>subnets.py</strong> e execute-o para criar os trs arquivos.</p>
</li>
<li><p>Combine os scripts de <strong>linear search</strong> e <strong>binary search</strong> em um nico arquivo</p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> sys
 <span class="hljs-keyword">import</span> time
 <span class="hljs-keyword">from</span> ipaddress <span class="hljs-keyword">import</span> ip_address

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">linear_search</span>(<span class="hljs-params">arr, target</span>):</span>
     <span class="hljs-keyword">for</span> i, prefix <span class="hljs-keyword">in</span> enumerate(arr):
         <span class="hljs-keyword">if</span> prefix == target:
             <span class="hljs-keyword">return</span> i
     <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_search</span>(<span class="hljs-params">arr, target</span>):</span>
     arr = sorted(arr)
     start, end = <span class="hljs-number">0</span>, len(arr) - <span class="hljs-number">1</span>
     <span class="hljs-keyword">while</span> start &lt;= end:
         mid = (start + end) // <span class="hljs-number">2</span>
         <span class="hljs-keyword">if</span> arr[mid] == target:
             <span class="hljs-keyword">return</span> mid
         <span class="hljs-keyword">elif</span> arr[mid] &lt; target:
             start = mid + <span class="hljs-number">1</span>
         <span class="hljs-keyword">else</span>:
             end = mid - <span class="hljs-number">1</span>
     <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

 <span class="hljs-comment"># L as sub-redes</span>
 <span class="hljs-keyword">with</span> open(sys.argv[<span class="hljs-number">1</span>], <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> f:
     data = [int(ip_address(line.strip())) <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> f]

 <span class="hljs-comment"># Obtm a sub-rede alvo</span>
 target = int(ip_address(input(<span class="hljs-string">"Digite uma sub-rede /24 (ex., 10.80.40.0): "</span>)))

 <span class="hljs-comment"># Linear search</span>
 start_time = time.time()
 index = linear_search(data, target)
 print(<span class="hljs-string">f"Linear Search: <span class="hljs-subst">{<span class="hljs-string">'Encontrado'</span> <span class="hljs-keyword">if</span> index != <span class="hljs-number">-1</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'No encontrado'</span>}</span> <span class="hljs-subst">{ip_address(target)}</span>"</span>)
 print(<span class="hljs-string">f"Tempo: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> segundos"</span>)

 <span class="hljs-comment"># Binary search</span>
 start_time = time.time()
 index = binary_search(data, target)
 print(<span class="hljs-string">f"Binary Search: <span class="hljs-subst">{<span class="hljs-string">'Encontrado'</span> <span class="hljs-keyword">if</span> index != <span class="hljs-number">-1</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'No encontrado'</span>}</span> <span class="hljs-subst">{ip_address(target)}</span>"</span>)
 print(<span class="hljs-string">f"Tempo: <span class="hljs-subst">{time.time() - start_time:<span class="hljs-number">.4</span>f}</span> segundos"</span>)
</code></pre>
</li>
<li><p>Execute o script com diferentes arquivos e sub-redes:</p>
<pre><code class="lang-python"> search_subnets.py ordered_ip.txt
</code></pre>
<p> Experimente buscar por <code>10.0.0.0</code> (melhor caso), <code>10.255.255.0</code> (pior caso) e uma sub-rede aleatria como <code>10.80.40.0</code>.</p>
</li>
</ol>
<p><strong>Desafio</strong>: Modifique o script para contar o nmero de comparaes que cada algoritmo faz e imprima-os. Isso ajudar a visualizar a diferena de eficincia diretamente!</p>
]]></description><link>https://autonetops.com/explorando-algoritmos-de-busca-para-engenheiros-de-redes-linear-search-vs-binary-search</link><guid isPermaLink="true">https://autonetops.com/explorando-algoritmos-de-busca-para-engenheiros-de-redes-linear-search-vs-binary-search</guid><category><![CDATA[pt-br]]></category><category><![CDATA[Python]]></category><category><![CDATA[networking]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Túneis SSH]]></title><description><![CDATA[<p><a target="_blank" href="https://www.ssh.com/academy/ssh/tunneling-example">Tneis SSH</a> so uma ferramenta poderosa para estabelecer conexes entre trs entidades que enfrentam restries ou limitaes para se comunicarem diretamente. Esses tneis so especialmente teis para superar desafios relacionados  direo da conectividade ou determinar qual entidade pode iniciar uma conexo com outra. O processo envolve o encaminhamento de trfego de rede de um host para outro por meio de um intermedirio, contornando barreiras de conectividade.</p>
<hr />
<h2 id="heading-jumphost">JumpHost</h2>
<p>Eu frequentemente utilizo o recurso de encaminhamento de tneis SSH para acessar endpoints disponveis a partir de um <em>JumpHost</em>, mas no do meu laptop.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728672617798/a8739993-0cfb-482c-8b08-ca6612be5278.png" alt="Diagrama JumpHost" class="image--center mx-auto" /></p>
<h3 id="heading-exemplo-de-configuracao">Exemplo de Configurao</h3>
<pre><code class="lang-bash">ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr

<span class="hljs-comment">## Exemplos</span>
ssh -L 8443:destino:443 usuario@jumphost
ssh -L 2022:destino:22 usuario@jumphost
</code></pre>
<p>Aqui est uma representao visual:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728670756938/1a01680f-caff-4221-8869-cc1df9117d09.png" alt="Representao visual do tnel" class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-proxy-reverso">Proxy Reverso</h2>
<p>A ideia  permitir que uma entidade acessvel por voc se conecte por meio de outra entidade que no consegue estabelecer essa conexo diretamente.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1728673381149/9ec749b0-15f9-4f0f-bdd9-973434bee310.png" alt="Diagrama Proxy Reverso" class="image--center mx-auto" /></p>
<p>O caso de uso mais comum que vi em outros artigos :</p>
<ul>
<li><p>Expor um servio de desenvolvimento  internet pblica para uma demonstrao.</p>
  <details><summary>Alvo</summary><div data-type="detailsContent">Pode ser um servidor web em sua empresa ou em sua prpria mquina, por exemplo.</div></details>

</li>
</ul>
<p>Outro caso de uso que precisei por algum tempo foi:</p>
<ul>
<li>Expor um servio pblico a um servidor interno.</li>
</ul>
<h3 id="heading-guia-passo-a-passo-do-meu-caso">Guia Passo a Passo do Meu Caso</h3>
<p>H um servidor da empresa que no tem acesso ao GitHub, onde armazeno uma grande quantidade de cdigo.</p>
<p>Minha mquina pessoal de trabalho tem acesso ao GitHub. Posso me conectar ao servidor a partir da minha mquina, mas no posso conectar ao meu computador a partir do servidor devido a regras de firewall que bloqueiam essa conexo (o que impede o uso da tcnica de JumpHost).</p>
<p>Portanto, preciso criar um tnel da minha mquina para o servidor para conceder acesso a algo.</p>
<p> necessrio configurar uma conexo de proxy reverso para que o servidor tenha acesso ao GitHub.</p>
<details><summary>Annimo</summary><div data-type="detailsContent">O agente que solicita o trfego seria o prprio gateway (o servidor).</div></details>

<h3 id="heading-no-servidor-remoto"> No Servidor Remoto</h3>
<ol>
<li><p>Certifique-se de <a target="_blank" href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent">adicionar as chaves SSH ao GitHub</a>.</p>
</li>
<li><p><strong>Carregar Permanentemente a Chave SSH no ssh-agent</strong></p>
</li>
</ol>
<pre><code class="lang-bash">nano ~/.bashrc
<span class="hljs-comment">#### Adicione ao final do arquivo</span>
<span class="hljs-built_in">eval</span> <span class="hljs-string">"<span class="hljs-subst">$(ssh-agent -s)</span>"</span>
ssh-add ~/.ssh/github_private_key
</code></pre>
<ol start="3">
<li><strong>Ajustar o Arquivo de Configurao do Git</strong></li>
</ol>
<pre><code class="lang-bash">nano ~/.ssh/config
</code></pre>
<pre><code class="lang-bash">Host localhost
    Hostname localhost
    Port 8088
    User git
</code></pre>
<ol start="4">
<li><strong>Configurar a Origem</strong></li>
</ol>
<p>No repositrio da sua pasta:</p>
<pre><code class="lang-bash">git remote set-url origin git@localhost:usuario/REPONOME.git
</code></pre>
<ol start="5">
<li><strong>Criar o Tnel (A partir da Sua Mquina Local)</strong></li>
</ol>
<pre><code class="lang-bash">ssh -R 8088:github.sua_empresa.com:22 servidor
</code></pre>
<ol start="6">
<li><strong>Validar o Acesso</strong></li>
</ol>
<pre><code class="lang-bash">ssh -T git@localhost
</code></pre>
<hr />
<h2 id="heading-referencias">Referncias</h2>
<p><a target="_blank" href="https://www.ssh.com/academy/ssh/tunneling-example">https://www.ssh.com/academy/ssh/tunneling-example</a></p>
<p><a target="_blank" href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh">https://docs.github.com/en/authentication/connecting-to-github-with-ssh</a></p>
]]></description><link>https://autonetops.com/tuneis-ssh</link><guid isPermaLink="true">https://autonetops.com/tuneis-ssh</guid><category><![CDATA[pt-br]]></category><category><![CDATA[ssh]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item><item><title><![CDATA[Entenda e mitigue loops de rede]]></title><description><![CDATA[<p>O Spanning Tree Protocol (STP) ajuda a criar uma topologia sem loops em redes comutadas. A pergunta que devemos nos fazer :</p>
<ul>
<li>O que causa um loop em uma rede?</li>
</ul>
<p><mark>Loops so introduzidos em uma rede quando adicionamos redundncia</mark>, criando mltiplos caminhos entre dois pontos. Isso pode fazer com que os dados circulem indefinidamente, causando problemas graves, como degradao de desempenho, bloqueios inesperados de portas, interrupes completas da rede e at falhas nos dispositivos.</p>
<p>Quando h um loop, os switches continuam encaminhando pacotes repetidamente at que uma das seguintes situaes ocorra:</p>
<ul>
<li><p>O loop  corrigido ao desconectar um dos cabos.</p>
</li>
<li><p>Os switches travam devido ao excesso de trfego.</p>
</li>
<li><p>Os quadros Ethernet, que <mark>no possuem um campo TTL (Time to Live), continuam circulando indefinidamente.</mark></p>
</li>
</ul>
<p>Esse comportamento tambm afeta o trfego BUM  broadcast, unicast desconhecido e multicast.</p>
<h3 id="heading-bpdu">BPDU</h3>
<p>Os switches que utilizam o STP trocam informaes por meio de mensagens especiais chamadas <strong>BPDU</strong> (Bridge Protocol Data Unit, ou Unidade de Dados de Protocolo de Ponte).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731775486973/62fb475c-e15c-4ce0-8436-967b6f2d0673.png" alt="Campos do BPDU" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731775600358/e9c4adaa-d191-4687-b27e-ef482b4adea1.jpeg" alt="Captura STP" class="image--center mx-auto" /></p>
<h2 id="heading-formacao-da-arvore">Formao da rvore</h2>
<p>O processo de formao da rvore segue estas etapas:</p>
<ul>
<li><p><strong>Eleio do switch raiz</strong>: Todas as portas do switch raiz estaro no estado de encaminhamento (forwarding).</p>
</li>
<li><p><strong>Switches no-raiz</strong>: Cada switch no-raiz deve encontrar o caminho mais curto at o switch raiz e eleger uma porta raiz (root port). - Isso acontece atraves do <mark>CUSTO</mark></p>
</li>
<li><p><strong>Outras portas</strong>: Todas as portas que recebem BPDUs (indicando a presena de um loop) passam por um processo de eleio para determinar se sero portas de encaminhamento ou bloqueio, eliminando o loop.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731787477307/7a658789-097f-49db-b788-3ed1ff3b3e80.png" alt="Diagrama de formao da rvore" class="image--center mx-auto" /></p>
<h3 id="heading-switch-raiz">Switch Raiz</h3>
<p>O switch raiz  aquele com o menor identificador de ponte (bridge ID), composto por <strong>prioridade + endereo MAC</strong>.</p>
<h3 id="heading-switches-nao-raiz">Switches No-Raiz</h3>
<p>Todos os switches no-raiz devem encontrar o caminho mais curto at o switch raiz. Como isso  feito? O STP atribui custos a cada interface com base na sua velocidade. A interface com o menor custo at o switch raiz  designada como a porta raiz, que encaminha o trfego.</p>
<p>As demais portas dos switches no-raiz decidem se encaminharo trfego ou sero bloqueadas para evitar loops. Todas as portas que recebem BPDUs passam por esse processo de eleio para determinar seu estado.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Lembre-se: os switches tomam decises apenas com base nos BPDUs recebidos! Eles no conhecem a topologia completa da rede. A nica informao disponvel  a interface que recebeu o melhor BPDU, ou seja, aquele com o caminho mais curto at o switch raiz.</div>
</div>

<h3 id="heading-processo-de-desempate">Processo de Desempate</h3>
<p>Quando o STP precisa tomar uma deciso, ele segue esta ordem de critrios:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731788673722/61fb2099-5310-4161-8ec8-369e8326985f.png" alt="Desempate de estados de porta" class="image--center mx-auto" /></p>
<ol>
<li><p><strong>Menor custo at o switch raiz</strong>: Quando um switch recebe mltiplos BPDUs, ele escolhe a interface com o menor custo at o switch raiz como a porta raiz.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731789297716/0171f470-3437-43d3-99cf-39b86dfa5030.png" alt="Custo at o switch raiz" class="image--center mx-auto" /></p>
</li>
<li><p><strong>Menor ID de ponte do remetente</strong>: Se um switch est conectado a dois outros switches que oferecem o mesmo custo at o switch raiz, ele escolhe a interface conectada ao switch com o menor ID de ponte como a porta raiz.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731789136961/70c6ea9c-d8ad-4a0f-bc14-5190419ee632.png" alt="Menor ID de ponte" class="image--center mx-auto" /></p>
</li>
<li><p><strong>Menor ID de porta do remetente</strong>: Se um switch possui duas interfaces conectadas ao mesmo switch e o custo at o switch raiz  igual, ele escolhe a interface com o menor nmero como a porta raiz.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1731789063235/4698ccc7-3de8-48b3-a212-ac123cea8b88.png" alt="Menor ID de porta" class="image--center mx-auto" /></p>
</li>
</ol>
<h3 id="heading-tabela-de-custos-de-porta-por-velocidade-de-interface"><strong>Tabela de Custos de Porta por Velocidade de Interface</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Velocidade da Interface</strong></td><td><strong>Custo STP</strong></td><td><strong>Descrio</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>10 Mbps</strong></td><td><strong>100</strong></td><td>Ethernet padro (Fast Ethernet)</td></tr>
<tr>
<td><strong>100 Mbps</strong></td><td><strong>19</strong></td><td>Fast Ethernet</td></tr>
<tr>
<td><strong>1 Gbps</strong></td><td><strong>4</strong></td><td>Gigabit Ethernet</td></tr>
<tr>
<td><strong>10 Gbps</strong></td><td><strong>2</strong></td><td>10-Gigabit Ethernet</td></tr>
<tr>
<td><strong>25 Gbps</strong></td><td><strong>1</strong></td><td>25-Gigabit Ethernet (se suportado)</td></tr>
<tr>
<td><strong>40 Gbps</strong></td><td><strong>1</strong></td><td>40-Gigabit Ethernet (se suportado)</td></tr>
<tr>
<td><strong>100 Gbps</strong></td><td><strong>1</strong></td><td>100-Gigabit Ethernet (se suportado)</td></tr>
</tbody>
</table>
</div><p><strong>Nota</strong>: Os custos acima seguem o padro <strong>IEEE 802.1D</strong>, amplamente implementado em dispositivos de rede. Algumas switches modernas podem suportar velocidades mais altas (como 25 Gbps, 40 Gbps ou 100 Gbps) com o mesmo custo mnimo de 10 Gbps.</p>
<p>O STP atribui custos s portas para determinar o caminho mais eficiente para os dados na rede. Custos menores so preferidos, o que significa que links de maior velocidade so priorizados.</p>
<h2 id="heading-melhores-praticas-para-evitar-loops-na-rede">Melhores Prticas para Evitar Loops na Rede</h2>
<p>Para garantir a estabilidade da rede e prevenir loops, siga estas recomendaes:</p>
<ol>
<li><p><strong>Priorize switches centrais no STP</strong>: Configure as prioridades do STP para garantir que o switch raiz seja o mais confivel. Isso otimiza os caminhos de dados e bloqueia links redundantes adequadamente.</p>
</li>
<li><p><strong>Ative proteo contra loops</strong>: Configure a proteo contra loops nas portas dos switches para desativ-las automaticamente quando um loop for detectado.</p>
</li>
<li><p><strong>Manuteno regular</strong>: Inspecione e substitua cabos defeituosos. Negociaes de link inadequadas podem causar mudanas de prioridade no STP (flapping), resultando em problemas persistentes de conectividade.</p>
</li>
</ol>
<p>Espero que esta reviso rpida do STP tenha sido til! H sempre mais a explorar, mas com essas informaes, voc tem uma base slida para diagnosticar e interpretar resultados de anlises.</p>
<p>At a prxima!</p>
]]></description><link>https://autonetops.com/entenda-e-mitigue-loops-de-rede</link><guid isPermaLink="true">https://autonetops.com/entenda-e-mitigue-loops-de-rede</guid><category><![CDATA[spanning tree]]></category><category><![CDATA[pt-br]]></category><dc:creator><![CDATA[pDamasceno]]></dc:creator></item></channel></rss>