<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Site Reliability Engineer Blog</title><link>https://vorozhko.net/</link><description>Recent content on Site Reliability Engineer Blog</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Fri, 23 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://vorozhko.net/index.xml" rel="self" type="application/rss+xml"/><item><title>Projects &amp; Open Source</title><link>https://vorozhko.net/projects/</link><pubDate>Fri, 23 Oct 2026 00:00:00 +0000</pubDate><guid>https://vorozhko.net/projects/</guid><description>&lt;p&gt;A curated catalog of open-source projects, cloud reliability guides, architectural experiments, and upstream contributions. Source code and activity are hosted on &lt;a href="https://github.com/vorozhko"&gt;GitHub: @vorozhko&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Uses</title><link>https://vorozhko.net/uses/</link><pubDate>Fri, 23 Oct 2026 00:00:00 +0000</pubDate><guid>https://vorozhko.net/uses/</guid><description>&lt;p&gt;A breakdown of the physical hardware, terminal cockpit, Kubernetes &amp;amp; IaC tooling, agentic workflows, and daily software I rely on for Site Reliability Engineering, platform architecture, and software development. Inspired by &lt;a href="https://uses.tech/"&gt;uses.tech&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Books I Read</title><link>https://vorozhko.net/books/</link><pubDate>Tue, 20 Oct 2026 00:00:00 +0000</pubDate><guid>https://vorozhko.net/books/</guid><description>&lt;p&gt;Books from my &lt;a href="https://www.goodreads.com"&gt;Goodreads&lt;/a&gt; &amp;ldquo;read&amp;rdquo; shelf.&lt;/p&gt;</description></item><item><title>How to recognize Great Work</title><link>https://vorozhko.net/posts/how-to-recognize-great-work/</link><pubDate>Sun, 27 Sep 2026 10:47:37 +0000</pubDate><guid>https://vorozhko.net/posts/how-to-recognize-great-work/</guid><description>&lt;p&gt;Evaluating performance isn’t about tracking hours or micromanaging, it’s about looking at two simple things: &lt;strong&gt;What you deliver&lt;/strong&gt; and &lt;strong&gt;How you work with the team&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;p&gt;Both matter equally. Delivering great results with a toxic attitude doesn’t work, and being super friendly without ever finishing tasks doesn’t work either.&lt;/p&gt;&#10;&lt;p&gt;Here is what defines great results:&lt;/p&gt;&#10;&lt;h3 id="1-great-outcome-the-what"&gt;1. Great Outcome (The “What”)&lt;/h3&gt;&#10;&lt;p&gt;Great outcomes mean delivering work above expectations without causing headaches down the line.&lt;/p&gt;</description></item><item><title>Bullet proofing Agentic Engineering</title><link>https://vorozhko.net/posts/bullet-proofing-agentic-engineering/</link><pubDate>Thu, 04 Jun 2026 13:47:25 +0000</pubDate><guid>https://vorozhko.net/posts/bullet-proofing-agentic-engineering/</guid><description>&lt;p&gt;I’m in the same boat as a lot of engineering teams right now: most of my code is agent-written, and there is no human capacity to review all of it line by line. That leaves two choices, and neither is a good choice:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Wait for human review&lt;/strong&gt; — and fall behind on delivery.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Merge without review&lt;/strong&gt; — and quietly lower the quality bar.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;So at McMakler we picked a third option: stop reviewing the code, and start building the machine that reviews it for us. Back to the drawing board to design a CI/CD system that &lt;em&gt;guarantees&lt;/em&gt; every change clears a minimum quality baseline — without a human reading every diff.&lt;/p&gt;</description></item><item><title>About</title><link>https://vorozhko.net/about/</link><pubDate>Thu, 01 Jan 2026 00:00:00 +0000</pubDate><guid>https://vorozhko.net/about/</guid><description>&lt;h2 id="what-i-care-about"&gt;What I care about&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;People:&lt;/strong&gt; I use RFCs, OKRs, Kanban and Scrum when they help, and I make continuous learning part of the job.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Reliability:&lt;/strong&gt; Service level objectives and error budgets let engineers and the business talk about risk in the same language.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Automation:&lt;/strong&gt; If I do something by hand twice, I automate it. If the automation breaks, I fix it.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Security:&lt;/strong&gt; It has to be there at every level: cloud, cluster, container and application code. That means access control, secrets management, multi-tenancy and a tested incident process.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Platforms:&lt;/strong&gt; Infrastructure as code, GitOps and CI/CD let teams test in ephemeral preview environments and ship with confidence.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;AI with guardrails:&lt;/strong&gt; AI makes teams faster, but only when there are real tests and checks behind it.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="experience"&gt;Experience&lt;/h2&gt;&#10;&lt;h3 id="2020--present--mcmakler"&gt;2020 – present · McMakler&lt;/h3&gt;&#10;&lt;p&gt;McMakler is the story of building a strong team and a strong platform. I lead the DevOps team. We run the Kubernetes platform on Google Cloud and AWS, observability, incident management, CI/CD and databases. Along the way my technical direction formed the platform which now supports hundred of services and many Merge requests a day to get build and deployed with the help of AI.&lt;/p&gt;</description></item><item><title>Improving Team Performance Measurement: A DORA and SLO/SLI Approach</title><link>https://vorozhko.net/posts/improving-team-performance-measurement-a-dora-and-slo-sli-approach/</link><pubDate>Sun, 16 Nov 2025 14:55:56 +0000</pubDate><guid>https://vorozhko.net/posts/improving-team-performance-measurement-a-dora-and-slo-sli-approach/</guid><description>&lt;p&gt;As a &lt;strong&gt;DevOps manager&lt;/strong&gt;, measuring your team’s performance and impact is crucial for guiding the &lt;strong&gt;next year’s roadmap&lt;/strong&gt;. By applying proven practices like the &lt;strong&gt;DORA research&lt;/strong&gt; combined with &lt;strong&gt;SRE tools&lt;/strong&gt; such as &lt;strong&gt;SLOs (Service Level Objectives)&lt;/strong&gt; and &lt;strong&gt;SLIs (Service Level Indicators)&lt;/strong&gt;, you can design a highly practical approach to team performance evaluation.&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h3 id="dora-and-slosli-practices"&gt;DORA and SLO/SLI Practices&lt;/h3&gt;&#10;&lt;p&gt;There are several frameworks which can guide you through measuring team performance, but I prefer DORA research paired with SLO/SLI and Error Budgets due to their simplicity and practical application.&lt;/p&gt;</description></item><item><title>The Reality of Self-Hosting AI model for Code Suggestions</title><link>https://vorozhko.net/posts/the-reality-of-self-hosting-ai-model-for-code-suggestions/</link><pubDate>Thu, 30 Oct 2025 18:28:51 +0000</pubDate><guid>https://vorozhko.net/posts/the-reality-of-self-hosting-ai-model-for-code-suggestions/</guid><description>&lt;p&gt;Recently I had a pleasure to test self-hosted AI model with RAG support for code suggestion task. Results as most predicted: &lt;strong&gt;the cost/performance ratio for small teams are still in favors of proprietary solutions.&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;Here’s a breakdown of the hardware, quality, and cost realities for teams considering open-source Large Language Models (LLMs) with Retrieval Augmented Generation (RAG) support.&lt;/p&gt;&#10;&lt;h2 id="-the-high-cost-of-the-free-model"&gt;💸 The High Cost of the &amp;ldquo;Free&amp;rdquo; Model&lt;/h2&gt;&#10;&lt;p&gt;While the models themselves (like Qwen or Mistral) are open-source, the Total Cost of Ownership (TCO) for the required infrastructure quickly escalates, making small, self-hosted LLMs surprisingly inefficient.&lt;/p&gt;</description></item><item><title>Kubernetes operators quick start</title><link>https://vorozhko.net/posts/kubernetes-operators-quick-start/</link><pubDate>Sun, 11 May 2025 11:13:54 +0000</pubDate><guid>https://vorozhko.net/posts/kubernetes-operators-quick-start/</guid><description>&lt;p&gt;Kubernetes operator provide easy and simple way to extend Kubernetes cluster with additional functionality.&lt;/p&gt;&#10;&lt;p&gt;For example you might find that you need custom operator in areas like:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Managing stateful applications: take any Database, Message Queue or Cache as example, it needs full lifecycle of operations to be good for production. For a long time running databases in Kubernetes was an anti-pattern, but with operators things started to changed.&lt;/li&gt;&#10;&lt;li&gt;Automating Application Lifecycle Management: the complexity of making new application can be overwhelmed for your development teams, so why not to introduce something more simple with just few core fields which are shared between all applications.&lt;/li&gt;&#10;&lt;li&gt;Enhancing Observability: operators like Prometheus operator or Alermanager hides complexity of managing these tools and provide simple interface to get started quick.&lt;/li&gt;&#10;&lt;li&gt;Automated Backup, Restore, and Disaster Recovery: For stateful applications, operators can automate the process of taking regular backups, storing them securely, and orchestrating the restoration process in case of data loss or system failure.&lt;/li&gt;&#10;&lt;li&gt;CI/CD and GitOps Automation: operators play crucial role in GitOps workflow. Tools like the Pulumi Kubernetes Operator enable managing infrastructure alongside Kubernetes workloads.&lt;/li&gt;&#10;&lt;li&gt;Networking and Security Management: Operators for service meshes like Istio or Linkerd simplify their installation, configuration, and upgrades across the cluster.&lt;/li&gt;&#10;&lt;li&gt;Building Platform-as-a-Service (PaaS)-like Capabilities: By abstracting away underlying Kubernetes resources, operators can provide a simplified, application-centric interface for developers, similar to what a PaaS offers.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="writing-your-own-operator"&gt;Writing your own operator&lt;/h2&gt;&#10;&lt;p&gt;If you think to get started to write your own operator it&amp;rsquo;s good to know what any operator consist of:&lt;/p&gt;</description></item><item><title>Solving Top-K problem - Leaderboard in Python</title><link>https://vorozhko.net/posts/solving-top-k-problem-leaderboard-in-python/</link><pubDate>Mon, 21 Apr 2025 15:38:24 +0000</pubDate><guid>https://vorozhko.net/posts/solving-top-k-problem-leaderboard-in-python/</guid><description>&lt;h3 id="what-is-top-k-problem"&gt;What is Top-K problem?&lt;/h3&gt;&#10;&lt;p&gt;Think about Real-time Gaming Leaderboard with a rank system. Determining the rank of a player is a problem we are trying to solve.&#10;This is implementation of Real-time Leaderboard solution from the System Design interview book.&#10;Check out full source code at &lt;a href="https://github.com/vorozhko/Leaderboard-Top-K-problem"&gt;Leaderboard - solving Top K Problem with Python&lt;/a&gt; Github project.&lt;/p&gt;&#10;&lt;h3 id="leader-board-requirements"&gt;Leader board requirements&lt;/h3&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Get top 10 ranked players&lt;/li&gt;&#10;&lt;li&gt;Show a current rank for each player&lt;/li&gt;&#10;&lt;li&gt;Show a slice of players around specific rank&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="solution-1-using-sql-database"&gt;Solution 1: using SQL database&lt;/h3&gt;&#10;&lt;p&gt;Direct approach is to use SQL kind of database and count rank in real time using &lt;code&gt;count&lt;/code&gt; until Player score points &amp;gt;= all other players. This solution fall short as soon as we need to scale it for high number of players.&lt;/p&gt;</description></item><item><title>LLM-Powered Unit Testing: Effortlessly Generate Domain Model Data</title><link>https://vorozhko.net/posts/llm-powered-unit-testing-effortlessly-generate-domain-model-data/</link><pubDate>Sat, 05 Apr 2025 13:49:32 +0000</pubDate><guid>https://vorozhko.net/posts/llm-powered-unit-testing-effortlessly-generate-domain-model-data/</guid><description>&lt;p&gt;Traditional approaches to generating model data for unit tests often involve setting up complex fixtures or writing cumbersome mock classes. This becomes especially challenging when your domain model is tightly coupled with your data mode.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Order&lt;/span&gt;(Base):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; product_name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Column(String, index&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; quantity &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Column(Integer)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In more advanced scenarios, your Domain model is decoupled from the Data model, allowing for cleaner architecture and improved maintainability.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Order&lt;/span&gt;(BaseModel):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; product_name: str&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; quantity: int&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;testOrder&lt;/span&gt;(self):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; order &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Order(product_name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Milk&amp;#34;&lt;/span&gt;, quantity&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; self&lt;span style="color:#f92672"&gt;.&lt;/span&gt;assertEqual(order&lt;span style="color:#f92672"&gt;.&lt;/span&gt;quantity, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using hard-coded data can be a sub-optimal approach. Every modification to the Domain model requires updates to the test suite.&lt;/p&gt;</description></item><item><title>🚀 Supercharge Your Python Code Reviews: Automate with GPT and OpenAPI Endpoints</title><link>https://vorozhko.net/posts/supercharge-your-python-code-reviews-automate-with-gpt-and-openapi-endpoints/</link><pubDate>Sat, 29 Mar 2025 20:00:03 +0000</pubDate><guid>https://vorozhko.net/posts/supercharge-your-python-code-reviews-automate-with-gpt-and-openapi-endpoints/</guid><description>&lt;p&gt;A common approach to getting code reviews with ChatGPT is by posting a prompt along with a code snippet. While effective, this process can be time-consuming and repetitive. If you want to streamline, customize, or fully automate your code review process, meet &lt;a href="https://github.com/gptscript-ai/gptscript"&gt;gptscript&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Gptscript is a powerful automation tool designed to build tools of any complexity on top of GPT models.&lt;/p&gt;&#10;&lt;p&gt;At the core of gptscript is a script defining a series of steps to execute, along with available tools such as Git operations, file reading, web scraping, and more.&lt;/p&gt;</description></item><item><title>Tech Team Leaders' Guide to Strategy</title><link>https://vorozhko.net/posts/tech-team-leaders-guide-to-strategy/</link><pubDate>Mon, 24 Mar 2025 16:28:25 +0000</pubDate><guid>https://vorozhko.net/posts/tech-team-leaders-guide-to-strategy/</guid><description>&lt;p&gt;Building a tech strategy is a core responsibility of the CTO, VP of Engineering, or Head of Engineering. Involving team leaders in this process ensures a more grounded and effective approach.&lt;/p&gt;&#10;&lt;p&gt;Tech team leaders play a crucial role by defining roadmaps for their teams, which, in turn, provide the foundation for an effective high-level strategy. To achieve the best results, continuous collaboration between leadership and team leaders is essential.&lt;/p&gt;&#10;&lt;p&gt;Let’s explore how to create a roadmap that is both practical and aligned with the company’s overall vision.&lt;/p&gt;</description></item><item><title>Collecting Datadog APM traces using Grafana Alloy and Tempo</title><link>https://vorozhko.net/posts/collecting-datadog-apm-traces-using-grafana-alloy-and-tempo/</link><pubDate>Thu, 20 Mar 2025 20:29:16 +0000</pubDate><guid>https://vorozhko.net/posts/collecting-datadog-apm-traces-using-grafana-alloy-and-tempo/</guid><description>&lt;h3 id="the-problem"&gt;The Problem&lt;/h3&gt;&#10;&lt;p&gt;Hybrid cloud is the future, but monitoring remains stuck in the past. Many organizations embrace hybrid infrastructure, yet struggle with fragmented observability tools. Why? Because monitoring providers still operate in silos.&lt;/p&gt;&#10;&lt;p&gt;One of the primary reasons hybrid monitoring isn’t as prevalent is the challenge of instrumentation. Many cloud providers offer their own monitoring solutions. Instrumentation libraries are often incompatible with one another, making cross-platform integration difficult.&lt;/p&gt;&#10;&lt;p&gt;The good news? With &lt;strong&gt;OpenTelemetry, Grafana, and Datadog&lt;/strong&gt;, hybrid monitoring is becoming easier and more flexible. 🚀&lt;/p&gt;</description></item><item><title>Cost saving strategy for Kubernetes platform</title><link>https://vorozhko.net/posts/cost-saving-strategy-for-kubernetes-platform/</link><pubDate>Mon, 17 Mar 2025 19:17:54 +0000</pubDate><guid>https://vorozhko.net/posts/cost-saving-strategy-for-kubernetes-platform/</guid><description>&lt;p&gt;Working on cost saving strategy involves looking at the problem from very different dimensions.&#10;Overall Kubernetes costs can be split on compute costs, networking costs, storage costs, licensing cost and SaaS costs.&#10;In this part I will cover: &lt;strong&gt;Right-size infrastructure &amp;amp; use autoscaling&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h2 id="right-size-infrastructure--use-autoscaling"&gt;&lt;strong&gt;Right-size infrastructure &amp;amp; use autoscaling&lt;/strong&gt;&lt;/h2&gt;&#10;&lt;h3 id="kubernetes-nodes-autoscaler"&gt;Kubernetes &lt;strong&gt;Nodes autoscaler&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p&gt;In a cloud environment Kubernetes &lt;strong&gt;Nodes autoscaler&lt;/strong&gt; plays important role in delivering just enough resources for your cluster. In a nutshell:&lt;/p&gt;</description></item><item><title>Multi provider DNS management with Terraform and Pulumi</title><link>https://vorozhko.net/posts/multi-provider-dns-management-with-terraform-and-pulumi/</link><pubDate>Tue, 04 Mar 2025 14:04:58 +0000</pubDate><guid>https://vorozhko.net/posts/multi-provider-dns-management-with-terraform-and-pulumi/</guid><description>&lt;h3 id="the-problem"&gt;The Problem&lt;/h3&gt;&#10;&lt;p&gt;Every DNS provider is very specific how they create DNS records. Using Terraform or Pulumi don&amp;rsquo;t guarantee multi provider support out of the box.&lt;/p&gt;&#10;&lt;p&gt;One example where AWS Route53 support values for multiple IP binding to the same name record. Where Cloudflare must have a dedicated record for each IP.&lt;/p&gt;&#10;&lt;p&gt;Theses API difference make it harder to write code which will work for multiple providers.&lt;/p&gt;&#10;&lt;p&gt;For AWS Route53 a single record can be created like this:&lt;/p&gt;</description></item><item><title>Grafana a new look</title><link>https://vorozhko.net/posts/grafana-a-new-look/</link><pubDate>Fri, 24 Jan 2025 19:59:06 +0000</pubDate><guid>https://vorozhko.net/posts/grafana-a-new-look/</guid><description>&lt;p&gt;As much as l like managed monitoring solutions it’s hard not to be excited about setting up your own platform based on Prometheus Grafana stack and save some bucks for the company.&lt;/p&gt;&#10;&lt;p&gt;After 5 years of using proprietary solutions I am again on the way to get into Grafana world.&lt;/p&gt;&#10;&lt;p&gt;Here I want to wrap up what I learnt so far about Grafana.&lt;/p&gt;&#10;&lt;h2 id="big-ecosystem-of-tools"&gt;Big ecosystem of tools&lt;/h2&gt;&#10;&lt;p&gt;The biggest change for me is ecosystem of projects which supports almost all imaginable monitoring needs.&lt;/p&gt;</description></item><item><title>Can ArgoCD replace Helm managers?</title><link>https://vorozhko.net/posts/can-argocd-replace-helm-managers/</link><pubDate>Sat, 30 Sep 2023 13:24:24 +0000</pubDate><guid>https://vorozhko.net/posts/can-argocd-replace-helm-managers/</guid><description>&lt;p&gt;&lt;a href="https://argo-cd.readthedocs.io/en/stable/"&gt;ArgoCD&lt;/a&gt;is a tool which provides GitOps way of deployment. It supports various format of applications including Helm charts.&lt;/p&gt;&#10;&lt;p&gt;Helm is one of the most popular packaging format for Kubernetes applications. It give a rise to various tools to manage helm chart like helmfiles, helmify and others.&lt;/p&gt;&#10;&lt;h3 id="why-argocd-is-replacing-helm-managers"&gt;Why ArgoCD is replacing Helm managers?&lt;/h3&gt;&#10;&lt;p&gt;For a long time Helm managers help to deploy Helm charts via different deploy strategies. It serves well, but the big disadvantage was a code drift which accumulate over time.&lt;/p&gt;</description></item><item><title>Path to Staff Engineer role</title><link>https://vorozhko.net/posts/the-path-to-staff-engineer-role/</link><pubDate>Sat, 16 Sep 2023 14:20:08 +0000</pubDate><guid>https://vorozhko.net/posts/the-path-to-staff-engineer-role/</guid><description>&lt;p&gt;Someday in your career you take your time to think what&amp;rsquo;s next for me? What is my next challenge to grow in a career ladder? If your answer is Staff Engineer, Tech lead, Team lead or Principal Engineer then you are on the way to Staff-plus Engineer role.&lt;/p&gt;&#10;&lt;p&gt;As a Staff-plus Engineer myself I want to share my few tips for you.&lt;/p&gt;&#10;&lt;h3 id="start-working-on-staff-engineer-package"&gt;Start working on Staff engineer package&lt;/h3&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;What&amp;rsquo;s your Staff level project? * What did you do and what was impact? * What behavior did you demonstrate and how complex projects were?&lt;/li&gt;&#10;&lt;li&gt;Link your Design Documents, RFCs and Proposals to support your package with your design and architecture contribution.&lt;/li&gt;&#10;&lt;li&gt;Can you quantify the impact of your projects? * Did it helps to increase revenue? * Save costs?&lt;/li&gt;&#10;&lt;li&gt;What glue work did you do to organization? * What&amp;rsquo;s the impact of the glue work?&lt;/li&gt;&#10;&lt;li&gt;Who have you mentored and through what accomplishments?&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="sharpen-your-soft-skills"&gt;Sharpen your soft skills&lt;/h3&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Communication. * Keep people informed and connected.&lt;/li&gt;&#10;&lt;li&gt;Negotiation * Be ready to resolve difficult situations&lt;/li&gt;&#10;&lt;li&gt;Presentation * Know your audience. Learn one or two presentation frameworks.&lt;/li&gt;&#10;&lt;li&gt;Networking * Don&amp;rsquo;t be shame to get in touch with other Staff-plus engineers in your company. * They are the best people to help you navigate the role inside the company.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="learn-staff-engineer-tools"&gt;Learn Staff Engineer tools&lt;/h3&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Leadership * Become a problem &lt;em&gt;&lt;strong&gt;solver&lt;/strong&gt;&lt;/em&gt;. Be a visionary in your area. Stay up to date with technologies in your area.&lt;/li&gt;&#10;&lt;li&gt;Planning and Goal orientation * Have a vision of what you do next in one or another area. * Take active participate on Planning meetings.&lt;/li&gt;&#10;&lt;li&gt;Collaboration and contribution * Propose new Decision docs, Proposals and RFCs. Make sure they are reviewed and discussed. * Implement POC to demo the idea out.&lt;/li&gt;&#10;&lt;li&gt;Team work and mentorship * Help your peers. Be a problem solver. Be visible. Become a go to person. * Try on a mentorship role.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="summary"&gt;Summary&lt;/h3&gt;&#10;&lt;p&gt;Getting Staff engineer role could take months or years to accomplish. However, it&amp;rsquo;s crucial to view this milestone not as the ultimate destination, but rather as a guiding roadmap for your career development. It&amp;rsquo;s not the title itself that holds the most significance, but rather the daily challenge we face and the positive impact we make as we progress in our journey.&lt;/p&gt;</description></item><item><title>Certified Kubernetes Administrator</title><link>https://vorozhko.net/posts/certified-kubernetes-administrator/</link><pubDate>Sat, 17 Apr 2021 13:21:08 +0000</pubDate><guid>https://vorozhko.net/posts/certified-kubernetes-administrator/</guid><description>&lt;p&gt;The CKA exam was a real challenge and great experience over all.&lt;/p&gt;&#10;&lt;p&gt;My first impression now I am officially part of Kubernetes world and CNCF.&lt;/p&gt;&#10;&lt;p&gt;But, I just love Kubernetes and it&amp;rsquo;s eco-system of open source projects and I had a lot of fun during my preparation and CKA exam. When you combine work with fun you can achieve really great results.&lt;/p&gt;&#10;&lt;p&gt;My advise for all future CKA participants is to have 80% of real Kubernetes practice and other 20% you can learn along the exam year.&lt;/p&gt;</description></item><item><title>Implementing RED method with Istio</title><link>https://vorozhko.net/posts/implementing-red-method-with-istio/</link><pubDate>Wed, 08 Jul 2020 09:20:02 +0000</pubDate><guid>https://vorozhko.net/posts/implementing-red-method-with-istio/</guid><description>&lt;p&gt;In this article I describe how to quickly get started with SLO and SLI practice using Istio. if you are new SLO and SLI read a &lt;a href="https://vorozhko.net/posts/brief-summary-of-site-reliability-engineering-best-practices/"&gt;Brief Summary of SRE best practices&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="red-or-rate-errors-duration"&gt;RED or Rate Errors Duration&lt;/h2&gt;&#10;&lt;p&gt;The RED method is an easy to understand monitoring methodology. For every service, monitor:&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Rate&lt;/strong&gt; - how many operations per second is placed on a service&#10;&lt;strong&gt;Errors&lt;/strong&gt; - what percentage of the traffic return in error state&#10;&lt;strong&gt;Duration&lt;/strong&gt; - the time it take to serve a request or process a job&lt;/p&gt;</description></item><item><title>Brief Summary of Site Reliability Engineering best practices</title><link>https://vorozhko.net/posts/brief-summary-of-site-reliability-engineering-best-practices/</link><pubDate>Fri, 26 Jun 2020 12:31:40 +0000</pubDate><guid>https://vorozhko.net/posts/brief-summary-of-site-reliability-engineering-best-practices/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;The goal of SRE is to accelerate product development teams and keep services running in reliable and continuous way.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;This article is a collection practical notes on explaining what is SRE, what kind of work SREs does and what type of processes they develop. The practices are based on Google SRE workbook.&lt;/p&gt;&#10;&lt;p&gt;This is a long article and If you will make it to the end I applaud to you!&lt;/p&gt;</description></item><item><title>Simple LRU cache implementation on Python 3</title><link>https://vorozhko.net/posts/simple-lru-cache-implementation-on-python-3/</link><pubDate>Wed, 24 Jun 2020 15:22:21 +0000</pubDate><guid>https://vorozhko.net/posts/simple-lru-cache-implementation-on-python-3/</guid><description>&lt;h2 id="what-is-lru-cache"&gt;What is LRU Cache?&lt;/h2&gt;&#10;&lt;p&gt;This is caching item replacement policy, so the least used items will be discarded first.&lt;/p&gt;&#10;&lt;h2 id="problem"&gt;Problem&lt;/h2&gt;&#10;&lt;p&gt;The LRU Cache algorithm requires keeping track of what was used when, which is expensive if one wants to make sure the algorithm always discards the least recently used item.&lt;/p&gt;&#10;&lt;h2 id="solution"&gt;Solution&lt;/h2&gt;&#10;&lt;p&gt;Approaching a problem I was thinking of two capabilities for data structures: a FIFO queue and Hash table.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;FIFO queue&lt;/strong&gt; will be responsible to evict least used items. &lt;strong&gt;Hash table&lt;/strong&gt; will be responsible to get cached items. Using this data structures make both operations in O(1) time complexity.&lt;/p&gt;</description></item><item><title>Filebeats configuration for Kubernetes</title><link>https://vorozhko.net/posts/filebeats-configuration-for-kubernetes/</link><pubDate>Mon, 08 Jun 2020 14:30:46 +0000</pubDate><guid>https://vorozhko.net/posts/filebeats-configuration-for-kubernetes/</guid><description>&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;filebeat.autodiscover&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;providers&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;kubernetes&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;node&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${NODE_NAME}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hints.enabled&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hints.default_config&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;container&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;paths&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;/var/log/containers/*${data.kubernetes.container.id}.log&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="whats-so-cool-about-above-configuration"&gt;What&amp;rsquo;s so cool about above configuration&lt;/h2&gt;&#10;&lt;h3 id="filebeat-autodiscover"&gt;Filebeat Autodiscover&lt;/h3&gt;&#10;&lt;p&gt;When you run applications on containers, they become moving targets to the monitoring system. Autodiscover allows you to track them and adapt settings as changes happen.&lt;/p&gt;&#10;&lt;p&gt;The &lt;strong&gt;Kubernetes autodiscover&lt;/strong&gt; provider watches for Kubernetes nodes, pods, services to start, update, and stop.&#10;As well it recognise a lot of additional labels and statuses related to Kubernetes objects.&lt;/p&gt;</description></item><item><title>Integrating Flask with Jaeger tracing on Kuberentes</title><link>https://vorozhko.net/posts/integrating-flask-with-jaeger-tracing-on-kuberentes/</link><pubDate>Sat, 06 Jun 2020 08:40:00 +0000</pubDate><guid>https://vorozhko.net/posts/integrating-flask-with-jaeger-tracing-on-kuberentes/</guid><description>&lt;p&gt;Distributed applications and microservices required high level of observability. In this article we will integrate a Flask micro framework with Jaeger tracing tool. All code will be deployed to Kubernetes minikube cluster.&lt;/p&gt;&#10;&lt;h2 id="flask"&gt;Flask&lt;/h2&gt;&#10;&lt;p&gt;Let&amp;rsquo;s build a simple task manager service using Flask framework.&lt;/p&gt;&#10;&lt;h3 id="code"&gt;Code&lt;/h3&gt;&#10;&lt;p&gt;tasks.py&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; flask &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Flask, jsonify&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Flask(__name__)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@app.route&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tasks &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;tasks&amp;#34;&lt;/span&gt;:[&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;task 1&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;uri&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;/task1&amp;#34;&lt;/span&gt;},&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;task 2&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;uri&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;/task2&amp;#34;&lt;/span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;root&lt;/span&gt;():&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;Service root&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; jsonify({&lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;:&lt;span style="color:#e6db74"&gt;&amp;#34;/tasks&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@app.route&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/tasks&amp;#39;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;tasks&lt;/span&gt;():&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;Tasks list&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; jsonify(tasks)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; __name__ &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Start up&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run(debug&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;True&lt;/span&gt;, host&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;,port&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5000&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have skipped other CRUD operations for simplicity.&lt;/p&gt;</description></item><item><title>Backup and restore of Etcd cluster</title><link>https://vorozhko.net/posts/backup-and-restore-of-etcd-cluster/</link><pubDate>Wed, 20 May 2020 09:13:30 +0000</pubDate><guid>https://vorozhko.net/posts/backup-and-restore-of-etcd-cluster/</guid><description>&lt;p&gt;Kubernetes disaster recovery plan is usually consist of backing up etcd cluster and having infrastructure as a code to provision new set of servers in the cloud. Let&amp;rsquo;s see how to do first - backup etcd in two basic and easy ways.&lt;/p&gt;&#10;&lt;h2 id="etcd-backup"&gt;Etcd backup&lt;/h2&gt;&#10;&lt;p&gt;The only stateful component of Kubernetes cluster is etcd server. The etcd server is where Kuberenetes store all API objects and configuration.&#10;Backing up this storage is sufficient for complete recovery of Kubernetes cluster state.&lt;/p&gt;</description></item><item><title>Having fun with Kubernetes deployment</title><link>https://vorozhko.net/posts/having-fun-with-kubernetes-deployments/</link><pubDate>Tue, 19 May 2020 12:43:09 +0000</pubDate><guid>https://vorozhko.net/posts/having-fun-with-kubernetes-deployments/</guid><description>&lt;h2 id="install-deployment"&gt;&lt;strong&gt;Install deployment&lt;/strong&gt;&lt;/h2&gt;&#10;&lt;h3 id="install-nginx-1122-with-2-pods"&gt;&lt;strong&gt;Install nginx 1.12.2 with 2 pods&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;p&gt;If you need to have 2 pods from the start then it could be done in three easy steps:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Create deployment template with nginx version 1.12.2&lt;/li&gt;&#10;&lt;li&gt;Edit nginx.yaml to update replicas count.&lt;/li&gt;&#10;&lt;li&gt;Apply deployment template to Kubernetes cluster&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# step 1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl create deployment nginx --save-config&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true --image&lt;span style="color:#f92672"&gt;=&lt;/span&gt;nginx:1.12.2 --dry-run&lt;span style="color:#f92672"&gt;=&lt;/span&gt;client -o yaml &amp;gt; nginx.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# step 2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;edit nginx.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# step 3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl apply --record&lt;span style="color:#f92672"&gt;=&lt;/span&gt;true -f nginx.yaml&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice use of &lt;code&gt;--record=true&lt;/code&gt; to save the state of what caused the deployment change&lt;/p&gt;</description></item><item><title>How to check Kubernetes cluster health?</title><link>https://vorozhko.net/posts/how-to-check-kubernetes-cluster-health/</link><pubDate>Mon, 18 May 2020 07:30:36 +0000</pubDate><guid>https://vorozhko.net/posts/how-to-check-kubernetes-cluster-health/</guid><description>&lt;p&gt;There are some essential tools to have a quick look at Kubernetes cluster health. Let&amp;rsquo;s review them here. As a result you would be able quickly tell if cluster has any obvious issues.&lt;/p&gt;&#10;&lt;h2 id="install-node-problem-detector"&gt;Install node problem detector&lt;/h2&gt;&#10;&lt;p&gt;node-problem-detector aims to make various node problems visible to the upstream layers in cluster management stack. It is a daemon which runs on each node, detects node problems and reports them to apiserver.&lt;/p&gt;</description></item><item><title>Multi node Kubernetes cluster on Vagrant</title><link>https://vorozhko.net/posts/multi-node-kubernetes-cluster-on-vagrant/</link><pubDate>Sun, 17 May 2020 19:43:50 +0000</pubDate><guid>https://vorozhko.net/posts/multi-node-kubernetes-cluster-on-vagrant/</guid><description>&lt;p&gt;This is fast and easy way to install Kubernetes on Vagrant with Metrics server addon.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git clone https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd vagrant/kubernetes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant up&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this point you would have one master node and two worker nodes ready.&lt;/p&gt;&#10;&lt;p&gt;Lets check cluster health&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vagrant ssh master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get nodes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NAME STATUS ROLES AGE VERSION&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;master Ready master 2m46s v1.18.2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;worker1 Ready &amp;lt;none&amp;gt; 35s v1.18.2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;worker2 Ready &amp;lt;none&amp;gt; 32s v1.18.2&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All nodes are ready.&lt;/p&gt;</description></item><item><title>Build Kubernetes control plane image with Packer</title><link>https://vorozhko.net/posts/build-kubernetes-control-plane-image-with-packer/</link><pubDate>Fri, 08 May 2020 12:20:25 +0000</pubDate><guid>https://vorozhko.net/posts/build-kubernetes-control-plane-image-with-packer/</guid><description>&lt;p&gt;Steps to prepare single control plane image is quite simple:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Prepare Docker and Kubernetes packages and settings&lt;/li&gt;&#10;&lt;li&gt;Execute kubeadm bootstrap script when EC2 start up first time&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;One unanswered question is: &lt;strong&gt;How to add additional control plane nodes and worker nodes which required tokens and certificates to be preset when joining the cluster?&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h2 id="packer-builders"&gt;Packer builders&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;Builders&lt;/strong&gt; section define base image, EC2 instate type and other settings to build an image.&lt;/p&gt;</description></item><item><title>Practical guide to Kubernetes Certified Administration exam</title><link>https://vorozhko.net/posts/practical-guide-to-kubernetes-certified-administration-exam/</link><pubDate>Mon, 27 Apr 2020 13:39:41 +0000</pubDate><guid>https://vorozhko.net/posts/practical-guide-to-kubernetes-certified-administration-exam/</guid><description>&lt;p&gt;I have published practical guide to Kubernetes Certified Administration exam &lt;a href="https://t.co/E9kmX6Ndyj?amp=1"&gt;https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2 id="covered-topics-so-far-are"&gt;Covered topics so far are:&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam/blob/master/kubeadm/single-control-plane/README.md"&gt;Kubernetes Single control plane with Kubeadm&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam/blob/master/kubeadm/ha-control-plane/README.md"&gt;Configure High Available Kubernetes cluster&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam/blob/master/kubeadm/upgrade-cluster/README.md"&gt;Upgrade Kubernetes cluster&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam/blob/master/guides/secure-cluster-communications.md"&gt;Configure secure cluster communications&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam/blob/master/apps/nginx/README.md"&gt;Testing Kubernetes AWS LoadBalancer with http/https, access logs and connection draining&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/vorozhko/practical-guide-to-kubernetes-administration-exam/blob/master/security/podsecuritypolicy/README.md"&gt;Container security with PodSecurityPolicy&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;and more to come&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="share-your-efforts"&gt;Share your efforts&lt;/h2&gt;&#10;&lt;p&gt;If your are also working on preparation to Kubernetes Certified Administration exam lets combine our efforts by sharing the practical side of exam.&lt;/p&gt;</description></item><item><title>Disaster recovery of single node Kubernetes control plane</title><link>https://vorozhko.net/posts/disaster-recovery-of-single-node-kubernetes-control-plane/</link><pubDate>Tue, 21 Apr 2020 05:42:31 +0000</pubDate><guid>https://vorozhko.net/posts/disaster-recovery-of-single-node-kubernetes-control-plane/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;&#10;&lt;p&gt;There are many possible root causes why control plane might become unavailable. Lets review most common scenarios and mitigation steps.&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;Mitigation steps in this article build around AWS public cloud features, but all popular public cloud offerings have similar functionality.&lt;/em&gt;&lt;/p&gt;&#10;&lt;h2 id="apiserver-vm-shutdown-or-apiserver-crashing"&gt;Apiserver VM shutdown or apiserver crashing&lt;/h2&gt;&#10;&lt;h3 id="results"&gt;Results&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;unable to stop, update, or start new pods, services, replication controller&lt;/li&gt;&#10;&lt;li&gt;existing pods and services should continue to work normally, unless they depend on the Kubernetes API&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="mitigations"&gt;Mitigations&lt;/h3&gt;&#10;&lt;h4 id="in-case-of-apiserver-crash"&gt;In case of apiserver crash&lt;/h4&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Apiserver is a POD, so it&amp;rsquo;s responsibility of kubelet to restart the pod.&lt;/li&gt;&#10;&lt;li&gt;Kubelet itself is monitored by systemd which will restart kubelet in case of failure.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4 id="in-case-of-vm-shutdown"&gt;In case of VM shutdown&lt;/h4&gt;&#10;&lt;p&gt;AWS Cloudwatch approach based on instance status check:&lt;/p&gt;</description></item><item><title>Thoughts on High available Kubernetes cluster with single control plane node</title><link>https://vorozhko.net/posts/high-available-kubernetes-cluster-with-single-control-plane-node/</link><pubDate>Thu, 16 Apr 2020 06:03:44 +0000</pubDate><guid>https://vorozhko.net/posts/high-available-kubernetes-cluster-with-single-control-plane-node/</guid><description>&lt;h2 id="why-single-node-control-plane"&gt;Why single node control plane?&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;Benefits are:&lt;/strong&gt;&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Monitoring and alerting are simple and on point. It reduce the number of false positive alerts.&lt;/li&gt;&#10;&lt;li&gt;Setup and maintenance are quick and straightforward. Less complex install process lead to more robust setup.&lt;/li&gt;&#10;&lt;li&gt;Disaster recovery and recovery documentation are more clear and shorter.&lt;/li&gt;&#10;&lt;li&gt;Application will continue to work even if Kubernetes control plane is down.&lt;/li&gt;&#10;&lt;li&gt;Multiple worker nodes and multiple deployment replicas will provide necessary high availability for your applications.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;Disadvantages are:&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Go http middleware chain with context package</title><link>https://vorozhko.net/posts/go-http-middleware-chain-with-context-package/</link><pubDate>Sat, 14 Dec 2019 20:44:43 +0000</pubDate><guid>https://vorozhko.net/posts/go-http-middleware-chain-with-context-package/</guid><description>&lt;p&gt;Middleware is a function which wrap http.Handler to do pre or post processing of the request.&lt;/p&gt;&#10;&lt;p&gt;Chain of middleware is popular pattern in handling http requests in go languge. Using a chain we can:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Log application requests&lt;/li&gt;&#10;&lt;li&gt;Rate limit requests&lt;/li&gt;&#10;&lt;li&gt;Set HTTP security headers&lt;/li&gt;&#10;&lt;li&gt;and more&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Go context package help to setup communication between middleware handlers.&lt;/p&gt;&#10;&lt;h2 id="implementation"&gt;Implementation&lt;/h2&gt;&#10;&lt;h4 id="middleware-chain"&gt;Middleware chain&lt;/h4&gt;&#10;&lt;p&gt;To compose handlers into a chain I choose &lt;a href="https://github.com/justinas/alice"&gt;Alice&lt;/a&gt;package which implement logic of looping through middleware functions.&lt;/p&gt;</description></item><item><title>How to enable minikube kvm2 driver on Ubuntu 18.04</title><link>https://vorozhko.net/posts/how-to-enable-minikube-kvm2-driver-on-ubuntu-18-04/</link><pubDate>Tue, 10 Dec 2019 13:09:43 +0000</pubDate><guid>https://vorozhko.net/posts/how-to-enable-minikube-kvm2-driver-on-ubuntu-18-04/</guid><description>&lt;h2 id="verify-kvm2-support"&gt;Verify kvm2 support&lt;/h2&gt;&#10;&lt;h4 id="confirm-virtualization-support-by-cpu"&gt;Confirm virtualization support by CPU&lt;/h4&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; egrep -c ‘(svm|vmx)’ /proc/cpuinfo&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An output of 1 or more indicate that CPU can use virtualization technology.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo kvm-ok&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Output &amp;ldquo;KVM acceleration can be used. &amp;quot; indicate that the system has virtualization enabled and KVM can be used.&lt;/p&gt;&#10;&lt;h4 id="install-kvm-packages"&gt;&lt;strong&gt;Install kvm packages&lt;/strong&gt;&lt;/h4&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sudo apt-get install qemu-kvm libvirt-bin bridge-utils virt-manager&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="start-libvirtd-service"&gt;&lt;strong&gt;Start libvirtd service&lt;/strong&gt;&lt;/h4&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sudo service libvirtd start&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="add-your-user-to-libvirt-and-kvm-group"&gt;Add your user to libvirt and kvm group&lt;/h4&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo adduser &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;id -un&lt;span style="color:#e6db74"&gt;`&lt;/span&gt; libvirt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo adduser &lt;span style="color:#e6db74"&gt;`&lt;/span&gt;id -un&lt;span style="color:#e6db74"&gt;`&lt;/span&gt; kvm&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and re-login the user&lt;/p&gt;</description></item><item><title>Istio sidecar injection</title><link>https://vorozhko.net/posts/istio-sidecar-injection/</link><pubDate>Sun, 22 Sep 2019 13:38:44 +0000</pubDate><guid>https://vorozhko.net/posts/istio-sidecar-injection/</guid><description>&lt;p&gt;There are several ways to inject istio sidecar configuration into Pods. For example: automated injection, YAML/JSON deployment update, using Helm or Kustomize and update of existing live deployment. We will look into each of them.&lt;/p&gt;&#10;&lt;h3 id="automatic-sidecar-injection"&gt;Automatic Sidecar injection&lt;/h3&gt;&#10;&lt;p&gt;Istio uses &lt;em&gt;ValidatingAdmissionWebhooks&lt;/em&gt; for validating Istio configuration and &lt;em&gt;MutatingAdmissionWebhooks&lt;/em&gt; for automatically injecting the sidecar proxy into user pods.&lt;/p&gt;&#10;&lt;p&gt;For automatic side car injection to work &lt;em&gt;admissionregistration.k8s.io/v1beta1&lt;/em&gt; should be enabled:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ kubectl api-versions | grep admissionregistration.k8s.io/v1beta1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;admissionregistration.k8s.io/v1beta1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Step two is to verify &lt;em&gt;MutatingAdmissionWebhook&lt;/em&gt; and &lt;em&gt;ValidatingAdmissionWebhook&lt;/em&gt; plugins are listed in the kube-apiserver &amp;ndash;enable-admission-plugins. That can be done by cluster administrators.&lt;/p&gt;</description></item><item><title>How to organize Namespaces in Kubernetes</title><link>https://vorozhko.net/posts/how-to-organize-namespaces-in-kubernetes/</link><pubDate>Sat, 14 Sep 2019 13:27:44 +0000</pubDate><guid>https://vorozhko.net/posts/how-to-organize-namespaces-in-kubernetes/</guid><description>&lt;p&gt;There are two main objectives:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;Users are able to do their job with the highest velocity possible&lt;/li&gt;&#10;&lt;li&gt;Users organized by groups in multi tenant setup&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="multi-tenancy"&gt;Multi tenancy&lt;/h2&gt;&#10;&lt;p&gt;Kubernetes namespaces help to setup boundaries between groups of users and applications in a cluster.&#10;To make it more pleasant and secure for your users to work in shared cluster Kubernetes has a number of policies and controls.&lt;/p&gt;&#10;&lt;h3 id="access-policies"&gt;Access policies&lt;/h3&gt;&#10;&lt;p&gt;&lt;strong&gt;RBAC&lt;/strong&gt; primary objective is authorize users and applications to do specific operations in the namespace or in whole cluster. Use RBAC to give your users enough permissions in the namespace, so they can do day to day operations on their own.&#10;&lt;strong&gt;Network Policy&lt;/strong&gt; control how pods can communicate with each other. Use it to firewall traffic between namespaces or inside namespace to critical components like Databases.&lt;/p&gt;</description></item><item><title>120 Days of AWS EKS in Staging</title><link>https://vorozhko.net/posts/120-days-of-aws-eks-kubernetes-in-staging/</link><pubDate>Sun, 03 Feb 2019 15:08:11 +0000</pubDate><guid>https://vorozhko.net/posts/120-days-of-aws-eks-kubernetes-in-staging/</guid><description>&lt;p&gt;My journey with Kubernetes started with Google Kubernetes Engine then one year later with self managed kuberntes and then with migration to Amazon EKS.&lt;/p&gt;&#10;&lt;p&gt;EKS as a managed kubernetes cluster is not 100% managed. Core tools didn&amp;rsquo;t work as expcted. Customers expectation was not aligned with functions provided. Here I have summarized all our experience we gained by running EKS cluster in Staging.&lt;/p&gt;&#10;&lt;p&gt;To run EKS you still have to:&lt;/p&gt;</description></item><item><title>Production Readiness Checklist</title><link>https://vorozhko.net/posts/production-readiness-checklist/</link><pubDate>Fri, 18 Jan 2019 17:00:01 +0000</pubDate><guid>https://vorozhko.net/posts/production-readiness-checklist/</guid><description>&lt;p&gt;In bookmarks - &lt;a href="https://gruntwork.io/devops-checklist/"&gt;production readiness checklist&lt;/a&gt;.&#10;Very good job by Gruntwork !&lt;/p&gt;</description></item><item><title>Amazon EKS Workshop</title><link>https://vorozhko.net/posts/amazon-eks-workshop/</link><pubDate>Thu, 17 Jan 2019 17:00:32 +0000</pubDate><guid>https://vorozhko.net/posts/amazon-eks-workshop/</guid><description>&lt;p&gt;I really hesitated to post about&lt;a href="https://eksworkshop.com/"&gt;Amazon EKS workshop&lt;/a&gt;, but this one is really looking good and it is free and open source!&lt;/p&gt;&#10;&lt;p&gt;Going through workshop you will learn how:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Setup manager kubernetes cluster in AWS&lt;/li&gt;&#10;&lt;li&gt;Spin up services and deploy micro services&lt;/li&gt;&#10;&lt;li&gt;Autoscaling&lt;/li&gt;&#10;&lt;li&gt;Deployment with Helm charts&lt;/li&gt;&#10;&lt;li&gt;Continuous integration and continuous deployment&lt;/li&gt;&#10;&lt;li&gt;Monitoring and logging&lt;/li&gt;&#10;&lt;li&gt;Istio service mesh&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>First class incident response process</title><link>https://vorozhko.net/posts/first-class-incident-response-process/</link><pubDate>Wed, 16 Jan 2019 19:39:19 +0000</pubDate><guid>https://vorozhko.net/posts/first-class-incident-response-process/</guid><description>&lt;p&gt;If you don&amp;rsquo;t have incident response process the chances are that sooner than later you will need one.&lt;/p&gt;&#10;&lt;p&gt;To understand where to start check out this first class &lt;a href="https://response.pagerduty.com/"&gt;incident response process&lt;/a&gt; documentation. It cover:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;how to prepare to incident&lt;/li&gt;&#10;&lt;li&gt;what actions to take during incident&lt;/li&gt;&#10;&lt;li&gt;what are post incident steps&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>Kubernetes Ingress controllers - spreadsheet</title><link>https://vorozhko.net/posts/kubernetes-ingress-controllers-spreadsheet/</link><pubDate>Fri, 11 Jan 2019 19:00:21 +0000</pubDate><guid>https://vorozhko.net/posts/kubernetes-ingress-controllers-spreadsheet/</guid><description>&lt;p&gt;Nice &lt;a href="https://docs.google.com/spreadsheets/d/16bxRgpO1H_Bn-5xVZ1WrR_I-0A-GOI6egmhvqqLMOmg/edit?usp=sharing"&gt;spreadsheet&lt;/a&gt;of all types of ingress controllers available for Kubernetes. Details are very well explained in Steven Acreman &lt;a href="https://kubedex.com/ingress/"&gt;post&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Serve a golang web application over HTTPS in one line</title><link>https://vorozhko.net/posts/serve-a-golang-web-application-over-https-in-one-line/</link><pubDate>Thu, 10 Jan 2019 20:00:13 +0000</pubDate><guid>https://vorozhko.net/posts/serve-a-golang-web-application-over-https-in-one-line/</guid><description>&lt;p&gt;This is next level of dealing with certificates. Great job by Matt Hold and open source community on Certmagic module.&lt;/p&gt;&#10;&lt;p&gt;Read his &lt;a href="https://twitter.com/mholt6/status/1073103807809085440"&gt;twitter thread&lt;/a&gt; on the subject.&lt;/p&gt;</description></item><item><title>AWS Transit Gateway to Simplify Your Network Architecture</title><link>https://vorozhko.net/posts/new-aws-transit-gateway/</link><pubDate>Wed, 09 Jan 2019 21:00:40 +0000</pubDate><guid>https://vorozhko.net/posts/new-aws-transit-gateway/</guid><description>&lt;p&gt;This is how your network architecture probably looks now&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2019/01/transit_gateway_before.png" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;this is how it can be with Transit Gateway&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2019/01/transit_gateway_after.png" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;Transit gateway was one of the missing peaces to full fill network administration needs.&lt;/p&gt;</description></item><item><title>Amazon EKS IAM based authentication explained</title><link>https://vorozhko.net/posts/eks-iam-based-authentication-explained/</link><pubDate>Tue, 08 Jan 2019 20:26:39 +0000</pubDate><guid>https://vorozhko.net/posts/eks-iam-based-authentication-explained/</guid><description>&lt;h2 id="one-image-worth-1000-words"&gt;One image worth 1000 words!&lt;/h2&gt;&#10;&lt;p&gt;Read &lt;a href="https://itnext.io/how-does-client-authentication-work-on-amazon-eks-c4f2b90d943b"&gt;full article&lt;/a&gt; by Daniel Weibel on how authentication and authorization works on amazon EKS.&lt;/p&gt;</description></item><item><title>Terraform remote state and state locking</title><link>https://vorozhko.net/posts/terraform-remote-state-locking/</link><pubDate>Sun, 05 Aug 2018 09:56:17 +0000</pubDate><guid>https://vorozhko.net/posts/terraform-remote-state-locking/</guid><description>&lt;p&gt;Terraform remote state and state locking is important part in team collaboration. What are challenges when working on Terraform in a team:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;how to synchronize terraform state between people&lt;/li&gt;&#10;&lt;li&gt;how to avoid collisions of running terraform at the same time&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="terraform-remote-state"&gt;Terraform remote state&lt;/h2&gt;&#10;&lt;p&gt;Terraform remote state is a mechanism to share state file by hosting it on a shared resource like aws s3 bucket or consul server.&lt;/p&gt;&#10;&lt;p&gt;Example of storing state in s3 bucket.&lt;/p&gt;</description></item><item><title>AWS best practices for Lambda functions in Production</title><link>https://vorozhko.net/posts/aws-best-practices-for-lambda-functions-in-production/</link><pubDate>Mon, 16 Apr 2018 20:17:26 +0000</pubDate><guid>https://vorozhko.net/posts/aws-best-practices-for-lambda-functions-in-production/</guid><description>&lt;p&gt;Hey folks,&lt;/p&gt;&#10;&lt;p&gt;just a month ago I have been involved in AWS project based on Lambda functions. In this article I will explain what I learned so far and how to create production Lambda AWS environment with best practices in mind.&lt;/p&gt;&#10;&lt;p&gt;I will start from top level and will explain everything you need to have basic infrastructure supporting your Lambda functions and other applications in your cloud.&lt;/p&gt;&#10;&lt;h4 id="vpc"&gt;VPC&lt;/h4&gt;&#10;&lt;p&gt;First, you need to created dedicated VPC and reserve range of IPs which doesn&amp;rsquo;t conflict with your other networks in case you would need to pair them together. As a general rule you should never use default VPC for production needs.&#10;Create a security group which only allow 80 and 443 incoming traffic.&lt;/p&gt;</description></item><item><title>Kubernetes sidecar pattern: nginx ssl proxy for nodejs</title><link>https://vorozhko.net/posts/kubernetes-sidecar-pattern-nginx-ssl-proxy-for-nodejs/</link><pubDate>Fri, 02 Mar 2018 10:34:20 +0000</pubDate><guid>https://vorozhko.net/posts/kubernetes-sidecar-pattern-nginx-ssl-proxy-for-nodejs/</guid><description>&lt;p&gt;I learn about sidecar pattern from Kubernetes documentation and later from blog post by Brendan Burns &lt;a href="http://blog.kubernetes.io/2015/06/the-distributed-system-toolkit-patterns.html"&gt;The distributed system toolkit&lt;/a&gt;. Sidecar is very useful pattern and work nice with Kubernetes.&lt;/p&gt;&#10;&lt;p&gt;In the tutorial I want to demonstrate how “legacy” application can be extend with https support by using sidecar pattern based on Kubernetes.&lt;/p&gt;&#10;&lt;h3 id="problem"&gt;Problem&lt;/h3&gt;&#10;&lt;p&gt;We have legacy application which doesn’t have HTTPS support. We also don’t want to send plain text traffic over network. We don’t want to make any changes to legacy application, but good thing that it is containerised.&lt;/p&gt;</description></item><item><title>Year 2017 in review</title><link>https://vorozhko.net/posts/year-2017-in-review/</link><pubDate>Sat, 20 Jan 2018 22:24:22 +0000</pubDate><guid>https://vorozhko.net/posts/year-2017-in-review/</guid><description>&lt;p&gt;My 2017 in pictures.&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/20170315_151534.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/20170318_135144.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;First time in UK, so unusual to hear English everywhere after 5 years in Germany :)&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/IMG_8169.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/IMG_8183.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/IMG_8226.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/IMG_8080.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/IMG_7815.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2018/01/20170508_221804.jpg" alt=""&gt;&lt;/p&gt;&#10;&lt;p&gt;Palma de Mallorca. For a May weather it was a great experience, I can&amp;rsquo;t imagine how good it is in summer. But, if you like me is a fun of active rest then May and June is the best time to go there.&lt;/p&gt;</description></item><item><title>calculating md5 sum using go lang</title><link>https://vorozhko.net/posts/calculating-md5-sum-using-go-lang/</link><pubDate>Mon, 18 Dec 2017 23:06:30 +0000</pubDate><guid>https://vorozhko.net/posts/calculating-md5-sum-using-go-lang/</guid><description>&lt;p&gt;Hi guys,&#10;this is day 18 out of 100 days of code.&lt;/p&gt;&#10;&lt;p&gt;To get md5 sum of a file you crypto/md5 library and io/ioutil for reading files.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;crypto/md5&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Args&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;expected filename as parameter&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;filename&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Args&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;filename&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;MD5 (%s) = %x\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;filename&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;md5&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sum&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Thanks!&lt;/p&gt;</description></item><item><title>Slow algorithm to insert strings into indexed file in alphabetical order</title><link>https://vorozhko.net/posts/slow-algorithm-to-insert-strings-into-indexed-file-in-alphabetical-order/</link><pubDate>Mon, 11 Dec 2017 18:00:26 +0000</pubDate><guid>https://vorozhko.net/posts/slow-algorithm-to-insert-strings-into-indexed-file-in-alphabetical-order/</guid><description>&lt;p&gt;Hi guys,&#10;this is day 17 out of 100 days of code in go lang.&lt;/p&gt;&#10;&lt;p&gt;Today I have played with files, sorting, bytes and strings. The goal was to create a kind of indexed file where all lines are arranged alphabetically.&#10;What I got is very slow algorithm which took 15 seconds to insert 10K strings in an empty file and 49 seconds to insert another 10K strings to the same file. So, it slowdown very quickly as size grow.&lt;/p&gt;</description></item><item><title>Random image file download with go</title><link>https://vorozhko.net/posts/random-image-file-download-with-go/</link><pubDate>Sun, 10 Dec 2017 13:31:38 +0000</pubDate><guid>https://vorozhko.net/posts/random-image-file-download-with-go/</guid><description>&lt;p&gt;Hi guys,&#10;this is day 16 out of 100 days of code.&lt;/p&gt;&#10;&lt;p&gt;With help of http and ioutil packages file download and storage is quite easy task.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://picsum.photos/200/300/?random&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;url&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Close&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;image&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadAll&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;WriteFile&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;./myimage.gif&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;image&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0644&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the example I am using &lt;a href="https://picsum.photos/"&gt;Lorem Picsum&lt;/a&gt; service to get random image every run.&lt;/p&gt;</description></item><item><title>Github issues reader in go lang</title><link>https://vorozhko.net/posts/github-issues-reader-in-go-lang/</link><pubDate>Sat, 09 Dec 2017 21:56:54 +0000</pubDate><guid>https://vorozhko.net/posts/github-issues-reader-in-go-lang/</guid><description>&lt;p&gt;Hi guys,&#10;this is day 15 out of 100 days of go land coding.&lt;/p&gt;&#10;&lt;p&gt;I continue github subject and today it is github issue reader. Example demonstrate how API results which come in json format convert into struct type.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;encoding/json&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;repo&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;repo&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;github owner/repo e.g. golang/go&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Int&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;issue id&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Parse&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;repo&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;--repo and --id parameters must be provided&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;issue&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;repo&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Print&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;issue&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Title&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// IssueData - specify data fields for new github issue submission&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IssueData&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;Title&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;title&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;body&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;read&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ownerRepo&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;) (&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;IssueData&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;apiURL&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;https://api.github.com/repos/%s/issues/%d&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ownerRepo&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;apiURL&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Close&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusCode&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusOK&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;IssueData&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NewDecoder&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;Decode&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Close&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Happy coding!&lt;/p&gt;</description></item><item><title>Create github issue ticket with golang</title><link>https://vorozhko.net/posts/create-github-issue-ticket-with-golang/</link><pubDate>Tue, 05 Dec 2017 22:43:45 +0000</pubDate><guid>https://vorozhko.net/posts/create-github-issue-ticket-with-golang/</guid><description>&lt;p&gt;Hi guys,&#10;today is day 14 out of 100 days of golang coding.&lt;/p&gt;&#10;&lt;p&gt;This time I was playing with &lt;a href="https://developer.github.com/v3/issues/#create-an-issue"&gt;github issues api&lt;/a&gt; and made small script which create new issues in given repository. However to use the code you would need to obtain github &lt;a href="https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/"&gt;personal token key&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;The interesting part was to make http post request with custom headers.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;encoding/json&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;token&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;github auth token&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;repo&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;repo&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;github owner/repo e.g. golang/go&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;title for new issue&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;body&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;body for new issue&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Parse&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;repo&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;--token, --repo and --title parameters must be provided&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;repo&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// NewIssue - specify data fields for new github issue submission&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NewIssue&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;Title&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;title&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;body&amp;#34;`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;create&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;ownerRepo&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;apiURL&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://api.github.com/repos/&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ownerRepo&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/issues&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//title is the only required field&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;issueData&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;NewIssue&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Title&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//make it json&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;jsonData&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Marshal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;issueData&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//creating client to set custom headers for Authorization&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;client&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Client&lt;/span&gt;{}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NewRequest&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;apiURL&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;bytes&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NewReader&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;jsonData&lt;/span&gt;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Header&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Set&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;token &amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;client&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Do&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Close&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusCode&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusCreated&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Response code is is %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StatusCode&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadAll&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//print body as it may contain hints in case of errors&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(string(&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Example usage is as follow:&lt;/p&gt;</description></item><item><title>github issue tracker with categories by date in go</title><link>https://vorozhko.net/posts/github-issue-tracker-with-categories-by-date-in-go/</link><pubDate>Mon, 04 Dec 2017 21:26:44 +0000</pubDate><guid>https://vorozhko.net/posts/github-issue-tracker-with-categories-by-date-in-go/</guid><description>&lt;p&gt;Hi guys,&#10;today is day 13 out of 100 days of code in go!&lt;/p&gt;&#10;&lt;p&gt;This time it is example of fetching issues from github and categorizing by created date.&#10;To run example you need to install github issue searcher package from The Go Progamming Language book&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go get gopl.io/ch4/github&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Full code&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;gopl.io/ch4/github&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;github&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;SearchIssues&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Args&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;:])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%d issues:\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TotalCount&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;dateformat&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Items&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;days&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; int(&lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Since&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;CreatedAt&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;Hours&lt;/span&gt;()) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;24&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;days&lt;/span&gt; &amp;lt; &lt;span style="color:#ae81ff"&gt;30&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;dateformat&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;less than a month old&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;days&lt;/span&gt; &amp;lt; &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;dateformat&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;less than a year old&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;dateformat&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;more than a year old&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s, #%-5d %9.9s %.55s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;dateformat&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Number&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;User&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Login&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;item&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Title&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Happy coding!&lt;/p&gt;</description></item><item><title>Sort map by it's keys in go</title><link>https://vorozhko.net/posts/sort-map-by-its-keys-in-go/</link><pubDate>Sun, 03 Dec 2017 12:46:12 +0000</pubDate><guid>https://vorozhko.net/posts/sort-map-by-its-keys-in-go/</guid><description>&lt;p&gt;Hi guys,&#10;this is day 12 out of 100 days of code. I didn&amp;rsquo;t post for a while, because I did a small break for hackaton, but now I am back on track.&lt;/p&gt;&#10;&lt;p&gt;When you print a map using range function it will access elements in randomized order. So, if you want to print map in sorted order you have to sort keys first. See how:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;sort&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;{&lt;span style="color:#e6db74"&gt;&amp;#34;A&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;B&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;AA&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;C&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;BBB&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//reverse keys and values of m map&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mapKeys&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Print&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Unsorted:\n&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s -&amp;gt; %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;mapKeys&lt;/span&gt; = append(&lt;span style="color:#a6e22e"&gt;mapKeys&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;sort&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Strings&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;mapKeys&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Print&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Sorted:\n&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;mapKeys&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s -&amp;gt; %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Solution is to use additional array for keys and sort it in wished order.&lt;/p&gt;</description></item><item><title>how to sort map values in go</title><link>https://vorozhko.net/posts/how-to-sort-map-values-in-go/</link><pubDate>Mon, 27 Nov 2017 22:57:20 +0000</pubDate><guid>https://vorozhko.net/posts/how-to-sort-map-values-in-go/</guid><description>&lt;p&gt;Hi guys,&#10;this is day 11 out of 100 days of go coding.&lt;/p&gt;&#10;&lt;p&gt;This time it is very short demo of go maps and simple sort by map values. &lt;strong&gt;Note that the example below will not work correctly if values has duplicates.&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;sort&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;//init a map with strings keys and int values&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; = make(&lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;Sun&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;7&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;Sat&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;6&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;Fri&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;Thu&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;Mon&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;Tue&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;[&lt;span style="color:#e6db74"&gt;&amp;#34;Wed&amp;#34;&lt;/span&gt;] = &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//reverse keys and values of m map&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;days&lt;/span&gt; = make(&lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//array of indexes for sorting&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;daykeys&lt;/span&gt; = make([]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, len(&lt;span style="color:#a6e22e"&gt;m&lt;/span&gt;))&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Print&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Unsorted days of week\n&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;counter&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s -&amp;gt; %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;days&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;] = &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;daykeys&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;counter&lt;/span&gt;] = &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;counter&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//sort indexes array here&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;sort&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Ints&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;daykeys&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Print&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Sorted days of week\n&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;daykeys&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;days&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;])&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I believe this code has a lot of room for optimization, so if you know how please write me in comments or ping me in twitter with your version.&lt;/p&gt;</description></item><item><title>Example of using struct in go for beginners</title><link>https://vorozhko.net/posts/example-of-using-struct-in-go-for-beginners/</link><pubDate>Sun, 26 Nov 2017 14:34:15 +0000</pubDate><guid>https://vorozhko.net/posts/example-of-using-struct-in-go-for-beginners/</guid><description>&lt;p&gt;Hi, this is day 9 out of 100 days of code in go.&lt;/p&gt;&#10;&lt;p&gt;Today I am playing with struct type. Struct is a go way to define custom types. Use it when standard types doesn&amp;rsquo;t suite you. Enough words, lets see code examples.&lt;/p&gt;&#10;&lt;p&gt;Classic example Employee type&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Employee - new type&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Employee&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;ID&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;Manager&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Employee&lt;/span&gt; &lt;span style="color:#75715e"&gt;//reference to itself&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ID and Name fields is quite obvious. Manager field is the same type as struct itself, so it must be a reference type and in our business logic will point to Manager data.&lt;/p&gt;</description></item><item><title>Transparent HTTP proxy with filter by user agent using golang</title><link>https://vorozhko.net/posts/transparent-http-proxy-with-filter-by-user-agent-using-golang/</link><pubDate>Fri, 24 Nov 2017 00:55:08 +0000</pubDate><guid>https://vorozhko.net/posts/transparent-http-proxy-with-filter-by-user-agent-using-golang/</guid><description>&lt;p&gt;This is day 10 out of 100 Days of golang coding!&lt;/p&gt;&#10;&lt;p&gt;Idea for today is to build transparent http proxy with ability to filter traffic. As for a filter I will use user agent which is common practice to filter traffic.&lt;/p&gt;&#10;&lt;p&gt;So, for the task I have used two go modules: user_agent and goproxy:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go get github.com/mssola/user_agent&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go get gopkg.in/elazarl/goproxy.v1&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First I have to setup a proxy and set a decide which hosts I want to match:&lt;/p&gt;</description></item><item><title>Count words frequency reading standard input with go</title><link>https://vorozhko.net/posts/count-words-frequency-reading-standard-input-with-go/</link><pubDate>Wed, 22 Nov 2017 01:52:40 +0000</pubDate><guid>https://vorozhko.net/posts/count-words-frequency-reading-standard-input-with-go/</guid><description>&lt;p&gt;Hi guys,&#10;today is day 8 out of 100 days of code.&lt;/p&gt;&#10;&lt;p&gt;The task for today is to count words frequency reading data from stdin. Input is scanned using bufio *Scanner with a split by words(ScanWords).&#10;Lets see the code:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;bufio&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//map to store words frequency&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;words&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//we will read from file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;in&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bufio&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NewReader&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Stdin&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;scanner&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;bufio&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NewScanner&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;in&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//we ask scanner to split input by words for us&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;scanner&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Split&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;bufio&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ScanWords&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//scan the inpurt&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;scanner&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Scan&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//get input token - in our case a word and update it&amp;#39;s frequence&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;words&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;scanner&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Text&lt;/span&gt;()]&lt;span style="color:#f92672"&gt;++&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;scanner&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Err&lt;/span&gt;(); &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fprintln&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Stderr&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;reading input:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Total words: %d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Words frequency: \n&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//todo: sort words by values for nice print&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;words&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s:%d\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Results are stored in a map words. The property of map that it doesn&amp;rsquo;t have defined order of keys, so the bonus here is to sort words map by frequency of words(by values).&lt;/p&gt;</description></item><item><title>Simple example of packages and imports in golang</title><link>https://vorozhko.net/posts/simple-example-of-packages-and-imports-in-golang/</link><pubDate>Tue, 21 Nov 2017 00:22:55 +0000</pubDate><guid>https://vorozhko.net/posts/simple-example-of-packages-and-imports-in-golang/</guid><description>&lt;p&gt;This is day 7 out of 100 days of golang coding.&lt;/p&gt;&#10;&lt;p&gt;By requests of my friends this post is about packages, files and imports.&lt;/p&gt;&#10;&lt;p&gt;Packages in go is the same as modules and libraries in other languages. To make a package you need two decide two things: package path and package name.&lt;/p&gt;&#10;&lt;p&gt;In my example package name is helloworld and because it is day7 it is inside day7 folder. Full path looks like: github.com/vorozhko/go-tutor/day7/helloworld.&#10;Full path is calculated based on $GOPATH variable which is ~/go by default, but can be set to any other in .bashrc file.&lt;/p&gt;</description></item><item><title>very basic web crawler on golang</title><link>https://vorozhko.net/posts/very-basic-web-crawler-on-golang/</link><pubDate>Fri, 17 Nov 2017 18:27:38 +0000</pubDate><guid>https://vorozhko.net/posts/very-basic-web-crawler-on-golang/</guid><description>&lt;p&gt;Hi guys,&lt;/p&gt;&#10;&lt;p&gt;this is day 6 out 100 days of code on go lang.&lt;/p&gt;&#10;&lt;p&gt;Following code implement recursive fetching of internal links on given web page.&lt;/p&gt;&#10;&lt;p&gt;What I want to do next is to add goroutines in action, because fetching process is nice to have run in parallel. Any suggestion how to do it?&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//todo:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - every link must be visited only once [done]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - keep a map of visited links [done]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - fix links and page concatination [done]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - extract domain from request uri to simplify crawling [done]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - rework how internal links are selected for crawling&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - fix how crawling settings are set like depth and maxLinks&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;io&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;golang.org/x/net/html&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//hash of visited links to prevent double visit&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;visitedLinks&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;baseURL&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;start url&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;visitedLinks&lt;/span&gt; = make(&lt;span style="color:#66d9ef"&gt;map&lt;/span&gt;[&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;]&lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Parse&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;baseURL&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;--url paramters is required&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;visitedLinks&lt;/span&gt;[&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;baseURL&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//set parameters for crawling&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;crawl&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;crawl&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;link&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//check if link already visited&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;visitedLinks&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;link&lt;/span&gt;] {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//set link as visited&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;visitedLinks&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;link&lt;/span&gt;] = &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Crawling %s ..................\n\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;baseURL&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;link&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;baseURL&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;link&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;defer&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Close&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;linkCounter&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getLinks&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//todo: rework how links are selected&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;) &amp;gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; string(&lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// only internal links&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;href&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;link&lt;/span&gt; { &lt;span style="color:#75715e"&gt;//skip current page&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;) &amp;gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; { &lt;span style="color:#75715e"&gt;//skip external links which start with //&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;linkCounter&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//fmt.Printf(&amp;#34;Found: %s\n&amp;#34;, href)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;crawl&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Second&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//Collect all links from response body and return it as an array of strings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getLinks&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;io&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Reader&lt;/span&gt;) []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;links&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;z&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NewTokenizer&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;z&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Next&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ErrorToken&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;links&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StartTagToken&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EndTagToken&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;z&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Token&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Data&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Attr&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Key&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;links&lt;/span&gt; = append(&lt;span style="color:#a6e22e"&gt;links&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Val&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://github.com/vorozhko/go-tutor/blob/master/day5/fetcher.go"&gt;Source code on github&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Get all links from html page with go lang</title><link>https://vorozhko.net/posts/get-all-links-from-html-page-with-go-lang/</link><pubDate>Thu, 16 Nov 2017 21:06:55 +0000</pubDate><guid>https://vorozhko.net/posts/get-all-links-from-html-page-with-go-lang/</guid><description>&lt;p&gt;Hi guys,&#10;this is day 5 out of 100 days of code!&lt;/p&gt;&#10;&lt;p&gt;Today I have coded html href links parser. This is part of web crawler project about which I will post in following days.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;io&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;golang.org/x/net/html&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;https://golang.org/&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getLinks&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;resp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Body&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//Collect all links from response body and return it as an array of strings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;getLinks&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;io&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Reader&lt;/span&gt;) []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;links&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;z&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;NewTokenizer&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;body&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;z&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Next&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;tt&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ErrorToken&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//todo: links list shoudn&amp;#39;t contain duplicates&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;links&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;StartTagToken&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;html&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;EndTagToken&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;token&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;z&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Token&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Data&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;token&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Attr&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Key&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;href&amp;#34;&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;links&lt;/span&gt; = append(&lt;span style="color:#a6e22e"&gt;links&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;attr&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Val&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>checking current time with go lang channels</title><link>https://vorozhko.net/posts/checking-current-time-with-go-lang-channels/</link><pubDate>Wed, 15 Nov 2017 19:32:49 +0000</pubDate><guid>https://vorozhko.net/posts/checking-current-time-with-go-lang-channels/</guid><description>&lt;p&gt;This is day 4 out of 100 days of code.&#10;Two code snippets today. First is very simple go channel.&#10;It get current system time and post it to a channel then on other end message retrieved out of the channel and printed.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;messages&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; make(&lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;go&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;messages&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sprintf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Time now %s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Now&lt;/span&gt;())&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Sleep&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;100&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;time&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Millisecond&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;messages&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Println&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Second code snippet is a program which check two strings for anagram. When one string is equal reverse of other it is anagram.&lt;/p&gt;</description></item><item><title>Recursive search through tree of files with golang</title><link>https://vorozhko.net/posts/recursive-search-through-tree-of-files-with-golang/</link><pubDate>Tue, 14 Nov 2017 21:51:39 +0000</pubDate><guid>https://vorozhko.net/posts/recursive-search-through-tree-of-files-with-golang/</guid><description>&lt;p&gt;This is day 3 out of 100 days of code in go lang.&lt;/p&gt;&#10;&lt;p&gt;This code snippet does recursive search through directory tree. One improvement which can be made is to replace custom recursive function readFiles with &lt;a href="https://golang.org/pkg/path/filepath/#Walk"&gt;filepath.Walk&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Full code:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;file path to search in&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;search&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;search string to look for&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Parse&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fi&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;os&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Stat&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//fix path if directory&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fi&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Mode&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;IsDir&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;TrimRight&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;readFiles&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;path must be a directory, but file was provided: &amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;readFiles&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;files&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadDir&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;files&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fullpath&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Mode&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;IsDir&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;readFiles&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fullpath&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Mode&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;IsRegular&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;searchInFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fullpath&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;searchInFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fullpath&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fullpath&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#75715e"&gt;//need to check for file type to detect filter off non-text files&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;fileType&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DetectContentType&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Index&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fileType&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//skip all non text files&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;line&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Split&lt;/span&gt;(string(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;), &lt;span style="color:#e6db74"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Index&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;line&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;) &amp;gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s: %s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;fullpath&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;line&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://github.com/vorozhko/go-tutor/blob/master/day3/grep.go"&gt;Source code at Github&lt;/a&gt;&lt;/p&gt;</description></item><item><title>very simple grep tool in GO - search substring in files</title><link>https://vorozhko.net/posts/very-simple-grep-tool-in-go-search-substring-in-files/</link><pubDate>Mon, 13 Nov 2017 18:53:02 +0000</pubDate><guid>https://vorozhko.net/posts/very-simple-grep-tool-in-go-search-substring-in-files/</guid><description>&lt;p&gt;Hi guys,&#10;here is day 2 of 100 days of code.&lt;/p&gt;&#10;&lt;p&gt;This time it is very simple implementation of grep tool. What it does it search string in specific directory and report matching lines.&#10;What have I learned is that strings.Index is very useful to work with text and http.DetectContentType was the way to detect binary files.&lt;/p&gt;&#10;&lt;p&gt;Full code:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;package&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; (&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#e6db74"&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;path&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;file path to search in&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;search&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;search&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;search string to look for&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Parse&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#a6e22e"&gt;files&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadDir&lt;/span&gt;(&lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;path&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;files&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Mode&lt;/span&gt;().&lt;span style="color:#a6e22e"&gt;IsDir&lt;/span&gt;() {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//to do: traverse directories recursively&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ioutil&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ReadFile&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;())&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;err&lt;/span&gt; &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Fatal&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#75715e"&gt;//need to check for file type to detect binary content&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fileType&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DetectContentType&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;line&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Split&lt;/span&gt;(string(&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;), &lt;span style="color:#e6db74"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;) {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Index&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;line&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;search&lt;/span&gt;) &amp;gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;strings&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Index&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fileType&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;text/plain&amp;#34;&lt;/span&gt;) &amp;gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;%s: %s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;(), &lt;span style="color:#a6e22e"&gt;line&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;} &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//best guess it is binary file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#75715e"&gt;//no need to go through all lines in binary file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Binary file %s matches\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;file&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;())&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;&#9;&lt;span style="color:#66d9ef"&gt;break&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="https://github.com/vorozhko/go-tutor/tree/master/day2"&gt;Source code at Github&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Simple example of golang os.Args and flag module</title><link>https://vorozhko.net/posts/simple-example-of-golang-os-args-and-flag-module/</link><pubDate>Sun, 12 Nov 2017 15:44:40 +0000</pubDate><guid>https://vorozhko.net/posts/simple-example-of-golang-os-args-and-flag-module/</guid><description>&lt;p&gt;Hi all,&#10;this is day 1 of 100 days I am coding one go program a day. Wish me good luck!&lt;/p&gt;&#10;&lt;p&gt;In this example I will show how to parse command line arguments with flag module and os.Args array.&lt;/p&gt;&#10;&lt;p&gt;Flag module is very powerful and can be as simple as this:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;import&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;String&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;user name&amp;#34;&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Parse&lt;/span&gt;()&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;fmt&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;user name is %s\n&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To have the &amp;ldquo;same&amp;rdquo; functionality with os.Args you have to do some work. In following example I added support for &amp;ndash;user, -user and &lt;code&gt;user=&amp;lt;value&amp;gt;&lt;/code&gt; arguments.&lt;/p&gt;</description></item><item><title>Continuous integration and deployment with Google Cloud Builder and Kubernetes</title><link>https://vorozhko.net/posts/ci-cd-with-google-cloud-builder-and-kubernetes/</link><pubDate>Sun, 20 Aug 2017 13:00:02 +0000</pubDate><guid>https://vorozhko.net/posts/ci-cd-with-google-cloud-builder-and-kubernetes/</guid><description>&lt;p&gt;Pipeline of Continuous Integration(CI) for containers has several basic steps. Lets see what they are:&lt;/p&gt;&#10;&lt;h3 id="setup-a-trigger"&gt;Setup a trigger&lt;/h3&gt;&#10;&lt;p&gt;Listen to a change in repositories(github, bitbucket) such like pull request, new tag or new branch.&lt;/p&gt;&#10;&lt;p&gt;It is basic step for any CI/CD tool and for google cloud builder it is pretty trivial task to setup. Check out Container Registry - Build Triggers tool in google cloud console.&lt;/p&gt;&#10;&lt;h3 id="build-an-image"&gt;Build an image&lt;/h3&gt;&#10;&lt;p&gt;When change to repository occur we want to start build of new Docker container image for a change. Good practice is to tag new image with branch name and git reference hash. E.g. master-00covfefe&lt;/p&gt;</description></item><item><title>Undocumented locust load API calls</title><link>https://vorozhko.net/posts/undocumented-locust-load-api-calls/</link><pubDate>Sun, 30 Jul 2017 15:05:27 +0000</pubDate><guid>https://vorozhko.net/posts/undocumented-locust-load-api-calls/</guid><description>&lt;p&gt;Hey folks,&lt;/p&gt;&#10;&lt;p&gt;today I found that locust load do support API calls, so you can grab statistics and manage it&amp;rsquo;s execution.&lt;/p&gt;&#10;&lt;p&gt;If you like me hear about it first time here is few examples:&lt;/p&gt;&#10;&lt;p&gt;Start locust task&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -XPOST $LOCUST_URL/swarm -d&lt;span style="color:#e6db74"&gt;&amp;#34;locust_count=100&amp;amp;hatch_rate=10&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Get stats&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl $LOCUST_URL/stats/requests&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Stop locust task&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl $LOCUST_URL/stop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All requests API endpoints can be found in &lt;a href="https://github.com/locustio/locust/blob/master/locust/web.py"&gt;locust source code on github&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;Another useful feature which is worth to mention is locust extension ability.&#10;Using it you can add your own routes to API&lt;/p&gt;</description></item><item><title>Prepare Application Launch Checklist</title><link>https://vorozhko.net/posts/prepare-application-launch-checklist/</link><pubDate>Sun, 13 Dec 2015 12:23:22 +0000</pubDate><guid>https://vorozhko.net/posts/prepare-application-launch-checklist/</guid><description>&lt;h3 id="introduction"&gt;Introduction&lt;/h3&gt;&#10;&lt;p&gt;Application Launch checklist is aimed for Devops, Sysops and anyone whois job to make website available and reliable.&#10;The checklist better works for applications which are going to be Live in near feature, but also useful to validate your Devops processes for already running applications.&lt;/p&gt;&#10;&lt;p&gt;This checklist is a complied notes from &lt;a href="https://cloud.google.com/docs/platform-launch-checklist"&gt;Launch Checklist for Google Cloud Platform&lt;/a&gt;. It is mostly targeted on Devops work routines and in a nutshell explain first and necessary Devops steps into launching applications.&lt;/p&gt;</description></item><item><title>Making simple Splunk Nginx dashboard</title><link>https://vorozhko.net/posts/how-to-monitor-nginx-logs-with-splunk/</link><pubDate>Wed, 09 Dec 2015 13:01:38 +0000</pubDate><guid>https://vorozhko.net/posts/how-to-monitor-nginx-logs-with-splunk/</guid><description>&lt;p&gt;As a DevOps guy I often do incident analysis, post deployment monitoring and usual logs checks. If you also is using Splunk as me when let me show for you few effective Splunk commands for Nginx logs monitoring.&lt;/p&gt;&#10;&lt;h3 id="extract-fileds"&gt;Extract fileds&lt;/h3&gt;&#10;&lt;p&gt;To make commands works Nginx log fields have to be extracted into variables.&#10;Where are 2 ways to extract fields:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;By default Splunk recognise “access_combined” log format which is default format for Nginx. If it is your case congratulations nothing to do for you!&lt;/li&gt;&#10;&lt;li&gt;For custom format of logs you will need to create regular expression. Splunk has built in user interface to extract fields or you can provide regular expression manually.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;img src="https://vorozhko.net/wp-content/uploads/2015/03/field_extractor.png" alt="field_extractor"&gt;&lt;/p&gt;</description></item></channel></rss>