Browsing:

Author: Jacqueline

Deploy linked Azure Resource Manager templates with a SAS token

ARM templates tend to get huge when your deployments get more complex.
With linking you can call an ARM template from another template and create a hierarchy of your templates, making it easier to adjust and reuse the templates. You can pass parameters from the master template to the linked template.

Linked templates are not very intuitive to use however. In this blog post I will walk you through an example where I deploy a storage account with a linked template. I will also show you how to use the template in a CD/CI pipeline in Visual Studio Team Services.

azure-arm

A complete example is on my Github repository.

 

The linked storage template

Let’s start with a regular template for storage. However, without the variables! A linked template only has parameters.
These parameters will be populated by the master template. These parameters can be hardcoded, populated by variables or declared in a separate parameters template.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "storageAccountType": {
            "type": "string",
            "defaultValue": "Standard_LRS",
            "allowedValues": [
                "Standard_LRS",
                "Standard_GRS",
                "Standard_ZRS",
                "Premium_LRS"
            ]
        },
        "storageAccountTier": {
            "type": "string",
            "defaultValue": "Standard",
            "allowedValues": [
                "Standard",
                "Premium"
            ]
        }
    },
    "resources": [
        {
            "apiVersion": "2017-10-01",
            "name": "[concat('disk', uniqueString(resourceGroup().id))]",
            "type": "Microsoft.Storage/storageAccounts",
            "sku": {
                "name": "[parameters('storageAccountType')]",
                "tier": "[parameters('storageAccountTier')]"
            },
            "kind": "Storage",
            "location": "[resourceGroup().location]",
            "tags": {}
        }
    ]
}

Let’s call this template storage.json.
Now we are going to call this template from a master template that I will name template.json.

 

The master template

Let’s create a folder structure like this:

In template.json I need to make a reference to storage.json. I could put my ARM Templates on Github or GitLab and reference the public URI of storage.json. But what if you are in an enterprise and you need to keep your templates private? What if you want to run the templates from a private storage account?
Then you will want to protect them with a SAS Token. How that works will be described in the last part of this article.

This is how the master.json file will look like:

 {
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "artifactsLocationSasToken": {
            "type": "string"
        },
        "artifactsLocationStorageAccount": {
            "type": "string"
        }
    },
    "variables": {
        "storageAccountType": "Standard_LRS",
        "storageAccountTier": "Standard",
        "nestedTemplates": {
            "storageTemplateUrl": "storageTemplateUrl": "[uri(deployment().properties.templateLink.uri, 'nestedtemplates/storage.json' )]"
        }
    },
    "resources": [
        {
            "name": "storageDeployment",
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2017-05-10",
            "dependsOn": [],
            "properties": {
                "mode": "Incremental",
                "templateLink": {
                    "uri": "[concat(variables('nestedTemplates').storageTemplateUrl, parameters('artifactsLocationSasToken'))]",
                    "contentVersion": "1.0.0.0"
                },
                "parameters": {
                    "storageAccountType": {
                        "value": "[variables('storageAccountType')]"
                    },
                    "storageAccountTier": {
                        "value": "[variables('storageAccountTier')]"
                    }
                }
            }
        },
    ],
    "outputs": {
    }
}

Some explanation: according to the Microsoft docs you can use deployment() to get the base URL for the current template, and use that to get the URL for other templates in the same location. The templateLink property is only returned when linking to a remote template with a URL. If you’re using a local template, that property isn’t available.

So we need to concatenate uri(deployment().properties.templateLink.uri plus nestedtemplates/storage.json. That looks like this:

"nestedTemplates": {
"storageTemplateUrl": "storageTemplateUrl": "[uri(deployment().properties.templateLink.uri, 'nestedtemplates/storage.json' )]"
}

And append the SAS Token” parameters('artifactsLocationSasToken') in our resource section:

"nestedTemplates": {
"templateLink": {
"uri": "[concat(variables('nestedTemplates').storageTemplateUrl, parameters('artifactsLocationSasToken'))]",
"contentVersion": "1.0.0.0"
},

 

Pass the parameters

As already mentioned, you can pass parameters:

  • Hardcoded the nested template (not recommended)
  • Hardcoded in the master template in parameters or variables (semi recommended)
  • In a separate parameters file (recommended)

I would recommend to use the parameters file to set values that are unique to your deployment. Then you can use the concat function to create other resources names in variables.

 

Nested templates and dependencies

You can reference to the deployment like this:

"nestedTemplates":
"dependsOn": [
"Microsoft.Resources/deployments/storageDeployment"
]

 

Deployment

Finally, the deployment. If you are in an enterprise and you need to keep your templates private you will want to run the templates from a private storage account. You can achieve this with a SAS Token.

The steps are as follows:

  • Create separate resource group with a storage account
  • Create a container in blob storage
  • Upload all templates and scripts to this container
  • Create a SAS Token for this container with a valid time of 2 hrs
  • Inject the SAS Token to your parameters.json file
  • Append the SAS Token to the nested template URI

Basically, this is what the PowerShell script does when you create an ARM Template in Visual Studio! However, I think it’s good to know what it actually does under the hood.

I would suggest you to create a service principal. Here is how.
We need the clientId, Secret, TenantId and SubscriptionId from the principal.

You can find the complete script here.

Then run the script:

$vars = @{
ClientId = ""
Secret = ""
TenantId = ""
SubscriptionId = ""
ResourceGroupName = "azure-vm-poc"
ArtifactsResourceGroup = 'my-artificats'
ArtifactsLocationStorageAccount = 'mybeautifulartifacts'
}

# modify path if needed
.\New-AzureDeploy.ps1 @vars -Verbose

 

Add the script to a build or release pipeline with VSTS

Simply add an Azure Powershell script task and call the script. Define the variables in VSTS.

Troubleshoot

Sometimes the error message in the PowerShell console are a bit cryptic. With this command you will get more verbose error messages:

(Get-AzureRmLog -Status "Failed" | Select-Object -First 1) | Format-List

Setting up Ubuntu 17.10 for .NET Core Development (including SQL Server, Visual Studio Code, PowerShell and SQL Operations Studio)

In this post I will show you how to set up an Ubuntu desktop that you can use for .NET Core Development.

Why?

Maybe because you want to do Microsoft development on older hardware or because you think Windows is too bloated.

Install the OS

In this example I use the latest Ubuntu version. Mind you, in April another LTS version will be out but I can’t wait and will probably update this article.

Update and essentials

Once installed, open up your terminal and enter:

sudo apt-get update -y
sudo apt-get upgrade -y

sudo apt-get install -y wget curl git gitk \ 
vim build-essential linux-headers-$(uname -r) zsh 

This the essentials you will want, build tools and zsh.

Oh My Zsh

I prefer the zsh and Oh My Zsh over Bash because of its auto complete features and eye candy.


wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh

And the Powerline fonts for a lovely prompt:

cd ~/Downloads
git clone https://github.com/powerline/fonts.git
cd fonts
./install.sh

Set the default shell to zsh:

chsh -s `which zsh`

Now log out and log back in.
You can then set your favorite theme by editing ~/.zshrc.

Node.js

Next we will install Node.js and fix npm so we can run it without sudo:

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
mkdir ~/npm-global -p
sudo chown -R $USER:$USER ~/npm-global
npm config set prefix '~/npm-global'

#add to path:
echo "export PATH=~/npm-global/bin:$PATH" >> ~/.zshrc

Trust the Microsoft sources

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg

Add the repo’s for the .Net Core SDK, Powershell, Visual Studio Code, SQL Server at once


sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-artful-prod artful main" > /etc/apt/sources.list.d/dotnetdev.list'

curl https://packages.microsoft.com/config/ubuntu/17.04/prod.list | sudo tee /etc/apt/sources.list.d/microsoft.list

sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'

sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/16.04/mssql-server-2017.list)"

sudo add-apt-repository "$(wget -qO- https://packages.microsoft.com/config/ubuntu/16.04/prod.list)"

Now install the software:

sudo apt-get update 
sudo apt-get install dotnet-sdk-2.1.3 powershell code mssql-server mssql-tools unixodbc-dev

Configure Sql Server

You will need to run setup to choose the correct Sql Server version and to set the SA password.

sudo /opt/mssql/bin/mssql-conf setup
# Verify
systemctl status mssql-server

Install Sql Server Tools

Next we need to instal sqlcmd:

wget http://download.microsoft.com/download/B/2/0/B20D3C84-C82A-4638-8E8C-164E09B96F71/sqlops-linux-0.25.4.deb
sudo dpkg -i sqlops-linux-0.25.4.deb

# Now login:
sqlcmd -S localhost -U SA -P ''

And we’re done

We now have an Ubuntu desktop for .NET Core development, including Sql Server. Now go ahead and do

dotnet new webapi

Next, install the Entity Framework Core package, create a full fledged backend and enjoy the fact that Microsoft has gone out of its way to make this all possible!

Script

For your convenience: here is a Gist that contains this script.

Links

https://github.com/PowerShell/PowerShell/blob/master/docs/installation/linux.md
https://code.visualstudio.com/docs/setup/linux
https://docs.microsoft.com/en-us/sql/sql-operations-studio/download
https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-ubuntu


Edit files quickly with Vim on Windows

Vim has always been my favorite text editor on Mac and Linux. But since I spend quite some time on Windows lately I figured it’s time to see how things are now with Vim in the Windows Department.

But first, why Vim? For me the most important reason is that I get to edit files quickly without leaving the terminal.
And that’s a big win. Besides, it’s easy on the eyes too!

Install Vim and ConEmu with Chocolatey

Choco, what else!
We need a decent terminal emulator for PowerShell so let’s install ConEmu as well.

choco install conemu -y
choco install vim -y

Now we can start vim with the vim command. But of course plain vim is ultimately boring, so let’s start configuring it.

Where are the config files

In ConEmu, open a Powershell shell and enter vim. This wil start Vim.
Then type

:version

Vim looks for configuration in a ‘vimrc’ file.
Now we get to see the environment settings of Vim so we know where to put our config.

system vimrc file: "$VIM\vimrc"
user vimrc file: "$HOME\_vimrc"
2nd user vimrc file: "$HOME\vimfiles\vimrc"
3rd user vimrc file: "$VIM\_vimrc"
user exrc file: "$HOME\_exrc"
2nd user exrc file: "$VIM\_exrc"
defaults file: "$VIMRUNTIME\defaults.vim"

Let’s continue using the second entry and create the vimrc file:
Exit Vim by typing

:q

And in your Powershell prompt enter:

echo $null >> ~/_vimrc

Next let’s add some plugins and modifications to our vimrc file.

Install Pathogen

With Pathogen installing Vim plugins is a breeze.

At the PowerShell prompt type:

mkdir ~/vimfiles/bundle;mkdir ~/vimfiles/autoload
Invoke-WebRequest https://tpo.pe/pathogen.vim -OutFile ~\vimfiles\autoload\pathogen.vim

Then install some plugins by cloning them to the bundle folder you just created:

cd ~\vimfiles\bundle
git clone https://github.com/scrooloose/nerdtree.git
git clone https://github.com/Valloric/MatchTagAlways.git
git clone https://github.com/vim-airline/vim-airline
git clone https://github.com/vim-airline/vim-airline-themes
git clone https://github.com/lukaszb/vim-web-indent.git
git clone https://github.com/altercation/vim-colors-solarized.git

Create your vimrc

Copy and paste this into your vimrc:

set laststatus=2
set number
set wrap
set linebreak
set expandtab
set shiftwidth=2
set softtabstop=2
set clipboard=unnamedplus
set paste
syntax on

execute pathogen#infect()

filetype plugin indent on

map  mzgg=G`z


let NERDTreeShowHidden=1
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif
autocmd vimenter * if !argc() | NERDTree | endif
map  :NERDTreeToggle

set t_Co=256
set background=dark
let g:airline_theme='solarized'
colorscheme solarized
set fillchars=""

The first section is self explanatory I think. Then this config:
– loads Pathogen
– maps the function key F7 to a command sequence that aligns the code.
– configures the NERDTree to load if you start Vim without a filename.
– The last section is to set the color theme to Solarized and the configure the Airline status bar.

Run Vim!


My Productivity System or How I Get Things Done

One could say: your productivity system can’t be that good because you haven’t written a blog post in ages. True, and here is why: I deliberately put some activities on hold the last 6 months. These ‘activities on hold’ happened to be the public ones: speaking, organizing meetups and blogging.

Why did I do that? Because I switched jobs AND I made a career switch. From an infrastructure architect, I decided to take the plunge and join a company that develops back-ends (API’s) and links and integrates them with all sort of systems. So I needed all my energy to be able to make this switch and in the same time add value to customers. Which is why all extra curricular activities where put on hold.

In the meantime I finally developed a GTD system which fits my needs and works for me. So let me to share that with you.

Why a productivity system?
Because in this day and age there is so much a person has to process and remember. At home there is taxes, bookkeeping, laundry, sports, shopping and so on. At work the customers, the team and the MT should be kept happy (and vice versa, obviously). On top of that I want to spend time with my SO as much as possible, to study and write code and blogs for fun.

With all this stuff going on one could easily become overwhelmed, lose control and end up having a burn-out. So I need to plan. I want to be able to concentrate to the tasks at hand and I want to improve my system over time. And obviously I need an app to help me remember and organise.

Turns out there is no single app that fits my needs do I have to combine three: Omnifocus, Harvest and Focus:

My personal system

So here it is. My personal system is like a funnel: I start collecting and organising all tasks, then I track time for a collection of tasks and I need to focus on a single task (‘deep work’).

This is how it works:

1. Note every single task item you can think of down.
2. Finish every task that will take only 2 minutes.
3. Put the remaining tasks into categories. E.g.: work, client x, sports, study.
4. Assign the tasks a start date or a due date..
5. Focus on your tasks for today and nothing else.
6. Track Time for these tasks
7. For the task at hand that requires deep thinking and concentration use the Pomodoro technique
8. Once a week: review the week and see when and where you were less efficient.

OmniFocus (only for Mac and IOS) fits well for this workflow. It helps you to focus only on the tasks you want (or can) do today, or place or when some condition is true.
This is a screenshot of the forecasting functionality of OmniFocus. For a given day you only get to see the tasks that you will be working on that day. And it has nice calendar integration a well.

OmniFocus does not a good job with time tracking, so in comes Harvest. Harvest is a very cool Time Tracking tool, which helps you see how productive you were on a day, a week and a month.

But Harvest does not let you focus. This is where I use the Pomodoro Technique. So in comes an app called Focus, which let me focus on the task at hand for 25 minutes.

The reason why I picked Focus is because of its integration with OmniFocus.

Mac only and Expensive?
Mac Only? Yes, unfortunately so (except for Harvest). I would love to OmniFocus going cross-platform, but it’s not going to happen.

Expensive? That depends. If you buy Asana or Todoist then you need to pay a monthly subscription to get at least similar functionality as OmniFocus. For the OmniFocus Pro version (and you are going to want that) you pay a whopping $79.99. So OmniFocus might be cheaper in the end. I use the free version of Harvest, and Focus costs around $7,99.

Take Aways
Developing a good productivity system that fits your needs can take months or even years. And in my case there was no single app that supported my needs. So I needed three. But I’m quite happy now. And I can see where I was less productive and why. And improve myself.

A big thank you for Asian Efficieny by the way. Their podcast is awesome and inspiring. Have a listen!


Docker for impatient newbies part 1: Getting started

If you are one of the few that have not yet taken the plunge into Docker don’t feel ashamed. I haven’t either. I’ve been too busy doing other stuff lately. But yesterday I actually started using Docker because I had a real life use case. I have a Node application that I wanted to ship in a Docker container. And I wanted it quickly.

So here is what you need to package a Node application in a Docker container.

Docker for Mac and Docker for Windows

Step 1 is to install the Docker engine for Mac or Windows. Head over to https://docs.docker.com/engine/installation/mac/ and install Docker for Mac or Docker for Windows.

What happens? You just transformed your machine into a Docker engine. With this Docker engine you can host containers, from images containing your applications.
This is how you get started and start developing. Production environments are better installed in another Docker Engine, somewhere in the cloud or in a datacenter.

Docker on Linux

The Docker Engine on Linux is in its natural habitat and installing it (on Ubuntu Xenial) is as easy as:

sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get update
apt-cache policy docker-engine
sudo apt-get install -y docker-engine

sudo usermod -aG docker $USER

First steps

First, check the installation:

docker version

1.12 is the latest version:

Let’s go ahead and create our first image for a Node Express app.

Package a Node.js Express app

Cd into a Node application you want to package, or clone mine. If you clone mine, install Node.js on your platform if you haven’t already. and check if it runs.

git clone https://github.com/jacqinthebox/node-express-starter
cd node-express-starter
npm install
gulp serve

If all is well you will be presented with a static website. The theme is from Black Tie.

First step is to create a Dockerfile.
Assuming you are still in the node-express-starter dir, run:

touch Dockerfile

This will be the folder structure from node-express-starter:

.
├── Dockerfile
├── app
├── bower.json
├── gulpfile.js
├── main.js
├── node_modules
└── package.json

This is how the Dockerfile should look like:

FROM mhart/alpine-node:6.3.0

MAINTAINER Jacqueline

# copy all the files from the Node app to /var/www in the container:
COPY  . /var/www

#set it as workdir
WORKDIR /var/www

#install dependencies from package.json
RUN npm install

# Expose port 3000 from the container to the host
EXPOSE 3000

ENTRYPOINT ["node","app.js"]

What does this mean?

  • FROM: here we need to put the base image for our image. Lots of these images yoy can find on the [Docker Hub](https://hub.docker.com/explore/). I want the image to be as small as possible. So that’s why I’m using an [Alpine](https://github.com/mhart/alpine-node) based image.
  • COPY: I copy all the files from my node project to the /var/www folder on my Docker image
  • WORKDIR: /var/www is the workdir (pwd)
  • RUN: while in /var/www, the npm install is run to install all dependencies of the Node app.
  • EXPOSE: here you can set the port for communication with the outside world. My Node app runs on port 3000
  • ENTRYPOINT: the command ‘node app.js’ will run upon starting the container (not when creating the image of course)

Now create the container image. You should still be in the node-express-starter dir. Run the following command (don’t forget the dot):

docker build -t jacqueline/impatient .

This has created a Docker image with the tag (-t) ‘jacqueline/impatient’.

Now run it

docker run -d -p 8080:3000 jacqueline/impatient

With -d the container instance is ran as a daemon and the -p is the port redirection (3000 we exposed in our image will be forwarded to port 8080)

Now head over to http://localhost :8080 and you should be presented with the Node web application:

Recap:

  • We installed the Docker Engine on our computer
  • We created a Docker image containing our Node app
  • We started an instance of this image

container

Stopping and cleaning up

If you work with containers, lots of harddrive space will be consumed. This is how you clean up stuff.

First, check which containers are currently running with ‘docker ps’:

docker ps

Obviously, the one we just ran is active:
docker
Notice the container ID. You can stop this instance with:

docker stop 45

Next, delete the container. First list all the containers:

docker ps -a

Again, notice the ID:

docker rm 45

Now that the container is deleted, we can go ahead and remove the image. First check which images are present:

docker images

There are 2. I’m only going to remove my own image, not the Alpine one.

docker rmi 78

In the screenshot above notice how I forgot to delete the container, but I could still delete the image with the -f flag.

The End. But will be continued.

Of course now that we took the Docker plunge, we now want to host our container in the cloud. At Digital Ocean, AWS or even Azure. This will be covered in part 2.