Archives for January, 2018

Docker nginx host not found in upstream error

published on January 30, 2018.

I’ve been toying around with Docker for the past couple of days, mostly to learn more about it, to understand it better. I just didn’t bother with it until now.

I started from scratch. Installing Docker, configuring it (I really don’t appreciate it filling my root partition with images), and, well, using it. I sort of figured out the docker command line interface, I get the difference between images and containers, I know how to write a Dockerfile, and when all the commands and options and flags start get confusing I know where to look in the help for help.

Happy with the progress I made, it was time to start connecting different containers so that they can talk to each other. Starting with a single container with nginx in it, and another container with php-fpm in it. Using their official images even.

To keep my sanity intact, as much as it is possible with software these days, I heeded Vranac’s advice and installed docker-compose for that.

No cheating, so I wrote my own docker-compose.yml file using just the documentation:

version: '3'
services:

    php:
        image: php:7.2-fpm
        expose:
            - "9000"
        volumes:
            - ./app:/app

    nginx:
        image: nginx:stable
        ports:
            - "8080:80"
        volumes:
            - ./site.conf:/etc/nginx/conf.d/default.conf
            - ./app:/app
        depends_on:
            - php

And now let’s build it and bring up the containers:

$ docker-compose build
$ docker-compose up

Aaaaaaand… It dies with an error like:

nginx: [emerg] host not found in upstream "php" in /etc/nginx/conf.d/default.conf:15

Blergh. I guess I missed something from the documentation. Fast-forward 2 hours, dozens of google searches and articles, countless rewrites of the docker-compose.yml file, and zero luck. Whatever I did, same error: “host not found in upstream”.

Then I finally remembered. What is the one thing that always causes me grief when trying to work with a web server? That’s right: SELinux!

Turn off selinux, restart docker, build && up, and it works. Sonofa. Works even with the very first version of docker-compose.yml I wrote.

OK, turning off selinux can’t be the solution, so I searched more… And no one, ever, recommends, or even mentions, that selinux might be the problem. I’ve installed the Docker SELinux package (it’s container-selinux on my Fedora 26). It should be working!

Another hour later, more searches and articles, I end up at the beginning, at the “Get Docker CE for Fedora” documentation page. Docker CE? What the fresh hell is this?

Well, it’s the docker version I should’ve installed in the first place.

Fedora’s repos have docker version 1.13.something. Docker-CE is at 17.12.something.

Remove old docker, re-enable selinux, install new docker, everything works just fine, and run the following:

sudo ausearch -c 'iptables' --raw | audit2allow -M my-iptables
sudo semodule -X 300 -i my-iptables.pp

I have no idea what that does, but it was required to make it work.

sigh

Happy hackin’!

Mockery partial mocks

published on January 28, 2018.

In dealing with legacy code I often come across some class that extends a big base abstract class, and the methods of that class call methods on that big base abstract class that do an awful lot of things. I myself have written such classes and methods in the past. Live and learn.

One of the biggest problems with this kind of code is that it is pretty hard to test. The methods from the base class can return other objects, have side effects, do HTTP calls…

A typical example of this would be a base model class that has a getDb() method:

AbstractModel.php

<?php

abstract class AbstractModel
{
    protected $db = null;

    protected function getDb()
    {
        if ($this->db == null) {
            $db = Config::get('dbname');
            $user = Config::get('dbuser');
            $pass = Config::get('dbpass');
            $this->db = new PDO('mysql:host=localhost;dbname='.$db, $user, $pass);
        }
        return $this->db;
    }
}

which can be called in child classes to get access to the database connection:

ArticleModel.php

<?php

class ArticleModel extends AbstractModel
{
    public function listArticles()
    {
        $db = $this->getDb();
        $stmt = $db->query('SELECT * FROM articles');

        return $stmt->fetchAll();
    }
}

If we want to write unit tests for this listArticles() method, the best option would probably be to refactor the models so that the database connection can be injected either through the constructor, or with a setter method.

In case refactoring is not an option for whatever reason, what we can do is to create a partial mock of the ArticleModel using Mockery and then mock (well, stub to be more precise) out only the getDb() method that will always return a mocked version of the PDO class:

tests/ArticleModelTest.php

<?php

use Mockery\Adapter\Phpunit;

class ArticleModelTest extends MockeryTestCase
{
    public function testListArticlesReturnsAnEmptyArrayWhenTheTableIsEmpty()
    {
        $stmtMock = \Mockery::mock('\PDOStatement');
        $stmtMock->shouldReceive('fetchAll')
            ->andReturn([]);
        $pdoMock = \Mockery::mock('\PDO');
        $pdoMock->shouldReceive('query')
            ->andReturn($stmtMock);

        // Create a partial mock of ArticleModel
        $articleModel = \Mockery::mock('ArticleModel')->makePartial();

        // Stub the getDb method on the ArticleModel
        $articleModel->shouldReceive('getDb')
            ->andReturn($pdoMock);

        // List all the articles
        $result = $articleModel->listArticles();
        $expected = [];

        $this->assertSame($expected, $result);
    }
}

When we tell Mockery to make a partial mock of a class, any method on that partially mocked class that has expectations set up will be mocked, but calls to other methods Mockery will pass through the real class. In other words, even though the ArticleModel is a partial mock, anytime we call the listArticles() method Mockery will pass that call to the original method, and only the calls to the getDb() method are being mocked.

Using partial mocks should probably be an option of a last resort and we should always aim to refactor code to be easier for testing, but there are cases when they can really help us in testing legacy code.

Happy hackin’!

Build and run Golang projects in VS Code

published on January 24, 2018.

I’ve been using VS Code for my Golang development needs for a few months now. Minor kinks here and there, nothing serious, and the development experience gets better with every update. I have also tried out IntelliJ Idea as the editor, and one feature that I’m missing in Code from Idea is the build-run-reload process. I thought to myself, that’s such a basic feature, it should be possible to have that.

And it is! VS Code Tasks to the rescue!

These tasks allow us to run different kind of tools and, well, tasks inside VS Code.

Go to Tasks -> Configure Default Build Task and then select the “Create tasks.json file from template” in the little pop-up window, and after that select the “Others” option. This tasks.json file will live inside the .vscode directory.

For my overcomplicated d20 roller, which is my first website built with Golang, I have the following content for the tasks:

.vscode/tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build and run",
            "type": "shell",
            "command": "go build && ./d20",
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

What this one task does is that it runs go build to build the project and then runs the generated executable, which for this project is d20.

I guess providing a standardized name to go build with the -o flag this could be made more portable so that the command part reads something like go build -o proj && ./proj, but I’m ok with this for now.

And now just type Ctrl+Shift+b and Code will execute this “Build and run” task for us! Hooray! The terminal window in Code will pop-up saying something like:

> Executing task: go build && ./d20 <

By going to http://localhost:8080 I can see that my little website is up and running. Cool.

But if we want to restart this taks, running Ctrl+Shift+b again won’t work and Code will complain that the “Task is already active blablabla…”.

Looking at the Tasks menu, we can see that there’s a “Restart running task…” menu entry. Clicking that, it pops up a window with a list of running tasks. In this case there’s only one, our “Build and run” task. Clicking through the menu every time would be boring, so let’s add a keyboard shortcut for it.

Go to File -> Preferences -> Keyboard shortcuts (or just hit Ctrl+k Ctrl+s), search for “Restart running task” keybinding, and set it to whatever you like. I’ve set it to Ctrl+Alt+r.

Finally, the flow is Ctrl+Shift+b to start the taks for the very first time, code-code-code, Ctrl+Alt+r to re-build. Sweet. Now the only annoying bit is that I have to pick out that one running task from the list of running tasks when restarting, but I can live with that. For now.

Happy hackin’!

Static web pages in Hugo

published on January 24, 2018.

Last week I created a page on this site that holds all the talks I have prepared for meetups and conferences. As this site is powered by Hugo, the process wasn’t that straightforward. I want to write down the steps I did to make it easier in the future.

Oh, and when I say “static” in the title of this post, I mean pages whose content is not completely powered by a markdown content file.

I have tried different approaches, but what ended up working is the following.

In the configuration file, I added a new type of permalink:

config.toml

[permalinks]
    talks = "/talks/"

I created a new type of an archetype under the archetypes directory of my theme:

themes/robertbasic.com/archetypes/talks.md

+++
draft = false
date = {{ .Date }}
title = "{{ replace .TranslationBaseName "-" " " | title }}"
+++

I have also created a new template file for that talks type, which actually has all the content I want to display, but is also capable of using the partials I have created before:

themes/robertbasic.com/layouts/static/list.html

{{ partial "header.html" . }}
...
&lt;div class="post">
    &lt;h1>
        Talks
    &lt;/h1>
    ...
&lt;/div>
&lt;div class="column">
    {{ partial "sidebar.html" . }}
&lt;/div>
...
{{ partial "footer.html" . }}

And finally create a markdown file for it with hugo new talks/page.md, leaving it as is.

Happy hackin’!

Tags: hugo, blog, talks.
Categories: Blablabla, Software.

Free the Geek interview

published on January 12, 2018.

Last year (feels weird to say “last year”, when it was less than a month ago) Matthew asked me if I’d be willing to appear as a guest on his Free the Geek podcast. To have a short chat about running my own software consultancy, freelancing, public speaking, and whatever else pops up.

Matthew is a great host, I have no idea why I was so nervous while chatting. Maybe because he also interviewed people like Matthew, and Matthew, and Chris, and Chris, all programmers that I learned and keep learning a lot from?

*wipes sweat off brow*

In the end I’m really happy that I did this, if nothing else, because now I’m even more determined to improve my public speaking skills, to talk more at local meetups, to submit to more conferences.

Anyway, have a listen to our chat, and make sure to subscribe to the podcast, I’m sure Matthew will have more great guests we can all learn from in the future.

Happy hackin’!

Tags: about, podcast, interview.
Categories: Blablabla.
Robert Basic

Robert Basic

Software engineer, consultant, open source contributor.

Let's work together!

If you require outsourcing or consulting help on your projects, I'm available!

Robert Basic © 2008 — 2018
Get the feed