<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Alvis F on Medium]]></title>
        <description><![CDATA[Stories by Alvis F on Medium]]></description>
        <link>https://medium.com/@falvis1999?source=rss-bd0d74873629------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*ygnKz5grpN7yA_BN</url>
            <title>Stories by Alvis F on Medium</title>
            <link>https://medium.com/@falvis1999?source=rss-bd0d74873629------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 24 May 2026 02:28:11 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@falvis1999/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Dynamic Programming Patterns]]></title>
            <link>https://levelup.gitconnected.com/dynamic-programming-patterns-800384e9e881?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/800384e9e881</guid>
            <category><![CDATA[leetcode]]></category>
            <category><![CDATA[dynamic-programming]]></category>
            <category><![CDATA[coding-interviews]]></category>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Mon, 24 Feb 2025 14:13:32 GMT</pubDate>
            <atom:updated>2025-02-24T14:13:32.207Z</atom:updated>
            <content:encoded><![CDATA[<p>Below is a comprehensive guide that combines explanations of each dynamic programming (DP) pattern with a list of practice problems to help you master them. Each section explains the core idea behind the pattern, provides sample Python code snippets for both recursive (top‐down) and iterative (bottom‐up) approaches, and lists recommended practice problems.</p><p><em>Iinspired by Atalyk Akash’s discussion, here are several common DP patterns rewritten in Python.</em></p><h3>1. Minimum (Maximum) Path to Reach a Target</h3><p><strong>Explanation:</strong><br> This pattern involves finding an optimal (minimum or maximum) cost, path, or sum to reach a target state. The idea is to choose the best among all possible previous states and then add the cost (or benefit) of the current state. This approach can be applied to problems such as climbing stairs, grid paths, or coin change.</p><p><strong>Python Examples:</strong></p><p><em>Top‐Down (Recursive with Memoization):</em></p><pre>def min_path(target, ways, cost, memo=None):<br>    if memo is None:<br>        memo = {}<br>    if target == 0:<br>        return 0<br>    if target in memo:<br>        return memo[target]<br>    <br>    best = float(&#39;inf&#39;)<br>    for w in ways:<br>        if target - w &gt;= 0:<br>            best = min(best, min_path(target - w, ways, cost, memo) + cost[target])<br>    memo[target] = best<br>    return best</pre><pre># Example usage:<br>target = 5<br>cost = [0, 1, 2, 3, 4, 5]  # sample cost array<br>print(min_path(target, ways=[1, 2], cost=cost))</pre><p><em>Bottom‐Up (Iterative):</em></p><pre>def min_path_bottom_up(target, ways, cost):<br>    dp = [float(&#39;inf&#39;)] * (target + 1)<br>    dp[0] = 0  # base case<br>    <br>    for i in range(1, target + 1):<br>        for w in ways:<br>            if w &lt;= i:<br>                dp[i] = min(dp[i], dp[i - w] + cost[i])<br>    return dp[target]</pre><pre>print(min_path_bottom_up(target, ways=[1, 2], cost=cost))</pre><p><strong>Practice Problems:</strong></p><ul><li><strong>[746] Min Cost Climbing Stairs (Easy):</strong><br> Practice accumulating minimal cost while climbing steps.</li><li><strong>[64] Minimum Path Sum (Medium):</strong><br> Find the minimum sum path through a 2D grid.</li><li><strong>[322] Coin Change (Medium):</strong><br> Determine the minimum number of coins needed to form a given amount.</li><li><strong>[120] Triangle (Medium):</strong><br> Compute the minimum path sum from top to bottom in a triangle structure.</li><li><strong>[1049] Last Stone Weight II (Medium):</strong><br> Partition stones into two groups to minimize the difference between their sums.</li><li><strong>[174] Dungeon Game (Hard):</strong><br> Calculate the minimum initial health required to navigate a grid with hazards.</li><li><strong>[871] Minimum Number of Refueling Stops (Hard):</strong><br> Decide optimal refueling points along a journey to reach your destination.</li></ul><h3>2. Distinct Ways to Reach a Target</h3><p><strong>Explanation:</strong><br> This pattern is used when you need to count the number of unique ways to reach a target state. Instead of taking a minimum or maximum, you sum up the ways to reach the current state from all valid previous states. It’s common in problems like climbing stairs or grid paths.</p><p><strong>Python Examples:</strong></p><p><em>Top‐Down (Recursive with Memoization):</em></p><pre>def count_ways(target, ways, memo=None):<br>    if memo is None:<br>        memo = {}<br>    if target == 0:<br>        return 1<br>    if target in memo:<br>        return memo[target]<br>    <br>    total = 0<br>    for w in ways:<br>        if target - w &gt;= 0:<br>            total += count_ways(target - w, ways, memo)<br>    memo[target] = total<br>    return total</pre><pre># Example usage:<br>print(count_ways(5, ways=[1, 2]))</pre><p><em>Bottom‐Up (Iterative):</em></p><pre>def count_ways_bottom_up(target, ways):<br>    dp = [0] * (target + 1)<br>    dp[0] = 1  # one way to reach 0<br>    for i in range(1, target + 1):<br>        for w in ways:<br>            if w &lt;= i:<br>                dp[i] += dp[i - w]<br>    return dp[target]</pre><pre>print(count_ways_bottom_up(5, ways=[1, 2]))</pre><p><strong>Practice Problems:</strong></p><ul><li><strong>[70] Climbing Stairs (Easy):</strong><br> Count the number of distinct ways to climb stairs taking one or two steps at a time.</li><li><strong>[62] Unique Paths (Medium):</strong><br> Count the number of unique paths from the top-left to the bottom-right of a grid.</li><li><strong>[1155] Number of Dice Rolls With Target Sum (Medium):</strong><br> Calculate the number of ways to achieve a target sum with dice rolls.</li><li><strong>[494] Target Sum (Medium):</strong><br> Decide how to add or subtract numbers to reach a target sum.</li><li><strong>[377] Combination Sum IV (Medium):</strong><br> Count combinations that add up to a target using given numbers.</li><li><strong>[1269] Number of Ways to Stay in the Same Place After Some Steps (Hard):</strong><br> Solve a challenging problem involving constrained movement.</li><li><strong>[1220] Count Vowels Permutation (Hard):</strong><br> Count valid vowel permutations under specified constraints.</li></ul><h3>3. Merging Intervals</h3><p><strong>Explanation:</strong><br> This pattern involves breaking a problem into subintervals and merging the solutions from the left and right segments optimally. It’s often used when the decision at one point depends on both preceding and succeeding elements. Problems like “Burst Balloons” are classic examples where merging intervals helps optimize the solution.</p><p><strong>Python Examples:</strong></p><p><em>Top‐Down (Recursive):</em></p><pre>def merge_intervals(nums, i, j, memo):<br>    if i &gt; j:<br>        return 0<br>    if (i, j) in memo:<br>        return memo[(i, j)]<br>    <br>    best = 0<br>    # Try every possible splitting point.<br>    for k in range(i, j + 1):<br>        left = merge_intervals(nums, i, k - 1, memo)<br>        right = merge_intervals(nums, k + 1, j, memo)<br>        best = max(best, left + nums[k] + right)<br>    <br>    memo[(i, j)] = best<br>    return best</pre><pre># Example usage:<br>nums = [3, 1, 5, 8]<br>print(merge_intervals(nums, 0, len(nums) - 1, {}))</pre><p><em>Bottom‐Up (Iterative):</em></p><pre>def merge_intervals_bottom_up(nums):<br>    n = len(nums)<br>    dp = [[0] * n for _ in range(n)]<br>    <br>    # l is the interval length.<br>    for l in range(1, n):<br>        for i in range(n - l):<br>            j = i + l<br>            for k in range(i, j + 1):<br>                left = dp[i][k - 1] if k - 1 &gt;= i else 0<br>                right = dp[k + 1][j] if k + 1 &lt;= j else 0<br>                dp[i][j] = max(dp[i][j], left + nums[k] + right)<br>    return dp[0][n - 1]</pre><pre>print(merge_intervals_bottom_up(nums))</pre><p><strong>Practice Problems:</strong></p><ul><li><strong>[1130] Minimum Cost Tree From Leaf Values (Medium):</strong><br> Merge numbers in an array to minimize the total cost.</li><li><strong>[1039] Minimum Score Triangulation of Polygon (Medium):</strong><br> Determine the optimal way to triangulate a polygon for minimum cost.</li><li><strong>[546] Remove Boxes (Medium):</strong><br> Remove boxes in an optimal order to maximize points.</li><li><strong>[1000] Minimum Cost to Merge Stones (Medium):</strong><br> Find the best strategy to merge stone piles with minimal cost.</li><li><strong>[312] Burst Balloons (Hard):</strong><br> Burst balloons in an order that maximizes coins earned.</li><li><strong>[375] Guess Number Higher or Lower II (Medium):</strong><br> Optimize guessing strategy to minimize the worst-case cost.</li></ul><h3>4. DP on Strings</h3><p><strong>Explanation:</strong><br> Many DP problems involve strings — either one string or two — where you need to compute results such as the longest common subsequence, edit distance, or palindromic substrings. Typically, you set up a 2D DP table where indices correspond to positions in the string(s) and update the table based on character matches or decisions.</p><p><strong>Python Examples:</strong></p><p><em>Longest Common Subsequence (LCS):</em></p><pre>def longestCommonSubsequence(text1, text2):<br>    n, m = len(text1), len(text2)<br>    dp = [[0] * (m + 1) for _ in range(n + 1)]<br>    <br>    for i in range(1, n + 1):<br>        for j in range(1, m + 1):<br>            if text1[i - 1] == text2[j - 1]:<br>                dp[i][j] = dp[i - 1][j - 1] + 1<br>            else:<br>                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])<br>    return dp[n][m]</pre><pre>print(longestCommonSubsequence(&quot;abcde&quot;, &quot;ace&quot;))</pre><p><em>Longest Palindromic Subsequence:</em></p><pre>def longestPalindromeSubseq(s):<br>    n = len(s)<br>    dp = [[0] * n for _ in range(n)]<br>    <br>    for i in range(n):<br>        dp[i][i] = 1<br>        <br>    for cl in range(2, n + 1):<br>        for i in range(n - cl + 1):<br>            j = i + cl - 1<br>            if s[i] == s[j]:<br>                dp[i][j] = 2 if cl == 2 else dp[i + 1][j - 1] + 2<br>            else:<br>                dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])<br>    return dp[0][n - 1]</pre><pre>print(longestPalindromeSubseq(&quot;bbbab&quot;))</pre><p><strong>Practice Problems:</strong></p><ul><li><strong>[1143] Longest Common Subsequence (Medium):</strong><br> Find the longest subsequence common to two strings.</li><li><strong>[647] Palindromic Substrings (Medium):</strong><br> Count all palindromic substrings within a string.</li><li><strong>[516] Longest Palindromic Subsequence (Medium):</strong><br> Determine the longest palindromic subsequence in a string.</li><li><strong>[72] Edit Distance (Hard):</strong><br> Compute the minimum number of operations to convert one string into another.</li><li><strong>[115] Distinct Subsequences (Hard):</strong><br> Count how many times a subsequence appears in a string.</li><li><strong>[712] Minimum ASCII Delete Sum for Two Strings (Medium):</strong><br> Remove characters to make two strings equal with minimum ASCII cost.</li><li><strong>[5] Longest Palindromic Substring (Medium):</strong><br> Identify the longest contiguous palindromic substring in a string.</li></ul><h3>5. Decision Making</h3><p><strong>Explanation:</strong><br> This pattern centers on making choices at each step — whether to include or exclude the current element — to optimize the overall result. The decision often involves comparing outcomes between taking the current element (with its associated benefit) or skipping it (preserving the previous optimal state). This is common in problems like house robbing or stock trading.</p><p><strong>Python Examples:</strong></p><p><em>House Robber:</em></p><pre>def rob(nums):<br>    if not nums:<br>        return 0<br>    n = len(nums)<br>    if n == 1:<br>        return nums[0]<br>        <br>    dp = [0] * (n + 1)<br>    dp[0] = 0<br>    dp[1] = nums[0]<br>    <br>    for i in range(2, n + 1):<br>        dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1])<br>    return dp[n]</pre><pre>print(rob([2, 7, 9, 3, 1]))</pre><p><em>Stock Trading with Transaction Fee:</em></p><pre>def maxProfit(prices, fee):<br>    cash, hold = 0, -prices[0]<br>    for price in prices[1:]:<br>        cash = max(cash, hold + price - fee)  # Sell the stock if profitable<br>        hold = max(hold, cash - price)          # Buy new stock if it improves the state<br>    return cash</pre><pre>print(maxProfit([1, 3, 2, 8, 4, 9], fee=2))</pre><p><strong>Practice Problems:</strong></p><ul><li><strong>[198] House Robber (Easy):</strong><br> Choose which houses to rob to maximize profit without alerting the police.</li><li><strong>[121] Best Time to Buy and Sell Stock (Easy):</strong><br> Find the optimal day to buy and sell stocks to maximize profit.</li><li><strong>[714] Best Time to Buy and Sell Stock with Transaction Fee (Medium):</strong><br> Incorporate transaction fees into your trading strategy.</li><li><strong>[309] Best Time to Buy and Sell Stock with Cooldown (Medium):</strong><br> Factor in a cooldown period between transactions for optimal trading.</li><li><strong>[123] Best Time to Buy and Sell Stock III (Hard):</strong><br> Optimize up to two transactions to maximize profit.</li><li><strong>[188] Best Time to Buy and Sell Stock IV (Hard):</strong><br> Tackle multiple transactions under constrained conditions.</li></ul><p><strong>Final Thoughts:</strong><br> Each section above outlines the core idea behind a common DP pattern, provides sample Python code to illustrate how to approach these problems, and lists targeted practice problems to help you deepen your understanding. Working through these examples and challenges will build a strong foundation in dynamic programming and prepare you for a variety of interview and competitive programming scenarios.</p><p>Happy coding and good luck mastering DP!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=800384e9e881" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/dynamic-programming-patterns-800384e9e881">Dynamic Programming Patterns</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Complete Maven, Jenkins, SonarQube, Jfrog & Tomcat set-up]]></title>
            <link>https://levelup.gitconnected.com/complete-maven-jenkins-sonarqube-jfrog-tomcat-set-up-4c32f6bab04f?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/4c32f6bab04f</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[jenkins]]></category>
            <category><![CDATA[sonarqube]]></category>
            <category><![CDATA[ci-cd-pipeline]]></category>
            <category><![CDATA[cloud]]></category>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Sun, 23 Jul 2023 23:14:59 GMT</pubDate>
            <atom:updated>2023-07-23T23:14:59.132Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*55qR85fGHXp8bxLh_YA4wg.png" /></figure><h3>Installing Jenkins</h3><ol><li>Open a web browser and navigate to the Jenkins download page: <a href="https://jenkins.io/download/">https://jenkins.io/download/</a></li><li>Scroll down to the “Long-term support release” section and click on the latest version of Jenkins.</li><li>On the next page, select the appropriate installer for your operating system.</li><li>Once the download is complete, run the installer and follow the on-screen instructions.</li><li>During the installation process, you will be prompted to choose a username and password for the Jenkins administrator account.</li><li>After the installation, open a web browser and navigate to <a href="http://localhost:8080/">http://localhost:8080/</a> (or the custom port you may have chosen during installation).</li><li>You will be prompted to enter the administrator username and password you created during installation.</li><li>Once you have successfully logged in, you can begin configuring Jenkins for your project needs.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MqWt5lF8YWDdChIkGz-P-g.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vzR0N8iUo2FG8mtAGgXl8A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zk5r4b0ufzGL7Fi7w-xKGQ.png" /></figure><h3>Install BlueOcean</h3><p>To install Blue Ocean in Jenkins, you will need to follow these steps:</p><ol><li>Open a web browser and navigate to your Jenkins instance.</li><li>Click on the “Manage Jenkins” link in the left-hand menu.</li><li>Click on the “Manage Plugins” link.</li><li>Click on the “Available” tab.</li><li>Search for “Blue Ocean” in the search bar.</li><li>Check the box next to “Blue Ocean” and any other desired plugins.</li><li>Click on the “Download now and install after restart” button.</li><li>Restart Jenkins to complete the installation of Blue Ocean.</li></ol><p>Once the installation is complete, you should see a new “Blue Ocean” link in the left-hand menu of your Jenkins instance.</p><h4>Creating Jenkins job</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*--dICWBziU7F896_hswcCA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nUqbn7KgwYdecHNW4ujfXA.png" /></figure><h3>Installing SonarQube</h3><ol><li>Open a web browser and navigate to the SonarQube download page: <a href="https://www.sonarqube.org/downloads/">https://www.sonarqube.org/downloads/</a></li><li>Scroll down to the “LTS” section and click on the latest version of SonarQube.</li><li>On the next page, select the appropriate installer for your operating system.</li><li>Once the download is complete, run the installer and follow the on-screen instructions.</li><li>During the installation process, you will be prompted to choose a username and password for the SonarQube administrator account.</li><li>After the installation, open a web browser and navigate to <a href="http://localhost:9000/">http://localhost:9000/</a> (or the custom port you may have chosen during installation).</li><li>You will be prompted to enter the administrator username and password you created during installation.</li><li>Once you have successfully logged in, you can begin configuring SonarQube for your project needs.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0amDsO_lpG9ITk9nIFpcKA.png" /></figure><h3>Configure SonarQube in Jenkins</h3><p>To install the SonarQube Scanner plugin in Jenkins, you can follow these steps:</p><ol><li>Open your Jenkins dashboard in a web browser and navigate to “Manage Jenkins” on the left-hand side.</li><li>Click on “Manage Plugins” to open the plugin manager.</li><li>In the “Available” tab, search for “SonarQube Scanner” using the search box.</li><li>Check the checkbox next to “SonarQube Scanner” in the list of available plugins.</li><li>Click on the “Install without restart” button to start the installation process.</li><li>On the next page, make sure to select the option “Download now and install after restart” if you prefer to install any additional required plugins.</li><li>Once the installation is complete, you will see a confirmation message.</li><li>Restart Jenkins by navigating to “Manage Jenkins” and clicking on the “Restart Jenkins” link if the installation requires a restart.</li></ol><p>Now you can use the SonarQube Scanner plugin in your Jenkins pipeline or projects to analyze code quality with SonarQube.</p><h3>Create a token for Jenkins in sonarqube</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eep3ZMToky8bxQvkpYM0eA.png" /></figure><ol><li>Go to ‘My Account’ and under ‘Security’ give a name and type as “Global Analysis Token” set your expiry days and hit Generate.</li><li>Copy the token and use it in Jenkins.</li></ol><p><strong>To configure the Environment of SonarQube with Jenkins, you will need to follow these steps:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kLNppKtsLsZe1n93y_uKkA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9I6LycL0l7s45kFo41xkjQ.png" /></figure><ol><li>Get the token from the sonarqube and add it to the system credentials shown above.</li><li>Configure the SonarQube server in Jenkins by providing the server URL and authentication token.</li><li>Give sonarserver as the name and click on add under Server authentication token and add the token.</li><li>In your Jenkins pipeline script, add the withSonarQubeEnv step to specify the SonarQube server environment variable.</li><li>Add the sonar:sonar command to your mvn command in the Jenkins pipeline script to run the SonarQube analysis.</li><li>Run the Jenkins pipeline script to build your project and run the SonarQube analysis.</li></ol><h3>Create a Jenkinsfile in the working repository</h3><p>Add the following code to the Jenkinsfile</p><pre>pipeline {<br>    agent any<br>    environment{<br>        SONARSERVER = &#39;sonarserver&#39;<br>    }<br>    stages {<br>        stage(&#39;SonarQube analysis&#39;) {<br>            steps {<br>                withSonarQubeEnv(&quot;${SONARSERVER}&quot;) {<br>                    sh &#39;mvn clean package sonar:sonar&#39;<br>                    }<br>            }<br>        }<br>        stage(&#39;Build&#39;) {<br>            steps {<br>                sh &#39;mvn -B -DskipTests clean package&#39;<br>            }<br>        }<br>        stage(&#39;Test&#39;) {<br>            steps {<br>                sh &#39;mvn test&#39;<br>            }<br>            post {<br>                always {<br>                    junit &#39;target/surefire-reports/*.xml&#39;<br>                }<br>            }<br>        }<br>        stage(&#39;Transfer to Artifactory&#39;) {<br>            steps {<br>                script {<br>                    sh &#39;mv ~/.jenkins/workspace/fp-java-maven/target/my-app-1.0-SNAPSHOT.jar ~/.jenkins/workspace/fp-java-maven/target/root.war&#39;<br>                    sh &#39;jfrog rt u ~/.jenkins/workspace/fp-java-maven/target/root.war fp-java-maven/root.war&#39;<br>                }<br>            }<br>        }<br>        stage(&#39;Deploy to tomcat server&#39;) {<br>            steps {<br>                script {<br>                    sh &#39;mv ~/.jenkins/workspace/fp-java-maven/target/root.war /usr/local/Cellar/tomcat/10.1.9/libexec/webapps/root.war&#39;<br>                }<br>            }<br>        }<br>    }<br>}</pre><p>This is a Jenkins pipeline script written in Groovy. It has three stages:</p><ol><li>Build: This stage compiles the code and packages it into an executable JAR file.</li><li>Test: This stage runs the unit tests and generates a report using JUnit.</li><li>build &amp;&amp; SonarQube analysis: This stage builds the code and runs a SonarQube analysis to evaluate code quality and security issues.</li></ol><p>PS: It also requires a SonarQube server to be running, which is specified as an environment variable.</p><ul><li>The pipeline block defines the overall structure of the pipeline, with the agent specifying the agent that will execute the pipeline, the environment defining environment variables, and stages defining the individual stages of the pipeline.</li><li>The first stage is SonarQube analysis, which runs a SonarQube analysis on the project. The withSonarQubeEnv step sets up the environment for running the analysis, including specifying the SonarQube server to use. The sh step then runs the mvn clean package sonar:sonar command to build the project and run the analysis.</li><li>The second stage is Build, which simply builds the project without running any analysis. The sh step runs the mvn -B -DskipTests clean package command to build the project.</li><li>The third stage is Test, which runs the project&#39;s tests. The sh step runs the mvn test command to execute the tests. The post block specifies a junit step to publish the test results in JUnit format.</li><li>The fourth stage is Transfer to Artifactory, which transfers the built artifact to an Artifactory repository. The sh step moves the built JAR file to a WAR file, and then the jfrog rt u command uploads the WAR file to the Artifactory repository.</li><li>The fifth stage is Deploy to tomcat server, which deploys the built WAR file to a Tomcat server. The sh step moves the WAR file to the Tomcat webapps directory.</li></ul><p>Make sure to replace the sonarserver with the name of your SonarQube server.</p><h3>Creating a JFrog Account</h3><ol><li>Open a web browser and navigate to the JFrog sign-up page: <a href="https://jfrog.com/signup/">https://jfrog.com/signup/</a></li><li>Fill out the form with your personal information, including your name, email address, and password.</li><li>Choose a subscription plan that best fits your needs.</li><li>Review and accept the terms and conditions of the JFrog platform.</li><li>Click the “Create Account” button to complete the sign-up process.</li><li>After creating your account, you can log in to the JFrog platform and begin using its features for your project needs.</li></ol><p><strong>Create a token for Jenkins</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JXhmDSRm-BqtsOWAEGObHQ.png" /></figure><p>Switch to Classic UI</p><ol><li>Log in to your JFrog instance and navigate to the JFrog platform’s administration section.</li><li>In the administration section, locate and click on the “Security” or “Users” tab.</li><li>Find the user account associated with Jenkins or the user account you want to generate the token for.</li><li>Click on the user account to open its details or edit the user account.</li><li>Look for an option like “Access Tokens,” “API Keys,” or “Authentication Tokens” (the exact wording may vary depending on the JFrog version you are using).</li><li>Click on the option to create a new token.</li><li>Provide a name or description for the token, such as “Jenkins Token” or any other meaningful name.</li><li>Select the appropriate permissions or scopes for the token, depending on the actions you want Jenkins to perform in JFrog. Ensure the token has the necessary permissions for uploading artifacts, downloading dependencies, or any other actions required by your Jenkins pipeline.</li><li>Save or generate the token. Note that some systems may display the token only once, so make sure to copy and securely store it.</li></ol><h3>Configure Jfrog with Jenkins</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t71fi9EdCVRF4Kvq-QaJFQ.png" /></figure><ol><li>In your Jenkins environment, navigate to the Jenkins dashboard and locate the project or pipeline configuration that requires access to JFrog.</li><li>Within the Jenkins configuration, find the appropriate location to add the JFrog token. This can be in the Jenkins global configuration or specific job/pipeline configurations, depending on your setup.</li><li>Add the JFrog token as a credential or environment variable in Jenkins. This will enable Jenkins to authenticate with JFrog using the token when performing relevant actions.</li></ol><h3>Installing Tomcat</h3><ol><li>Open a web browser and navigate to the Apache Tomcat download page: <a href="https://tomcat.apache.org/download-80.cgi">https://tomcat.apache.org/download-80.cgi</a></li><li>Scroll down to the “Binary Distributions” section and click on the latest version of Tomcat.</li><li>On the next page, select the appropriate installer for your operating system.</li><li>Once the download is complete, run the installer and follow the on-screen instructions.</li><li>During the installation process, you will be prompted to choose a username and password for the Tomcat administrator account.</li><li>After the installation, open a web browser and navigate to <a href="http://localhost:8000/root">http://localhost:8000/root</a> (or the custom port you may have chosen during installation).</li><li>You will be prompted to enter the administrator username and password you created during installation.</li><li>Once you have successfully logged in, you can begin deploying your application to Tomcat.</li></ol><h3>Run the script from BlueOcean</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UuIZ8BmD4nJHS7zvFGpu2Q.png" /></figure><p>Open the project in BlueOcean and hit Run</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uweaYeDRj4uZvqVrUJMUiw.png" /></figure><p>You will now see the scripts running</p><p><strong>To view the SonarQube report:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sA8T-kLm2d5X5YPRcckQoA.png" /></figure><ol><li>Log in to your SonarQube server.</li><li>Click on the project you want to view the report for.</li><li>In the left-hand menu, click on “Measures”.</li><li>You will see a list of measures for your project, including code coverage, code complexity, and code duplication.</li><li>Click on any of the measures to view a more detailed report.</li><li>You can also view the code quality “gates” for your project by clicking on “Quality Gates” in the left-hand menu.</li><li>If your project fails any of the quality gates, you will need to address the issues before the code can be considered “production-ready”.</li></ol><p><strong>View the Status of the Jenkins build</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9xOUc8DDhbYUrjFhv75F7w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZnKMPxyg97PWuPtyDsripA.png" /></figure><h3>Uploaded build file in Jfrog</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Oxdex5GCo5SXbeD8sMTHzw.png" /></figure><h3>Result</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CqqJqDFdUzClbOTUgGt-hA.png" /></figure><p><a href="https://www.linkedin.com/in/alvisf/">www.linkedin.com/in/alvisf/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4c32f6bab04f" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/complete-maven-jenkins-sonarqube-jfrog-tomcat-set-up-4c32f6bab04f">Complete Maven, Jenkins, SonarQube, Jfrog &amp; Tomcat set-up</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[IBM Cloud Technical Advocate V3 Exam Cheat Sheet]]></title>
            <link>https://medium.com/@falvis1999/ibm-cloud-technical-advocate-v3-exam-cheat-sheet-b9c7fbf9324c?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/b9c7fbf9324c</guid>
            <category><![CDATA[ibm-cloud]]></category>
            <category><![CDATA[certification]]></category>
            <category><![CDATA[ibm]]></category>
            <category><![CDATA[cheet-sheets]]></category>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Wed, 07 Sep 2022 03:59:46 GMT</pubDate>
            <atom:updated>2022-09-07T03:59:46.399Z</atom:updated>
            <content:encoded><![CDATA[<p>Hi I have recelty got my Cloud V3 Badge for IBM Cloud and I have created a cheet sheet for anyone who is going to take up the exam. ALL THE BEST!!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zYzon5NX39e3OFG70llvpA.png" /></figure><p><strong>START-Define Cloud Computing, its Essential Characteristics, History, and Emerging Trends</strong></p><p>In <em>Define Cloud Computing, its Essential Characteristics, History, and Emerging Trends</em>, you should have learned that:</p><ul><li>In 2006, Amazon launched what would become AWS, with IBM, Microsoft, and Google launching services in the following years.</li><li>Cloud computing is a technology that has evolved over time.</li><li>Cloud computing enables convenient access to a shared network of computer resources.</li><li>On-demand self service is a simple interface with no human interaction.</li><li>Multiple virtual machines can run on a single computer, improving resource utilization and company returns.</li><li>Cloud computing changes quickly and trends should be monitored</li></ul><p><strong>Business Case Studies for Cloud Computing</strong></p><p>In <em>American Airlines Case Study-Transformation</em>, you should have learned that:</p><ul><li>Some companies motivated to adopt the cloud are looking to transform their operations to better serve customers.</li><li>The pay-as-you-go model helps companies save money.</li><li>Switching to the cloud results in faster development and release of new applications.</li><li>Migrating to the cloud can help businesses respond faster to customer needs.</li></ul><p>In <em>Port of Rotterdam Case Study-Modernization</em>, you should have learned that:</p><ul><li>Companies who switch to the cloud experience improved efficiency, decreased development time, and decreased expenses.</li><li>Companies who transform using cloud technologies find they are leading change and innovation in their industry.</li><li>Operation efficiency improves by changing to a cloud environment.</li><li>Companies have easier access to data and an ability to more efficiently process large amounts of data in the cloud.</li></ul><p><strong>Service and Deployment Models of Cloud Computing</strong></p><p>In <em>The Cloud Service Models</em>, you should have learned that:</p><ul><li>Cloud service providers own, manage, and maintain IT assets.</li><li>Organizations save money by accessing and scaling IT resources through a cloud service provider.</li><li>IaaS, PaaS, and SaaS are the most common types of cloud services offered.</li><li>More than one cloud service model can be used at the same time.</li></ul><p>In <em>The Cloud Deployment Models</em>, you should have learned that:</p><ul><li>Ongoing operating expenses are more predictable when using a public cloud model.</li><li>Using a combination of cloud environments at the same time can be more cost effective and efficient for businesses.</li><li>Individual security needs can be tailored by using a virtual private cloud.</li><li>A private cloud provides exclusive access to the infrastructure with greater control over resources.</li></ul><p><strong>Cloud Architecture Components and Relevance</strong></p><p>In <em>IBM Cloud Platform</em>, you should have learned that:</p><ul><li>Many components within the cloud platform work together to provide a consistent, dependable cloud experience for users.</li><li>With the cloud platform, it is possible to provide higher levels of compliance, security, and management.</li><li>The three core services the cloud provides are containers, storage, and servers.</li><li>Data centers around the world deploy cloud platform services.</li></ul><p>In <em>IBM Cloud Infrastructure Architecture</em>, you should have learned that:</p><ul><li>Cloud architecture models provide a secure foundation for various workloads.</li><li>Cloud infrastructure provides a secure environment for applications.</li><li>Data is isolated in a cloud infrastructure.</li><li>The cloud infrastructure architecure uses open source technologies.</li></ul><p>In <em>Virtual Private Cloud Architecture</em>, you should have learned that:</p><ul><li>Private cloud architecture provides greater control and security along with the benefits of a public cloud.</li><li>Customers can connect securely to on premises or remote infrastructure.</li><li>A network can be extended by creating a dedicated connection between the cloud and on premises resources.</li><li>Responsive cloud applications are possible with a virtual private cloud architecture.</li></ul><p><strong>Cloud Compliance and Governance Practices</strong></p><p>In <em>IBM Compliance Programs</em>, you should have learned:</p><ul><li>IBM Cloud provides programs and certifications that help organizations meet global guidelines.</li><li>The CIS IBM Cloud Foundations Benchmark helps organizations securely adopt IBM Cloud services.</li><li>The cloud features multiple, overlapping tiers of protection to stop cybersecurity threats.</li><li>IBM Cloud for Government data centers adhere to global, industry, and regional compliance programs.</li></ul><p>In <em>IBM Cloud Hosting Options</em>, you should have learned:</p><ul><li>Government agencies can trust that the IBM Cloud environment housing their applications provides flexibility and enhanced security features.</li><li>IBM data centers are available across multiple regions and countries around the world.</li><li>The same set of regulatory services are available in each IBM Cloud availability zone within six regions around the world.</li><li>Those managing multiple clouds have full visibility and control across the cloud and data center infrastructure.</li></ul><p><strong>Cloud Catalog Services</strong></p><p>In <em>IBM Cloud Catalog and IBM Cloud Docs Overview</em>, you learned that:</p><ul><li>The IBM Cloud Catalog is where services created by IBM and third parties are located.</li><li>You can filter services based on a variety of parameters including provider, pricing plan, and category.</li><li>Services can be added to your IBM Cloud account using their “Create” tab in the catalog.</li><li>The API Docs and general documentation can be accessed using the appropriate links in the IBM Cloud Catalog.</li><li>The left-hand menu in documentation is used to navigate through major topics.</li><li>The right-hand menu in documentation is used to navigate the topics and sub-topics included in the currently open documentation.</li><li>Breadcrumbs at the top of the screen allow you to quickly go back to a previous topic.</li></ul><p><strong>Locating Services to Deliver Specific Functions</strong></p><p>In <em>IBM Cloud Catalog Services</em>, you learned that:</p><ul><li>You can find additional information about each service in the IBM Cloud Catalog using the “About” tab.</li><li>Code Engine can be used to build container images.</li><li>IBM Cloud Object Storage is a way to store data in units called buckets for easy access.</li><li>Db2 is a relational database with enterprise-grade performance.</li><li>Cloudant is a NoSQL database that uses JSON files to store and index documents.</li><li>Watson Assistant can be used to add chat functionality to an application.</li><li>Watson Discovery is used to gain a deeper understanding of data and implement natural language document search capabilities.</li><li>Watson Studio allows you to customize machine learning models.</li><li>Certificate Manager provides a centralized location to store and manage your security certificates.</li><li>Hyper Protect Crypto Service provides hardware solutions to manage your crypto keys.</li></ul><p><strong>Delivering Cloud Services to DevSecOps Teams</strong></p><p>In <em>DevOps vs DevSecOps</em>, you learned that:</p><ul><li>DevOps was designed to create an integrated working environment between developers and IT operations.</li><li>DevSecOps added security into the development cycle.</li><li>DevOps was intended to decrease development time by adding automation to the process.</li><li>Instead of releasing a couple updates per year, DevOps is designed to continually release smaller updates as needed.</li></ul><p>In <em>Continuous Delivery</em>, you learned that:</p><ul><li>Toolchains are sets of tools that are used to automate the process of developing and deploying code.</li><li>Pipelines are used to build, test, and deploy code with minimal human intervention.</li><li>An integrated web-based environment allows developers to work from anywhere.</li></ul><p><strong>Core Groups of Available Database Integration and Analytical Services</strong></p><p>In <em>Databases on IBM Cloud</em>, you learned that:</p><ul><li>IBM Cloud Databases for PostgreSQL are customizable, open-source object-relational databases.</li><li>IBM Cloud Databases for EnterpriseDB optimize the built-in features of PostgreSQL while adding compatibility with Oracle.</li><li>IBM Db2 on Cloud is based on the enterprise-class IBM Db2 database engine and provides a fully managed solution.</li><li>IBM Cloudant is a document database that uses JSON.</li><li>IBM Cloud Databases for MongoDB is a JSON-based document store which includes rich query functionality.</li><li>IBM Cloud Databases for DataStax is a NoSQL database built on Apache Cassandra which is best for high-availability and workload flexibility.</li><li>IBM Cloud Databases for Elastisearch are based on JSON document databases and allow full-text search.</li><li>IBM Cloud Databases for Redis are designed for in-memory functionality making them very fast.</li><li>IBM Cloud HyperProtect can be used with PostgreSQL and MongoDB for fully managed, highly secure applications.</li></ul><p>In <em>Analytics of IBM Cloud</em>, you learned that:</p><ul><li>There are three types of analytics: descriptive, diagnostic, and prescriptive.</li><li>IBM Cloud Analytics use two open-source technologies: Apache Hadoop and Apache Spark.</li><li>IBM Analytics Engine builds on Apache Hadoop and Apache Spark but separates compute and storage functionality.</li><li>IBM Information Server on Cloud can analyze a wide variety of data and is easily scalable.</li><li>IBM Streaming Analytics allows you to analyze fast moving, real-time data.</li></ul><p>In <em>Integration on IBM Cloud</em>, you learned that:</p><ul><li>API Connect is used to create and manage APIs to your applications.</li><li>App Connect is used to connect various applications to each other.</li><li>Event Streams are built on Apache Kafka and are used as high throughput message buses.</li><li>MQ provides enterprise-grade messaging capabilities between applications.</li></ul><p><strong>IBM Cloud Documentation</strong></p><p>In <em>IBM Cloud Documentation</em>, you should have learned:</p><ul><li>Where to find product-specific guides and tutorials from across all of IBM docs, including site tours, learning more about the console, developer tools, resources for deploying, and API &amp; SDK references.</li><li>IBM’s reference architectures are a source to help architect solutions that enable ways to meet business objectives using leading edge hybrid cloud and AI technologies.</li><li>The IBM developer site contains a collection of learning paths for step-by-step technical training, tutorials, articles, videos, and more.</li><li>Code patterns are a collection of common use cases with ready to use code.</li></ul><p><strong>Building IBM Cloud Solutions that Adhere to IBM Security Compliance Guidelines</strong></p><p>In <em>IBM Cloud Security Strategy Overview</em>, you learned that:</p><ul><li>There are three types of encryption: data at rest, data in motion, and data in use.</li><li>IBM Cloud Identity and Access Management (IAM) is used to identify users and grant them access to specific parts of an application or network.</li><li>There are two common types of IAM used in IBM Cloud: Attribute-Based Access Control (ABAC) and Role-Based Access Control (RBAC).</li><li>There are three network encryption options: Secure Socket Layer (SSL), Transport Layer Security (TLS), and Hypertext Transfer Protocol Secure (HTTPS).</li><li>IBM Certificate Manager is used to manage SSL and TLS certificates.</li><li>Data in IBM Object Storage is divided up and distributed across multiple data centers.</li><li>Once data in IBM Object Storage is deleted, it is impossible to retrieve it.</li></ul><p><strong>Compute Options</strong></p><p>In <em>IBM Cloud Bare Metal Offerings</em>, you should have learned:</p><ul><li>Bare Metal servers are servers that are physical and dedicated to a single tenant.</li><li>Some of the benefits of Bare Metal servers are that they are isolated physically, powerful, consistent, and can scale seamlessly.</li><li>The two Bare Metal server options are fast provisioning servers and custom-based servers.</li></ul><p>In <em>IBM Cloud Virtual Server for Classic</em>, you should have learned:</p><ul><li>Classic Virtual Servers are easily deployed and can be created on shared or dedicated infrastructure.</li><li>Classic Virtual Servers are customizable, can be provisioned quickly, are scalable, and integrated seamlessly.</li><li>Some of the deployment options are public virtual servers, transient virtual servers, and dedicated virtual servers.</li><li>Some of the key differences between bare metal servers and virtual servers are that bare metal servers can offer better performance and security for certain workloads and are more ideal for heavy workloads. However, virtual servers provision more quickly and offer a more flexible and scalable environment than bare metal.</li></ul><p>In<em> IBM Cloud Virtual Private Cloud</em>, you should have learned:</p><ul><li>Virtual Private Cloud (VPC) allows the creation of a private cloud computing environment on a shared public cloud infrastructure. VPC saves on cost and focuses on convenience for clients.</li><li>VPC offers virtual server instances (VSIs) with a wide range of vCPU and memory options.</li><li>Under VPC, block storage can be provisioned and attached to virtual server instances. Block storage either has defined IOPS tiers or you can provision storage with custom IOPS.</li></ul><p>In <em>IBM Cloud for VMware Solutions Offerings</em>, you should have learned:</p><ul><li>Some benefits of VMware Solutions are being able to have the full use of VMware vCenter Server (VCS), multiple storage options, private and dedicated environment, and the use of VMware vCenter Server with Hybridity Bundle.</li><li>The key features of VMware Solutions Shared, VMware Solutions Dedicated, VMware Solutions Regulated Workloads, and VMware Solutions Dedicated Security and Compliance Readiness Bundle.</li></ul><p>In <em>IBM Cloud Power Systems Virtual Server</em>, you should have learned:</p><ul><li>Power Systems Virtual Servers can be quickly created and deployed through the IBM Cloud console but are colocated with IBM Cloud resources.</li><li>Power Systems Virtual Servers can run AIX, IBM i, or Linux operating systems.</li><li>Some key features are monthly billing rates, customized infrastructure, and images from AIX and IBM i.</li><li>Backup strategies for AIX are Veeam AIX and IBM Spectrum Project and IBM i uses IBM Backup, Recovery, and Media Services.</li></ul><p>In <em>IBM Cloud Code Engine</em>, you should have learned:</p><ul><li>Code engine is a serverless platform and offers several benefits including:</li><li>Building apps with your code using IBM’s infrastructure</li><li>Being able to run HTTP-driven apps and run-to-completion batch jobs,</li><li>Having private workloads</li><li>Allowing clients to determine who gets access to the resources</li></ul><p><strong>Compute Option Use Cases</strong></p><p>In <em>Bare Metal Use Case</em>, you should have learned:</p><ul><li>Bare Metal servers are typically used where performance is a key concern — such as where data needs to be retrieved quickly from local storage or where a specific hardware type is required for high bandwidth, encrypted data processing.</li><li>Bare Metal servers are also great when a dedicated environment is needed due to security, policy, or compliance requirements.</li></ul><p>In <em>Virtual Server Use Cases on IBM Cloud</em>, you should have learned:</p><ul><li>There are three virtual compute options, Virtual Server for VPC, Virtual Servers for Classic Infrastructure, and Power Systems Virtual Servers.</li><li>Some use cases for Virtual Server for VPC are hosting and building apps and advancing workload capacities.</li><li>Use cases for Virtual Server for Classic include high-level needed for computing and apps that have multiple levels.</li><li>Use cases for Power Systems Virtual Servers include developing and experimenting IBM power apps and workloads, along with disaster recovery.</li></ul><p>In<em> VMware Use Cases on IBM Cloud</em>, you should have learned:</p><ul><li>VMware in IBM Cloud enables:</li><li>Datacenter transformation and the ability to easily increase capacity or migrate to newer hardware more cost-effectively.</li><li>The simple creation of a disaster recovery environment in the cloud.</li><li>A secure environment through data encryption.</li><li>The option of running RedHat OpenShift on VMware to provide cloud-native services.</li></ul><p>In <em>Skytap Service on IBM Cloud Offerings</em>, you should have learned:</p><ul><li>Skytap is a cloud service that can easily migrate AIX, IBM i, and Linux and can be quickly provisioned. It is highly available and can create a self-managed application environment.</li></ul><p>In<em> Virtual Desktop Applications for IBM Cloud Offering</em>, you should have learned:</p><ul><li>Some virtual desktop applications include Citrix and Dizzion. Citrix allows for easy management of the virtual desktop infrastructure on the IBM Cloud.</li><li>Dizzion allows organizations to build remote work environments. There are two service levels for Dizzion: Dizzion DaaS and Dizzion Managed DaaS.</li><li>Dizzion DaaS is provided by IBM and Dizzion and controls Horizon 7 to handle virtual desktops. Dizzion Managed DaaS is similar to Dizzion DaaS but has additional features such as Desktop Patching, Pool Management, GPO assistance, etc.</li></ul><p><strong>IBM Cloud Satellite</strong></p><p>In <em>IBM Cloud Satellite</em>, you have learned:</p><ul><li>IBM Cloud Satellite enables organizations to run IBM Cloud Services in the location of their choice: on-premises, a competitor’s cloud, or at the edge.</li><li>IBM Cloud Satellite enables users to run select IBM Cloud Services on-premises, behind their corporate firewall, allowing them to meet more demanding security rules or simply process data closer to its source</li><li>There are four main Satellite components: hosts, link, location, and endpoints.</li><li>A host is a customer-provided computer running Red Hat Enterprise Linux 7.x. A minimum of three hosts are required for a Satellite location.</li><li>A Satellite location is a customer data center, competitors’ cloud, or edge location, at which the Satellite Hosts are deployed and run.</li><li>A Satellite Link is an encrypted TLS tunnel that allows you to securely connect the Satellite installation to other services running in IBM Cloud and to manage and monitor the Satellite instance from the IBM Cloud Console.</li><li>Satellite Link has two types of Endpoint: a Cloud Endpoint and a Location Endpoint. The Cloud Endpoint destination is outside of the Satellite location, while the Location Endpoint provides access to a server, service, or app that runs in your Satellite location from a client that is connected to the IBM Cloud private network.</li></ul><p><strong>IBM Cloud Storage Offerings and Use Cases</strong></p><p>In <em>Introduction to Storage Options</em>, you should have learned that:</p><ul><li>The three most common types of storage in IBM Cloud are block, file, and object.</li></ul><p>In <em>Block Storage</em>, you should have learned that:</p><ul><li>Block storage stores data by breaking it into evenly sized blocks, which is written to disk. The data stored is highly available because each block is stored multiple times across different disks.</li><li>Block storage is used for computing situations where users require fast, efficient, and reliable data storage.</li><li>Block storage decouples data from user environments. This allows that data to be spread across multiple environments enabling the user to retrieve it quickly.</li><li>Block storage can be deployed on a Virtual Private Cloud (VPC) or classic environments.</li><li>There are two available tiers: the IOPS tier, and the Custom IOPS profile tier.</li></ul><p>In<em> File Storage,</em> you should have learned that:</p><ul><li>File storage uses a hierarchical structure to organize files, folders, and subfolders.</li><li>There are strategic benefits to choosing file storage: reducing costs, and scaling up capacity.</li><li>It is available in the endurance and performance tier.</li></ul><p>In <em>Object Storage</em>, you should have learned that:</p><ul><li>Object storage is a storage option that manages unstructured data into self-contained units called Objects. Object storage is referred to as unstructured as it does not use a conventional ‘folder/subfolder’ structure to store objects. Instead, it uses a flat structure known as a “bucket.”</li><li>IBM Cloud Object Storage stores encrypted and dispersed data across multiple geographic locations.</li><li>There are some advantages to using object storage. It enables customers to handle large amounts of unstructured data, is scalable and cost-effective, uses metadata allowing users to maximize the search feature, and quickly access the object they need.</li><li>IBM Cloud Object Storage service offers different levels of resiliency: cross region, regional, and single data center.</li><li>There are four tiers, including Smart, Standard, Vault, and Cold Vault tier.</li></ul><p>In <em>Software Defined Storage (SDS) Offerings</em>, you should have learned that:</p><ul><li>Software-defined storage (SDS) is a storage architecture that separates storage software from its hardware.</li><li>It enables organizations to increase their storage capacity quickly making it flexible and scalable.</li><li>SDS allows the organization to use existing hardware that they currently have, which can be a tremendous cost savings.</li><li>Portworx is a highly available SDS that can be used as persistent storage management for containerized applications.</li></ul><p><strong>Backup, Recovery, and Replication Solutions</strong></p><p>In <em>IBM Cloud Backup Capabilities</em>, you should have learned that:</p><ul><li>IBM Cloud Backup Portal is a browser-based management utility that enables customers to back up data between servers or data centers on the IBM Cloud network.</li><li>Backup and restore make periodic copies of data and applications to a secondary device.</li><li>RTO is the maximum amount of time the organization can afford to be without access to the data or application. In other words, how quickly the customer needs to recover the data and application.</li><li>RPO is the amount of data an organization can afford to lose and effectively dictates how frequently they need to back up their data to avoid losing more.</li><li>There are four types of backup devices or services a customer can use: tape drive, HDD or SDD, backup server, or cloud backup.</li><li>Commonly used back and restore methods include full image only, incremental, differential, CDP, bare metal backup, and instant recovery.</li><li>Disaster recovery is much different than backup and restore. Disaster recovery is a plan that is created to deal with an outage that impacts applications, data, and IT resources.</li><li>Data replication allows the use of real-time information that captures data that is constantly changing to allow for efficient data growth management.</li></ul><p>In <em>Zerto, Veeam, and IBM Spectrum Protect Plus within VMware Solutions in IBM Cloud</em>, you should have learned that:</p><ul><li>There are a wide variety of services used for disaster recovery and protection. Zerto, Veeam, and IBM Spectrum Protect Plus are the most commonly used for these services.</li><li>Zerto is a service that provides replication and disaster recovery capabilities using continuous data replication with journaling versus snapshots.</li><li>Veeam is a service that integrates directly with VMware hypervisors to help an organization achieve high availability to control backup and restore for all the virtual machines attached to their infrastructure from one console.</li><li>IBM Spectrum Protect Plus creates an efficient and scalable solution for clients who need data protection, reuse, and recovery in virtual environments.</li></ul><p>In<em> Disaster Recovery options in IBM Power Systems Virtual Server,</em> you should have learned that:</p><ul><li>In the event of a hardware failure, the IBM Power Systems Virtual Server service will restart the virtual servers on a different host system to provide uninterrupted service.</li><li>There are four strategies used for data recovery, including image capture, AIX backup, IBM i backups, and cloud object storage.</li></ul><p><strong>Networking Components and their Advantages</strong></p><p>In <em>Basic Networking Options</em>, you should have learned:</p><ul><li>Automatic VLANs are provisioned and removed automatically based on whether there are cloud services which need them.</li><li>VRF allows multiple instances of a routing table to exist in a router and to work simultaneously.</li><li>The cloud automatically assigns and manages primary subnets.</li></ul><p>In <em>Load Balancer Options</em>, you should have learned:</p><ul><li>Distributing connections using load balancers prevents server overload and enhances uptime.</li><li>Cloud Internet Services provide global load balancer services.</li></ul><p>In <em>Direct Link Offerings</em>, you should have learned:</p><ul><li>Direct Link offerings provide connectivity from external sources into a private cloud network.</li><li>Direct Link Connect on Classic provides private access to the cloud infrastructure.</li><li>Global routing can be added to all Direct Link products.</li></ul><p>In <em>Virtual Private Cloud Networking</em>, you should have learned:</p><ul><li>A VPC provides cloud security to workloads.</li><li>By default, resources in a VPC are isolated from other services.</li><li>A VPC can contain multiple subnets within each zone.</li><li>A public gateway can be attached to a VPC subnet to allow the subnet to route traffic to and from the internet.</li></ul><p><strong>IBM Networking Components</strong></p><p>In <em>Direct Link Use Cases</em>, you should have learned that:</p><ul><li>Direct Link creates private connections between on-premises environment and cloud resources.</li><li>Private connects are created without using the public internet.</li><li>Workloads with large and frequent data transfers are supported.</li></ul><p>In <em>Public And Private Components Use Cases</em>, you should have learned that:</p><ul><li>VRF connections to resources are more secure because of the use of a private network endpoint.</li><li>The BYOIP option enables users to connect existing networks to cloud infrastructure.</li><li>Workload isolation helps virtual machines and bare metal servers securely deploy with less risk.</li></ul><p>In <em>Use Cases for Local and Global Load Balancers</em>, you should have learned that:</p><ul><li>Load balancing helps prevent failure when resources are overloaded.</li><li>Hardware load balancers are less flexible and scalable.</li><li>A global load balancer helps balance workloads across regions.</li></ul><p><strong>VPC and Related Networking Concepts</strong></p><p>In <em>VPCs</em>, you should have learned that:</p><ul><li>A virtual private cloud provides a private cloud environment on a shared public cloud infrastructure.</li><li>VPC infrastructure is deployed across three zones.</li><li>VPC cloud resources have their own isolated virtual network.</li></ul><p>In <em>Transit Gateways</em>, you should have learned that:</p><ul><li>Transit gateways connect VPC resources across multiple regions.</li><li>Routing options stay in the private cloud infrastructure.</li><li>Connecting transit gateways to Direct Link enables connection to an on-premises network and other networks connected to the transit gateway.</li></ul><p><strong>Integration use case</strong></p><p>In <em>When to Use API Connect, APP Connect, or IBM Messaging Options</em>, you should have learned that:</p><ul><li>Some organizations have adapted to the added difficulty of integration by replacing large code silos with small, independent components called microservices. This strategy offers greater scalability, resilience, and agility, which is why it is called agile integration.</li><li>Agile integration decentralizes services, so applications teams can better control the creation and exposure of their application program interfaces (APIs), messages, and events.</li><li>IBM API Connect lets users create, secure, expose, manage, socialize, and analyze its APIs across clouds.</li><li>IBM APP Connect integrates data and applications from existing systems, and ties together technologies across environments, including legacy and SaaS systems.</li><li>Apache Kafka-based IBM Event Streams enable organizations to create smart applications that react to events as soon as they happen.</li><li>IBM MQ is a scalable messaging platform that uses Java Message Service (JMS) and other technologies to integrate applications and put information such as product availability on the cloud, where consumers can easily retrieve it.</li></ul><p><strong>Edge Solutions</strong></p><p>In <em>How Edge Functions Work</em>, you should have learned that:</p><ul><li>Edge computing is a distributed computing method that aims to use bandwidth more efficiently, by bringing applications close to where data is created and actions are performed.</li><li>By eliminating the need to send data over a network, edge computing reduces latency and enables real-time processing.</li><li>When implementing an IBM Cloud Internet Service (CIS) Edge function, developers consider the actions they want it to perform. For each action, they define a uniform resource identifier (URIs) called a trigger. IBM CIS Edge intercepts user requests, compares them against the list of triggers, and performs the associated action if it finds a match, called a trigger event.</li><li>Because edge functions run code on trusted CIS Edge servers, users don’t need to use a modern browser.</li><li>If processing needs to occur on client-provided servers physically located at the edge, IBM Cloud Satellite may be a more appropriate solution.</li></ul><p><strong>Cloud AI and analytics use case</strong></p><p>In <em>IBM’s AI Ladder</em>, you should have learned that:</p><ul><li>IBM’s AI Ladder views the process of gathering, preparing, and using data in terms of a ladder comprised of four steps: collecting data, organizing data, analyzing data to scale business insight, and infusing data to implement AI with trust and transparency.</li></ul><p>In <em>IBM Services That Support Analytics and AI</em>, you should have learned that:</p><ul><li>IBM offers many services that use AI and analytics to improve business processes. These include:</li><li>Watson Assistant, which can build dynamic, branded chatbots.</li><li>Watson Studio, which can create custom data models using RStudio and Jupyter Notebooks.</li><li>Watson OpenScale, which can track AI outcomes, monitor compliance, and measure alignment with business goals.</li></ul><p>In <em>Use Cases Associated with Analytics and AI</em>, you should have learned that:</p><ul><li>Two applications of AI and analytics include COVID-19 information delivery and explanations of AI methods.</li></ul><p><strong>IBM Cloud Managed Database Options</strong></p><p>In <em>When to Use SQL and NoSQL Databases</em>, you should have learned that:</p><ul><li>Most databases fall into one of two groups:</li><li>SQ</li><li>NoSQL</li></ul><p>In <em>Benefits of Database-as-a-Service (DBaaS)</em>, you should have learned that:</p><ul><li>DBaaS, sometimes called “managed database service,” lets users access and use a database over the cloud. The provider handles upgrades, backups, and other maintenance tasks to keep the system running 24/7.</li><li>Benefits include cost savings, scalability, simplicity, rapid development, security, reduces risk, and quality.</li><li>Factors to consider in selecting a DBaaS provider include how specialized the application will be, the architecture, test results, and other provider offerings.</li></ul><p>In <em>IBM-Managed Cloud Databases</em>, you should have learned that:</p><ul><li>IBM offers managed cloud databases for various applications, including web and mobile apps, developer tools, confidential data, and business intelligence.</li></ul><p><strong>Benefits and Options of IBM Hyper Protect Crypto Services</strong></p><p>In <em>IBM Hyper Protect Crypto Services Features</em>, you should have learned that:</p><ul><li>IBM Cloud Hyper Protect Crypto Services (HPCS) is a dedicated key management service that uses a dedicated cryptographic processing Hardware Security Module (HSM) to generate, encrypt, store, and decrypt keys.</li><li>The HSM is built on FIPS 140–2 Level 4 certified hardware: the highest level available for cryptographic security.</li><li>Customers retain exclusive control of their keys with a feature called Keep Your Own Key (KYOK).</li></ul><p>In <em>Key Database Services that Integrate with IBM Hyper Protect Crypto Services</em>, you should have learned that:</p><ul><li>Users can integrate HPCS with selected managed database services to bring and manage their own encryption in the cloud.</li><li>Integration involves associating user-managed HPCS root keys to control the randomly generated ones from the database service, and then adding another layer of protection, envelope encryption, to the data.</li></ul><p>In <em>Key Management Concepts</em>, you should have learned that:</p><ul><li>By default, cloud providers control system keys. But for even greater protection, users should control their own keys.</li><li>In order to keep <strong>all </strong>of their keys, users must set up the HSM themselves, which requires a dedicated solution like HPCS.</li></ul><p>In <em>Use Cases Associated with IBM Hyper Protect Crypto Services</em>, you should have learned that:</p><ul><li>Customers benefit from HPCS cryptographic capabilities in many ways: image protection, app development, database encryption, and enterprise environments.</li></ul><p><strong>Compute Security Options</strong></p><p>In <em>Compute Security Options,</em> you should have learned that:</p><ul><li>A Virtual Private Cloud (VPC) is a private, secure location that enables organizations to define and control a virtual network that is essentially isolated from other users in the public cloud environment.</li><li>Logical isolation secures VPCs.</li></ul><p>In <em>Security Groups and Access Control Lists (ACLs) Secure Solutions in IBM Cloud VPC</em>, you should have learned that:</p><ul><li>Security Groups and ACLs are the primary way to enhance security to subnets and instances and can be used independently or together.</li></ul><p>In<em> Encryption Options Available in IBM Cloud to Protect Compute Focus Solutions,</em> you should have learned that:</p><ul><li>IBM-managed encryption, customer-managed encryption, and end-to-end encryption are the encryption options available in IBM Cloud.</li></ul><p>In <em>Methods of Securing IBM Cloud VMware based solutions</em>, you should have learned that:</p><ul><li>IBM Cloud for VMware Solutions enables users to manage resources like they are on-premises through dedicated infrastructure.</li><li>IBM Cloud for VMware Regulated Workloads provides encryption.</li></ul><p>In <em>Role-Based Access Control Security uses within IBM Cloud</em>, you should have learned that:</p><ul><li>IBM Cloud Identity and Access Management (IAM) provides access to services in IBM Cloud through the model of least privilege and does this through Resource Groups and Access Groups.</li></ul><p><strong>Network Security Options</strong></p><p>In <em>Network Security Options, </em>learners should have learned that:</p><ul><li>ACLs and security groups are two types of network access controls that make up the layers of VPC security.</li><li>Network security provides security to information in a network and also controls who can access the network, but there are vulnerable entry points that warrant defense mechanisms for enhanced security.</li></ul><p>In<em> Network Encryption Options Available in IBM Cloud to Protect Solutions,</em> learners should have learned that:</p><ul><li>Juniper vSRX is a router, firewall, and security device that exists as a virtual appliance and provides a firewall, VPN gateway, and NAT as an encryption feature.</li><li>There are multiple ways to secure data in transit or data at rest.</li></ul><p><strong>Storage Security Options</strong></p><p>In <em>Advantages of Using IBM Cloud Storage Services Security Options when Building Solutions, </em>you should have learned that:</p><ul><li>IBM Cloud File Storage and IBM Cloud Block Storage are provisioned with Endurance or Performance options.</li><li>IBM Cloud Object Storage provides the ability to store large volumes of unstructured data.</li></ul><p>In <em>RBAC Secures Solutions built on IBM Cloud</em>, you should have learned that:</p><ul><li>IAM, OpenShift &amp; Containers, and VMware provide varying levels of access policies in order to secure solutions built on IBM Cloud.</li></ul><p>In<em> Various Storage Services Protect Solutions in IBM Cloud,</em>you should have learned that:</p><ul><li>Block Storage for VPC gives users the ability to provide hypervisor-mounted, high-performance data storage for any VSIs that can be provisioned within a VPC.</li><li>IBM Cloud Object Storage provides storage for large volumes of unstructured data that provides security, availability, and reliability.</li></ul><p>In <em>Secure Storage Options when Utilizing IBM Cloud VMware Solutions, </em>you should have learned that:</p><ul><li>When utilizing VMware Solutions Dedicated, data can be stored locally, or using IBM Cloud File Storage or Cloud Object Storage.</li><li>When using VMware Solutions Shared, the workload data is in an IBM-managed cloud infrastructure account.</li><li>VSIs and customer-managed encryption are other options to secure data.</li></ul><p><strong>PaaS Security Options</strong></p><p>In <em>Network Security, you</em> should have learned that:</p><ul><li>Data Shield is an IBM Cloud service that helps protect data in containerized workloads that run on Kubernetes Service and OpenShift clusters while the data is in use.</li><li>Service endpoints are a connectivity option for securely accessing cloud service endpoints.</li><li>Application exposure services enable users to securely expose applications to external traffic.</li></ul><p>In <em>Authenticating Users,</em> you should have learned that:</p><ul><li>SSO provides authentication between multiple web apps.</li><li>App ID is a service provided by IBM Cloud that allows users to create and use SSO for their own applications.</li><li>vCenter Single Sign-On (SSO) is an authentication broker and security token exchange infrastructure. This allows vSphere to communicate with each other via a secure token mechanism.</li></ul><p>In<em> Encryption, Secrets, and Certificates,</em> you should have learned that:</p><ul><li>Secrets Manager creates dynamic secrets and manages the lifecycle of the secrets.</li><li>IBM Key Protect securely stores and applies secrets for apps. It provides encryption solutions and allows data to be secured and stored in IBM Cloud through envelope encryption.</li><li>Hyper Protect Crypto Services is a key management system that provides keep your own key (KYOK) capabilities for cloud data encryption. It provides lifecycle management for keys, encryption for IBM Cloud services, access management, auditing, and security certification.</li><li>VMware integrates on-premises vSphere vCenter networks to the IBM Cloud for VMware solutions deployment.</li></ul><p>In <em>IBM Cloud Code Engine and Security</em>, you should have learned that:</p><ul><li>IBM Code Engine provides a security solution by isolating customers and their workloads.</li></ul><p>In <em>Delivery Pipeline Private and Public Workers</em>, you should have learned that:</p><ul><li>Delivery Pipeline Private Workers and the IBM Cloud Continuous Delivery Development teams work together to use the private worker in their toolchain.</li></ul><p>In <em>Other Security Topics, </em>you should have learned that:</p><ul><li>Terraform is a third-party service used by IBM Cloud, and it enables predictable provisioning of the IBM Cloud platform, classic infrastructure, and VPC infrastructure.</li><li>Data Shield is an IBM Cloud service that helps protect data in containerized workloads that run on Kubernetes and OpenShift clusters while the data is in use.</li></ul><p><strong>Core Principles and Practices of Building Cloud-Native Applications</strong></p><p>In <em>Define Cloud Native, its Benefits, and List Use Cases</em>, you learned that:</p><ul><li>Scaling of cloud native applications is very easy.</li><li>Cloud native applications are made up of microservices.</li></ul><p>In <em>The Twelve-Factor App Methodology and How Microservices Benefit the Organization</em>, you learned that:</p><ul><li>Microservices are independently deployable.</li><li>Microservices have specialized functionality.</li><li>Twelve-factor app methodology uses a declarative approach, reducing the time needed to onboard new developers.</li></ul><p>In <em>Key Enabling Technologies and Tools for a Cloud Native Solution</em>, you learned that:</p><ul><li>Containers are self-contained.</li><li>Container orchestration systems are used to manage containers.</li><li>Kubernetes is an example of a container orchestration system.</li><li>IBM Cloud Functions and IBM Code Engine are examples of serverless technologies.</li><li>APIs allow applications to communicate with each other.</li><li>REST APIs have additional architectural constraints to standard APIs.</li><li>Messaging and event streaming are used for routine status updates from applications.</li><li>Serverless architecture is designed to be a flexible alternative to a traditional server.</li></ul><p><strong>High-Level Benefits of Modernizing Existing Applications to be Cloud-Native</strong></p><p>In <em>The Importance of Application Modernization</em>, you learned that:</p><ul><li>Modernization can reduce the cost of managing applications.</li><li>Containerization can be an easy yet effective approach to modernizing applications.</li><li>Security and compliance of an application can be increased by modernization.</li><li>Development speed can be increased by modernizing.</li></ul><p>In <em>Application Modernization Approaches</em>, you learned that:</p><ul><li>Existing applications can be modernized by replacing existing functionality with microservices.</li><li>APIs can be used to expose parts of an existing application, making it easier to use microservices for new functionality.</li></ul><p>In <em>Whether to Modernize or Rebuild an Existing Application</em>, you learned that:</p><ul><li>The first step in application modernization is to assess how ready the application is to be moved to the cloud.</li><li>Containerization can reduce costs and resources when modernizing an application.</li><li>Rebuilding an application is made easier by using existing microservices.</li></ul><p><strong>IBM Container Orchestration</strong></p><p>In <em>Containers and How They Differ From Virtual Machines (VMs)</em>, you learned that:</p><ul><li>Containers are self-contained units that are designed to hold applications as well as all libraries and dependencies that the application requires.</li><li>Containers do not have an operating system of their own. Instead, they access the operating system of the device they are running on using a hypervisor.</li></ul><p>In <em>Containers, Container Orchestration, and Kubernetes</em>, you learned that:</p><ul><li>The process of designing and packaging software in containers is called containerization.</li><li>When an application is containerized, it is packaged with its relevant environment variables, configuration files, libraries, and software dependencies.</li><li>Container orchestration is a way to manage large volumes of containers.</li><li>Kubernetes is a platform that enables customers to manage their containerized workloads. It provides tools that enable developers to deploy, automate, monitor, and scale their apps efficiently.</li></ul><p>In <em>An Overview of Red Hat OpenShift on IBM Cloud</em>, you learned that:</p><ul><li>Red Hat OpenShift on IBM Cloud enables customers to deploy apps on Red Hat OpenShift clusters. These clusters run on the Red Hat OpenShift on IBM Cloud container platform software.</li><li>Red Hat OpenShift on IBM Cloud provides customers with a fast, secure, and scalable solution.</li></ul><p>In <em>IBM Cloud Kubernetes Service and its Benefits</em>, you learned that:</p><ul><li>IBM Cloud Kubernetes Service is a certified Kubernetes provider that enables customers to create their own Kubernetes cluster of compute hosts to deploy and manage their containerized apps.</li><li>Some benefits of IBM Cloud Kubernetes Service include that customers can choose to deploy clusters with Red Hat OpenShift or Kubernetes installed, it is a single-tenant Kubernetes clusters with compute, network, and storage infrastructure isolation, supports multizone clusters, has image security compliance with Vulnerability Advisor, has highly available masters, continuous monitoring of the cluster health, and secure exposure of apps to the public.</li></ul><p><strong>Solution Scalability</strong></p><p>In <em>Horizontal and Vertical Scaling for Containers</em>, you learned that:</p><ul><li>Customers can quickly scale up simply by increasing the CPU and RAM.</li><li>Customers can scale out by provisioning additional VMs to spread out the workload.</li></ul><p>In <em>Scaling Clusters Using Cluster Autoscaler</em>, you learned that:</p><ul><li>The cluster autoscaler periodically scans the cluster and adjusts the number of worker nodes based on the workload requests.</li><li>If there are insufficient compute resources to schedule the pod on a worker node, that pod is considered pending. If a pending pod is detected, the autoscaler scales up the worker nodes evenly across zones.</li><li>If a pod is not fully utilized — meaning less than 50% of the total compute resources have been requested in the last 10 minutes — the autoscaler considers it underutilized and will scale the worker node down one at a time. This threshold can be customized by the customer.</li></ul><p>In <em>Horizontal and Pod Autoscalers</em>, you learned that:</p><ul><li>An HPA enables customers to determine the minimum or the maximum number of pods to run, the CPU, and memory utilization the pods should utilize.</li><li>The HPA automatically scales the workload to match the demand.</li><li>When there is an increased workload, it deploys more pods.</li><li>When there is a decrease in the workload, it communicates to the workload resource to scale back down.</li></ul><p>In <em>Vertical Pod Autoscalers</em>, you learned that:</p><ul><li>Vertical pod autoscaling (VPA) helps size pods for optimal CPU and memory utilization.</li><li>Like HPA, VPA uses the cluster nodes efficiently because the pods use exactly what they need.</li></ul><p><strong>Hybrid and Multicloud Architectures</strong></p><p>In <em>Technology and Strategies in Hybrid Cloud Solutions</em>, you learned that:</p><ul><li>The hybrid cloud combined the public cloud, private cloud, and on-premises infrastructure. It enables customers to have a distributed environment where they can run their traditional or cloud-native workloads as they need to.</li><li>The hybrid cloud enables customers to have improved developer productivity, greater infrastructure efficiency, improved regulatory compliance and security, and overall business acceleration.</li><li>Multicloud is the use of cloud services from more than one cloud vendor.</li><li>A multicloud solution is a solution that is portable across these providers’ cloud infrastructures, usually build on open-source, cloud-native technologies.</li><li>IBM Cloud Satellite provides consistency in services and the ability to deploy anywhere.</li></ul><p>In <em>The Role of IBM Cloud Paks in the Hybrid Multicloud Strategy</em>, you learned that:</p><ul><li>Cloud Paks are pre-integrated Artificial Intelligence (AI), powered software that is designed to run in a customer’s cloud environment managed by a single intelligent control plane.</li><li>IBM Cloud Paks are portable, can run anywhere, are certified, and secure.</li><li>There are 12 foundational services available.</li></ul><p><a href="https://www.linkedin.com/in/alvisf/">https://www.linkedin.com/in/alvisf/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b9c7fbf9324c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Get HTTPS ! How to Get SSL\TLS Certificate in AWS for EC2 Hosted Application.]]></title>
            <link>https://levelup.gitconnected.com/get-https-how-to-get-ssl-tls-certificate-in-aws-for-ec2-hosted-application-8d14771a6ff6?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/8d14771a6ff6</guid>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Sun, 27 Feb 2022 20:19:36 GMT</pubDate>
            <atom:updated>2022-02-27T20:19:36.718Z</atom:updated>
            <content:encoded><![CDATA[<p>Today we will look at how you can get an HTTPS for your website/Application hosted on EC2.</p><p>We need to set up the nginx if you have configured it to HTTP previously. Once you are done with can we can move on to the next step.</p><p><strong>Steps to get HTTPS</strong></p><ol><li>Get SSL/TLS Certificated</li><li>Create a LoadBalancer</li><li>Route all Trafic via LoadBalancer</li><li>Route all Trafic via HTTPS</li></ol><p>Now In this example in using route 53’s Domain name service. Even if you don’t have one you can still use the tutorial with slight changes which will be mentioned.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*nPPwuTi-chFhH8qc" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*fjA3CpsHdKVxMiWs.png" /></figure><h3>Get SSL/TLS Certificated</h3><p>Now we can get a free certificate from the AWS Certificate Manager</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*pDStKkCqrZ1k8n3J" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/653/0*d5l9i5sO6-d2qm7C.png" /></figure><ol><li>Goto Certificate Manager</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*bigdcLxLGku5ndsm" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*HAjIVn5lXbaWqxyC.png" /></figure><p>2. Click on request a certificate</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*xzXzKlOKeGA2zFbe" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*8WAzwJNoMt1BFGpw.png" /></figure><p>3. Select Public Certificate &amp; click request certificate</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*uWqvw-EFNvmXYQme" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*WLuHSS-d-NtjkQrX.png" /></figure><p>4. Enter your domain name with .com or any subdomain if needed. &amp; click Next</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*jeUliQ4gTfRGO-Oi" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*sQB7_V4kZOHWHrKO.png" /></figure><p>5. Select DNS validation for quick certificate generation but of course, you can use Email validation if needed &amp; click Next</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*fxKMYH8dSMcpG5Ir" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*KCPy1ULt0ij6z4Mu.png" /></figure><p>6. If you would like to add tags you can but I’m skipping for now &amp; click Review</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*EjyDMExYGBc0kDhy" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*veBvHP9ZjSkLOvOU.png" /></figure><p>7. Review all the details if they are correct now click Confirm and request.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*w72u1cJRsh_LUcf2" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*f4Cw817HOkDXpjWV.png" /></figure><p>8. Now you need to create a record in your hosted zone with this value. But AWS offers you to do the work for you. So you can just click on create a record in Route 53 or manually do it yourself &amp; click Continue</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*_6hqJ3vtHxVszcM_.png" /></figure><p>Wait for a few minutes you will get an issued status. Once you get that you can you can move on to the next step.</p><h3>Create a LoadBalancer</h3><p>If your application is hosted on an EC2 instance we need to make sure we have trafficked it via a load balancer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*diHSP5bHAg0goU_n" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/695/0*vAauqjnU7Munrx9b.png" /></figure><p>We can only attach the ACM Certificate with a loadbalancer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*geq_BCiCeH-jSLkO" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*a2_HhFwBnRgOep0R.png" /></figure><ol><li>Create a new Loadbalancer choose https/https</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*GHqeyICh7XFOgwwy" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*OZJmXDAcF4KQZ3tW.png" /></figure><p>2. add a listener and add https with port 443 &amp; click configure security settings</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*Y8jo97KLexqYSXyO" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*1zoW1ImgGrky1lMS.png" /></figure><p>3. Select Choose a certificate from ACM and choose the certificate you just got &amp; click next</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*Y9RU3MZl-ECMK3cb" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*dsxjAbQ8oafD5A0Q.png" /></figure><p>4. choose the protocol to connect to the target group as HTTP with port 80 because you don’t need your loadbalncer to talk to your ec2 instance via a HTTPS, HTTP would be more than sufficient to do the job &amp; click next</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*XrRDdZBfHGlgaeda" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*HfmEbe8Lr1i3zQId.png" /></figure><p>5. Add your EC2 to your target group and click next</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*2gaocQ7AsSHDaeLu" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*FvYdr5vLwdTIEH62.png" /></figure><p>6. Review all the information &amp; click Create</p><p>Now we have successfully created a loadbalancer and HTTPS should work in a few minutes.</p><p>clear your browser cache or see if your target group is set via port 80.</p><h3>Route all Trafic via HTTPS</h3><p>This must be the shortest step of all. All we are trying to achieve here is to force traffic to go through HTTPS even if they try to go through HTTP.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*MrXTKt_MVP29chDu" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*W025I4rgvIfHBgaX.png" /></figure><ol><li>go to your loadbalncer and select your loadbalancer and choose port 80 and hit edit</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/30/0*Q6Z0ImUynTbfdRj7" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*ydPGWWiuV-CRZLvj.png" /></figure><p>2. change the route to redirect to HTTPS and click on Update at the top.</p><blockquote><em>🥳 That’s it, you have successfully changed your HTTP app to HTTPS</em></blockquote><p><a href="https://www.linkedin.com/in/alvisf/">Alvis F - Software Engineer - EY | LinkedIn</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8d14771a6ff6" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/get-https-how-to-get-ssl-tls-certificate-in-aws-for-ec2-hosted-application-8d14771a6ff6">Get HTTPS 🔐! How to Get SSL\TLS Certificate in AWS for EC2 Hosted Application.</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Change Data Capture with Debezium Kafka and MySQL]]></title>
            <link>https://levelup.gitconnected.com/change-data-capture-with-debezium-kafka-and-mysql-359f7bc6b29a?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/359f7bc6b29a</guid>
            <category><![CDATA[debezium]]></category>
            <category><![CDATA[kafka]]></category>
            <category><![CDATA[postgres]]></category>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Sun, 19 Dec 2021 20:11:02 GMT</pubDate>
            <atom:updated>2021-12-19T20:11:02.641Z</atom:updated>
            <content:encoded><![CDATA[<h3>What is Change Data Capture?</h3><p>Moving data from your application database into another database with negligible effect on the functionality of your application is the key inspiration for using a shift data capture architecture pattern.</p><h4>Uses</h4><ol><li>tracking data changed to feed into an elastic search index.</li><li>moving data changes from OLTP to OLAP in real-time</li><li>creating audit logs, etc</li></ol><h3>Project overview</h3><p>We are going to use Mysql for our database</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*GZ6xYb6r_cv-ZibP.png" /></figure><p>‍</p><h3>Components</h3><h3>Prereq Installations</h3><p>In order to follow along you will need the tools specified below</p><ol><li><a href="https://docs.docker.com/get-docker/">docker</a> (preferred) to run postgres, debezium and kafka</li><li><a href="https://github.com/dbcli/pgcli">pgcli</a> to connect to our postgres instance</li></ol><h3>1. Postgres</h3><p>This will serve as our application database. To understand how CDC (with debezium) works we need to understand what happens when a transaction occurs. When a transaction occurs, the transaction is logged in a place called Write Ahead Log (WAL) in the disk and then the data change or update or delete is processed. The transactions are generally held in cache and flushed to disk in bulk to keep latency low. In case of a database crash we may loose the cache but the database can recover using the logs in WAL in disk. Using WAL, only logs are written to the disk which is less expensive than writing all the data changes to the disk, this is a tradeoff the developers of postgres had to make to keep latency of transactions low and have the ability to recover in case of crash(using WAL).</p><p>You can think of the WAL as an append only log that contains all the operations in a sequential manner with the timestamp denoting when the transaction was logged. The WAL files are periodically removed or archived so that the size of the database is kept small.</p><p>We are going to use docker to run a postgres instance</p><pre>docker run -d --name postgres -p 5432:5432 -e POSTGRES_USER=start_data_engineer \<br>-e POSTGRES_PASSWORD=password debezium/postgres:12</pre><p>The above docker command starts a postgres docker container named postgres. The user name is set as start_data_engineer and password is password. If you notice you will see we have used the debezium/postgres:12 image, the reason for using the debezium’s docker of postgres was to enable the settings that postgres requires to operate with debezium. Let’s take a look at those settings</p><pre>docker exec -ti postgres /bin/bash</pre><p>Use the above command to execute the /bin/bash command on the postgres container in interactive mode -it. You are now inside your docker container. Type in</p><pre>cat /var/lib/postgresql/data/postgresql.conf</pre><p>to view the configuration settings for postgres.</p><h4>postgresql.conf</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FvM5tGp6-clj4oBk.png" /></figure><p>‍</p><p>The Replication section is where we set the configuration for the database to write to the WAL. The</p><ol><li>wal_level has options of minimal: minimal information required to restart from a database crash, archive: enables the database engine to be able to do WAL archiving, hot_standby: enables the database engine to create a read only replica of our server, logical: is what we want for our purposes, it adds all the information necessary to make this (WAL) data available for other systems to consume.</li><li>max_wal_senders the WAL senders are process that run on the database to send WAL to receivers (other replica or systems).This config denotes the maximum number of WAL sender processes allowed.</li></ol><p>Let’s create the data in postgres. We use pgcli to interact with our postgres instance</p><pre>pgcli -h localhost -p 5432 -U start_data_engineer<br>#password is password</pre><pre>CREATE SCHEMA bank;<br>SET search_path TO bank,public;<br>CREATE TABLE bank.holding (<br>    holding_id int,<br>    user_id int,<br>    holding_stock varchar(8),<br>    holding_quantity int,<br>    datetime_created timestamp,<br>    datetime_updated timestamp,<br>    primary key(holding_id)<br>);<br>ALTER TABLE bank.holding replica identity FULL;<br>insert into bank.holding values (1000, 1, &#39;VFIAX&#39;, 10, now(), now());<br>\q</pre><p>The above is standard sql, with the addition of replica identity. This field has the option of being set as one of DEFAULT, NOTHING, FULL and INDEX which determines the amount of detailed information written to the WAL. We choose FULL to get all the before and after data for CRUD change events in our WAL, the INDEX option is the same as full but it also includes changes made to indexes in WAL which we do not require for our project’s objective. We also insert a row into the holding table.</p><h3>2. Kafka</h3><p>Kafka is a message queue system with an at least once guarantee. A quick overview of some key kafka concepts</p><ol><li>Kafka is a distributed message queue system. The distributed cluster management is provided by zookeeper.</li><li>The broker handles consumer write, producer request and metadata config. One server within a kafka cluster is one kafka broker, there can be multiple brokers within a single kafka cluster</li><li>A Topic is a specific queue into which the producers can push data into and consumers can read from.</li><li>Partitions are way to distribute the content of a topic over the cluster.</li><li>You can think of offset (specific to a partition) as the pointer pointing to which message you are in while reading messages from that topic-partition.</li></ol><p>In our project the kafka broker will be used to store the data changes being made in the postgres database as messages. We will set up a consumer in the later sections to read data from the broker.</p><p>Let’s start zookeeper and a kafka broker</p><pre>docker run -d --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 debezium/zookeeper:1.1<br>docker run -d --name kafka -p 9092:9092 --link zookeeper:zookeeper debezium/kafka:1.1</pre><p>Again we are using debezium images for ease. You can see for the zookeeper we keeps ports 21821, 2888, 3888 open, these are required for zookeeper operations. And similarly we keep 9092 open for kafka, we can communicate with kafka through this port.</p><h3>3. Debezium</h3><p>We use a kafka tool called Connect to run debezium. As the name suggests connect provides a framework to connect input data sources to kafka and connect kafka to output sinks. It runs as a separate service.</p><p>Debezium is responsible for reading the data from the source data system (in our example postgres) and pushing it into a kafka topic (automatically named after the table) in a suitable format.</p><p>Let’s start a kafka connect container</p><pre>docker run -d --name connect -p 8083:8083 --link kafka:kafka \<br>--link postgres:postgres -e BOOTSTRAP_SERVERS=kafka:9092 \<br>-e GROUP_ID=sde_group -e CONFIG_STORAGE_TOPIC=sde_storage_topic \<br>-e OFFSET_STORAGE_TOPIC=sde_offset_topic debezium/connect:1.1</pre><p>Notice we are specifying the kafka host and endpoint with BOOTSTRAP_SERVERS env variable. The GROUP_ID here represents a group this connect service belongs to. We can use curl to check for registered connect services Note: wait for a few seconds (atleast 10 sec) before running the curl command below</p><pre>curl -H &quot;Accept:application/json&quot; localhost:8083/connectors/<br>[]</pre><p>We can register a debezium connect service using a curl command to the connect service on port 8083</p><pre>curl -i -X POST -H &quot;Accept:application/json&quot; -H &quot;Content-Type:application/json&quot; \<br>localhost:8083/connectors/ -d &#39;{&quot;name&quot;: &quot;sde-connector&quot;, &quot;config&quot;: {&quot;connector.class&quot;: &quot;io.debezium.connector.postgresql.PostgresConnector&quot;, &quot;database.hostname&quot;: &quot;postgres&quot;, &quot;database.port&quot;: &quot;5432&quot;, &quot;database.user&quot;: &quot;start_data_engineer&quot;, &quot;database.password&quot;: &quot;password&quot;, &quot;database.dbname&quot; : &quot;start_data_engineer&quot;, &quot;database.server.name&quot;: &quot;bankserver1&quot;, &quot;table.whitelist&quot;: &quot;bank.holding&quot;}}&#39;</pre><p>Let’s take a look at the configuration part of the api call above</p><pre>{<br>  &quot;name&quot;: &quot;sde-connector&quot;,<br>  &quot;config&quot;: {<br>    &quot;connector.class&quot;: &quot;io.debezium.connector.postgresql.PostgresConnector&quot;,<br>    &quot;database.hostname&quot;: &quot;postgres&quot;,<br>    &quot;database.port&quot;: &quot;5432&quot;,<br>    &quot;database.user&quot;: &quot;start_data_engineer&quot;,<br>    &quot;database.password&quot;: &quot;password&quot;,<br>    &quot;database.dbname&quot;: &quot;start_data_engineer&quot;,<br>    &quot;database.server.name&quot;: &quot;bankserver1&quot;,<br>    &quot;table.whitelist&quot;: &quot;bank.holding&quot;<br>  }<br>}</pre><ol><li>The database.* configs are connection parameters for our postgres database</li><li>database.server.name is a name we assign for our database</li><li>table.whitelist is a field that informs the debezium connector to only read data changes from that table. Similarly you can whitelist or blacklist tables or schemas. By default debezium reads from all tables in a schema.</li><li>connector.class is the connector used to connect to our postgres database</li><li>name name we assign to our connector</li></ol><p>Let’s check for presence of connector</p><pre>curl -H &quot;Accept:application/json&quot; localhost:8083/connectors/<br>[&quot;sde-connector&quot;]%</pre><p>We can see the sde-connector is registered.</p><h3>4. Consumer</h3><p>Now that we have our connector pushing in message into our kafka broker, we can consume the messages using a consumer. Let’s take a look at only the first message in the kafka topic bankserver1.bank.holding using the command below</p><pre>docker run -it --rm --name consumer --link zookeeper:zookeeper --link kafka:kafka debezium/kafka:1.1 watch-topic -a bankserver1.bank.holding --max-messages 1 | grep &#39;^{&#39; | jq</pre><p>In the above we start a consumer container to watch the topic bankserver1.bank.holding which follows the format {database.server.name}.{schema}.{table_name} and we have set the maximum number of messages to be read by this consumer to be 1 . The grep is to filter out non JSON lines, as the docker container will print out some configs. <a href="https://stedolan.github.io/jq/download/">jq</a>(optional download) is to format the json. The output should be similar to the structure shown below</p><pre>{<br>  &quot;schema&quot;: {<br>    &quot;type&quot;: &quot;struct&quot;,<br>    &quot;fields&quot;: [<br>      {<br>        &quot;type&quot;: &quot;struct&quot;,<br>        &quot;fields&quot;: [<br>          {<br>            &quot;type&quot;: &quot;int32&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;holding_id&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int32&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;user_id&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;holding_stock&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int32&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;holding_quantity&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;name&quot;: &quot;io.debezium.time.MicroTimestamp&quot;,<br>            &quot;version&quot;: 1,<br>            &quot;field&quot;: &quot;datetime_created&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;name&quot;: &quot;io.debezium.time.MicroTimestamp&quot;,<br>            &quot;version&quot;: 1,<br>            &quot;field&quot;: &quot;datetime_updated&quot;<br>          }<br>        ],<br>        &quot;optional&quot;: true,<br>        &quot;name&quot;: &quot;bankserver1.bank.holding.Value&quot;,<br>        &quot;field&quot;: &quot;before&quot;<br>      },<br>      {<br>        &quot;type&quot;: &quot;struct&quot;,<br>        &quot;fields&quot;: [<br>          {<br>            &quot;type&quot;: &quot;int32&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;holding_id&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int32&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;user_id&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;holding_stock&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int32&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;holding_quantity&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;name&quot;: &quot;io.debezium.time.MicroTimestamp&quot;,<br>            &quot;version&quot;: 1,<br>            &quot;field&quot;: &quot;datetime_created&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;name&quot;: &quot;io.debezium.time.MicroTimestamp&quot;,<br>            &quot;version&quot;: 1,<br>            &quot;field&quot;: &quot;datetime_updated&quot;<br>          }<br>        ],<br>        &quot;optional&quot;: true,<br>        &quot;name&quot;: &quot;bankserver1.bank.holding.Value&quot;,<br>        &quot;field&quot;: &quot;after&quot;<br>      },<br>      {<br>        &quot;type&quot;: &quot;struct&quot;,<br>        &quot;fields&quot;: [<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;version&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;connector&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;name&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;ts_ms&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;name&quot;: &quot;io.debezium.data.Enum&quot;,<br>            &quot;version&quot;: 1,<br>            &quot;parameters&quot;: {<br>              &quot;allowed&quot;: &quot;true,last,false&quot;<br>            },<br>            &quot;default&quot;: &quot;false&quot;,<br>            &quot;field&quot;: &quot;snapshot&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;db&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;schema&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;table&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;txId&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;lsn&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: true,<br>            &quot;field&quot;: &quot;xmin&quot;<br>          }<br>        ],<br>        &quot;optional&quot;: false,<br>        &quot;name&quot;: &quot;io.debezium.connector.postgresql.Source&quot;,<br>        &quot;field&quot;: &quot;source&quot;<br>      },<br>      {<br>        &quot;type&quot;: &quot;string&quot;,<br>        &quot;optional&quot;: false,<br>        &quot;field&quot;: &quot;op&quot;<br>      },<br>      {<br>        &quot;type&quot;: &quot;int64&quot;,<br>        &quot;optional&quot;: true,<br>        &quot;field&quot;: &quot;ts_ms&quot;<br>      },<br>      {<br>        &quot;type&quot;: &quot;struct&quot;,<br>        &quot;fields&quot;: [<br>          {<br>            &quot;type&quot;: &quot;string&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;id&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;total_order&quot;<br>          },<br>          {<br>            &quot;type&quot;: &quot;int64&quot;,<br>            &quot;optional&quot;: false,<br>            &quot;field&quot;: &quot;data_collection_order&quot;<br>          }<br>        ],<br>        &quot;optional&quot;: true,<br>        &quot;field&quot;: &quot;transaction&quot;<br>      }<br>    ],<br>    &quot;optional&quot;: false,<br>    &quot;name&quot;: &quot;bankserver1.bank.holding.Envelope&quot;<br>  },<br>  &quot;payload&quot;: {<br>    &quot;before&quot;: null,<br>    &quot;after&quot;: {<br>      &quot;holding_id&quot;: 1000,<br>      &quot;user_id&quot;: 1,<br>      &quot;holding_stock&quot;: &quot;VFIAX&quot;,<br>      &quot;holding_quantity&quot;: 10,<br>      &quot;datetime_created&quot;: 1589121006547486,<br>      &quot;datetime_updated&quot;: 1589121006547486<br>    },<br>    &quot;source&quot;: {<br>      &quot;version&quot;: &quot;1.1.1.Final&quot;,<br>      &quot;connector&quot;: &quot;postgresql&quot;,<br>      &quot;name&quot;: &quot;bankserver1&quot;,<br>      &quot;ts_ms&quot;: 1589121006548,<br>      &quot;snapshot&quot;: &quot;false&quot;,<br>      &quot;db&quot;: &quot;start_data_engineer&quot;,<br>      &quot;schema&quot;: &quot;bank&quot;,<br>      &quot;table&quot;: &quot;holding&quot;,<br>      &quot;txId&quot;: 492,<br>      &quot;lsn&quot;: 24563232,<br>      &quot;xmin&quot;: null<br>    },<br>    &quot;op&quot;: &quot;c&quot;,<br>    &quot;ts_ms&quot;: 1589121006813,<br>    &quot;transaction&quot;: null<br>  }<br>}</pre><p>Basically there 2 main sections</p><ol><li>schema: The schema defines the schema of the payload for before, after, source, op, ts_ms and transaction sections. This data can be used by the consumer client program to parse the input.</li><li>payload: This contains the actual data, there are before and after sections showing the columns of holding, before and after the data change. The data change is represented by the op which is one of c create (insert), u for update, d for delete, and r for read (at snapshot). The source section shows the WAL configurations with the tx_id denoting the transaction id and lsn log sequence number which are used to store the byte offset of the log file per WAL record.</li></ol><p>We care about the before and after sections. We will use python to format this into the pivot structure we defined at the start.</p><pre>#!/usr/bin/env python3 -u<br># Note: the -u denotes unbuffered (i.e output straing to stdout without buffering data and then writing to stdout)</pre><pre>import json<br>import os<br>import sys<br>from datetime import datetime</pre><pre>FIELDS_TO_PARSE = [&#39;holding_stock&#39;, &#39;holding_quantity&#39;]</pre><pre>def parse_create(payload_after, op_type):<br>    current_ts = datetime.now().strftime(&#39;%Y-%m-%d-%H-%M-%S&#39;)<br>    out_tuples = []<br>    for field_to_parse in FIELDS_TO_PARSE:<br>        out_tuples.append(<br>            (<br>                payload_after.get(&#39;holding_id&#39;),<br>                payload_after.get(&#39;user_id&#39;),<br>                field_to_parse,<br>                None,<br>                payload_after.get(field_to_parse),<br>                payload_after.get(&#39;datetime_created&#39;),<br>                None,<br>                None,<br>                current_ts,<br>                op_type<br>            )<br>        )</pre><pre>return out_tuples</pre><pre>def parse_delete(payload_before, ts_ms, op_type):<br>    current_ts = datetime.now().strftime(&#39;%Y-%m-%d-%H-%M-%S&#39;)<br>    out_tuples = []<br>    for field_to_parse in FIELDS_TO_PARSE:<br>        out_tuples.append(<br>            (<br>                payload_before.get(&#39;holding_id&#39;),<br>                payload_before.get(&#39;user_id&#39;),<br>                field_to_parse,<br>                payload_before.get(field_to_parse),<br>                None,<br>                None,<br>                ts_ms,<br>                current_ts,<br>                op_type<br>            )<br>        )</pre><pre>return out_tuples</pre><pre>def parse_update(payload, op_type):<br>    current_ts = datetime.now().strftime(&#39;%Y-%m-%d-%H-%M-%S&#39;)<br>    out_tuples = []<br>    for field_to_parse in FIELDS_TO_PARSE:<br>        out_tuples.append(<br>            (<br>                payload.get(&#39;after&#39;, {}).get(&#39;holding_id&#39;),<br>                payload.get(&#39;after&#39;, {}).get(&#39;user_id&#39;),<br>                field_to_parse,<br>                payload.get(&#39;before&#39;, {}).get(field_to_parse),<br>                payload.get(&#39;after&#39;, {}).get(field_to_parse),<br>                None,<br>                payload.get(&#39;ts_ms&#39;),<br>                None,<br>                current_ts,<br>                op_type<br>            )<br>        )</pre><pre>return out_tuples</pre><pre>def parse_payload(input_raw_json):<br>    input_json = json.loads(input_raw_json)<br>    op_type = input_json.get(&#39;payload&#39;, {}).get(&#39;op&#39;)<br>    if op_type == &#39;c&#39;:<br>        return parse_create(<br>            input_json.get(&#39;payload&#39;, {}).get(&#39;after&#39;, {}),<br>            op_type<br>        )<br>    elif op_type == &#39;d&#39;:<br>        return parse_delete(<br>            input_json.get(&#39;payload&#39;, {}).get(&#39;before&#39;, {}),<br>            input_json.get(&#39;payload&#39;, {}).get(&#39;ts_ms&#39;, None),<br>            op_type<br>        )<br>    elif op_type == &#39;u&#39;:<br>        return parse_update(<br>            input_json.get(&#39;payload&#39;, {}),<br>            op_type<br>        )<br>    # no need to log read events<br>    return []</pre><pre>for line in sys.stdin:<br>    # 1. reads line from unix pipe, assume only valid json come through<br>    # 2. parse the payload into a format we can use<br>    # 3. prints out the formatted data as a string to stdout<br>    # 4. the string is of format<br>    #    holding_id, user_id, change_field, old_value, new_value, datetime_created, datetime_updated, datetime_deleted, datetime_inserted<br>    data = parse_payload(line)<br>    for log in data:<br>        log_str = &#39;,&#39;.join([str(elt) for elt in log])<br>        print(log_str, flush=True)</pre><p><strong>Note</strong>: Use <a href="https://github.com/tmux/tmux/wiki">tmux</a> for easy multi terminal viewing.</p><pre>docker run -it --rm --name consumer --link zookeeper:zookeeper \<br>--link kafka:kafka debezium/kafka:1.1 watch-topic \<br>-a bankserver1.bank.holding | grep --line-buffered &#39;^{&#39; \<br>| &lt;your-file-path&gt;/stream.py &gt; &lt;your-output-path&gt;/holding_pivot.txt</pre><p>The above command starts a consumer container, grep to allow only line that start with { denoting a json, the –line-buffered option tells grep to output one line at a time without buffering(the buffer size depends on your os) and then use the python script to transform the message into a format we want and write the output to a file called holding_pivot.txt.</p><p>In another terminal do the following</p><pre>tail -f &lt;your-output-path&gt;/holding_pivot.txt</pre><p>The above command opens the holding_pivot.txt file and follows along, so you can see if there are any new lines added to the file. In another terminal open a connection to your postgres instance using</p><pre>pgcli -h localhost -p 5432 -U start_data_engineer<br># the password is password</pre><p>Try the following sql scripts and make sure the output you see in the holding_pivot.txt is accurate</p><pre>-- C<br>insert into bank.holding values (1001, 2, &#39;SP500&#39;, 1, now(), now());<br>insert into bank.holding values (1002, 3, &#39;SP500&#39;, 1, now(), now());</pre><pre>-- U<br>update bank.holding set holding_quantity = 100 where holding_id=1000;</pre><pre>-- d<br>delete from bank.holding where user_id = 3;<br>delete from bank.holding where user_id = 2;</pre><pre>-- c<br>insert into bank.holding values (1003, 3, &#39;VTSAX&#39;, 100, now(), now());</pre><pre>-- u<br>update bank.holding set holding_quantity = 10 where holding_id=1003;</pre><p>Your output should be</p><pre>1000,1,holding_stock,None,VFIAX,1589121006547486,None,None,2020-05-10-10-31-23,c<br>1000,1,holding_quantity,None,10,1589121006547486,None,None,2020-05-10-10-31-23,c<br>1001,2,holding_stock,None,SP500,1589121109691459,None,None,2020-05-10-10-31-50,c<br>1001,2,holding_quantity,None,1,1589121109691459,None,None,2020-05-10-10-31-50,c<br>1002,3,holding_stock,None,SP500,1589121109695248,None,None,2020-05-10-10-31-50,c<br>1002,3,holding_quantity,None,1,1589121109695248,None,None,2020-05-10-10-31-50,c<br>1000,1,holding_stock,VFIAX,VFIAX,None,1589121112732,None,2020-05-10-10-31-53,u<br>1000,1,holding_quantity,10,100,None,1589121112732,None,2020-05-10-10-31-53,u<br>1002,3,holding_stock,SP500,None,None,1589121116301,2020-05-10-10-31-56,d<br>1002,3,holding_quantity,1,None,None,1589121116301,2020-05-10-10-31-56,d<br>1001,2,holding_stock,SP500,None,None,1589121116303,2020-05-10-10-31-56,d<br>1001,2,holding_quantity,1,None,None,1589121116303,2020-05-10-10-31-56,d<br>1003,3,holding_stock,None,VTSAX,1589121119075024,None,None,2020-05-10-10-31-59,c<br>1003,3,holding_quantity,None,100,1589121119075024,None,None,2020-05-10-10-31-59,c<br>1003,3,holding_stock,VTSAX,VTSAX,None,1589121121916,None,2020-05-10-10-32-02,u<br>1003,3,holding_quantity,100,10,None,1589121121916,None,2020-05-10-10-32-02,u</pre><h3>Data Flow</h3><p>This represents how we use CDC pattern to capture changes from our application database, transform it into a different format without having an impact on the application performance or memory.</p><h4>Design Data Flow</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*5VPjC4QJxj6cABiD.png" /></figure><p>‍</p><h4>Docker commands</h4><pre># starting a pg instance<br>docker run -d --name postgres -p 5432:5432 -e POSTGRES_USER=start_data_engineer -e POSTGRES_PASSWORD=password debezium/postgres:12</pre><pre># bash into postgres instance<br>docker exec -ti postgres /bin/bash</pre><pre># zookeeper and kafka broker<br>docker run -d --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 debezium/zookeeper:1.1<br>docker run -d --name kafka -p 9092:9092 --link zookeeper:zookeeper debezium/kafka:1.1</pre><pre># Kafka connect<br>docker run -d --name connect -p 8083:8083 --link kafka:kafka --link postgres:postgres -e BOOTSTRAP_SERVERS=kafka:9092 -e GROUP_ID=sde_group -e CONFIG_STORAGE_TOPIC=sde_storage_topic -e OFFSET_STORAGE_TOPIC=sde_offset_topic debezium/connect:1.1</pre><pre># register debezium connector<br>curl -i -X POST -H &quot;Accept:application/json&quot; -H &quot;Content-Type:application/json&quot; localhost:8083/connectors/ -d &#39;{&quot;name&quot;: &quot;sde-connector&quot;, &quot;config&quot;: {&quot;connector.class&quot;: &quot;io.debezium.connector.postgresql.PostgresConnector&quot;, &quot;database.hostname&quot;: &quot;postgres&quot;, &quot;database.port&quot;: &quot;5432&quot;, &quot;database.user&quot;: &quot;start_data_engineer&quot;, &quot;database.password&quot;: &quot;password&quot;, &quot;database.dbname&quot; : &quot;start_data_engineer&quot;, &quot;database.server.name&quot;: &quot;bankserver1&quot;, &quot;table.whitelist&quot;: &quot;bank.holding&quot;}}&#39;</pre><pre># sample consumer<br>docker run -it --rm --name consumer --link zookeeper:zookeeper --link kafka:kafka debezium/kafka:1.1 watch-topic -a bankserver1.bank.holding --max-messages 1 | grep &#39;^{&#39;</pre><pre># stream consumer, parse it and write to file<br>docker run -it --rm --name consumer --link zookeeper:zookeeper --link kafka:kafka debezium/kafka:1.1 watch-topic -a bankserver1.bank.holding | grep --line-buffered &#39;^{&#39; | &lt;your-file-path&gt;/stream.py &gt; &lt;your-output-path&gt;/holding_pivot.txt</pre><h3>Stop Docker containers</h3><p>You can stop and remove your docker containers using the following commands</p><pre>docker stop $(docker ps -aq)<br>docker rm $(docker ps -aq)</pre><pre>docker stop &lt;your-container-name&gt; # to stop and remove specific container<br>docker rm &lt;your-container-name&gt;</pre><h3>Things to be aware off</h3><ol><li>We have seen data changed but not data schema changes, depending on your use case this can get extremely tricky.</li><li>You need postgres version 9.4 or higher.</li><li>WAL configurations need to be set carefully to prevent overloading the database.</li><li>As with most distributed systems, there are multiple points of failure, for e.g the database could crash, kafka cluster could crash, your consumer may crash, etc. Always plan for failures and have recovery mechanisms to handle these issues.</li><li>Both kafka and debezium offers atleast once event delivery guarantee. This is very good, but your consumer or user have to be designed to deal with duplicates. A good approach for this would be to use upsert based data ingestion on the consumer side.</li></ol><h3>Conclusion</h3><p>Hope this post gives you an idea of what change data capture is, when you use it, how to implement it using debezium and common pitfalls to be aware of. Let me know if you have any questions in the comment section below.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=359f7bc6b29a" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/change-data-capture-with-debezium-kafka-and-mysql-359f7bc6b29a">Change Data Capture with Debezium Kafka and MySQL</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dockerized  Flask Celery RabbitMQ Redis Application]]></title>
            <link>https://levelup.gitconnected.com/dockerized-flask-celery-rabbitmq-redis-application-df74c837a0a1?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/df74c837a0a1</guid>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Thu, 04 Nov 2021 04:19:19 GMT</pubDate>
            <atom:updated>2021-11-04T04:19:19.674Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jSKd2tBYO5Ui09dc.gif" /></figure><p>This explains how to configure Flask, Celery, RabbitMQ, and Redis, together with Docker to build a web service that dynamically uploads the content and loads this content when it is ready to be displayed. We’ll focus mainly on Celery and the services that surround it. Docker is a bit more straightforward.</p><p>A Video Explanation</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FZxVpsClqjdw%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DZxVpsClqjdw&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FZxVpsClqjdw%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/9c9dce5f5fb1597496e6d36e43233736/href">https://medium.com/media/9c9dce5f5fb1597496e6d36e43233736/href</a></iframe><h3>Project Structure</h3><p>The finished project structure will be as follows:</p><pre>├── Dockerfile<br>├── docker-compose.yml<br>├── README.md<br>├── app<br>│ ├── app.py<br>│ ├── tasks.py<br>│ └── templates<br>│ ├── download.html<br>│ └── index.html<br>├── scripts<br>│ ├── run_celery.sh<br>│ └── run_web.sh<br>└── requirements.txt</pre><h3>Creating the Flask application 🌶</h3><p>First, we create a folder for our app. For this example, our folder is called `app`. Within this folder, create an `app.py` file and an empty folder named `templates` where our HTML templates will be stored.</p><p>For our app, we first include some basic Flask libraries and create an instance of the app:</p><pre>from io import BytesIO<br>from flask import Flask, request<br>from flask import render_template, make_response<br>APP = Flask(__name__)</pre><p>We define three routes for Flask to implement: a landing page, a secondary page that embeds and image, and a route for the image itself. Our image route crops an image dynamically. For this example, it crops an image using `pillow`, and some delays are also included so that the time taken to create the image is more apparent.</p><pre><a href="http://twitter.com/APP">@APP</a>.route(‘/’)<br>def index():<br>   return render_template(‘index.html’)<br><a href="http://twitter.com/APP">@APP</a>.route(‘/image_page’)<br>def image_page():<br>   job = tasks.get_data_from_strava.delay()<br>   return render_template(‘home.html’)<br><a href="http://twitter.com/APP">@APP</a>.route(&#39;/result.png&#39;)<br>def result():<br>   &#39;&#39;&#39;<br>   Pull our generated .png binary from redis and return it<br>   &#39;&#39;&#39;<br>   jobid = request.values.get(&#39;jobid&#39;)<br>   if jobid:<br>      job = tasks.get_job(jobid)<br>      png_output = job.get()<br>      png_output=&quot;../&quot;+png_output<br>      return png_output<br>   else:<br>      return 404</pre><p>Next, we need to open our `templates` folder and create the following two templates:</p><p><strong>index.html</strong></p><pre>&lt;div id=”imgpl”&gt;&lt;img src=”result.png?{{JOBID}}” /&gt;&lt;/div&gt;</pre><p>If we add the following code then run the script, we can load up our webpage and test the image generation.</p><pre>if __name__ == ‘__main__’:<br>   APP.run(host=’0.0.0.0&#39;)</pre><p>We see that our page load takes a while to complete because the request to `result.png` doesn’t return until the image generation has completed.</p><h3>Expanding our web app to use Celery 🥬</h3><p>In our `app` directory, create the `tasks.py` file that will contain our Celery tasks. We add the necessary Celery includes:</p><pre>from celery import Celery, current_task<br>from celery.result import AsyncResult</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/583/0*zgZtNf7st25A-BGL.png" /></figure><p>Assuming that our RabbitMQ service is on a host that we can reference by `rabbit` and our Redis service is on a host referred to by `Redis` we can create an instance of Celery using the following:</p><pre>REDIS_URL = ‘redis://redis:6379/0’<br>BROKER_URL = ‘amqp://admin:mypass@rabbit//’CELERY = Celery(‘tasks’,backend=REDIS_URL,broker=BROKER_URL)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/914/0*X9b0N6YlQyUixyb0.png" /></figure><p>We then need to change the default serializer for results. Celery with versions 4.0 and above use JSON as a serializer, which doesn’t support serialization of binary data. We can either switch back to the old default serializer (pickle) or use the newer MessagePack which supports binary data and is very efficient.</p><p>Since we’re changing the serializer, we also need to tell Celery to accept the results from a non-default serializer (as well as still accepting those from JSON).</p><pre>CELERY.conf.accept_content = [‘json’, ‘msgpack’]<br>CELERY.conf.result_serializer = ‘msgpack’</pre><p>First, we’ll implement a function that returns jobs given an ID. This allows our app and the Celery tasks to talk to each other:</p><pre>def get_job(job_id):<br> return AsyncResult(job_id, app=CELERY)</pre><p>Next, we define the asynchronous function and move the image generation code from `app.py` and add the function decorator that allows the method to be queued for execution:</p><pre><a href="http://twitter.com/CELERY">@CELERY</a>.task()<br>def image_demension(img):<br>   time.sleep(2)<br>   im = Image.open(img)<br>   width, height = im.size<br>   left = 4<br>   top = height / 5<br>   right = 154<br>   bottom = 3 * height / 5<br>   # Cropped image of above dimension \<br>   im1 = im.crop((left, top, right, bottom))<br>   newsize = (300, 300)<br>   im1 = im1.resize(newsize)<br>   width, height = im1.size<br>   location=os.path.join(‘static/worker-img’,’cropped_img.’+im.format.lower())<br>    im1.save(os.path.join(‘static/worker-img’,’cropped_img.’+im.format.lower()))<br>   print(width,height)<br>   print(“pass”)<br>   return location</pre><p>Instead of building a response, we return the binary image which will be stored on Redis. We also update the task at various points with a progress indicator that can be queried from the Flask app.</p><p>We add a new route to `app.py` that checks the progress and returns the state as a JSON object so that we can write an ajax function that our client can query before loading the final image when it’s ready.</p><pre><a href="http://twitter.com/APP">@APP</a>.route(‘/progress’)<br>def progress():<br>   jobid = request.values.get(‘jobid’)<br>   if jobid:<br>   job = tasks.get_job(jobid)<br>   if job.state == ‘PROGRESS’:<br>   return json.dumps(dict(<br>      state=job.state,<br>      progress=job.result[‘current’],<br>   ))<br>   elif job.state == ‘SUCCESS’:<br>   return json.dumps(dict( <br>      state=job.state,<br>      progress=1.0,<br>   ))<br>return ‘{}’</pre><p>Extend our `templates/download.html` with the following Javascript code:</p><pre>&lt;script src=”//code.jquery.com/jquery-2.1.1.min.js”&gt;&lt;/script&gt;<br>&lt;script&gt;<br>function poll() {<br>   $.ajax(“{{url_for(‘.progress’, jobid=JOBID)}}”, {<br>      dataType: “json”<br>     , success: function(resp) {<br>     if(resp.progress &gt;= 0.99) {<br>         $(“#wrapper”).html(‘’);<br>         $.get(“result.png?jobid={{JOBID}}”, function(data, status){<br>            end_file=data;  <br>            $(“#imgpl”).html(‘&lt;img src=’+end_file+’&gt;’);<br>            console.log(“success”)<br>          });<br>      return;<br>     }<br>     else {<br>        setTimeout(poll, 500.0);  <br>     }<br>   } <br>  });<br>}<br>$(function() {<br>   var JOBID = “{{ JOBID }}”;<br>   poll();<br>});<br>&lt;/script&gt;</pre><p>The `poll` function repeatedly requires the `/progress` route of our web app. When it reports that the image has been generated, it replaces the HTML code within the placeholder with the URL of the image, which is then loaded dynamically from our modified `/result.png` route:</p><pre><a href="http://twitter.com/APP">@APP</a>.route(‘/result.png’)<br>def result():<br>‘’’<br>Pull our generated .png and return it<br>‘’’<br>   jobid = request.values.get(‘jobid’)<br>   if jobid:<br>   job = tasks.get_job(jobid)<br>   png_output = job.get()<br>   png_output=”../”+png_output<br>   return png_output<br>   else:<br>   return 404</pre><p>At this stage, we have a working web app with asynchronous image generation.</p><p>Using Docker to package our application 🐳</p><p>Our app requires 4 separate containers for each of our services:</p><p>- Flask</p><p>- Celery</p><p>- RabbitMQ 🐇</p><p>- Redis</p><p>Docker provides prebuilt containers for [RabbitMQ](https://hub.docker.com/_/rabbitmq/) and [Redis](https://hub.docker.com/_/redis/). These both work well, and we’ll use them as is.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/915/0*VndYfGSp_b-fyCFH.png" /></figure><p>For Flask and Celery, we’ll build two identical containers from a simple `Dockerfile`.</p><p>Dockerfile</p><pre># Pull the latest version of the Python container.<br>FROM python:latest<br># Add the requirements.txt file to the image.<br>ADD requirements.txt /app/requirements.txt<br># Set the working directory to /app/.<br>WORKDIR /app/<br># Install Python dependencies.<br>RUN pip install -r requirements.txt<br># Create an unprivileged user for running our Python code.<br>RUN adduser — disabled-password — gecos ‘’ app</pre><p>We pull all of this together with a Docker compose file, `docker-sdfcompose.yml`. While early versions composing one needed to expose ports for each service, we can link the services together using the `links` keyword. The `depends` keyword ensures that all of our services start in the correct order.</p><p>docker-compose.yaml</p><pre>version: &#39;3&#39;<br>services:<br>  redis:<br>    image: redis:latest<br>    hostname: redis<br>  rabbit:<br>    hostname: rabbit<br>    image: rabbitmq:latest<br>    environment:<br>      - RABBITMQ_DEFAULT_USER=admin<br>      - RABBITMQ_DEFAULT_PASS=mypass<br>  web:<br>    build:<br>      context: .<br>      dockerfile: Dockerfile<br>    hostname: web<br>    command: ./scripts/run_web.sh<br>    volumes:<br>      - .:/app<br>    ports:<br>      - &quot;5000:5000&quot;<br>    links:<br>      - rabbit<br>      - redis<br>  worker:<br>    build:<br>      context: .<br>      dockerfile: Dockerfile<br>    command: ./scripts/run_celery.sh<br>    volumes:<br>      - .:/app<br>    links:<br>      - rabbit<br>      - redis<br>    depends_on:<br>      - rabbit</pre><p>To create and run the container, use:</p><pre>docker-compose builddocker-compose up</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/0*IL2cdYjlrjPo1wRd.png" /></figure><p>One of the major benefits of Docker is that we can run multiple instances of a container if required. To run multiple instances of our Celery consumers, do:</p><p>docker-compose scale worker=N</p><p>where N is the desired number of backend worker nodes. Visit <a href="http://localhost:5000/">http://localhost:5000</a> to view our complete application. 🥳</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/0*L7NnGj2-GjiPn79m.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/0*hmIoltx693On20BL.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/0*Uqj0pCFJ0QcCA2PM.png" /></figure><h3>Github 🧟</h3><p><a href="https://github.com/alvisf/Dockerized-Flask-Celery-RabbitMQ-Redis">alvisf/Dockerized-Flask-Celery-RabbitMQ-Redis</a></p><h3>Conclusion 🤝</h3><p>This is a simple POC on how to use everything together and get the async function up and running.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=df74c837a0a1" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/dockerized-flask-celery-rabbitmq-redis-application-df74c837a0a1">Dockerized 🐳 Flask Celery RabbitMQ Redis Application</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Setup SSH between Jenkins and Github]]></title>
            <link>https://levelup.gitconnected.com/setup-ssh-between-jenkins-and-github-e4d7d226b271?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/e4d7d226b271</guid>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Thu, 14 Oct 2021 14:06:54 GMT</pubDate>
            <atom:updated>2021-10-14T14:06:54.716Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/558/0*-glKKNMDf0w8I_cJ.png" /></figure><p>In this story, you will learn how to set up SSH between <a href="https://www.jenkins.io/">Jenkins</a> and <a href="https://github.com/">Github</a>. Using this approach, you do not need to provide your credentials to configure the git repo in your Jenkins job, and you will achieve the password-less connection</p><p>Recently other methods have been deprecated for security reasons, and this is the new standard.</p><h3>Steps</h3><ol><li>Generate the SSH keys</li><li>Copy the public key in Github</li><li>Configure in Jenkins Credentials</li><li>Configure a sample job in Jenkins using SSH connection</li></ol><h3>Configure Jenkins user</h3><p>Generate the ssh keys and ensure the ssh-agent is running</p><pre>ssh-keygen<br>sudo eval $(sudo ssh-agent -s)<br>ssh-add ~/.ssh/id_rsa</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GwQfgZsHyJ5KGnTm.png" /></figure><p>An SSH key is generated successfully and allows you to achieve the password-less connection between Jenkins and Github</p><p>Copy the public key using the below command (or where ever your ‘.ssh’ folder is and copy the key)</p><p>cat /home/ubuntu/.ssh/id_rsa.pub</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/688/0*ar_I4-SdwwLi_iiq.png" /></figure><h3>Github Configuration</h3><p>Go to GitHub repository -&gt; setting -&gt; add deploy keys</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*k-_QvRJHy7aJSaHj.png" /></figure><h3>Configure Jenkins Credentials</h3><p>Now we will configure the private key of the jenkins user in the Jenkins configuration</p><h3>Add SSH Key inside Jenkins</h3><ul><li>Login to Jenkins</li><li>Now go to Manage Jenkins from the left panel inside the Jenkins console and then click Manage Credentials:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FjXBTQWnDJxdH0kg.png" /></figure><p>After this, select ‘Add Credentials’. This will open a new form for us. In the dropdown, select ‘SSH username with private key’ and then give a name for it.</p><p>Copy the private key from the Jenkins server.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1tMG_iHQCJzrWezi.png" /></figure><p>Now you can clone any git repo in this Jenkins instance. You do not need to provide the credentials while configuring the job in Jenkins.</p><p>Configure Jenkins Job</p><ul><li>Create a freestyle job in Jenkins</li><li>Configure SSH URL of your git repo</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jvPesLlsH1FUhVuK" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/898/0*74mEbIoD9dZinG8m" /></figure><h3>Conclusion:</h3><p>We have successfully set up SSH between Jenkins and Github for achieving a passwordless connection. Using this approach, you do not need to provide your credentials to configure the git repo in your Jenkins job.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e4d7d226b271" width="1" height="1" alt=""><hr><p><a href="https://levelup.gitconnected.com/setup-ssh-between-jenkins-and-github-e4d7d226b271">Setup SSH between Jenkins and Github</a> was originally published in <a href="https://levelup.gitconnected.com">Level Up Coding</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploy a Flask App in Kubernetes ]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/deploy-a-flask-app-in-kubernetes-f3e12100de9a?source=rss-bd0d74873629------2"><img src="https://cdn-images-1.medium.com/max/1708/0*6sIHgq-YOWhhO9wN.png" width="1708"></a></p><p class="medium-feed-snippet">An Ingress is an API object that defines rules which allow external access to services in a cluster. An Ingress controller fulfills the&#x2026;</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/deploy-a-flask-app-in-kubernetes-f3e12100de9a?source=rss-bd0d74873629------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/deploy-a-flask-app-in-kubernetes-f3e12100de9a?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/f3e12100de9a</guid>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Thu, 14 Oct 2021 14:06:27 GMT</pubDate>
            <atom:updated>2021-10-14T14:06:27.292Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Expand AWS EBS with Zero Downtime]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/expand-aws-ebs-with-zero-downtime-197469b34cf7?source=rss-bd0d74873629------2"><img src="https://cdn-images-1.medium.com/max/1500/0*06Fpfo5eDW2TmY0Y.jpeg" width="1500"></a></p><p class="medium-feed-snippet">This can be applied whenever you need to extend your EBS volume size avoiding stopping the instance and detach the volume.</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/expand-aws-ebs-with-zero-downtime-197469b34cf7?source=rss-bd0d74873629------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/expand-aws-ebs-with-zero-downtime-197469b34cf7?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/197469b34cf7</guid>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Tue, 14 Sep 2021 23:44:06 GMT</pubDate>
            <atom:updated>2021-09-14T23:44:06.106Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[How to Mount S3 Bucket on an EC2 Linux Instance]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://levelup.gitconnected.com/how-to-mount-s3-bucket-on-an-ec2-linux-instance-df44c7885aae?source=rss-bd0d74873629------2"><img src="https://cdn-images-1.medium.com/max/1200/0*QeblyzeIpgFnz8Ho.png" width="1200"></a></p><p class="medium-feed-snippet">We will Mount S3 as the file system for the EC2 instance.</p><p class="medium-feed-link"><a href="https://levelup.gitconnected.com/how-to-mount-s3-bucket-on-an-ec2-linux-instance-df44c7885aae?source=rss-bd0d74873629------2">Continue reading on Level Up Coding »</a></p></div>]]></description>
            <link>https://levelup.gitconnected.com/how-to-mount-s3-bucket-on-an-ec2-linux-instance-df44c7885aae?source=rss-bd0d74873629------2</link>
            <guid isPermaLink="false">https://medium.com/p/df44c7885aae</guid>
            <dc:creator><![CDATA[Alvis F]]></dc:creator>
            <pubDate>Wed, 11 Aug 2021 01:06:48 GMT</pubDate>
            <atom:updated>2021-08-11T01:06:48.551Z</atom:updated>
        </item>
    </channel>
</rss>