Monday, 21 December 2020

MS Orleans - .NET and the (virtual) actor model

Just a short note to share something I've been experimenting with this year - MS Orleans. I remember experimenting with Earlang some years ago and recently I started thinking about the actor model implementation for .NET. I found a number of libraries/frameworks out of which I relatively extensively tried Akka.NET and Orleans. To me, Orleans feels like a good opportunity to dive into the actor model with .NET with a relatively straightforward codebase.

I've been writing various PoC's this year but I think the special mention goes to the last one: the road to orleans (https://github.com/PiotrJustyna/road-to-orleans) which I wrote with two other engineers. Down to earth, realistic examples, .NET 5 and F# support out of the box and we're constantly expanding it.

Feel free to comment and contribute!

Friday, 15 February 2019

Pivotal Cloud Foundry - "access denied" for custom buildpacks written on Windows

Writing custom buildpacks on Windows can lead to some unnecessary frustrations. Today I would like to cover one of those frustrations: buildpack scripts not being executable on PCF. Creating buildpack scripts on windows can lead to cryptic errors during buildpack execution like "access denied" or "permission denied".

The problem is caused by the fact that any new file created on Windows is automatically set to mode 644 aka rw-r--r-- (linux standards), but at the same type is automatically executable (-rwxr-xr-x) by windows standards.

Result? Listing your buildpack scripts using git bash on windows you see:

drwxr-xr-x 1 Piotr_Justyna 1049089    0 Feb 13 20:46 ./
drwxr-xr-x 1 Piotr_Justyna 1049089    0 Feb 13 20:44 ../
-rwxr-xr-x 1 Piotr_Justyna 1049089  137 Feb 13 20:44 detect*
-rwxr-xr-x 1 Piotr_Justyna 1049089   40 Feb 13 20:46 finalize*
-rwxr-xr-x 1 Piotr_Justyna 1049089  102 Feb 13 20:44 release*
-rwxr-xr-x 1 Piotr_Justyna 1049089  135 Feb 13 20:46 supply*

While in fact all of them are by default mode 644 (rw-r--r--). Trying to execute those scripts on PCF will result in "access denied" errors. It is pretty annoying, so I prepared a little cheat sheet for those of you who work with custom buildpacks, windows and git bash:

Executable files:

  • DON'T:
    chmod +x file
    
  • DO:
    git update-index --chmod=+x file
    

List files with their access modes:

  • DON'T:
    ls -la
    
  • DO:
    git ls-files -s
    

Copying files:

  • DON'T:
    cp file file_copy (that defaults the access mode of the copy to 644 even if the file is e.g. 755)
    
  • DO:
    cp file file_copy *and then* git update-index --chmod=+x file_copy
    

chmod-calculator.com is a very handy tool, especially for those who don't work with linux too often.

Sunday, 14 October 2018

Linux: permanently update your PATH.

To permanent change your PATH:

  1. Locate your profile file. This is your user-specific initialization file for your shell and you can find it in the root of your home directory (~). It can be named slightly differently depending on your distribution and the type of shell you are using (.bash_profile, .zprofile, etc.), but it's really not easy to miss. In my case (Fedora & bash), my profile file is named .bash_profile.
  2. Make desired changes to your PATH. There's a good chance the file already has some PATH changes, so just append yours.

    # .bash_profile
    
    # Get the aliases and functions
    if [ -f ~/.bashrc ]; then
     . ~/.bashrc
    fi
    
    # User specific environment and startup programs
    
    PATH=$PATH:$HOME/.local/bin:$HOME/bin
    PATH=$PATH:~/Documents/rebar3
    
    export PATH
    

  3. Now for the changes to take effect you can either simply log out and log back in or run:

    source ~/.bash_profile
    

    That will basically execute the command defined in ~/.bash_profile using your current shell.
And that's it.

Thank you and happy hacking!

Piotr

Friday, 13 April 2018

Haskell & Yesod - sample REST API.

Here's a sample Haskell & Yesod application demonstrating a basic REST API. It could serve as a starting point of a toy project: Haskell & Yesod - REST API.

I wrote this application as a supplement to the "RESTful Content" chapter of the "Haskell and Yesod" book. I felt the examples given in that chapter, while good, could be further developed into a working application (with IO, custom types, etc.).

Your feedback is welcome and please expect some changes to that application as time goes on.

Happy hacking,
Piotr

Saturday, 30 September 2017

Docker image to build and run your Haskell Warp server code (built on Windows).

At the time of writing this, the most helpful resources I could find covering this were simply:

  1. Stack's official dockerfile.
  2. This great gist.

I played a bit with the two and came up with my own version, suitable to produce images able to build and host simple Haskell server code. This is no production setup, but will open the door to more fine-tuned experimentation.

Let's jump right into it!

  1. First of all, here is the source code of a minimal Haskell Warp server I'm going to be hosting: haskell-warp.
  2. Secondly, the dockerfile (also contained in the github repository from the previous point):

    FROM ubuntu:16.04
    
    MAINTAINER piotr - dot - justyna - at - gmail.com
    
    # Install dependencies.
    RUN apt-get update && \
        apt-get install --assume-yes curl gcc libgmp-dev make xz-utils zlib1g-dev
    
    # Install Stack.
    RUN curl --location https://www.stackage.org/stack/linux-x86_64-static > stack.tar.gz && \
      tar xf stack.tar.gz && \
      cp stack-*-linux-x86_64-static/stack /usr/local/bin/stack && \
      rm -f -r stack.tar.gz stack-*-linux-x86_64-static/stack && \
      stack --version
    
    # Install GHC.
    WORKDIR /haskell-warp
    COPY haskell-warp/stack.yaml /haskell-warp
    RUN stack setup && stack exec -- ghc --version
    
    # Build.
    COPY /haskell-warp /haskell-warp
    RUN stack build --copy-bins --local-bin-path /usr/local/bin
    
    # Run project.
    ENV HOST 0.0.0.0
    ENV PORT 3000
    EXPOSE 3000
    CMD /usr/local/bin/haskell-warp-exe
    
  3. Now it's time to build my image (this will take a good while):

    $ docker build -t haskell-ubuntu:16.04 .
    
  4. Next, time to create a running container from the image:

    docker run --name haskell-warp -d -p 80:3000 haskell-ubuntu:16.04
    
  5. Finally, time to test the code we've just deployed:
And that's it! We've just built ourselves a working image able to host a Haskell Warp server.

Keep hacking!
Piotr

Thursday, 14 September 2017

Configure ECS to use a docker image and host static files globally.

As a continuation of Hosting static HTML files locally with Docker, today I'm focusing on running that image in ECS.

This part wasn't complicated at all and really you can just follow ECS's tutorial to see your containerized application up and running in the cloud. Minimal hassle. I don't think that there's a point in rewriting the ECS tutorial, so I'll just do two things:

The next part should be quite exciting and it is to prepare an image to run a Haskell-powered page locally. Sounds like fun.

Stay tuned and happy hacking!
Piotr

Friday, 8 September 2017

Hosting static HTML files locally with Docker

In my last post I outlined my plan for Haskell, Docker & AWS development workflow. Here's the first part of my plan:

Prepare a basic Docker image to host static HTML files locally.

I'm going to cover two methods here:
  1. Use a vanilla HTML server image and map the resources to be hosted.
    This way you can make changes to the hosted HTML files and see them reflected in the browser without the need of restarting or creating a new container.
  2. Use a vanilla HTML server image to build your own image on top of it.
    This way you can generate dockerfiles which, when built, will include the hosted resources in the docker images they produce.
Let's take a closer look at the two methods.



Prearation

If you're completely new to do Docker, I highly recommend watching this video. 40 minutes well spent and in that time you will have the contents of this post explained in detail. I will be using Docker version 17.06.1-ce and Windows.

When you're ready, there's some preparation to be done for both methods: we're going to need a web server able to host static HTML files. One of the most popular choices is nginx and at the time of writing this, the latest stable version is 1.12.1. In this post I'm going to use the 1.12.1-alpine simply because the image itself is small.

Let's pull that image:

docker pull nginx:1.12.1-alpine


Method 1

Command:

docker run --name tiny-nginx -d -v c:\temp\:/usr/share/nginx/html:ro -p 80:80 nginx:1.12.1-alpine

Explanation:
Run a docker container named (--name) "tiny-nginx" as a daemon (-d), bind mount a volume (-v) containing the resource you'd like to host in the following way: "container-host-HTML-folder-path:container-HTML-folder-path" (see how my windows container host path - "c:\temp"*, neatly mixes with the linux container path - "/usr/share/nginx/html"?**), in a read-only manner (:ro), exposing container's port 80 to my container host port 80 (so that I can actually access the HTML page from my local machine) using image "nginx" tagged as "1.12.1-alpine".

*It is important to note that we are mounting folders and not individual files. **This folder was given in the nginx image documentation.

Windows is going to ask for your permission to share the selected folder:



And now you're set. Your shared and mounted folder is now being hosted by the tiny-nginx container and every time you make changes to the HTML file locally, they should be reflected in the browser every time you refresh the hosted page. This method is pretty neat and allows for rapid write & verify iterations.

Method 2

In this method we're also going to create a docker container based on an image, but this time the image we're going to use is going to be built by ourselves on top of an existing one: nginx:1.12.1-alpine.

To do that, we first need a dockerfile. This is going to serve as a definition of our image.

Code (file: dockerfile):

FROM nginx:1.12.1-alpine
MAINTAINER piotr - dot - justyna - at - gmail.com
COPY html /usr/share/nginx/html

Explanation:
Based on image nginx, tagged 1.12.1-alpine (FROM), create a new image with a given maintainer and while creating the image, copy the contents of the container host's "html" folder* to container's "/usr/share/nginx/html"** folder (COPY).

*It is important to note that we are mounting folders and not individual files and that the folder referenced as in the example, must be available in the current, working directory.
**This folder was given in the nginx image documentation.

This basic dockerfile can now be converted (built) into an actual new image.

Command:

docker build -t static-content-nginx:1.12.1-alpine .

Explanation:
Build and optionally tag (-t) and image (name:tag -> static-content-nginx:1.12.1-alpine) using a dockerfile found in the current folder (.).

Now the image should get added to the list of docker's images. We can now run it as if it was any other image pulled from the Internet (see the Preparation section).

Command:

docker run --name tiny-nginx -d -p 80:80 static-content-nginx:1.12.1-alpine

Note the similarities between this command and the one I used in Method 1. The only difference is that we're not mounting a shared folder. Simply because it has already been added to the image itself during the build phase.



Both methods should result in the file being hosted in the locally running containers. For now, there should be only one container hosting the HTML file at any given time. Results:


That's it for now and you can find the dockerfile together with some sample HTML to be hosted here. In the next part I'm going to cover how to use the image we created in Method 2 in ECS (and not Method 1 as sharing and mounting local resources would be quite tricky!) and publish my sophisticated HTML code globally.

Stay tuned and keep hacking! Piotr