Wednesday, April 29, 2015

Frameworks vs. Libraries

I got thinking about Rob Aston’s article Look ma, no frameworks and the viceral, zealous reactions it provoked. I suppose that the people defending frameworks have not had the same horrifying experiences with them as I have. [And I will be honest, those are really the only two non-Microsoft frameworks I have worked with. But if I had to chose between working with another “enterprise” framework and slamming nails in my ears, I would take the nails.]

Granted not all frameworks are as enterprisy as the two piles of cow feces I got to work with, and one should not paint a broad brush, but nonetheless I have to agree with Rob. Now maybe some of those people disagreeing have worked with really lean productive frameworks (assuming lean productive frameworks exist). On the other hand I suspect some of them are responsible for creating these monstrosities and feel the need to defend them. If you are one of those people, please leave your company name in the comments so I can make sure I never ever work there.

Things really got out of control when he went off on Angular. I still think that is one of the most hilarious pieces of tech writing I have ever read. It was like reading an Old Man Murray review. The reactions on the other hand were like reading creationist comments on an episode of SciShow.

But as I said, I got thinking about the argument. And I realized that the framework vs. library dispute is a bit of a rehash of inheritance over composition. Anyone who has used a giant framework, or pretty much any framework, will have to admit that you are deriving your application from it. In fact, frameworks often make heavy use of class-level inheritance. Take ASP.NET MVC for example, you cannot get started without first inheriting from System.Web.Mvc.Controller.

As with classes, I do not see why we would not all be in general agreement to favour composing our applications with libraries over inheriting from frameworks. All the same reasons hold true. Some of the problems with frameworks are:

  1. They are very rigid and impose a certain way of doing things. If you go off the beaten path, you will be stung. (WCF I am looking at you)
  2. They often abstract the wrong things or at the wrong times.
  3. Lock in. Oh my, the lock in. They tend to be an all or nothing proposition. As someone who has tried to migrate functionality out/off of a framework I can attest to the fact that it is nearly impossible. To the point re-writing the application can take less time.
  4. Further to #3 they can be a maintenance headache. Often functionality is buried in them, strewn across various layers.
  5. There are times where doing things with the framework is more work than without (Hey WCF! You again.)

What it comes down to is that with composition of libraries, you are a puppeteer controlling an assortment of marionettes. You are free to move them as you please, decorate them, or cut their strings if you so choose. Conversely, frameworks are the puppeteers and you are the puppet. (I wonder if that is why the same framework advocates seem to be in love with Dependency Injection? They adore inverting control?)

Maybe I am jaded by my recent experiences but it seems to me there is a really strong tendency lately for people to reach for the most complicated solution first. The sudden rampant use of DI, repositories and service layers is burying tons of simple applications under a morass of abstraction and convolution. I am not sure what happened to KISS and YAGNI, but they seemed to have died somewhere along the way.

One thing I assume is true, the people writing these monstrosities must never stick around long enough to maintain them, or I am sure they would stop. Actually, come to think of it, what these people really need to do is maintain an app built with someone else’s custom framework. Then they would see the light.

Wednesday, April 22, 2015

Yummy CherryPy

I recently resurrected an ancient project of mine called JBox. It’s an HTML/Javascript front-end for an MP3 player.

Way back in 2001 I had a headless Linux machine that I had setup as a router and firewall for my home network. Its proximity to the cable modem put it next to the TV and stereo. I soon got the idea to dump all my MP3s onto and connect it to the stereo. To play them, I would SSH onto the machine and queue them up with mpg123. That worked great for me, but no so great for my two roommates.

Teaching them SSH proved futile. Therefore, they could not skip songs or control the music in any way. We would just leave it running all the time and turn the stereo on and off. When it was playing, you got what you got. When it died, and it did so often, there was no music until I could remote it and re-queue it.

I threw about a couple of client-server models before settling on a web-based HTML interface. I looked at Icecast, building my own desktop app and protocol and streaming the sound over the network. None of it was appealing at the time. HTML was ideal since nothing had to be installed locally.

Fast-forward to today and I had this mad idea of putting it up on Github. Sure there are better ways of doing it now, but I still think it’s neat and it proves that I can (or could) program in Python. Now I have found myself getting carried away improving it.

I sought to improve it in two major ways:

  1. Convert to HTML5 and modern Javascript
  2. Make the backend more self-contained and easier to deploy.

In practice that meant:

  1. Rewriting the front-end as a single page application in AngularJS
  2. Integrating a web server into the back-end and eliminating the need for Apache, suexec and cgi-bin.

Lately I have been working with the Go programming language and one of the things that I absolutely love is the low level and elegant way that you can write web applications with it. For example, here is a minimal server from their documentation:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Registering handlers and writing code is such a breath of fresh air from building .NET apps buried in layers of abstraction. I wanted to get this same elegance in Python. After searching and researching Python’s copious amount of web frameworks, I came across the beautiful CherryPy project. The example from their homepage was all I needed to know.

import cherrypy

class HelloWorld(object):
    def index(self):
        return "Hello World!"
    index.exposed = True

cherrypy.quickstart(HelloWorld())

Because I was writing the front-end in AngularJS, all I really need from the back-end is a series of REST based web resources. Therefore, the first thing I needed was to incorporate a static webserver. Typically I would let nginx play this role and just have it reverse proxy to my application. However, in this case I wanted a truly self contained application. Remember, this is a “desktop” application with a HTML interface, not a website.

It actually took a bit of searching to find how to do this in the simplest way possible. In fact, I ended up sending a pull request to improve the documentation, to make it easier for the next gal/guy.

    import os
    import cherrypy

    class Root(object):
        pass

    if __name__ == '__main__':
        CONF = {
                '/': {
                    'tools.staticdir.root': os.path.abspath(os.getcwd()),
                    'tools.staticdir.on': True,
                    'tools.staticdir.dir': 'site',
                    'tools.staticdir.index': 'index.html'
                      }
        }
        cherrypy.quickstart(Root(), '/', CONF)

It is basically all in the CONF. CherryPy expects an object passed to quickstart, so we just create an empty one. For the config, we simply turn staticdir on, point it to the folder to serve (in this case ‘site’) and set the index file to index.html.

To enable my REST endpoints, I had to add a few more lines. First

SETUP = {'/': {'request.dispatch': cherrypy.dispatch.MethodDispatcher()}}

The MethodDispatcher tells CherryPy to map the request type to the corresponding method. For example, the http verb GET will map to the GET(self) method. Note that the key, '/', is relative off the mount point, not absolute from the root of the server.

Then I just mount a bunch of objects into the web server hierarchy and

cherrypy.tree.mount(songs.Songs(), '/api/songs', SETUP)
cherrypy.tree.mount(volume.Volume(), '/api/volume', SETUP)
cherrypy.tree.mount(nowplaying.NowPlaying(), '/api/nowplaying', SETUP)
...

Here I am mounting an instance of the Songs class to the absolute path /api/songs off the root of the website. It is configured to use the MethodDispatcher. And so on with the Volume and NowPlaying classes.

Here is an example of one of the REST handlers:

    import cherrypy
    from jbox.core import volume

    class Volume(object):
        def __init__(self, config):
            self.exposed = True
            self.vol = volume.Volume(config)

        @cherrypy.tools.json_out()
        def GET(self):
            return {'level': self.vol.level()}

        @cherrypy.tools.json_in()
        def PUT(self):
            json = cherrypy.request.json
            self.vol.set_level(json['level'])

I just love the simplicity of it.

There is, however, one darkside here that I am not terribly happy about. It may turn out that I am missing something, but as far as their documentation is concerned, this is how you send and receive JSON data. I find the implementation a little problematic. Without JSON, the methods would look like this:

    def GET(self):
        return self.vol.level()
        # or maybe still 
        # return {'level': self.vol.level()}

    def PUT(self, level):
        self.vol.set_level(level)

Here the PUT parameters are pulled out of the request and passed into the method. As soon as we want JSON we have to remove the parameter, mark up the method as sending/receiving JSON and then manually pull the JSON out of the request. But what if we want XML?

What I see lacking from the framework/api is Content Negotiation. That is, if the client wants JSON, it should ask for it. And get it. If it wants XML, that should be supplied too. Hard-coding my api to JSON is fine since I am the only client, but in general resources should be separate from representations. /api/volume is the resource, JSON is the representation. Ideally, it would be best to allow multiple request and response types with the same resource implementation.

Overall I am very pleased with CherryPy and am looking forward to completing my project with it. The final step is throwing in a little web socket IO with ws4py, which I may blog about down the road.

Wednesday, April 15, 2015

Deploying dacpacs with Octopus Deploy

Introduction

Microsoft’s Data-tier Application Packages (dacpacs) provide a nice mechanism for deploying your database schema and keeping your environments in sync. SSDT provides the ability to publish SQL Server projects via Visual Studio; however, in a professional setting you will want an automated and repeatable way to deploy your dacpacs. My tool of choice is Octopus Deploy. I will show you how to ingrate the two.

The SSDT Project

SSDT Sql Server projects present a bit of an issue when it comes to adding functionality to them: you can’t install NuGet packages.

This affects us in two way. The first part is that in my organization, we like to package our Octopus Deploy.ps1 and configuration transforms into a NuGet so that we can easily add them to our various projects, which we can’t do with database projects. The second issue is that you can’t install the OctoPack NuGet.

OctoPack Error

Deployment Script

To work around the first issue you must manually add a Deploy.ps1 file to the root of the project.

Adding a Deployment Script

To script the deployment of a dacpac we are going to call out to SqlPackage.exe. Here is the template that I use:

$TargetConnectionString = $OctopusParameters["ConnectionString"]
$smartDefaults = $OctopusParameters["GenerateSmartDefaults"]
$dataLoss = $OctopusParameters["BlockOnPossibleDataLoss"]

if (!$smartDefaults) {
    $smartDefaults = "False"
}

if (!$dataLoss) {
    $dataLoss = "True"
}

if (!$TargetConnectionString) {
    throw "Target connection parameter missing!"    
}

Write-Host "Deploying database now..." -NoNewline

New-Alias -Name sqlpackage -Value "C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin\sqlpackage.exe"
sqlpackage /Action:Publish /SourceFile:"[[DACPAC_NAME]].dacpac" /tcs:$TargetConnectionString `
    /p:GenerateSmartDefaults=$smartDefaults /p:BlockOnPossibleDataLoss=$dataLoss

Write-Host "deployed"

To populate the script, you have to replace [[DACPAC_NAME]] with the name of your dacpac file and ensure the path to sqlpackage.exe is correct for the server you are deploying to.

The first three lines retrieve variables from Octopus. The first is the connection string. The next two are some common parameters that you might find helpful. Please refer to the SSDT documentation to read more about the BlockOnPossibleDataLoss and GenerateSmartDefaults options. If they are not specified, the script will default to safe values (the SSDT defaults).

Passing Additional Variables

Sometimes you need additional variables in your dacpac project. For example, suppose that your database scripts reference another database. If that database has a different name in various environments, you will need to vary this per install (note: I don’t recommend ever doing this, but sometimes that is just how things are). Because the database name changes, you need some way to pass it in from Octopus.

For example purposes let’s assume that our database is called OtherDatabase_dev in our development enviornment and OtherDatabase_prod in our production environment. Our main database contains a script that needs to reference that database, for example:

CREATE PROCEDURE [dbo].[Procedure1]
AS
    SELECT * FROM [OtherDatabse_dev].[dbo].[Customers]
RETURN 0

The first thing that we need to do change the database name to a variable. SQLCMD variables use the syntax $(Name).

CREATE PROCEDURE [dbo].[Procedure1]
AS
    SELECT * FROM [$(OtherDatabse)].[dbo].[Customer]
RETURN 0

Now if you compile your dacpac, you will get a warning that Warning 1 SQL71562: Procedure: [dbo].[Procedure1] has an unresolved reference to object [$(OtherDatabase)].[dbo].[Customer]. You can either ignore this error, or add a reference to the database.

Add a Reference

There are two ways to provide a reference to your “OtherDatabase”. If it is also part, or can be part of your solution, you can add a reference to the other project in the solution:

Add Database Reference

Once you click, the next dialog will show up:

Adding Database Reference

Here you want to select Database projects in the current solution and point it to OtherDatabase. You also want to specify where the database will be located in your environment. Your options are:

  1. Same Database
  2. Different Database, same server
  3. Different Database, different server

Here I will assume we are using the second option. To be honest, I don’t know what affect the Database name field has. It will default to the name of your project. For the Database variable field enter the variable name you wish to use.

Now if you compile solution, the warning will disappear.

The alternate way to add a database reference is to refer directly to another dacpac. I have used this when the two database projects are in different solutions. You need to do the following:

  1. Build the other database to produce a dacpac
  2. Copy the dacpac into your source tree (and add to source control).
  3. Reference the dacpac.

To reference the dacpac, follow the same steps as before except this time you want to select Data-tier Application (.dacpac) from the list of options. Browse to the dacpac file. The other options remain the same.

Dacpac Referece

Again, compiling the solution will see the warning eliminated.

Adding the Variable

Now we can actually add the variable that will get populated from Octopus. Right-click the project and select Properties. From the properties dialog, click on the SQLCMD Variables tab. In the table of variables, add your variable name:

Add Variable

You can also add a default value. I recommend putting your development value in there.

Lastly, we need to augment the deployment script to retreive the value from Octopus and pass it along to the dacpac. To the top of the retrieve the value with something similar to:

$otherDatabase = $OctopusParameters["OtherDatabase.Name"]

At the end of the sqlpackage invocation pass in the variable:

/v:OtherDatabase="$otherDatabase"

The above is SQLCMD variable syntax. You can pass as many of these to SqlPacakge as you like. The syntax is /v:Name=Value

Packaging for Octopus

Since we can’t add OctoPack to the project, we have to get creative here. How to implement the package is heavily influenced by how you will be automating your build. You might be using TFS, TeamCity, psake or something else. Essentially, you just need to get the dacpac file and the Deploy.ps1 file into a NuGet.

For example, if you were using psake, you might put octo.exe into your projects folder and call it directly:

.\octo.exe pack –id=Database –basePath=bin\Debug –version=1.0.0.0

In our environment, we use TFS Build. We run “Custom After Microsoft Common Targets” extensions as I have described previously.

With our common targets, we override the Dacpac’s version, copy the dacpac and dlls to a staging folder and then call the CreateOctoPackPackage task with our version and the location of the staging folder.

If you are interested in additional details of how we implement the custom build, please leave a comment.

Deploying with Octopus

Finally, we are ready to configure Octopus Deploy to deploy the database. If you don’t have a Project in Octopus, create one now.

Open your project and click on the Process tab:

Add step

Click Add step and select Deploy a NuGet package from the list.

In the Step details add the Step name, Machine roles and NuGet package ID. In my case, the NuGet package ID is always the .NET project name and I label the step with the same value. The machine role is also typically DatabaseServer but will, of course, be specific to your environment.

Step Details

Now click on the variables tab. There are to variables you must enter:

  1. ConnectionString
  2. OtherDatabase.Name

You can also optionally add BlockOnPossibleDataLoss and GenerateSmartDefaults.

Adding Variables

Conclusion

Dacpacs provide a pretty slick way to deploy a database schema and keep your environments in sync (although they are not without their issues, which I will write about at a later date). Deploying them with Octopus Deploy is straightforward and only requires a basic PowerShell script. Many advanced features are available SQLCMD variables and SqlPackage parameters, all of which can be controlled from the Octopus interface.

Wednesday, April 8, 2015

PowerShell: Needs a Little Help from its Friends

Poor little PowerShell… It just doesn’t get any love.

It has been around for a decade now and I still find that it has not penetrated the consciousness of .NET developers. It’s sad. There’s this huge cohort of devs that don’t know anything outside of Windows and have this very powerful tool at their disposal, but tend to be oblivious to it.

There are a multitude of crazy one-offs that you can do to improve your efficiency on Windows. But the real Power comes from its two-way integration with .NET. By two-way, I mean that you can both load .NET objects in your scripts and write script components in .NET (binary cmdlets).

The real Power comes from its two-way integration with .NET.

I know some people are not terribly happy with the programming language, but I don’t have any problems with it. Yeah it isn’t the most beautiful, but after working with it for awhile, the syntax melts away and you won’t find it any better or worse than any other programming language. Well… expect Perl and Python. Nothing’s better than Python and nothing’s worse that Perl ;-)

On the other hand, the pipeline of objects vs. text is a crazy awesome advancement from the existing paradigm. The drawback is that it increases the learning curve. I know when I first started with PowerShell I found the objects frustrating when I just wanted text. It requires you to learn all these selectors and formatting tricks to get a display of what you’re looking for.

But, at the end of the day, any scripting language is only as good a the environment it lives in. At that, sadly, is where PowerShell falls down. In fact, it really does not have much to do with PowerShell. All scripting languages suffer on Windows. Be it Perl, Python or PowerShell, Windows just doesn’t have the tooling for these “glue languages” to glue together.

Be it Perl, Python or PowerShell, Windows just doesn’t have the tooling for these “glue languages” to glue together.

In fact, PowerShell does have the most, because it can leverage .NET, COM, WMI and all the other things Microsoft has thrown at its devs over the years. But it still lives in a land of GUIs, where everything is done with mouse clicks. Here are a few examples:

  1. Add the Log on as a service right to an account. Unix admins, read that and weep. It’s a fact! You can’t script what isn’t scriptable. If you search hard enough, you will find that, yeah, it can be done. But your eyes will have to bleed in the process.
  2. You can’t even work with NTFS permissions without installing a module. That’s right, simple basic sys admin stuff. Fundamental sysadmin stuff! Just changing the ACLs on Windows is not supported out-of-the-box. It is 2015 and Microsoft still struggles to match the basic functionality that Unix has had for 40 years (see chmod).

These examples reveal the truth from Microsoft. It’s not just the .NET devs in the wild that haven’t adopted PowerShell. Remarkably, not even the developers inside Microsoft have. As long as they are stuck in the 90s do-everything-by-the-gui mentality nothing will improve. PowerShell, as a whole, will stay inferior to much more modest shells like Bash.

Hammers never show their true value in the absense of nails.

Wednesday, April 1, 2015

SSH Passphrase Chaos

Surprise, We Moved your Cheese!

Recently I stumbled onto another Easter Egg left my the K/Ubuntu team. I was trying to connect to my webserver as usual, and instead of asking me for my SSH passphrase, a strange GUI dialog I have never seen before appeared:

Passphase GUI

I have a really long, randomly-generated passphrase that I store in KWallet. As the result of a different bug, I typically add it to the ssh-agent that runs at login by manually running a script.

The first couple of times this new dialog appeared I looked up my passphrase in KWallet, pasted it into the window, and moved on with what I was doing. Looking it up was a pain and running my script that adds the key to the agent did not change anything in regards to this dialog appearing, or not.

Confused, I looked in my KWallet. The passphrase was still there. As I often do, when in doubt, I deleted it. I tried logging into my server again. When this strange app asked, I put in my passphrase and clicked the “Remember when I login” option. I was hoping it would add my passphrase back to KWallet and things would be good again.

Things Get Really Weird

Typically, when you add your passphrase to ksshaskpass and tell it to remember it, you are asked to unlock your KWallet the first time you use your key. But now I was not getting asked for my KWallet password or my key’s passphrase. I have no idea where my passphrase was stored! I revoked ksshaskpass’s permission to KWallet, so I definitely know it is not there, or at least that ksshaskpass is not the program with the dialog (it’s been years since I last saw ksshaskpass’s dialog, so I do not exactly remember what it looked like – similar though).

A few days later, I noticed the same thing happened on my laptop. Since I had added my passphrase to the mystery application on my workstation, it had become a lot harder to figure out what was going on. Now the dialog was not appearing and I had limited options to figure out the issue.

With the same issue occurring on my laptop, I was now granted the opportunity to get to the bottom of things. This time I ran the system monitor to determine what app was running. I closed the dialog and tried logging into my server while watching the system monitor. This time, when the dialog appeared, I saw an application called gcr-prompter appear.

Something with prompt in the name told me I was likely on the right track. On the command line, I ran

$ locate gcr-prompter

I found that it is at /usr/lib/gcr/gcr-prompter. Next I ran

$ dpkg -S /usr/lib/gcr/gcr-prompter

I found out that it comes from the package gcr. dpkg -S is one of my favourite features of Debian/apt!

After searching for gcr-prompter, I found out that “gcr” is the “GNOME crypto services”. I do not know where this package came from or why it is was on my machine. Both of my machines have now been messed up by it, but I do not run GNOME on either of them.

When I searched for which packages depend on it, it was clear that it is in the task kubuntu-desktop. So, it appears this is standard in Kubuntu. I wish there was some communication on these things. It would be nice if, when when you upgraded, they would warn you that behaviours or packages xyz have changed. It is so frustrating to have such random things sprung on you with each upgrade.

I searched online and nothing reveals any sort of policy change. Even when seeking out this information, you cannot find it. It is very aggravating and I am getting toward my whit’s end with these breakages. I am tired of things randomly changing and having to spend hours fixing things when I am trying to get work done.

At this point I decided to just uninstall the gcr application:

$ sudo aptitude purge gcr
$ sudo apt-get autoremove

Based on this Q&A I found out where it hides its data.

As a result, I ran:

$ rm -rf .local/share/keyrings

Then I was able to run my script ~/bin/askpass.sh, re-add my passphrase to ksshaskpass and select the option to store it in KWallet.

Correct SSH Dialog

Everything back to normal… for now.