Proximos cursos: docker, kubernetes, terraform, github actions


Introducción


Hola,

Voy a estar trabajando en algunos cursos que estarán disponibles aquí a través de GitHub Sponsors, pero quería explicar qué obtendrás al patrocinarme y cómo funciona a un nivel alto. Al convertirte en patrocinador, obtendrás acceso de por vida a los cursos. Estos cursos serán altamente prácticos con explicaciones y la teoría necesaria para entender el tema en cuestión. Todo lo demás será de código abierto (ejemplos de código, etc.). Al apoyarme, recibirás más contenido a cambio 😄


Próximos cursos:

  • Docker: Comprende Docker desde cero.
  • Kubernetes: Despliega tus aplicaciones y gestiona clústeres, autoescala tus apps y mejores prácticas.
  • Terraform: Codifica tu infraestructura y automatízala a través de GitHub y Atlantis.
  • GitHub Actions: Configura tus pipelines para construir, probar y desplegar tus aplicaciones en Kubernetes.
  • Observabilidad: Aprende a desplegar y usar Prometheus y Grafana para observar y monitorear tus aplicaciones, crear dashboards y también alertas significativas.

Espero lanzar oficialmente el curso de Docker en aproximadamente un mes. Los demás cursos comenzarán después de eso. Además, al unirte, recibirás una invitación para Discord/Slack (por definir) para que puedas conectarte conmigo y hacerme cualquier pregunta que puedas tener.


Gracias 💥


Pero espera… ¿cómo funciona?

Mencioné que todo iba a ser de código abierto, incluso este blog o plataforma de aprendizaje. ¿No podríamos simplemente leer los artículos ya que están en texto plano en el repositorio? tr, y sería una pregunta justa. Presentando “Cloak”, el contenido patrocinado estará, de hecho, en el repositorio, legible por cualquiera, pero encriptado y solo será renderizado para aquellos que inicien sesión a través de GitHub (porque necesito conocer tu nombre de usuario) y también para asegurarme de que, de hecho, eres un patrocinador 🥲.

Con solo algunas llamadas a este módulo, podemos encriptar y desencriptar el contenido de una página dada. Por ejemplo, así es como se ve:


%{
  title: "Domina Docker desde cero (próximamente...)",
  author: "Gabriel Garrido",
  description: "Este será un curso corto para dominar Docker en Linux. Consistirá en 3 partes y será el primer contenido patrocinado publicado aquí (video y texto)",
  tags: ~w(docker cursos),
  published: true,
  image: "docker-logo.svg",
  sponsored: true,
  video: "AQpBRVMuR0NNLlYxTJxSRfOfhl7jf3JuF/iCr59Ft4wVtu0td5HG//On8X1qfAwkUvdCST8aXPtgFedBaVfkKIATz1TgZNoe9R17SdiB066J",
  encrypted_content: "AQpBRVMuR0NNLlYxJJUZ6S+zhjv81zDHqUMSo3g5JkVGsTchQlKfB7fZfxg//hMIyX/XsUCygsFRr+MFlpw0vne8FxO2Si6jshOw8lKDMNvoXioHNmgQeozlahuIce0+D0NCh5vFFsbJIi//TTpac1coUdiEbReH94yDQ07V4O848C5J7F5JjZslhGekKVjq0eT3T7PmIibJfii391tqgYUBHIg/jpY2LifxzgrHW5jaFRzrsIZNuCiBF1M4lUjSORF01aPgT68s1vHcG/+r0LE8EsCsHRT9VDvKl0F6ntgwoTUY/OSqONCbkzE2wfWsy5jGGV3YN8jCkMYIWi7FylgpCrMbb99DfNIKRA37GpvoLx08+X8YPbBRHoL1Gs3JGIi91UBAMQ=="
}
---

Luego tenemos nuestro vault configurado (es solo un Genserver que nos da capacidades de encriptar/desencriptar dada una clave particular), que será este módulo en particular:

defmodule Tr.Vault do
  @moduledoc """
  Este módulo se encarga de interactuar con el vault
  """
  use Cloak.Vault, otp_app: :tr

  @impl GenServer
  def init(config) do
    config =
      Keyword.put(config, :ciphers,
        default: {
          Cloak.Ciphers.AES.GCM,
          tag: "AES.GCM.V1", key: decode_env!("CLOAK_KEY"), iv_length: 12
        }
      )

    {:ok, config}
  end

  defp decode_env!(var) do
    var
    |> System.get_env()
    |> Base.decode64!()
  end
end

Para mantener los límites de tasa bajo control, cada 5 minutos hago polling a la API GraphQL de GitHub para obtener la lista de patrocinadores y almacenarla en la DB local:

defmodule Tr.Sponsors do
  @moduledoc """
  Tarea básica para obtener la lista de patrocinadores desde GitHub
  """
  @app :tr

  defp load_app do
    Application.load(@app)
  end

  defp start_app do
    load_app()
    Application.ensure_all_started(@app)
  end

  @doc """
  """
  def start do
    start_app()

    # contemplar más de 100 patrocinadores
    sponsors = get_sponsors(100)

    Enum.each(get_in(sponsors, ["data", "user", "sponsors", "nodes"]), fn sponsor ->
      Tr.SponsorsCache.add_or_update(sponsor)
    end)
  end

  @doc """
    # Ejemplo de salida:

    %Neuron.Response{
      body: %{
        "data" => %{
          "user" => %{
            "sponsors" => %{
              "nodes" => [
                %{"login" => "nnnnnnn"},
                %{"login" => "xxxxxxx"},
                %{...},
                ...
              ],
              "totalCount" => 123
            }
          }
        }
      }
  """
  def get_sponsors(limit) do
    token = System.get_env("GITHUB_BEARER_TOKEN")

    {:ok, body} =
      Neuron.query(
        "{ user(login:\"kainlite\") { ... on Sponsorable { sponsors(first: #{limit}) { totalCount
      nodes { ... on User { login } ... on Organization { login } } } } } }",
        %{},
        url: "https://api.github.com/graphql",
        headers: [authorization: "Bearer #{token}"]
      )

    body.body
  end
end

El último paso sería simplemente desencriptar y renderizar el contenido:

    <%= cond do %>
      <% @post.sponsored && @current_user && Tr.SponsorsCache.sponsor?(@current_user.github_username) -> %>
        <br />
        <p>
          <iframe
            width="100%"
            height="800px"
            src={decrypt(@post.video)}
            title=""
            frameBorder="0"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
            allowFullScreen
          >
          </iframe>
        </p>
        <br />
        <%= raw(Earmark.as_html!(decrypt(@post.encrypted_content))) %>
    ...
    ...

A alto nivel, así es como funciona. ¿Te interesa aprender más sobre esto o el enfoque adoptado aquí? Dejá un comentario 👇



No tienes cuenta? Regístrate aqui

Ya registrado? Iniciar sesión a tu cuenta ahora.

Iniciar session con GitHub
Iniciar sesion con Google
  • Comentarios

    Online: 0

Por favor inicie sesión para poder escribir comentarios.

by Gabriel Garrido