Learning New Stuff–Terraform, AWS, Lambda, DotNetCore

This last week has been a crash course in new stuff for me.  I’m helping with the scripts that manage the infrastructure around a project – freeing up the developer to work on user stories, I’m taking care (or trying to take care) of the deployment aspects of it.   In a way, its a big catch-up to other folks who have been charging ahead into newer technologies – so its not like I’m having to discover things on my own.  On the other hand, everything is already evolved to N+2, and I’m at N-1, so its a bit of a firehose.

Here goes though, stuff I’ve picked up this week:

  • Teamcity build calling a powershell script to do deployment stuff. 
    • New to me: I didn’t know PSPROJ was a thing – that I could step debug through powershell in Visual Studio now.  Come a long way since Powershell 1.0.
    • Dotnet lambda package, zipping, sending to S3…   Somebody else whose first name rhymes with “Miss” and last name rhymes with “Aye Lee” wrote this part for something else, I get to adapt it for the current project.
  • AWS API Gateway => AWS Lambda => C# NetCore1.0 => MVC  chain
    • Got to learn about the “Version Hell” that happens in NetCore1.0.   It will probably be much nicer by the time we get to 2.0 or better.. just the 1.0 to 1.1 is pretty rough at the moment.   Get the intersection of the bleeding edge of NetCore as it was 7 months ago with the bleeding edge of where AWS is taking their Amazon Linux.   We had to do a deviation and host some stuff via EB rather than Lambda. 
    • I’ll be playing more with this on Monday as I try to debug something into not giving me a 500 internal server error.
  • Terraform as a way of deploying AWS Resources
    • Modules, and Variables, and Data sources, oh my.
    • Debugging Terraform – I found the GET/POST requests.. the problem was a Content/Type for a resource in an S3 bucket.  Can’t get .body that way, so couldn’t get the hash value.
    • Partial apply’s because sometimes you don’t recognize a change and don’t want to mess up somebody else’s experimentation
    • I got to copy what Miss Aye Lee did, nice job Dude.
  • Rewrapping my brain around Build Configurations
    • Thanks to previous training, Build Config = Debug (PDB) vs Release, but also = XSLT Config Transforms to get configuration values per environment.
    • Now, Build Config = just Debug vs Release for “how debuggable do you want this”
    • There’s another avenue for “which settings do you want to use” which is completely different.
    • More playing with this on Monday.
  • AWS Security stuff
    • IAM User’s for local access from visual studio while developing
    • Roles for when running in Lambda, EC2, etc.  (Built by Terraform)
    • Policy documents describing what access available to what (built by Terraform), shared by the IAM and Role.
    • All the stuff that was actually built by Terraform using a Terraform runner credential
    • The Terraform Runner’s policy that allows it to create all the things
    • All running in another account that we cross-account assume roles into.
    • Somebody whose first name does not sound like XML and whose last name might have to do with Whiskey is a good teacher and dreamer.

The end result:

  • If starting from scratch – done by human.
    • cd env-shared;  terraform plan & apply to create shared resources, like S3 buckets, VPC’s, RDS’s, etc
    • Any further environment changes, also applied by human via script file.  No clicky the mouse.
  • New environment – like QA1 or QA2 or other – done by human
    • cd env-qa1 (or mkdir, if starting new)
    • copy and edit a file that says what the environment name is
    • terraform plan and apply to create all the things
      • DynamoDB tables
      • Queues
  • Every build to be deployed – automated, not done by human.
    • powershell to get stuff up to S3
    • powershell to call terraform to deploy
      • Lambda
      • API Gateway hangs out with this.

Pretty powerful stuff.     Glad I’m learning it.   It will feel better end of next week when I actually have something completely checked in that completely works.   

Automerging in TFS

There’s an ongoing thread in my head on “what’s different in the land of Feature Branches”, but it hasn’t fermented into something postable yet.  However, there’s one low hanging fruit I can pluck: automatic merge between branches.

In the beginning, there was a branch…

First day hanging out with this team.  The client already has a stellar team of developers; we were discussing how we could work with them on this “other” feature that they don’t have time to handle. Overly dramatized:

  • We:  Pray tell, dear client, where shalt we code? 
  • Client:  Forsooth!  Thy code may be smelly as in fish; and perhaps thy project shalt be backburnered; thus thou shalt code here:  a subbranch from our development branch.
  • We: That shalt be wonderful, for we shall make this place our own, and be merry.

2 months go by.  The feature takes form, completely changes, and takes form again, and our code [B] is not so smelly.  However, we are also two months out of sync from their development branch; and we’re getting to the spot where we could think about releasing.  The problem:  They have had one release for feature [A], and then have another feature coming up [C] which is not ready to go.image

The painful merge

We ended merging our code [A] back into their code [C] … and then followed their normal release path up to QA and out.   Luckily, we were able to extract “just our feature” (plus a few extra styles) without moving their feature [C] (but that was luck, really).

That merge took a while:

  • 3 days: Dev1 to Dev2, code + database changes + 67 conflicts.  Dev2 now contains A+B+C. Merging sprocs outside of version control can be painful, thank you Beyond Compare for being wonderful.
  • 1.5 days: Dev2 back to Dev1, mostly dealing with merging (the same) stored procedures and schema, 4 (easy) code conflicts.   Dev1 now contains A+B+C.
  • Easy:  Parts of Dev1 (the “most recent commits”) to QA.  QA now has A+B and very little of C (a few styles crept in). 
  • Again: We were lucky that there was almost no overlap between B and C. 

Having no desire to redo that pain, we came up with a plan.

TeamCity Automerge script under TFS

We use TeamCity as our “easily installable build server”, so we set up a daily task at 5:30 in the morning to automatically merge anything new in our parent branch down to our branch:

$tf = get-item "c:\program files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\TF.EXE"
# http://youtrack.jetbrains.com/issue/TW-9050
& $tf workspaces /server:http://TFSSERVER/tfs/defaultcollection
# Its very important that the right branch (source of automerge) be listed below. 
& $tf merge /candidate $/PROJECTNAME/Dev/A . /r
& $tf merge            $/PROJECTNAME/Dev/A . /r /noprompt
#if ($a -eq 0) { 
    & $tf checkin /comment:"automerge from A" /recursive /noprompt /override:"no workitem applies"
    # checkin with no changes yields a errorlevel 1
    if ($a -eq 1) { $a=0 } 
# move this out to a seperate build step to be sure it runs
& $tf undo . /r
exit $a
  • We had a problem with getting tf to recognize workspaces, hence the extra tf workspaces call.
  • the tf /merge candidate lists the possible items to merge – used for populating the build log with information for humans.
  • the actual merge yields a 0 if there were no conflict errors.  We save that to return later.  If there’s no changes, that’s a 0.
  • if there were no conflicts, do a checkin.   In this case, no changes is an error, so ignore that error.
  • finish up with a tf undo to “unlock” the files in tfs server. 
  • return the exit code that would indicate a conflict if there was one.
  • We are running Teamcity under one of our accounts, thus there’s no login information in the calls to TFS.  Most other VCS’s, we end up putting passwords in the script;  its not the best, but there are few alternatives.   Most companies that have a good build infrastructure usually have a build user for these kinds of things, which only the build admins know the password for, which once again would exclude us from using it.

Living with an Automerge

Most days it works fine.  But some days it has conflicts.   When it does have a conflict, it shows up as a failed build in TeamCity:


We started off with a 1-week rotation for dealing with conflicts, but that ended up being unfair to Tanner, he got 5 bad days in a row, so we switched to a round-robin “who has not done it recently” approach instead.

On the days that it did run green, opening the build log shows what got merged.  We hardly ever look at this:


New Branching Strategy

Learning something, and having now earned the client’s trust, our next branch is rooted at the QA level, so that our development branch is a peer to theirs.  This is a continuing experiment; there’s more to consider, hence the still-cooking post on Feature Branching.    

Till Later!