<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Software Engineering on ACIM.NET</title><link>https://acim.net/categories/software-engineering/</link><description>Recent content in Software Engineering on ACIM.NET</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 16 Jul 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://acim.net/categories/software-engineering/index.xml" rel="self" type="application/rss+xml"/><item><title>What's new in pgx v5: CollectRows, RowToStructByName, CollectOneRow, RowToStructByPos and ForEachRow</title><link>https://acim.net/blog/pgx-v5-3/</link><pubDate>Sun, 16 Jul 2023 00:00:00 +0000</pubDate><guid>https://acim.net/blog/pgx-v5-3/</guid><description>&lt;p&gt;This is the third part of the &lt;code&gt;pgx v5&lt;/code&gt; series. Let&amp;rsquo;s discuss the new features from the title.&lt;/p&gt;&#10;&lt;h3 id="collectrows-and-rowtostructbyname"&gt;CollectRows and RowToStructByName&lt;/h3&gt;&#10;&lt;p&gt;&lt;code&gt;CollectRows&lt;/code&gt; allow us to fetch an array of rows and set them into a slice of structs. Further, &lt;code&gt;RowToStructByName&lt;/code&gt; is a long awaited feature which allows to store a row into a struct. &lt;a href="https://github.com/jmoiron/sqlx" target="_blank" rel="noopener"&gt;sqlx&lt;/a&gt;&#10; module became very popular in Go community exactly for this reason, but &lt;code&gt;pgx&lt;/code&gt; now supports something similar. &lt;code&gt;RowToStructByName&lt;/code&gt; is a generic function of the &lt;code&gt;func(row CollectableRow) (T, error)&lt;/code&gt; and it&amp;rsquo;s not the only one of this type, there are also &lt;code&gt;RowTo&lt;/code&gt;, &lt;code&gt;RowToStructByPos&lt;/code&gt; and &lt;code&gt;RowToStructByNameLax&lt;/code&gt;. Under the hood, &lt;code&gt;RowToStructByName&lt;/code&gt; is using reflection so it may be slightly slower than classic way of scanning the rows, but if you don&amp;rsquo;t mind this, it is very easy to use. All field names are going to be mapped to lowercased public struct field names and you may also use &lt;code&gt;db&lt;/code&gt; struct tags if some field name differs from the struct field name. This explanation may sound difficult, but the following example will actually show that it is actually very easy to use.&lt;/p&gt;</description></item><item><title>What's new in pgx v5: QueryRewriter and NamedArgs</title><link>https://acim.net/blog/pgx-v5-2/</link><pubDate>Sat, 15 Jul 2023 00:00:00 +0000</pubDate><guid>https://acim.net/blog/pgx-v5-2/</guid><description>&lt;p&gt;In this second part of the &lt;code&gt;pgx v5&lt;/code&gt; series, we are going to discuss the &lt;code&gt;QueryRewriter&lt;/code&gt; interface and &lt;code&gt;NamedArgs&lt;/code&gt;. Let&amp;rsquo;s first check out the signature of the &lt;code&gt;Exec&lt;/code&gt; method of the &lt;code&gt;pgxpool.Pool&lt;/code&gt; struct.&lt;/p&gt;</description></item><item><title>How to install Docker and kubectl on Ubuntu 22.04 desktop</title><link>https://acim.net/blog/install-docker-kubectl-ubuntu-22-04/</link><pubDate>Sat, 18 Mar 2023 00:00:00 +0000</pubDate><guid>https://acim.net/blog/install-docker-kubectl-ubuntu-22-04/</guid><description>&lt;p&gt;Since some time apt-key is deprecated and lot of Ubuntu 22.04 based systems throws the following warning:&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-txt" data-lang="txt"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Key is stored in legacy trusted.gpg keyring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can easily fix this by properly installing Docker and Kubernetes apt archives public keys:&lt;/p&gt;</description></item><item><title>What's new in pgx v5: Introduction</title><link>https://acim.net/blog/pgx-v5-1/</link><pubDate>Sun, 04 Dec 2022 00:00:00 +0000</pubDate><guid>https://acim.net/blog/pgx-v5-1/</guid><description>&lt;p&gt;Go has very rich standard library which also contains &lt;a href="https://pkg.go.dev/database/sql" target="_blank" rel="noopener"&gt;database/sql&lt;/a&gt;&#10; module with generic interface over SQL databases. Further, &lt;a href="https://github.com/lib/pq" target="_blank" rel="noopener"&gt;lib/pq&lt;/a&gt;&#10; &lt;code&gt;PostgreSQL&lt;/code&gt; driver is fully compatible with &lt;code&gt;database/sql&lt;/code&gt; and provides all basic database operations. However, since this is generic implementation over all supported databases, using it is a trade-off not supporting some PostgreSQL specific features. Fans of &lt;code&gt;PostgreSQL&lt;/code&gt; (in further text &lt;code&gt;pg&lt;/code&gt;) may want more and here comes &lt;a href="https://github.com/jackc/pgx" target="_blank" rel="noopener"&gt;pgx&lt;/a&gt;&#10; in help. &lt;code&gt;pgx&lt;/code&gt; is a very rich &lt;code&gt;pg&lt;/code&gt; driver supporting &lt;code&gt;LISTEN / NOTIFY&lt;/code&gt;, &lt;code&gt;COPY&lt;/code&gt;, type mapping between &lt;code&gt;pg&lt;/code&gt; and &lt;code&gt;Go&lt;/code&gt;, all specific &lt;code&gt;pg&lt;/code&gt; types, wire protocol and much more.&lt;/p&gt;</description></item><item><title>Check type of generic parameter in Go</title><link>https://acim.net/blog/check-type-of-generic-parameter/</link><pubDate>Sat, 03 Dec 2022 00:00:00 +0000</pubDate><guid>https://acim.net/blog/check-type-of-generic-parameter/</guid><description>&lt;p&gt;Go is over ten years old language but generics (type parameters) are introduced just in the March this year. Hence, still lot of developers avoid using them or have certain problems once decided to give it a try. One of the common problems is how to check the concrete type of a generic parameter, specially of non constrained parameters. So, if you try to do the following, it won&amp;rsquo;t work:&lt;/p&gt;</description></item><item><title>How to write complex HTTP middlewares in Go</title><link>https://acim.net/blog/complex-go-middlewares/</link><pubDate>Sun, 13 Nov 2022 00:00:00 +0000</pubDate><guid>https://acim.net/blog/complex-go-middlewares/</guid><description>&lt;p&gt;Lot of the tutorials on the Web show different ways of writing Go HTTP middlewares, but most of them use functional approach meaning using functions that get dependencies as parameters and return HTTP handler function or handler. There is nothing wrong about this, but it can be quite messy to write a complex middlewares like database based authentication and authorization or simply middlewares which have lot of dependencies. In this article I am going to explain how to use more object oriented way of writing such middlewares. Let&amp;rsquo;s start with the basic object oriented middleware example:&lt;/p&gt;</description></item><item><title>Build Rust container images faster using layer caching</title><link>https://acim.net/blog/rust-container-image-buildkit-buildx/</link><pubDate>Fri, 03 Jun 2022 00:00:00 +0000</pubDate><guid>https://acim.net/blog/rust-container-image-buildkit-buildx/</guid><description>&lt;p&gt;In the previous blog post I described how to define GitHub Actions pipeline to benefit from caching Rust dependencies and container images&amp;rsquo; layers. But the final result may also depend on your Dockerfile. Namely, &lt;a href="https://github.com/marketplace/actions/docker-buildx" target="_blank" rel="noopener"&gt;Docker Buildx Action&lt;/a&gt;&#10; supports &lt;a href="https://github.com/moby/buildkit" target="_blank" rel="noopener"&gt;BuildKit&lt;/a&gt;&#10; and &lt;a href="https://github.com/docker/buildx" target="_blank" rel="noopener"&gt;buildx&lt;/a&gt;&#10; and in order to benefit from this, your &lt;code&gt;Dockerfile&lt;/code&gt; has to explicitly cache layers. Actually, this is quite easy to achieve, let&amp;rsquo;s see the example:&lt;/p&gt;</description></item><item><title>How I speeded up my Rust builds on GitHub ~30 times</title><link>https://acim.net/blog/speed-up-github-actions-rust-pipelines/</link><pubDate>Wed, 18 May 2022 00:00:00 +0000</pubDate><guid>https://acim.net/blog/speed-up-github-actions-rust-pipelines/</guid><description>&lt;p&gt;&lt;a href="https://www.rust-lang.org/" target="_blank" rel="noopener"&gt;Rust&lt;/a&gt;&#10; is a great programming language, but it&amp;rsquo;s compiler is known to be slow. The main reason is that it checks so many things during the compilation in order to provides memory and concurrency safety. Like in many other cases, pipelines may be speeded up by caching, but it is very important to set the caching properly, otherwise it won&amp;rsquo;t help. Besides compiling your code may be slow, you also may want to use some &lt;a href="https://doc.rust-lang.org/cargo/" target="_blank" rel="noopener"&gt;cargo&lt;/a&gt;&#10; tools to lint and check your code and this will require to be compiled as well, if you don&amp;rsquo;t want to download binaries. Some popular tools are:&lt;/p&gt;</description></item><item><title>How to fix possible missing firmware warning during kernel update on Linux Mint</title><link>https://acim.net/blog/linux-mint-ubuntu-possible-missing-firmware/</link><pubDate>Wed, 18 May 2022 00:00:00 +0000</pubDate><guid>https://acim.net/blog/linux-mint-ubuntu-possible-missing-firmware/</guid><description>&lt;p&gt;If you are running default kernel with your Ubuntu or Linux Mint installation, you probably won&amp;rsquo;t face this problem during kernel updates because all packages are coming from the official distribution sources. However, if you like to run the newest Linux kernels and update them using &lt;a href="https://ubuntuhandbook.org/index.php/2020/08/mainline-install-latest-kernel-ubuntu-linux-mint/" target="_blank" rel="noopener"&gt;mainline&lt;/a&gt;&#10; kernel installer, you may get warning &lt;code&gt;possible missing firmware&lt;/code&gt; during the installation.&lt;/p&gt;</description></item><item><title>Custom Go HTTP handlers using generics</title><link>https://acim.net/blog/custom-generic-go-http-handlers/</link><pubDate>Sun, 19 Dec 2021 00:00:00 +0000</pubDate><guid>https://acim.net/blog/custom-generic-go-http-handlers/</guid><description>&lt;p&gt;Few days ago Go 1.18beta1 was released and with it the first official generics support. I was embarrassed with standard Go&amp;rsquo;s HTTP handler functions for quite a while. If you are not familiar with Go, you probably wonder why, but if you are familiar, I believe you know. For example, implementing a RESTful API using idiomatic Go requires lot of code repetition in order to JSON decode request bodies and JSON encode response bodies. This problem was possible to solve in some way but never in such elegant way like using generics.&lt;/p&gt;</description></item><item><title>Parsing custom datetime format in Rust using serde</title><link>https://acim.net/blog/parsing-custom-datetime-in-rust/</link><pubDate>Sun, 24 Oct 2021 00:00:00 +0000</pubDate><guid>https://acim.net/blog/parsing-custom-datetime-in-rust/</guid><description>&lt;p&gt;Most of the date and time related crates like &lt;a href="https://github.com/time-rs/time" target="_blank" rel="noopener"&gt;time&lt;/a&gt;&#10; or &lt;a href="https://github.com/chronotope/chrono" target="_blank" rel="noopener"&gt;chrono&lt;/a&gt;&#10; already implement &lt;a href="https://github.com/serde-rs/serde" target="_blank" rel="noopener"&gt;serde&lt;/a&gt;&#10; traits making date or datetime parsing quite easy. This applies just if the format is standard, but what happens if the format is not standard? Let&amp;rsquo;s say we want to parse datetime looking like this &lt;code&gt;2021-10-24T07:48:26.389646Z&lt;/code&gt;. There is no timezone information so I decided to try the &lt;code&gt;PrimitiveDateTime&lt;/code&gt; type from time crate. I didn&amp;rsquo;t consider using chrono at the moment because of the &lt;a href="https://rustsec.org/advisories/RUSTSEC-2020-0159" target="_blank" rel="noopener"&gt;RUSTSEC-2020-0159&lt;/a&gt;&#10; problem.&lt;/p&gt;</description></item><item><title>Running stack of microservices using docker-compose and acim/go-reflex image</title><link>https://acim.net/blog/running-microservice-stack-in-docker/</link><pubDate>Sat, 23 Oct 2021 00:00:00 +0000</pubDate><guid>https://acim.net/blog/running-microservice-stack-in-docker/</guid><description>&lt;p&gt;Go is very attractive language for microservices&amp;rsquo; development, but using &lt;a href="https://github.com/acim/go-reflex" target="_blank" rel="noopener"&gt;acim/go-reflex&lt;/a&gt;&#10; image and docker-compose you can run multiple microservices including your gateway on your local machine. This image can run virtually any Go server based application and also reacts on changes in the code and recompiles the binary on the fly. If you want to debug your microservices&amp;rsquo; stack or develop a new feature where you have to touch multiple services, this is very good tool to do so. Let&amp;rsquo;s take a look at the docker-compose stack example:&lt;/p&gt;</description></item><item><title>Parsing JSON in Rust easily explained</title><link>https://acim.net/blog/parsing-json-in-rust/</link><pubDate>Wed, 20 Oct 2021 00:00:00 +0000</pubDate><guid>https://acim.net/blog/parsing-json-in-rust/</guid><description>&lt;p&gt;Parsing JSON in a proper way requires representing the JSON data in a structured format so that the language can find out which fields have to be parsed and which type they are. The Rust way of representing the structured data are so called &lt;a href="https://doc.rust-lang.org/book/ch05-01-defining-structs.html" target="_blank" rel="noopener"&gt;structs&lt;/a&gt;&#10;. We could make appropriate structs manually, but thanks to the great online converter, &lt;a href="https://transform.tools/json-to-rust-serde" target="_blank" rel="noopener"&gt;transform.tools&lt;/a&gt;&#10;, we can generate the structs very easily. In this article we will parse data from &lt;a href="https://www.songsterr.com/" target="_blank" rel="noopener"&gt;songsterr.com&lt;/a&gt;&#10;, a web site with guitar tabs. Let&amp;rsquo;s make the request to their API. Just &lt;a href="https://www.songsterr.com/a/ra/songs.json?pattern=Beatles" target="_blank" rel="noopener"&gt;click here &lt;/a&gt;&#10; and look at the data in your browser. Scarry? Not really, just copy all data and paste &lt;a href="https://transform.tools/json-to-rust-serde" target="_blank" rel="noopener"&gt;here&lt;/a&gt;&#10; at the left hand side box. Rust structs should appear on the right side almost immediately.&lt;/p&gt;</description></item><item><title>Firefox audio crackling and popping on Linux Mint</title><link>https://acim.net/blog/linux-mint-firefox-sound-problem/</link><pubDate>Sat, 02 Oct 2021 00:00:00 +0000</pubDate><guid>https://acim.net/blog/linux-mint-firefox-sound-problem/</guid><description>&lt;p&gt;This problem was bugging me for quite a while and today I finally decided to address it. There are lot of advices online to try to run Firefox in safe mode and see if that fixes the problem, so I tried that first but it didn&amp;rsquo;t help. Safe mode actually just turns off extensions, but in my case it didn&amp;rsquo;t help.&lt;/p&gt;</description></item><item><title>VSCode setup for Go developers</title><link>https://acim.net/blog/vscode-go/</link><pubDate>Tue, 16 Mar 2021 17:00:00 +0000</pubDate><guid>https://acim.net/blog/vscode-go/</guid><description>&lt;p&gt;According to lot of online polls, Visual Studio Code is the most popular IDE among Go developers. You can start Go development immediately after installing &lt;a href="https://marketplace.visualstudio.com/items?itemName=golang.Go" target="_blank" rel="noopener"&gt;Go extension&lt;/a&gt;&#10; for VSCode, but some tuning may make your life easier. First of all, you may want to format the source code and reorganize imports automatically on each file save or code paste. In order to do so, put the following JSON snippet in your &lt;code&gt;settings.json&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>Upcoming Go's generics</title><link>https://acim.net/blog/upcoming-gos-generics/</link><pubDate>Fri, 26 Feb 2021 00:00:00 +0000</pubDate><guid>https://acim.net/blog/upcoming-gos-generics/</guid><description>&lt;p&gt;In the very early adoption of Go by the open source community, lot of developers already suggested the lack of generics. However, some other claimed that simplicity of Go shouldn&amp;rsquo;t be compromised by generics. Few days ago, the never ending discussions pro and contra generics are finally over. The proposal is accepted and we can expect generics in Go 1.18 somewhere in spring of 2022. You may wonder why does it take that long, but this is not just about the compiler but also some parts of the standard library may need to be rewritten in order to replace the old code which could benefit from generics.&lt;/p&gt;</description></item><item><title>Go vanity imports</title><link>https://acim.net/blog/go-vanity-imports/</link><pubDate>Sun, 21 Feb 2021 00:00:00 +0000</pubDate><guid>https://acim.net/blog/go-vanity-imports/</guid><description>&lt;p&gt;If you have just started learning Go or already developing in Go for quite some time, you may noticed that most of the Go packages are imported directly from their respective VCS repositories, but there are some packages imported from URL&amp;rsquo;s like &lt;a href="https://golang.org/x/text" target="_blank" rel="noopener"&gt;golang.org/x/text&lt;/a&gt;&#10; or &lt;a href="https://go.uber.org/zap" target="_blank" rel="noopener"&gt;go.uber.org/zap&lt;/a&gt;&#10;. If you try to visit such URL&amp;rsquo;s, you may see different results like being redirected to documentation or just some dummy page. This is completely different from packages hosted on GitHub, for example &lt;a href="https://github.com/pkg/errors" target="_blank" rel="noopener"&gt;github.com/pkg/errors&lt;/a&gt;&#10; where you can see the real source code. This feature of Go is called vanity imports.&lt;/p&gt;</description></item><item><title>A first impression of Rust from the perspective of a Go developer</title><link>https://acim.net/blog/rust-from-the-perspective-of-a-go-developer/</link><pubDate>Sat, 26 Dec 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/rust-from-the-perspective-of-a-go-developer/</guid><description>&lt;p&gt;In these uncertain times and multiple months of remote work, at least we have some more time to dive into something new. I have been developing in Go since 2017, learned some TypeScript in the meantime, but few days ago I wanted to get into Rust once again. First time, approximately a year ago I gave up very quickly, realizing that Rust requires lot of time to learn and I didn&amp;rsquo;t have that much time at the moment.&lt;/p&gt;</description></item><item><title>Automated MySQL MariaDB tables optimization in Kubernetes</title><link>https://acim.net/blog/automated-mysql-mariadb-tables-optimization-in-kubernetes/</link><pubDate>Sat, 26 Dec 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/automated-mysql-mariadb-tables-optimization-in-kubernetes/</guid><description>&lt;p&gt;Kubernetes simplified applications management a lot and this also applies to databases like MySQL/MariaDB, but lot of DevOps forget to apply traditional maintenance and optimization which is still necessary unless you are using some &lt;a href="https://operatorhub.io/" target="_blank" rel="noopener"&gt;operator&lt;/a&gt;&#10; capable of doing so. The optimization method that will be described here applies just to single and master-slave replicated MySQL/MariaDB instances. If you run some clustered version like &lt;a href="https://galeracluster.com/" target="_blank" rel="noopener"&gt;Galera&lt;/a&gt;&#10;, you probably have to find another way because of possible consistence and performance problems during the eventual optimization. This method would still work but you may have unpredictable consequences.&lt;/p&gt;</description></item><item><title>Run Docker as normal user on Ubuntu 20.04</title><link>https://acim.net/blog/run-docker-as-normal-user-on-ubuntu-20-04/</link><pubDate>Tue, 17 Nov 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/run-docker-as-normal-user-on-ubuntu-20-04/</guid><description>&lt;p&gt;In lot of instructions how to run docker on Ubuntu 20.04 (same applies to Linux Mint Ulyana) you may find that after installing docker you have to add your user to docker group by the following command:&lt;/p&gt;</description></item><item><title>Changes in Go implementation of the new protobuf and gRPC</title><link>https://acim.net/blog/changes-in-go-implementation-of-the-new-protobuf-and-grpc/</link><pubDate>Sun, 15 Nov 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/changes-in-go-implementation-of-the-new-protobuf-and-grpc/</guid><description>&lt;p&gt;If you don&amp;rsquo;t know yet, there were &lt;a href="https://github.com/protocolbuffers/protobuf-go" target="_blank" rel="noopener"&gt;major changes by Google&lt;/a&gt;&#10; in protobuf and gRPC implementation for Go. New version should be better in all means so you should switch as soon as possible, if you are already using these technologies. In this article I am going to focus on Linux variant, but the upgrade procedure should be quite similar on OSX or Windows.&lt;/p&gt;</description></item><item><title>Sync Kubernetes volume with S3 bucket</title><link>https://acim.net/blog/sync-kubernetes-volume-with-s3-bucket/</link><pubDate>Tue, 06 Oct 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/sync-kubernetes-volume-with-s3-bucket/</guid><description>&lt;p&gt;In the Cloud era topics like backup became kind of less important. One of the reasons is probably possibility to take automated snapshots of your volumes, another maybe that you can use some kind of redundancy. However, there are still use cases where you need more traditional ways to backup your data. In this article we will discuss about syncing files from your Kubernetes volume to S3 compatible storage.&lt;/p&gt;</description></item><item><title>Develop Kubernetes native applications in Golang with auto-recompile and auto-restart</title><link>https://acim.net/blog/develop-kubernetes-native-applications-golang-autorecompile-autorestart/</link><pubDate>Fri, 28 Aug 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/develop-kubernetes-native-applications-golang-autorecompile-autorestart/</guid><description>&lt;p&gt;Do you develop or plan to develop a Kubernetes native application in Golang, controller or operator? Such application strongly depends on being inside Kubernetes and development outside of Kubernetes may be a real hassle. Usually you have to build an image over and over again and restart the pod (with &lt;em&gt;imagePullPolicy&lt;/em&gt; set to &lt;em&gt;Always&lt;/em&gt;). This is very boring and time consuming procedure.&lt;/p&gt;</description></item><item><title>Using Traefik 2.2 middlewares with Kubernetes Ingress resources</title><link>https://acim.net/blog/traefik-2-2-middlewares/</link><pubDate>Sat, 01 Aug 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/traefik-2-2-middlewares/</guid><description>&lt;p&gt;Since Traefik 2.0, this feature was possible just with custom IngressRoute resources, but it is now possible with normal Kubernetes Ingress as well.&lt;/p&gt;&#10;&lt;p&gt;So, what is the Traefik middleware, anyways? It is a piece of code which is triggered just before the Ingress itself. Here you can find the &lt;a href="https://docs.traefik.io/middlewares/overview/#available-middlewares" target="_blank" rel="noopener"&gt;full list&lt;/a&gt;&#10; of available directives that you can use to create your middleware. In this article we are going to define two middlewares, one to redirect &lt;em&gt;&lt;a href="https://www.example.io" target="_blank" rel="noopener"&gt;www.example.io&lt;/a&gt;&#10;&lt;/em&gt; to &lt;em&gt;example.io,&lt;/em&gt; so that we make SEO happy and another one for basic authentication. Here is how this would look like using &lt;a href="https://github.com/roboll/helmfile" target="_blank" rel="noopener"&gt;helmfile&lt;/a&gt;&#10; declaration:&lt;/p&gt;</description></item><item><title>Traefik 2.2 can again fully utilize Kubernetes Ingress resources</title><link>https://acim.net/blog/traefik-2-2-ingress/</link><pubDate>Fri, 31 Jul 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/traefik-2-2-ingress/</guid><description>&lt;p&gt;Learn how to setup &lt;a href="https://containo.us/blog/traefik-2-2-ingress/" target="_blank" rel="noopener"&gt;Traefik 2.2&lt;/a&gt;&#10; on Kubernetes and how to automatically get TLS wildcard certificates.&lt;/p&gt;&#10;&lt;p&gt;Traefik is a modern Web server made in the cloud era so it&amp;rsquo;s authors define it as a Cloud Native edge router. It is written in Go and it&amp;rsquo;s maybe not as fast as nginx or HAProxy, but it is fast enough and in the same time it has great features not present in traditional Web servers. These features include automatic care of TLS certificates, nice control panel, support for Docker stacks and Kubernetes, etc.&lt;/p&gt;</description></item><item><title>Install cert-manager using helmfile</title><link>https://acim.net/blog/install-cert-manager-using-helmfile/</link><pubDate>Tue, 28 Jul 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/install-cert-manager-using-helmfile/</guid><description>&lt;p&gt;You may wonder what the heck is &lt;a href="https://github.com/roboll/helmfile" target="_blank" rel="noopener"&gt;helmfile&lt;/a&gt;&#10;? Well, I would say what is &lt;em&gt;docker-compose&lt;/em&gt; to &lt;em&gt;Docker&lt;/em&gt;, this is &lt;em&gt;helmfile&lt;/em&gt; to &lt;em&gt;&lt;a href="https://helm.sh/" target="_blank" rel="noopener"&gt;Helm&lt;/a&gt;&#10;&lt;/em&gt;. Basically, it allows us to install the whole stack of applications to our Kubernetes cluster in a declarative way.&lt;/p&gt;</description></item><item><title>Add Google search engine to your Linux Mint</title><link>https://acim.net/blog/add-google-search-engine-to-your-linux-mint/</link><pubDate>Sun, 26 Jul 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/add-google-search-engine-to-your-linux-mint/</guid><description>&lt;p&gt;I had a problem recently not being able to set Google as default search engine in Firefox of my Linux Mint installation. It is not that I like Google that much, it is actually opposite, but DuckDuckGo as default search engine doesn&amp;rsquo;t give me the satisfying search so it seems it is not possible to skip Google tracking and keep your privacy, at least not at this moment.&lt;/p&gt;</description></item><item><title>NFS provisioner for your K8S cluster</title><link>https://acim.net/blog/k8s-nfs-provisioner/</link><pubDate>Sun, 26 Jul 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/k8s-nfs-provisioner/</guid><description>&lt;p&gt;Do you need &lt;strong&gt;ReadWriteMany&lt;/strong&gt; storage class and your cloud provider doesn&amp;rsquo;t offer it?&lt;/p&gt;&#10;&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Network_File_System" target="_blank" rel="noopener"&gt;Wikipedia&lt;/a&gt;&#10;, &lt;strong&gt;Network File System&lt;/strong&gt; (&lt;strong&gt;NFS&lt;/strong&gt;) is a &lt;a href="https://en.wikipedia.org/wiki/Distributed_file_system" target="_blank" rel="noopener"&gt;distributed file system&lt;/a&gt;&#10; protocol originally developed by &lt;a href="https://en.wikipedia.org/wiki/Sun_Microsystems" target="_blank" rel="noopener"&gt;Sun Microsystems&lt;/a&gt;&#10; (Sun) in 1984, allowing a user on a client &lt;a href="https://en.wikipedia.org/wiki/Computer" target="_blank" rel="noopener"&gt;computer&lt;/a&gt;&#10; to access files over a &lt;a href="https://en.wikipedia.org/wiki/Computer_network" target="_blank" rel="noopener"&gt;computer network&lt;/a&gt;&#10; much like local storage is accessed.&lt;/p&gt;</description></item><item><title>Serving Single-Page Applications in Go</title><link>https://acim.net/blog/serving-spa/</link><pubDate>Sun, 03 May 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/serving-spa/</guid><description>&lt;p&gt;Someone may ask what is so special about serving single-page applications? Well, if you use hash (#) based URL&amp;rsquo;s like &lt;a href="https://yourdomain.com/#/yourroute" target="_blank" rel="noopener"&gt;&lt;em&gt;https://yourdomain.com/#/yourroute&lt;/em&gt;&lt;/a&gt;&#10;, there is no problem because browser recognize that this is a default page with some parameters and doesn&amp;rsquo;t make another request to the server. However, if you want to use non-hash based routes, there is a problem if you try to refresh a non-default route. In this case browser&amp;rsquo;s default action is to load such URL from the server and there is no such document on the server. For example, if you load your SPA at URL &lt;a href="https://yourcomain.com" target="_blank" rel="noopener"&gt;&lt;em&gt;https://yourdomain.com&lt;/em&gt;&lt;/a&gt;&#10; and then you click on another route, you will see in your browser&amp;rsquo;s URL field something like &lt;a href="https://yourdomain.com/yourroute" target="_blank" rel="noopener"&gt;&lt;em&gt;https://yourdomain.com/yourroute&lt;/em&gt;&lt;/a&gt;&#10;. That works fine unless you try to reload the page. In that case browser doesn&amp;rsquo;t know this is actually already loaded SPA, but it actually tries to fetch &lt;em&gt;/yourroute&lt;/em&gt; URI from server. As there is no such URI on the server, you will usually get the famous 404 error and your application breaks.&lt;/p&gt;</description></item><item><title>Svelte await blocks</title><link>https://acim.net/blog/svelte-await-blocks/</link><pubDate>Wed, 15 Jan 2020 00:00:00 +0000</pubDate><guid>https://acim.net/blog/svelte-await-blocks/</guid><description>&lt;p&gt;Few weeks ago I came across Svelte, &lt;em&gt;a radical new approach to building user interfaces&lt;/em&gt; (quote from &lt;a href="https://svelte.dev/" target="_blank" rel="noopener"&gt;Svelte homepage&lt;/a&gt;&#10;). Svelte is actually a compiler, not tradional framework like React, Angular or Vue, but it can do pretty much everything as the mentioned ones. It doesn&amp;rsquo;t use virtual DOM, but instead it compiles to vanilla JavaScript and access the DOM directly. As a consequence, Svelte generated JavaScript is very small comparing to competition, but also quite fast.&lt;/p&gt;</description></item><item><title>Using kubectl patch in continuous deployment</title><link>https://acim.net/blog/using-kubectl-patch-to-deploy/</link><pubDate>Wed, 23 Oct 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/using-kubectl-patch-to-deploy/</guid><description>&lt;p&gt;How to deploy new Docker images to your Kubernetes cluster? Of course, there are many ways and one of the most common ways is to use &lt;em&gt;kubectl set image&lt;/em&gt;, for example:&lt;/p&gt;</description></item><item><title>Generators, wait groups and closures in Golang</title><link>https://acim.net/blog/generators-waitgroups-closures-golang/</link><pubDate>Fri, 04 Oct 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/generators-waitgroups-closures-golang/</guid><description>&lt;p&gt;This is the first step of my intention to write a series of articles where I would explain some common patterns used in Golang. Let&amp;rsquo;s start with &lt;a href="https://en.wikipedia.org/wiki/Generator_%28computer_programming%29" target="_blank" rel="noopener"&gt;generator pattern&lt;/a&gt;&#10;:&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 style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Generator&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;() &lt;span style="color:#f92672"&gt;&amp;lt;-&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;chan&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Generator is a function or method which returns a sequence of values. In Golang, this usually means returning a channel of values of desired type. In our example, we will return a channel of integers. Let&amp;rsquo;s see an implementation of this:&lt;/p&gt;</description></item><item><title>Add flag to Linux Mint application start command</title><link>https://acim.net/blog/add-flag-linux-mint/</link><pubDate>Thu, 03 Oct 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/add-flag-linux-mint/</guid><description>&lt;p&gt;Modern Linux desktop distributions contain really powerful settings possibilities, but it is very often difficult to find out how to configure something. You may want, for example, to add &amp;ndash;disk-cache-dir flag to Chromium start command in order to configure cache directory, so how to do it?&lt;/p&gt;</description></item><item><title>Install Golang package on Ubuntu Linux</title><link>https://acim.net/blog/install-golang-ppa/</link><pubDate>Thu, 03 Oct 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/install-golang-ppa/</guid><description>&lt;p&gt;Official Golang documentation contains just tar.gz package to be &lt;a href="https://golang.org/dl/" target="_blank" rel="noopener"&gt;downloaded&lt;/a&gt;&#10; and installed on Ubuntu Linux, but this is not quite comfortable way because Golang won&amp;rsquo;t be automatically updated after new release. Fortunatelly, there is &lt;a href="https://github.com/golang/go/wiki/Ubuntu" target="_blank" rel="noopener"&gt;trustable PPA&lt;/a&gt;&#10; that can be used.&lt;/p&gt;</description></item><item><title>New kind on the Block</title><link>https://acim.net/blog/new-kind-on-the-block/</link><pubDate>Thu, 03 Oct 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/new-kind-on-the-block/</guid><description>&lt;p&gt;Few months ago I wrote an article about &lt;a href="https://acim.net/blog/forget-about-minikube-try-microk8s/"&gt;replacing Minikube with MicroK8s&lt;/a&gt;&#10;, but now we have even better soluion, &lt;a href="https://kind.sigs.k8s.io/" target="_blank" rel="noopener"&gt;kind&lt;/a&gt;&#10;. Like dind allows running Docker inside Docker containers, kind allows running Kubernetes inside Docker containers. kind basically abstracts nodes as Docker containers and then runs Kubernetes inside.&lt;/p&gt;</description></item><item><title>Inexpensive managed Kubernetes solutions</title><link>https://acim.net/blog/inexpensive-managed-kubernetes-solutions/</link><pubDate>Thu, 26 Sep 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/inexpensive-managed-kubernetes-solutions/</guid><description>&lt;p&gt;&lt;a href="https://www.scaleway.com" target="_blank" rel="noopener"&gt;Scaleway&lt;/a&gt;&#10;, a French company based in Paris, owned by &lt;a href="https://en.wikipedia.org/wiki/Iliad_SA" target="_blank" rel="noopener"&gt;Illiad&lt;/a&gt;&#10; telecommunication provider, just announced public availability of their managed Kubernetes solution called &lt;a href="https://www.scaleway.com/en/betas/#kubernetes-kapsule" target="_blank" rel="noopener"&gt;Kapsule&lt;/a&gt;&#10;. Scaleway has 5 data centers, 4 in France and 1 in Netherlands, but at the moment Kapsule (public beta version) is available just in the datacenter in Paris. &lt;a href="https://www.digitalocean.com/products/kubernetes/" target="_blank" rel="noopener"&gt;DigitalOcean&lt;/a&gt;&#10; just got competition, so we can compare the pricing schemes in the later text.&lt;/p&gt;</description></item><item><title>Run K8S like ninja</title><link>https://acim.net/blog/run-k8s-like-ninja/</link><pubDate>Sun, 21 Jul 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/run-k8s-like-ninja/</guid><description>&lt;p&gt;I&amp;rsquo;ve just seen a talk on YouTube where running self managed Kubernetes cluster was described as ninja technique. I strongly disagree with this and actually want to disapprove it in this article. Running self managed K8S can also be inexpensive if you use a provider such as Hetzner Cloud.&lt;/p&gt;</description></item><item><title>Forget Minikube, try MicroK8s</title><link>https://acim.net/blog/forget-about-minikube-try-microk8s/</link><pubDate>Wed, 22 May 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/forget-about-minikube-try-microk8s/</guid><description>&lt;p&gt;&lt;a href="https://kubernetes.io/docs/setup/minikube/" target="_blank" rel="noopener"&gt;Minikube&lt;/a&gt;&#10; is very popular and the most known &lt;a href="https://kubernetes.io/" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;&#10; version for local software development. It runs inside a virtual machine like &lt;a href="https://www.virtualbox.org/" target="_blank" rel="noopener"&gt;VirtualBox&lt;/a&gt;&#10; and allows developers to run Kubernetes applications locally. As &lt;a href="https://www.docker.com/" target="_blank" rel="noopener"&gt;Docker&lt;/a&gt;&#10; runs natively just on Linux, you may wonder why do we need virtual machine on Linux? Well, not anymore.&lt;/p&gt;</description></item><item><title>Complete your Kubernetes resources as code using helmfile and raw Helm chart</title><link>https://acim.net/blog/complete-your-kubernetes-resources-as-code-using-helmfile-and-raw-chart/</link><pubDate>Sat, 11 May 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/complete-your-kubernetes-resources-as-code-using-helmfile-and-raw-chart/</guid><description>&lt;p&gt;&lt;a href="https://helm.sh/" target="_blank" rel="noopener"&gt;Helm&lt;/a&gt;&#10; is a great tool to deploy popular services and applications to your Kubernetes cluster, but from the moment I started using it I had a feeling that something is missing. You could easily configure and install whatever, but each chart that you use is a separate unit and there is no code containing all resources. This practically means in case of disaster it was still not easy to recreate the cluster, at least not in a quick time frame. Another contra is that in order to pin exact image versions, you would have to edit each values file every time you want to upgrade something.&lt;/p&gt;</description></item><item><title>Backup Kubernetes MySQL database to DigitalOcean Spaces</title><link>https://acim.net/blog/backup-mysql-databases-to-digital-ocean-spaces/</link><pubDate>Sun, 17 Feb 2019 00:00:00 +0000</pubDate><guid>https://acim.net/blog/backup-mysql-databases-to-digital-ocean-spaces/</guid><description>&lt;p&gt;Few days ago, &lt;a href="https://blog.digitalocean.com/announcing-managed-databases-for-postgresql/" target="_blank" rel="noopener"&gt;DigitalOcean announced PostgreSQL DBaaS&lt;/a&gt;&#10;, which is really nice, but even better, they promised soon availability of MySQL and Redis managed services. While we are waiting for this, I will describe in this article how to backup your Kubernetes MySQL database to &lt;a href="https://www.digitalocean.com/products/spaces/" target="_blank" rel="noopener"&gt;Spaces&lt;/a&gt;&#10;, DigitalOcean&amp;rsquo;s S3 compatible storage.&lt;/p&gt;</description></item></channel></rss>