For our blue/green deployments in Octopus Deploy, we created some custom Powershell cmdlets to talk to our A10 Thunder load balancer. The cool thing about our cmdlets is that it uses the A10’s nicely documented REST APIs to manipulate all sorts of things in the device. And this is a good thing, because, frankly, the A10 web based dashboard UI really sucks. Using the API has proven to be a lot faster, with the added benefit of enabling us to create a custom Hubot script (but that’s a blog post for a different day).
I had a situation today where I needed to modify one of these Powershell cmdlets that sends a JSON request for updating a virtual service. The request was previously just created as a string since it was so simple (just needed to update a single “service-group” property). But today, I had to optionally update an aFlex rule associated with a virtual service. And in this case, string manipulation seemed really ugly.
Here’s what the code previously looked like:
$body = “{ “”ports”” : { “”service-group”” : “”$ServiceGroup”” } }”
This is simple enough, and just shoving it into the request as a string was sufficient. But, now, to make this a bit more “future proof,” let’s turn this into a custom Powershell object instead:
$body = @{ “ports” = @{ “service-group” = “$ServiceGroup” }}
Cool, now we have “service-group” as a property. And converting this into a JSON string to send in our request is easy:
PS D:\> ConvertTo-Json $body { "ports": { "service-group": "staging-service-group" } }
Now, for my new requirement, I need to modify the object’s port.aflex-scripts property. According to the A10 AXAPIv3 documentation, the property is a JSON array of “aflex” objects. So let’s do this:
$body.ports += @{ “aflex-scripts” = @( @{ “aflex” = “$AflexRule” } ) }
This is creating a new property called “aflex-scripts” as an array. This array has a single element with a name of “aflex” and a value of the $AflexRule variable that was passed into the function. So now when we convert to JSON, we have the desired shape:
PS D:\> ConvertTo-Json $body { "ports": { "aflex-scripts": [ "System.Collections.Hashtable" ], "service-group": "staging-service-group" } }
Wait a sec, the JSON is showing “System.Collections.Hashtable.” That’s not right. We need to use the “-Depth” parameter to tell the conversion to apply for the various levels of our object. So let’s fix that:
PS D:\> ConvertTo-Json $body -Depth 3 { "ports": { "aflex-scripts": [ { "custom-redirect-rule" } ], "service-group": "staging-service-group" } }
Ok, that looks much better. And is exactly what we want.