<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gustavo Gordillo</title>
    <description>The latest articles on DEV Community by Gustavo Gordillo (@gustavo_gordillo_aec0b580).</description>
    <link>https://dev.to/gustavo_gordillo_aec0b580</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1235484%2Ff46b41fb-e474-43c1-9d5e-54f27f43ab25.png</url>
      <title>DEV Community: Gustavo Gordillo</title>
      <link>https://dev.to/gustavo_gordillo_aec0b580</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gustavo_gordillo_aec0b580"/>
    <language>en</language>
    <item>
      <title>Connecting MongoDB with Tableau: A Step-by-Step Guide (Macbook client)</title>
      <dc:creator>Gustavo Gordillo</dc:creator>
      <pubDate>Mon, 09 Sep 2024 17:49:58 +0000</pubDate>
      <link>https://dev.to/gustavo_gordillo_aec0b580/connecting-mongodb-with-tableau-a-step-by-step-guide-macbook-client-5heb</link>
      <guid>https://dev.to/gustavo_gordillo_aec0b580/connecting-mongodb-with-tableau-a-step-by-step-guide-macbook-client-5heb</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndtms2ma50ly50otfczx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fndtms2ma50ly50otfczx.jpg" alt="mongo+tableau" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In today's data-driven world, visualizing data is crucial for understanding trends and making informed decisions. MongoDB, a powerful NoSQL database, offers flexibility and scalability, while Tableau is one of the top tools for data visualization. By combining these two, you can effectively represent unstructured or semi-structured data stored in MongoDB. In this tutorial, we’ll guide you through the process of connecting MongoDB with Tableau using the MongoDB BI Connector, helping you to visualize your data effortlessly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Table of Contents
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Downloading Drivers&lt;/li&gt;
&lt;li&gt;Connecting MongoDB to Tableau Using the BI Connector&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  Step 1: Prerequisites
&lt;/h4&gt;

&lt;p&gt;Before starting, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tableau Desktop&lt;/strong&gt;: If you don't already have Tableau installed, you can download it from &lt;a href="https://www.tableau.com/products/desktop/download" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection String&lt;/strong&gt;: The MongoDB connection string provided by your database service. It will look something like this:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;mongodb://atlas-sql-[id]-yp1td.a.query.mongodb.net/[db]?ssl=true&amp;amp;authSource=admin&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your database provider should supply this, along with the appropriate &lt;strong&gt;username&lt;/strong&gt; and &lt;strong&gt;password&lt;/strong&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  Step 2: Install MongoDB JDBC Driver
&lt;/h4&gt;

&lt;p&gt;MongoDB offers official support for connecting to Tableau via the MongoDB BI Connector. Follow these steps to set up the connection and start visualizing your MongoDB data in Tableau.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download the MongoDB JDBC Driver&lt;/strong&gt;
Download the latest version of the MongoDB JDBC driver from the official MongoDB documentation. You can find it &lt;a href="https://www.mongodb.com/docs/atlas/data-federation/query/sql/tableau/connect/#std-label-sql-connect-tableau" rel="noopener noreferrer"&gt;here&lt;/a&gt;. In this case, the most recent version is &lt;code&gt;mongodb-jdbc-2.2.0-all.jar&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pqsbgrsq9qzhowvspsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pqsbgrsq9qzhowvspsk.png" alt="MongoDB JDBC Driver Download" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fliqvdibztnl2unib76uv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fliqvdibztnl2unib76uv.png" alt="MongoDB JDBC Driver Example" width="800" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Move the &lt;code&gt;.jar&lt;/code&gt; File into Tableau Driver folder&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After downloading the &lt;code&gt;.jar&lt;/code&gt; file, move it to the appropriate directory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the home directory in the Finder app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8mvexuokkg01wvybdpt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8mvexuokkg01wvybdpt.png" alt="Open home directory" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open Finder and press &lt;code&gt;Shift + Command + .&lt;/code&gt; to reveal hidden folders.&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;Library&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Inside &lt;code&gt;Library&lt;/code&gt;, go to &lt;code&gt;Tableau/Drivers&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Copy and paste the downloaded &lt;code&gt;.jar&lt;/code&gt; file into the &lt;code&gt;Drivers&lt;/code&gt; folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltzi7ysjwthuzu4ngftr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltzi7ysjwthuzu4ngftr.png" alt="macOS Drivers Folder" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Install the Tableau Connector (&lt;code&gt;.taco&lt;/code&gt; File)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download the Tableau Connector (&lt;code&gt;.taco&lt;/code&gt;) File&lt;/strong&gt;
The &lt;code&gt;.taco&lt;/code&gt; file is required to complete the connection. Download it from &lt;a href="https://www.mongodb.com/try/download/tableau-connector" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceirjli37ttwqji1tgoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceirjli37ttwqji1tgoi.png" alt="Download Tableau Connector" width="800" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add the &lt;code&gt;.taco&lt;/code&gt; File to Tableau Repository&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Open Tableau.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;code&gt;File &amp;gt; Repository Location&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvihvem82t16qczr6itt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcvihvem82t16qczr6itt.png" alt="Tableau Repository Location" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find and open the &lt;code&gt;Connectors&lt;/code&gt; folder in the Tableau repository.&lt;/li&gt;
&lt;li&gt;Copy and paste the downloaded &lt;code&gt;.taco&lt;/code&gt; file into this folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0hfjetqyrsjitgu1csv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0hfjetqyrsjitgu1csv.png" alt="Add  raw `.taco` endraw  File to Connectors Folder" width="799" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig3iwz1kwbbykye7i7i9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fig3iwz1kwbbykye7i7i9.png" alt="Connector Placement in Tableau" width="776" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once these steps are completed, MongoDB should appear now in Tableau as an optional connection.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Connecting MongoDB to Tableau Using the BI Connector
&lt;/h4&gt;

&lt;p&gt;To connect MongoDB Atlas to Tableau, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8smnol5aewdkbvt5yjrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8smnol5aewdkbvt5yjrk.png" alt="MongoDB Atlas Connection Screen" width="800" height="728"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Select MongoDB Atlas by MongoDB&lt;/strong&gt; from the available options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enter your MongoDB URI&lt;/strong&gt; (ask your database administrator for this information).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specify the database&lt;/strong&gt; you want to access (ask your database administrator for this information).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Authentication Method&lt;/strong&gt;: Use &lt;em&gt;Username and Password&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input Username&lt;/strong&gt; (ask your database administrator for this information).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input Password&lt;/strong&gt; (ask your database administrator for this information).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click Sign In&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf5pcmyzt8p6euk7zt8f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf5pcmyzt8p6euk7zt8f.png" alt="MongoDB Atlas Connection Success" width="506" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it! You are now successfully connected to your MongoDB database. Congratulations! 🥳🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;MongoDB Atlas Tableau Connector Documentation: &lt;a href="https://www.mongodb.com/docs/atlas/data-federation/query/sql/tableau/connect/#std-label-sql-connect-tableau" rel="noopener noreferrer"&gt;MongoDB Atlas Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tableau Desktop MySQL Connection Documentation: &lt;a href="https://help.tableau.com/current/pro/desktop/en-us/examples_mysql.htm" rel="noopener noreferrer"&gt;Tableau Guide&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mongodb</category>
      <category>powerapps</category>
      <category>business</category>
      <category>database</category>
    </item>
    <item>
      <title>Setup a GO Bazel Monorepo (using bzlmod)</title>
      <dc:creator>Gustavo Gordillo</dc:creator>
      <pubDate>Fri, 28 Jun 2024 00:29:30 +0000</pubDate>
      <link>https://dev.to/gustavo_gordillo_aec0b580/setup-a-go-bazel-monorepo-using-bzlmod-1df8</link>
      <guid>https://dev.to/gustavo_gordillo_aec0b580/setup-a-go-bazel-monorepo-using-bzlmod-1df8</guid>
      <description>&lt;p&gt;In this article, we’ll walk through setting up your own Bazel repository using &lt;strong&gt;bzlmod&lt;/strong&gt;, the new external dependency system introduced in Bazel 5 and later. We’ll also add a small Go “Hello, World!” project to demonstrate how to include additional projects in a monorepo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xxnakweao9kdawu75jb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xxnakweao9kdawu75jb.png" alt="Bazel logo" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a new directory&lt;/strong&gt; for your Bazel project. For this example, we’ll call it &lt;code&gt;bazel-intro&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the &lt;code&gt;bazel-intro&lt;/code&gt; directory, create two files: &lt;code&gt;MODULE.bazel&lt;/code&gt; and &lt;code&gt;BUILD&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Directory structure so far:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;bazel-intro&lt;br&gt;
│&lt;br&gt;
├─ MODULE.bazel&lt;br&gt;
├─ BUILD&lt;/p&gt;
&lt;h3&gt;
  
  
  About the MODULE.bazel File
&lt;/h3&gt;

&lt;p&gt;According to the official &lt;a href="https://bazel.build/external/overview#bzlmod" rel="noopener noreferrer"&gt;Bazel docs on bzlmod&lt;/a&gt;, the &lt;code&gt;MODULE.bazel&lt;/code&gt; file should be at the root of your workspace (where the &lt;code&gt;WORKSPACE&lt;/code&gt; file would normally be). Unlike &lt;code&gt;WORKSPACE&lt;/code&gt;, you do &lt;strong&gt;not&lt;/strong&gt; list all transitive dependencies here—only direct dependencies. Bazel will automatically process the &lt;code&gt;MODULE.bazel&lt;/code&gt; files of your dependencies to find any transitive dependencies. In this example, we don’t need a &lt;code&gt;WORKSPACE&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;
  
  
  Editing MODULE.bazel for Go Support
&lt;/h3&gt;

&lt;p&gt;Since we’re going to use Go, we need to specify the necessary Bazel dependencies for Go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bazel_dep(name = "gazelle", version = "0.37.0")
bazel_dep(name = "rules_go", version = "0.48.1")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;gazelle&lt;/strong&gt;: A build file generator that automatically creates or updates BUILD files for Go projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;rules_go&lt;/strong&gt;: Provides rules to build Go code with Bazel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find more recent versions of these dependencies on the Bazel Registry.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Go Extensions
&lt;/h3&gt;

&lt;p&gt;According to the rules_go and gazelle docs, add the following lines to MODULE.bazel to set up the Go SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

# Download a suitable Go SDK.
go_sdk.download(version = "1.20.3")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding Gazelle Integration and Dependencies
&lt;/h3&gt;

&lt;p&gt;Next, integrate Gazelle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")

use_repo(go_deps,
         "com_github_gofiber_fiber_v2", 
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s what we did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;go_deps.from_file(go_mod = "//:go.mod")&lt;/strong&gt;: Points Gazelle to our Go module file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;use_repo(go_deps, "com_github_gofiber_fiber_v2")&lt;/strong&gt;: Registers a Go dependency (github.com/gofiber/fiber/v2) that we’ll use in our example HTTP server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you need more dependencies, you can simply list them inside use_repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use_repo(go_deps, 
         "com_github_gofiber_fiber_v2", 
         "com_github_joho_godotenv"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updating the BUILD File
&lt;/h3&gt;

&lt;p&gt;Now let’s populate the top-level BUILD file to integrate Gazelle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;load("@gazelle//:def.bzl", "gazelle")

gazelle(name = "gazelle")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sets up Gazelle at the root of our workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Sample Go Project
&lt;/h2&gt;

&lt;p&gt;Next, we’ll create a simple Go project within our repository to test everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updated directory structure:
&lt;/h3&gt;

&lt;p&gt;bazel-intro&lt;br&gt;
│&lt;br&gt;
├─ MODULE.bazel&lt;br&gt;
├─ BUILD&lt;br&gt;
└─ services&lt;br&gt;
   └─ app&lt;br&gt;
      └─ main.go&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inside bazel-intro, create a services directory.&lt;/li&gt;
&lt;li&gt;Inside services, create an app directory.&lt;/li&gt;
&lt;li&gt;In the app directory, create a main.go file with the following code:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gofiber/fiber/v2"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fiber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fiber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SendString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":3000"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Initializing Go Modules
&lt;/h3&gt;

&lt;p&gt;In your terminal, navigate to bazel-intro and initialize a Go module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod init bazel-intro/services
go mod tidy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a go.mod and a go.sum file in the root. Gazelle will use these to understand and update dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Gazelle and Building the Project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run Gazelle&lt;/strong&gt; to generate BUILD files for Go code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bazel run //:gazelle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build all targets:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bazel build //...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run the application:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bazel run services/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything goes correctly, you should see the Fiber HTTP server running on port 3000. Open your browser and navigate to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; to see the “Hello, World!” message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawbd30bcekik19oamw4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawbd30bcekik19oamw4v.png" alt="Go fiber http server running" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You’ve successfully set up a Bazel repository using bzlmod, integrated Go support, and created a small service using Fiber. From here, you can add more services, dependencies, and tooling to expand your monorepo.&lt;/p&gt;

&lt;p&gt;Happy coding! 🎉&lt;/p&gt;

</description>
    </item>
    <item>
      <title>SQL Server &amp; MongoDB sync (Kafka + Kubernetes + Debezium)</title>
      <dc:creator>Gustavo Gordillo</dc:creator>
      <pubDate>Sun, 17 Dec 2023 21:17:28 +0000</pubDate>
      <link>https://dev.to/gustavo_gordillo_aec0b580/sql-server-mongodb-sync-kafka-kubernetes-debezium-1alc</link>
      <guid>https://dev.to/gustavo_gordillo_aec0b580/sql-server-mongodb-sync-kafka-kubernetes-debezium-1alc</guid>
      <description>&lt;p&gt;&lt;strong&gt;The problem to solve&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some months back, I encountered a scenario where I needed to synchronize two databases: one based on SQL Server and the other on MongoDB. The SQL Server database was the primary source of information derived from the client's business logic, and the MongoDB was the source of information for our proprietary e-commerce sites. &lt;/p&gt;

&lt;p&gt;We needed to synchronize some of the client SQL server operations on our Mongo DB. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem in pieces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After some research, we found a way to achieve this using an event-driven architecture pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We must capture events from SQL Server (INSERT, DELETE, UPDATES, etc.. )&lt;/li&gt;
&lt;li&gt;Stream those events &lt;/li&gt;
&lt;li&gt;Consume events and update the MongoDB. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We used the change data capture (CDC) of SQL Server in combination with &lt;a href="https://debezium.io/documentation/reference/2.4/connectors/index.html"&gt;Debizium connectors&lt;/a&gt; to capture the SQL operations (such as inserts, deletes, updates, etc..) and send them to &lt;a href="https://kafka.apache.org/documentation/"&gt;Apache Kafka&lt;/a&gt;, an open-source event streaming platform. And for the consumers part we develop our own using python.&lt;/p&gt;

&lt;p&gt;The architecture will look like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W1nsig31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8iqaq7r6f0lpku0ym4rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W1nsig31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8iqaq7r6f0lpku0ym4rj.png" alt="Debeizum architecture Docs" width="800" height="169"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image from &lt;a href="https://debezium.io/documentation/reference/2.4/architecture.html"&gt;Debizium documentation&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tutorial&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I will explain how to do it using MiniKube (local kubernetes) ideal for testing before production. You probably need to have some basic knowladge of Kubernetes. &lt;/p&gt;

&lt;p&gt;The first part in this process is to enable change data capture for the table of your interest &lt;a href="https://learn.microsoft.com/en-us/sql/relational-databases/track-changes/enable-and-disable-change-data-capture-sql-server?view=sql-server-ver16"&gt;(Microsoft Docs)&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Enable CDC for a table specifying filegroup&lt;/span&gt;
&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="n"&gt;MyDB&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;

&lt;span class="k"&gt;EXEC&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sp_cdc_enable_table&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;source_schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="s1"&gt;'dbo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;source_name&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="s1"&gt;'MyTable'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;role_name&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="s1"&gt;'MyRole'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;filegroup_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="s1"&gt;'MyDB_CT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;supports_net_changes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;GO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you enable the CDC, we can start using minikube to deploy locally our cluster. &lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying architecture in Minikube
&lt;/h3&gt;

&lt;p&gt;To deploy the architecture locally I strongly suggest to follow the steps in the &lt;a href="https://debezium.io/documentation/reference/2.4/operations/kubernetes.html"&gt;debizium documentation&lt;/a&gt;, It's straigh forward and the only thing I could do is rewrite it here, and its not worth it. Insted I will hightligth some key steps to use it with SQl server connector insted of Mysql connector (which is the current example in the docs)&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuring Kafka connect
&lt;/h4&gt;

&lt;p&gt;In order to connect to SQL Server you need to use the Kafka connect connector: debizium-sqlserver-connnector, you can find it here: &lt;a href="https://repo1.maven.org/maven2/io/debezium/debezium-connector-sqlserver/"&gt;https://repo1.maven.org/maven2/io/debezium/debezium-connector-sqlserver/&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Then use the next kafka-connect-configuration file to create the connector&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kafka.strimzi.io/v1beta2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;KafkaConnect&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;strimzi-cluster-operator&lt;/span&gt;
&lt;span class="c1"&gt;#  annotations:&lt;/span&gt;
&lt;span class="c1"&gt;#  # use-connector-resources configures this KafkaConnect&lt;/span&gt;
&lt;span class="c1"&gt;#  # to use KafkaConnector resources to avoid&lt;/span&gt;
&lt;span class="c1"&gt;#  # needing to call the Connect REST API directly&lt;/span&gt;
&lt;span class="c1"&gt;#    strimzi.io/use-connector-resources: "true"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.5.1&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;bootstrapServers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-cluster-kafka-bootstrap:9093&lt;/span&gt;
  &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;trustedCertificates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-cluster-cluster-ca-cert&lt;/span&gt;
        &lt;span class="na"&gt;certificate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ca.crt&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;group.id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;connect-cluster&lt;/span&gt;
    &lt;span class="na"&gt;offset.storage.topic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;connect-cluster-offsets&lt;/span&gt;
    &lt;span class="na"&gt;config.storage.topic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;connect-cluster-configs&lt;/span&gt;
    &lt;span class="na"&gt;status.storage.topic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;connect-cluster-status&lt;/span&gt;
    &lt;span class="c1"&gt;# -1 means it will use the default replication factor configured in the broker&lt;/span&gt;
    &lt;span class="na"&gt;config.storage.replication.factor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
    &lt;span class="na"&gt;offset.storage.replication.factor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
    &lt;span class="na"&gt;status.storage.replication.factor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# (2)&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;here-go-your-container-repository-registry&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;pushSecret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;your-secret&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# (3)&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;debezium-sqlserver-connector&lt;/span&gt;
        &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tgz&lt;/span&gt;
            &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://repo1.maven.org/maven2/io/debezium/debezium-connector-sqlserver/2.3.3.Final/debezium-connector-sqlserver-2.3.3.Final-plugin.tar.gz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see on (2) in the image field of the yaml file, you need to write a container repository registry pointing to a docker image that will be use to build the kafka-connect container. Example: gustavo/kafka-connect-sql-server:latest, use your own. I use docker hub for this one. &lt;/p&gt;

&lt;p&gt;And finally you need to create a kubernetes's secret, you can name it as you wish, for example: secret-kafka.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret docker-registry secret-kafka &lt;span class="nt"&gt;-n&lt;/span&gt; kafka &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--docker-email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-user-email-goes-here &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--docker-username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-user-name-goes-here &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--docker-password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-password-goes-here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;note that in this example we are pointing to the the kafka namespace (-n kafka) if you are following the debizium tutorial, you should use the same namespace. &lt;/p&gt;

&lt;h4&gt;
  
  
  Creating the Debizium SQL Server Connector
&lt;/h4&gt;

&lt;p&gt;Finally this how your kafka-connection should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnector
metadata:
  name: debezium-connector-sqlserver
  labels:
    strimzi.io/cluster: debezium-connect-cluster
spec:
  class: io.debezium.connector.sqlserver.SqlServerConnector
  tasksMax: 1
  config:
    schema.history.internal.kafka.bootstrap.servers: debezium-cluster-kafka-bootstrap:9092
    database.hostname: your-sql-server-hostname
    database.port: you-sql-server-port
    database.user: your-sql-server-user
    database.password: your-sql-server-password
    database.dbname: your-sql-server-db
    database.server.name: your-sql-server-name
    topic.prefix: chose-a-prefix
    database.names: database-name
    database.encrypt: &lt;span class="nb"&gt;true
    &lt;/span&gt;database.trustServerCertificate: &lt;span class="nb"&gt;true
    &lt;/span&gt;database.include.list: database-list-comma-separated
    table.include.list: table-list-comma-separated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look the &lt;a href="https://debezium.io/documentation/reference/2.4/connectors/sqlserver.html"&gt;sql server connector docs&lt;/a&gt; for more details.&lt;br&gt;
&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
table.include.list = dbo.table0, dbo.table1, dbo.table2&lt;br&gt;
topic.prefix = dev-prefix&lt;br&gt;
database.names = SQLENTERPRISE&lt;/p&gt;
&lt;h3&gt;
  
  
  Consumers
&lt;/h3&gt;

&lt;p&gt;Through this step you should have a running cluster using minikube. &lt;/p&gt;

&lt;p&gt;The last step is to make some consumers to capture kafka events. You can refert to &lt;a href="https://docs.confluent.io/kafka-clients/python/current/overview.html"&gt;confluent documentation&lt;/a&gt; to install the confluent kafka client, this will help us interact with the kafka cluster. &lt;/p&gt;

&lt;p&gt;Let's create a file that will help us to listen kafka events&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;decorators.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;confluent_kafka&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;KafkaError&lt;/span&gt;

&lt;span class="c1"&gt;# Define the Kafka consumer configuration
&lt;/span&gt;&lt;span class="n"&gt;consumer_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bootstrap.servers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;10.10.1.1:9092&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Replace with your Kafka broker(s) address
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;group.id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;connect-cluster-id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;auto.offset.reset&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;earliest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Start consuming from the beginning of the topic
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Create a Kafka consumer instance
&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Consumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consumer_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Subscribe to a Kafka topic
&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dev-prefix.SQLENTERPRISE.dbo.table1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dev-prefix.SQLENTERPRISE.dbo.table2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dev-prefix.SQLENTERPRISE.dbo.table3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# Replace with the name of the topic you want to consume from
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Subscribed to topic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                    &lt;span class="c1"&gt;# Handle any errors that occurred during consumption
&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;code&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;KafkaError&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_PARTITION_EOF&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="c1"&gt;# End of partition event
&lt;/span&gt;                        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Reached end of partition for topic &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; partition &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                
                        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error while consuming message: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# kafka logic
&lt;/span&gt;                    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Consumed message: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
                    &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyboardInterrupt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;
        &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Close the Kafka consumer when done
&lt;/span&gt;            &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;main.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;util.decorators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="nd"&gt;@loop&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dev-prefix.SQLENTERPRISE.dbo.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dev-prefix.SQLENTERPRISE.dbo.table0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dev-prefix.SQLENTERPRISE.dbo.table1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dev-prefix.SQLENTERPRISE.dbo.table2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;topic not found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally you could replace the &lt;code&gt;print(payload)&lt;/code&gt; to a POST call pointing to a microservice that you want to delegate mongoDB updates or you could do it rigth there. &lt;/p&gt;

&lt;p&gt;And that it all! 🎉🎉 &lt;/p&gt;

&lt;p&gt;In the future, I will explain how to deploy it on production using google cloud.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>kafka</category>
      <category>debezium</category>
    </item>
  </channel>
</rss>
