Friday, November 16, 2018

Coffee Roasting #1

I recently came into fifty pounds of green coffee beans and decided to try roasting some at home.  Here we go.

Coffee Roasting Experiment #1

Green coffee beans, origin unknown.
8" square cast iron pan.
Wooden spatula.
Multimeter with infrared thermometer.
Propane stove.
Timer.

Preheated the pan for several minutes on my stove's second to lowest setting.
Added green coffee beans.
Started timer.
Stirred constantly with wooden spatula.  Stirred using a back and forth, up and down pattern.  Tried to get the beans to flip over by pushing them up the sides of the pan.
Heard a crack at the 15 minute mark.
Temperature of the pan 250 degrees Celsius.
Took beans out of the pan at the 23 minute mark because they had a nice brown color.
Put into a small glass dish.
Temperature of the beans out of the pan was 150 degrees Celsius.
Left roasted beans uncovered at room temperature on the counter.
Weight of the beans post-roasting 11g.




Monday, August 13, 2018

Grilled chicken breast

Grilled skinless, boneless chicken breast can be tough to cook. Too much heat and the breast is dry, tough and leathery.  So how to grill the leanest of lean meats without drying it out?

Skip to past the following recipe for explanations and source material.  Directions are for a Weber Kettle Grill (sorry gas grillers).  This won't make grill marks on your chicken. If you want to do that get a different recipe.

Spice Rubbed Grilled Skinless Boneless Chicken Breast

Prep time: 10 - 15 minutes.
Cook time: 30 - 45 minutes.

Spice rub

2 tbs kosher salt
3 tbs brown sugar
2 tbs chili powder
2 tbs sweet paprika
2 tsp black pepper
1/4 - 1/2 cayenne pepper

Ingredients

Skinless, boneless chicken breast, enhanced
Vegetable oil
Gallon plastic storage bag

For the chicken


Prep

Trim the chicken breasts, remove bone, cartilage, fat and any dangly bits not attached to the main breast.

Flatten

One at a time, put the breast in a gallon plastic storage bag.
Flatten the breast to an even thickness.
Whack the thick part of the breast three to four times with a blunt instrument. Rubber mallet, 6 qt pan, your skull.  All work well.

Rub

Coat the chicken with the spice rub.
Put it in a plastic storage bag and in the fridge for 1 - 4 hours.
You will have leftover spice rub.

Cooking


Prep your grill

Cut a small log of peach wood about 1" in diameter and 4" long or 2 oz by weight.
Fill a chimney starter 3/4ths with charwood and light it.
When the coals are white ash dump them all on one side of the grill.
Clean your grill grates well.
Put the lid on.

Put the chicken on the grill

Get the chicken out of the fridge.
Coat the breasts with vegetable oil.  Just pour a little on and use your hands to coat evenly.

Get cooking

Lift up the grill grate and put the peach wood directly on the hot coals. 
Put all the chicken breasts opposite the coals on the grill.
Put the lid on.
Open the lid vents all the way and place them over the chicken.
Keep the bottom vents open.

Don't f*cking touch it (much)

Leave the lid closed for 20 minutes. 
Temp the chicken breast, it should be close to 165 degrees Fahrenheit.
Rotate any pieces that seem to be cooking faster.
Close the lid and let the chicken cook for another 15 minutes.
Temp the chicken breast, it should be 165 degrees Fahrenheit.  If it's not, you can curse me and leave the chicken on for another 10 minutes or until you think it will be done.


Why did you..?


OK, so what's going on in this recipe and why did I do X?  What's with the mallet, why am I flattening chicken?  There's a couple things going on that make this work and I'll touch on them here.

The spice rub is Cook's Illustrated Picnic Chicken.  I would link to it but the bastards have a paywall.  The rub is pretty basic with salt, sugar and some spices.  Make it hotter with more cayenne.  Use the salt and sugar as a base and experiment.  The salt and sugar will work their way into the meat the longer you let it sit.  Watch out for double salt jeopardy with "enhanced" chicken.

What's "enhanced"?  Enhanced chicken was injected or brined during processing.  Check your packaging and it will tell you.  It's not bad but you may want to adjust your salt down because it has salt in it.  If your chicken is not enhanced use a basic brine recipe: 1 cup table salt to 1 gallon of water, 2 - 4 hours, take it out and rub it before you grill it.

Do not use skin-on split chicken breast and expect this to work.  We're basically brining/salting the breast in a plastic bag, it will make the skin flabby and it will not crisp properly.

You gotta trim that chicken. There's all sorts of dangly bits, pieces of bone and cartilage left over from processing.  I use a pair of kitchen shears, trim the breasts and then boil the trimmings for dog food.  Add some rice and veggies and your dog will love it.  I use a 1-1-1 ratio of protein-grain-vegetables.  Check with your vet.

You ever take a whole chicken breast and throw it on the grill?  That thicker end (on the left) is done before the thinner end (on the right).  The thinner end gets dried out and it sucks.


To fix the uneven cooking problem we whack the thicker end of the breast so the entire breast is (more or less) the same thickness.  The more uniform shape will evenly cook.  Read more from Serious Eats or Meathead.  Don't whack it too much or it'll be limp and strung out.  We just want a nice, even thickness.  Three or four times will work.  I like to use a small Farberware pot.

A Word About Fire


Don't soak the wood.  Meathead disproved the wood soaking theory.  Amazing thing about wood, it really doesn't absorb that much water.  That "smoke" you're seeing from wet wood is just steam.  Toss your wood in dry.  See Meathead's guide on how much wood.  I use a piece of dried peach wood about 1" in diameter and 4" long.  It didn't completely burn during the short cooking time.

All the coals are going on to one side of the grill.  This chicken will go on the opposite side and cook via convection.  That is, the hot coals will heat the surrounding air, the lid will trap the heat and that heat will go into the chicken.  The chicken will cook more evenly.  See Meathead's guide on heat transfer.

I wish I used charcoal but I'm still using up all my charwood at the moment.  The pieces are uneven, unlike charcoal, and you really can't compare a chimney starter full of charwood to one with charcoal.  We're not looking for Hellfire, just 3/4ths of a chimney starter filled with charwood did it for me.  I used a cardboard egg carton as firestarter.  It works well and doesn't leave a lot of ash.

This is lean chicken breast.  We're not going low and slow because that'll just dry it out.  Use a full quart of charcoal to get the grill up to temp, anywhere between 350 - 450.  Don't go lower than 350, the chicken will take too long to cook and dry out.  I've done it, it sucks.

There's no grill marks.  Yeah, that's a design decision.  You could probably coat the chicken with a sauce near the end and toss them on the hot side of the coals for a few minutes to brown them up a bit.

The vents are positioned over the chicken breasts to draw smoke over the breasts as it exits the grill.  They are also open otherwise the coals would starve for oxygen and go out.  Also, we don't "warm up" the breast before cooking.  Another myth Meathead busted.

The Result


Cook the chicken until it hits the magic number, 165 Fahrenheit, and take it off the grill.  No need to let it rest, just serve and tuck right in.  The peach wood will add a bit of smokiness to the breast.  It'll be juicy and flavorful thanks to indirect cooking and the salt/sugar/brine.

Wednesday, August 8, 2018

A Weekend New Hampshire Hike, Southern Presidentials.

My wife and I made a trip to the White Mountains the weekend of August 3rd, 2018 for a hike of the Southern Presidentials.  We planned to stay at two Appalachian Mountain Club (AMC) huts and hike about 14 miles.  The weather ended up being lousy for most of the hike but we got some great views on Sunday as the skies cleared.  I'll go over our itinerary, gear list and general thoughts as a way for others interested in multi-day hikes to get a sense of what's required.  A huge thanks to the resource http://home.earthlink.net/~ellozy/, without which the hike would not have been possible.

The problem with some multi-day hikes is that you don't end the hike at your car.  This means you have to do some automobile acrobatics, shuffling cars between start and end points, or get a ride.  I opted to get a ride from a guy named Bruce who's been shuttling hikers for 14 years.  Call the AMC Joe Dodge Loge or Highland Center for a list of people who can shuttle you for a small fee.  The AMC shuttle runs on a schedule and did not meet our needs.

Our hiking speed was about one hour behind the AMC Book Time.  We don't hike often, this was our first trip to the Whites this year, so I expected us to go a bit slower and take more frequent breaks.  Knowing the book time and our position on the trail helped us estimate our speed and when we would need to start hiking in order to reach our destination on time.

You can skip the following novel and head right to the Itinerary, which has both my Estimated and Actual times, and Gear List of stuff we brought and wouldn't bring again.

We're about 4 - 5hrs away from the White Mountains and needed to get started early so we could get to our first hut. The first order of business was to drop off our dog for boarding. We got up early to get her there for 06:30 and hit the road to Joe Dodge Lodge.

We arrived an hour early so we called Bruce and he was able to pick us up.  There was some confusion about which trailhead we needed to be dropped of at.  We wanted the Webster-Jackson Trailhead but he dropped us off at a different point, thinking we wanted to go up Mt. Webster. I used Elephant Head as a landmark and he knew the place.  Had we not double checked the wrong trailhead would have added 2 miles to our trip and probably made us late for dinner.

It was 12:00 when we arrived at the Webster-Jackson Trailhead, Crawford Notch, Route 302 near Elephant Head and started hiking.  We took the side trail to Elephant Head which gave us a lookout over Route 302 and the AMC Highland Center.  It wasn't worth the extra .5 miles.

The hike was 4.3 miles with an elevation gain of 2,150 feet and a book time of 3:15.  We took the Jackson Branch of the Webster-Jackson Trail to Mount Jackson, followed by the Webster Cliff Trail to Mizpah Hut.  It was fairly easy, except for a brief scramble up to the summit of Mount Jackson.  The summit has excellent views in all directions.  The trail is in good condition and we took a couple breaks, one to eat our trail lunch a flatbread PB&J.

There was light rain that continued throughout the day and it was overcast.  We didn't use the gaiters I bought for the trip or any of our rain gear.  It was too muggy for any of that and we were already soaked to the skin from sweat.  There was no drying off that day it was so humid.

After taking in the view at Mt. Jackson we hiked to Mizpah Hut and got there at 16:30 soaking wet.  It was good to change in to dry clothes and we were tired out.  Dinner was OK.  The chicken was a little dry, a theme to be repeated at Lake of the Clouds Hut, but the lemon cake dessert was great.

I woke up early Saturday morning and treated myself to some coffee in the dining room at Mizpah.  Wakeup call was at 06:30 and we were serenaded by one of the Croo with a song on the guitar.  Breakfast was good and we prepped our gear to start a day of hiking to Lake of the Clouds.

The weather report was dismal, rain all day with a chance of thunderstorms.  We decided to push on through and hope there were no thunderstorms.  Based on our previous days hike we expected it to take about 5hrs to get to Lake of the Clouds.  We didn't want to be eating lunch on the trail though, weather being was it was and the exposure we'd have on the ridge between Mt. Pierce and Lake of the Clouds.

At 08:10 we started our hike in the rain.  It wasn't a hard rain, just constant.  We wore all our rain gear this day, except rain pants, and used our pack covers.  The hike from Mizpah to Lakes is 5.0 miles with an elevation gain of 1,650 feet and a book time of 3:45.  We followed the Webster Cliff Trail to its end, summiting Mt. Pierce in the process, and then took the Crawford Path to the hut.  The trail is almost continuously exposed from the summit of Mount Pierce onwards; there are patches of scrub before reaching Mount Eisenhower, none after that.

The light rain turned into a downpour, flooding the trail.  We were soaking wet inside and out from the rain and our gear trapping our body heat and moisture.  The Crawford Path became the Crawford River. All the careful rock hopping we did early on ended when we could no longer stay out of the water, soaking our boots.  The trail slippery and made it slow going.  We slipped several times along the rocks on the trail.

AT 09:00 we summited Mt. Pierce, by 11:00 we summited Mt. Eisenhower in pouring, driving rain.  The rain and wind lessened some coming down Eisenhower.  When we arrived at the Monroe Loop at 12:00 we were so tired, wet and upset we bypassed Mt. Monroe.  All we wanted was to change clothes and get some soup at the hut if available.  We headed straight for the hut and arrived there at 12:30, our expected time.  The rain had stopped and we changed into dry clothes.  We tried drying our boots outside the hut as it was very windy.  Everything else we hung inside our bunkroom since we were first there.  Thankfully, they had soup so we warmed up with a bowl, had a cup of tea and dried out.

By 13:00 we were rested and dried out a bit.  We had planned to summit Washington but we didn'tdo any more hiking that day.  Conditions were good, partly cloudy and no rain, but we weren’t in the mood for it.

Dinner was at 18:00, the famous AMC turkey dinner with all the fixings.  I don't know how, but the Croo killed the turkey and dried it out to leather.  Worst bird I ever had.  Even my knife couldn't cut it.  To add insult to injury the pumpkin pies for dessert were also burnt.

We took part in the Croo's program for the night where they talked about all the ways the huts make themselves self-sustainable.  By 20:00 we saw beautiful sunset and the skies were clear.  

Sunday brought cloudy morning skies.  Somehow the Croo screwed up oatmeal but the remainder of breakfast was OK.  We packed our things and got started at 08:10 on the Crawford path to Camel Trail.  Our hike was 4.5 miles with 3,001 feet descent and an estimated time of 3:15.  We took the Camel Trail to Davis Path to Boott Spur.  Then we followed Boott Spur to Tuckerman Ravine Trail (approx 2.9 miles).  Tuckerman Ravine Trail was undergoing some constructions so we were detoured down the ski trail to end at Joe Dodge Lodge / AMC Pinkham Notch Visitor Center.

We lost all track of time after starting our hike and the following times are estimates.  The views were lackluster in morning due to being in the clouds.  It was in the 50s and breeze when we started so we started with our rain jackets.  By the time we got to the Davis Path it warmed up and we shedded layers.  Due to the early morning cloud cover we could not see “The Lawn” or Mt Washington.  Later on it became partly sunny and breezy.

At 08:45 we climbed Boott Spur (pile of rock), making good time because it's all very flat between Boott Spur and the Lakes Hut.  It was windy and the views cleared up allowing us to see Tuckerman’s Ravine.  We used cairns guide our way from the hut all the way to the tree line after we coming down Boott Spur.  There were great views of Pinkham Notch coming down Boott Spur.  It was very steep and we carefully picked our way down the slope.  This trail is all exposed and is not suitable to hike in really bad weather.

At the Boott Spur Link we stopped to apply some first aid to our feet and eat a snack.  We were starting to or already had blisters and brought out the moleskin and second skin from the first aid kit.

By about 10:30 as we were descending we started to see people heading up for the day.  There's a great outlook on Boott Spur where you can see Tuckerman’s headwall and Hermit Lake.  We met another couple and traded cameras, taking each other's picture.

Below tree line the trail was still wet from the previous day's rain.  During our descent my wife twisted her knee on those wet rocks and then slipped, fell off crude bridge landing on her wrist.  The wet rocks and injury added an additional hour to our descent.

The last .5 mi or so of Boott Spur was diverted to the ski trail while Tuckerman’s is under construction.  We finished the last .5 mi in a steep, muddy, hot trail.  I had trouble walking down and my wife was in pain every time she took a step.

At 14:00 we arrived at Joe Dodge Lodge and I almost threw up from exhaustion in the parking lot.  I had drank all 2L of water on the trail emptying the water blatter about 1mi from Joe Dodge lodge.  In retrospect we probably didn’t rest enough or didn’t eat enough in our rush to hike down.

We stopped for lunch at J-Town deli in Jackson.  They have great subs, you can dine in or out.  They are part general store, carrying a wide array of items.

It was 19:20 by the time we got home, almost an hour and a half later than we expected.  Our delay in getting off the mountain and traffic had set us back.

Itinerary Review

The following are my raw notes and comparison of my estimated and actual times.


Estimated
Actual

Start Friday 8/3
06:00 Leave. Drop Daisy off. Driving to Joe Dodge Lodge.
06:30 actual leave/drop off time

12:00 Arrive Joe Dodge Lodge, leave for Crawford Path Trailhead. Leave RAV4. Get a ride from Bruce to Webster-Jackson Trailhead
11:00 Arrived early, called bruce and he picked us up. Dropped us off at wrong trailhead but knew how to get to elephant rock.

13:00 Arrive Webster-Jackson Trailhead, Crawford Notch, Route 302 near Elephant Head.
12:00 arrived trail head and started hiking.

13:30 Start Hiking Webster-Jackson and Webster Cliff Trails. Depending on weather.
12:10 arrived trail head and started hiking. Took detour to elephant rock, not worth it.
(One Way: 4.3 miles, 2,150 feet, 3:15) Jackson Branch of the Webster-Jackson Trail to Mount Jackson, followed by the Webster Cliff Trail to the hut . This route is fairly easy, except for a brief scramble up to the summit of Mount Jackson, which has excellent views in all directions.
15:30 Summited Mt. Jackson. Just about book time. Took a break to eat a sandwich.
Light rain. Rain became steady as we approached Mizpah, not hard. Didn’t use gaiters/pack cover or rain jacket. Soaked from sweat. So humid.

17:00 - 18:00 Arrive Mizpah Hut
16:30 Arrived Mizpah wet.

18:00 Dinner
18:00 dinner was ok. Chicken was dry but ok. Dessert, lemon cake, was great.

20:00 Sunset.
Couldn’t see anything, cloudy. exhausted. Went to bed.

Saturday 8/4
05:30 Sunrise
06:30 Wakeup call
07:00 Breakfast
07:00 Breakfast was OK.

08:00 Start Hiking From Mizpah Hut To Lake of the Clouds Hut
08:10 started hiking. Rain. Not too hard, just constant. Put on pack covers, rain gear, gaiters, no rain pants.
(One way: 5.0 miles; 1,650 feet; Book time 3:45 h:mm) Follow the Webster Cliff Trail to its end.  Take the Crawford Path to the hut.  Summit Mount Eisenhower and Mount Monroe. This route is almost continuously exposed from the summit of Mount Pierce onwards; there are patches of scrub before reaching Mount Eisenhower, none after that.
Rain turned into a complete downpour. Soaking wet inside and out, rain gear trapped heat/moisture. “Stewing in our own juices”. Trail conditions bad, flooded. Trail became a river and couldn’t stay out of it, feet soaking wet. Trail slippery, Steph slipped a couple of times.
09:00 Summited Mt. Pierce
11:00 Summited Mt. Eisenhower in pouring rain. Rain lessened some coming down Eisenhower.
12:00 Arrived at the Monroe Loop, bypassed Mt. Monroe and headed straight for the hut.

11:30 - 12:00 Arrive Lake of the Clouds Hut
12:00 Lunch
12:30 Arrived, Lake of the Clouds hut. Demoralized, soaking wet. Rain had stopped. Changed into dry clothes. Tried to get boots to dry outside of hut, very windy. Was able to hang everything since we were first in the room. Got choice bunks.  Ate hot soup, tea.

13:00  Summit Mount Washington
(Round trip: 3.0 miles; 1,300 feet;  Book time 2:10 h:mm) The easiest way of climbing Mount Washington is as a two day trip, with a night spent at the Lakes Hut. The Crawford Path to the summit is a good trail, with reasonable footing and grades. It is, of course, totally exposed to the elements, but when the weather is good the views are exceptional.
13:00 rested and dried out. Did not summit any peaks. Conditions cleared but we weren’t in the mood for it.  Boots soaking wet.

18:00 Dinner
18:00 Dinner could have been better.  The turkey was dried out to leather and the pies were burnt.

20:00 Sunset
20:00 saw beautiful sunset. clear.  Went to bed around 20:30 - 21:00.

Sunday 8/5
05:30 Sunrise
06:30 Wakeup call
07:00 Breakfast
07:00 breakfast was ok.

08:00 Start Hiking
08:10 Started hiking Crawford path to Camel Trail.
(One way: 4.5 miles; 3,001 feet descent; Estimated time 3:15 h:mm) Hike Camel Trail to Davis Path to Boott Spur. Follow Boott Spur to Tuckerman Ravine Trail (approx 2.9 miles). Hike Tuckerman Ravine Trail going East to Joe Dodge Lodge / AMC Pinkham Notch Visitor Center.
Lost all track of time after this. Views were crappy in morning, could not see “The Lawn” or Washington, they were in the clouds.  Partly sunny. Breezy. Started hiking w/ rain jacket as it was a bit cold, windy.  Took it off on Camel Trail.

08:45 (Maybe) Summited Boott Spur (pile of rock), made good time because it was very flat.
Windy, good views. Views cleared when we got to Boott Spur. Could see Tuckerman’s Ravine.  Used cairns to travel from Hut all the way to the tree line after we came down Boott Spur, a few miles.  Great views of Pinkham Notch coming down Boott Spur. Very steep, lots of rock picking.  All exposed.  Would not hike in bad weather.

10:30 (Maybe) We were descending and started to see people.  Great outlook coming down Boott Spur, could see Tuckerman’s headwall and met some people who took our picture.

11:00 (Maybe) Boott Spur Link. Steph remembers being hungry but it wasn’t lunch time. Could have been 11:30.

Steph twisted knee on Boott Spur when we got below tree line, then slipped, fell off crude bridge and landed on her wrist.  Mike almost threw up in the parking lot.  Drank all 2L of water, ran out of water on the trail about 1mi from Joe Dodge lodge.

Probably didn’t stop enough, didn’t eat enough.

Boott Spur diverted to Ski Trail while Tuckerman’s is under construction. Finished last .5mi in mud. Could barely walk, Steph in pain going downhill.

12:00 Lunch and drive back home
14:00 Arrived at Joe Dodge Lodge.
14:20 Got lunch at J-Town deli in Jackson, great subs.

18:00 Arrive Home
19:20 Arrive home, traffic and we left later than planned.


Gear Review

Every trip I do a gear review of what worked and didn't work.

Backpacks
Ok Osprey Aero 65, Deuter 36
Didn’t use, not sure it’s needed. Small, gray daypack

bedding
Warm enough 50deg sleeping bag, steph
crappy, would like to replace w/ travel sack. Cotton travel sheet, mike
Ok Pillow case, 2

Didn’t use but would keep Floss, 1
Used Toothbrush, 2
Used Small, travel toothpaste, 1
Used Deodorant, 1
Didn’t use, wouldn’t bring again Bar soap and travel case, 1
Didn’t use, might bring again facecloth, 2
Didn’t use, wouldn’t bring again Wipes, small travel pack, 1
Used, must bring sunscreen
Didn’t use, wouldn’t bring again Bug spray

Must bring. Would try to consolidate asprin, find smaller bottles.
Personal first aid kit
Emergency poncho
Mylar blanket
Ace bandage/athletic wrap
Nail clippers
Aspirin (am/pm)
Tape
Gauze
bandaids
Hand sanitizer
Antibiotic
Moleskin
Blister second skin
Gauze roll
Tweezers
Foldable scissors

Mike would have brought zip-aways, cold at night Shorts
boxers
Short sleeve wool shirts, 3
Mike should have brought a mid. midlayer, 1 steph
Boots
sneakers
Just right amount, Mike. Steph glad she brought 6. Socks, 4 (mike); 6 (Steph)
Unclear if this helped Steph. Blue rain jacket too hot, Mike. Rain jacket
Didn’t use. Rain pants
Must have. Hat
Worked OK until we had to wade through the Crawford River. (Trail flooded) gaiters
Mike should have brought PJs Pjs (Steph only)

Knife
map
compass
paracord
Tenacious tape
pencil
pad
headlamp
Extra batteries
Mike shouldn’t have brought two books. Book (mike, 2)
didn’t use Handkerchief, mike
Watch, steph

Just right. Protein bars, 8
Water bladders
Water bottle, small, steph
Didn’t eat, but should still keep. Emergency food. Beef jerky
Good number. Didn’t eat 2, that’s OK. Pb & J flatbread sandwiches, 8 

Friday, March 3, 2017

Providence VMUG Announcement

  I answered the call to start Providence VMUG from Rob Bergin (then Liberty Mutual, now Cisco) who was involved with Boston VMUG at the time.  Back then VMUG was just getting started.  In the Northeast we had Chris Harney and the VTUG for a few years but VMUG was a new thing.

  My boss, Andy Fuss at CharterCare Health, was supportive and helped run the first meeting.  We had Presidio sponsor and went to Trinity Brewhouse for a great social hour after the meeting.  It was a memorable first meeting.  Since 2012 we've held fifteen meetings and several vBeers meetups.

  Last year we successfully completed a service project working with the non-profit Tech Collective where we trained fifteen people over the course of six weeks.  We had volunteers from Providence VMUG and VMware proctor and help attendees, donating over 50 volunteer hours of their time.

  It has been a wonderful and fantastic journey and now it's time to move on.  As I focus more on devops tools, process and people I've moved away from VMware technologies.  I'm working closer with developers, managing systems as code and adopting software development practices and using a variety of technology and tools.

  Today I'm stepping down as VMUG Leader for the Providence VMware User Group to let people more connected with VMware lead the group on to new topics.  I'm not far if you need advice, a speaker or just want to chat.  The great VMUG community has my sincere thanks for everything and I'll always be a part of that.

Thursday, September 1, 2016

Making PS DSC modules available to nodes.

Editor's Note: Started working with Desired State Configuration (DSC) and boy do I miss the things Puppet automates for me!


I've been working with PowerShell DSC and have an interesting scenario:
  • You want to use other resources, like xFirewall, to manage firewall state on a node.
  • You are 'push'ing your configuration to nodes.
  • Problem: nodes need the modules installed on them.
You might run into an error similar to this:
Cannot find module xNetworking_2.11.0.0 from the server
https://pull.contoso.com:8080/PSDSCPullServer.svc/Module(ConfigurationId='c41c31d5-67e4-4f80-8204-f749ff1ae192',ModuleName='xNetworking',ModuleVersion='2.11.0.0')/ModuleContent. Could not install module dependencies needed by the configuration.
You could switch your nodes from push to pull mode.  Nodes will pull modules in addition to their configuration.  But maybe you don't want to use pull mode.

First you'll need to configure your nodes to use a pull server.  Configure the DSC Local Manager like you normally would for a node but only use this configuration.  Leave the node in push mode.  But now the node knows where to look for modules, if required.  Replace ServerUrl with your pull server.  What do you mean you don't have a pull server?
  ConfigurationRepositoryWeb PullServer
 {
  ServerUrl = 'https://pull.contoso.com:8080/PSDSCPullServer.svc'
 }
See the gist if you haven't opened it yet.  The gist shows a DSC where we're using xFirewall and xSmbShare resources, both resources aren't installed by default.  They come from the xNetworking and xSmbShare modules, respectively.

The gist includes some additional powershell to package the modules we're using and place them in the pull server's modules directory.

Packaging modules for download by nodes is a pain in the ass.  Maybe you've come across an error like this:
module file did not contain a module with required version
You cannot simply archive the module at its path:
C:\Program Files\WindowsPowerShell\Modules\xNetworking
You must archive the files within the directory corresponding the module version you want.  Assuming you want the latest version, you can use the cmdlet Get-Module find the version.
$version = (Get-Module -ListAvailable $module).Version.ToString()
Then you can package all the files in the module's base directory, ala the method .ModuleBase from Get-Module, into an archive named "$module_$version.zip"

I'd like to find a way to use the $modules array in the Import-DscResource statement on line 11.  It would make this sort of snippet more reusable.  I wouldn't be repeating myself by defining required modules in two places.

Tuesday, May 31, 2016

Speaking History

Over the past couple years I've been lucky enough to present and give a few talks either at conferences or on webinars.  Here's a list along with links to the slides (if any).








Tuesday, May 10, 2016

Testing Puppet Code: Bundle, Rake and Gems. Oh My! Part 3

This is the third post in a series on testing Puppet code.  The first two posts explored why we should test code and how to use Puppet's 'puppet parser validate' and rodjek's 'puppet-lint' commands.  In this post we'll set up the Ruby framework needed to run 'puppet parser validate' and 'puppet-lint' via the Ruby gem.  The Ruby framework will also allow us to add unit tests with rspec.

A collection of Puppet code, tests, and associated templates and files is called a Puppet Module.  All of those files should be in a single directory named 'your_puppet_module'.  Your Puppet manifests should be in a directory named 'manifests'.  See the Puppet documentation for more information on Puppet module layout.  Although not required, if your Puppet code is not currently in a module format you should try to get it into a module format now.

Example:
- your_puppet_module
|
| - manifests
  | - init.pp
  | - another_manifest.pp

Before following the examples please install ruby and bundler on your system.

The Gemfile and Rakefile


We'll use Ruby's 'rake' command to run puppet-lint.  'rake' is a Ruby tool used to run repetitive tasks, such as tests.  'rake' uses a special file named 'Rakefile' where we configure the tasks we want to run.

The 'Rakefile' can require other Ruby gems to run the tasks we write.  We will use the Ruby dependency manager bundler to manage the Ruby gems our 'Rakefile' needs.  'bundle' uses a configuration file named a 'Gemfile'.  The 'Gemfile' lists the Ruby gems and version.

Our sample Puppet module has a 'Rakefile', 'Gemfile', and a manifests directory with a sample manifest.  The 'Gemfile' contains our two dependencies: 'puppet-lint' and 'rake'.  The 'Rakefile' requires the 'puppet-lint' gem.

Clone the sample repository and look at the 'Rakefile' and 'Gemfile'.
git clone https://github.com/mmarseglia/testing_puppet.git

Running puppet-lint


According to the 'puppet-lint' documentation all we have to do is run 'rake lint' after the module is installed.

Clone the sample repository.
git clone https://github.com/mmarseglia/testing_puppet.git
Enter the directory and checkout example1.
cd testing_puppet
git checkout example1 
Use bundler to install required Ruby gems in a directory local to our project,
bundle install --path vendor/bundle
Run the puppet-lint task on our Puppet code. We prefix the 'rake' command with 'bundle exec'.  This runs 'rake' in context of the gems we installed.
bundle exec rake lint

Congratulations!  We just ran puppet-lint as a rake task and it checked all the Puppet manifests in our project.  puppet-lint found some problems but those files aren't part of our project.  We'll need to configure puppet-lint to ignore that directory.

Checkout the tag named 'example2'.
git checkout example2
In example2 I've made two modifications to the Rakefile:
  1. Clear any previous definition of the rake task named 'lint'.
  2. Configure puppet-lint to ignore vendor directory

Run the rake task again and puppet-lint is no longer checking files in the vendor directory.


puppet-lint can be configured entirely in the 'Rakefile'.  You can still use puppet-lint's configuration file named .puppet-lint.rc when puppet-lint is called as a rake task. 

Running puppet syntax checks


Adding Puppet syntax checks to the 'Rakefile' is just as easy.  Let's look at example 3 to see the changes.

Checkout the tag named 'example3'.
git checkout example3
We need two new Ruby gems: puppet-syntax and puppet.  The puppet-syntax gem has a rake task named 'syntax' that will check our manifests and depends on the puppet gem.  The Ruby gems are added to our Gemfile.


We require the puppet-syntax gem in the 'Rakefile' to be able to run the 'syntax' task and, like puppet-lint, we'll configure it to ignore the 'vendor' directory.



Run the rake command to check our manifests for any syntax errors.  No errors!
bundle exec rake syntax 

What if we had errors in our code?  What would that look like?  I've inserted an error into example 4 so we can see what happens.

Checkout the tag named 'example4'.
git checkout example4
 Run the 'rake' command to check our manifests for any syntax errors.
bundle exec rake syntax

Puppet could not parse our manifest, init.pp, due to a missing curly brace at the end of the file.  The syntax check will tell you the line number, the file and error message.  The error message is the same if we run the 'puppet parser validate' command.


The puppet-syntax rake task will also check templates and hiera YAML files if present.  You can read the full documentation for puppet-syntax on GitHub.

Conclusion


In the previous blog posts I demonstrated running 'puppet-lint' and 'puppet parser validate' on the command line.  Many shell scripts take advantage of those command line utilities and I relied heavily on scripts when I started.  The command line utilities may have a place in your environment but advancing to the next level of testing with rspec and beaker requires laying a foundation.

We started with our Puppet code and gathering our manifests, templates and file into something more resembling a Puppet module.  Then we install ruby and bundler in our development environment.  After bundler is installed we add the 'Gemfile' to our project to manage our Ruby gem dependencies.  Lastly we create a 'Rakefile' that defines the rake tasks we will repeatedly run to lint and syntax check our Puppet code.  Now we have a project that can be easily added to a continuous integration system and can start building a software development pipeline for our Puppet code.