Beginning My First PowerShell Module

If this is the first post you land on within my site, then you probably don’t really know the passion I have for working with PowerShell. I won’t wax philosophical about it, nor will I give you a life story before getting to the recipe (I am not a food blogger), but I’ll try to do my best to explain the way I went about getting started on this, my first attempt, of a PowerShell module.

First and foremost, I’m not, nor have I ever pretended to be, a developer. That being said, I’ve taken my share of programming classes, I’ve tried to keep up on the way that modern programmers do their work, and I have friends and colleagues who are professional developers. I like to say that I know enough to be dangerous about a plethora of things technology-related.

About a year ago, I was introduced to a new piece of software that my company started to use for our community. As I do with all new technology, I got in and started kicking the tires. I learned how data was organized, how various portions interact with each other, and generally the way things operate from a “user” perspective. I knew that, at some point, I’d be asked to be a part of the administration of this service, so I wanted to get a better understanding of the day-to-day operations. During those early days, I didn’t really think about leveraging the community’s API, but that didn’t last for long.

Why the API?

I have professed in the past my mantra about scripting:

  1. Do it once, do it by hand.
  2. Do it twice, think about ways to script it.
  3. Do it thrice, it should be scripted.

If we are all honest with ourselves, there are just some things that work better when automated – especially if it eliminates the human error or saves you time. Time is that one resource you will never be able to recover. Since I was going to be interacting with this product daily, I wanted to see if there was any way I could automate some of the more tedious and error-prone work. For this solution, the way to do that was via the RESTful API.

Let’s take the simplest of scenarios: I want to lookup a member by their username or email address. This is trivial in the administration interface – simply type in the information you have and you get matches back. It couldn’t be simpler. This made looking up a user a great test to see if I could work with the API.

First Tests with PowerShell

Once I knew that I wanted to try my hand with this simple task, I needed to learn a little bit more about how the API operates. Thankfully, Telligent has provided excellent documentation around all parts of their API. The part I read was Show User REST Endpoint. To be completely fair, I’m a scripter and not a developer, so I read the top block about the URIs and parameters to use and then scrolled down to the cURL example to understand what’s actually going over the network.

curl -H "Rest-User-Token: ENCODED_TOKEN" -X GET https://mysite.com/api.ashx/v2/user.xml

My mind broke this up into three different pieces: the header, the base URL for the community, and the segments that make up the rest of the URI. I read a little bit more about how to get and authenticate with an encoded token, then wrote a few lines of PowerShell to do this work for me.

[Convert]::ToBase64String( [Text.Encoding]::UTF8.GetBytes( "$( $ApiKey ):$( $Username )" ) )

Put in the API Key and the username and it spits back the encoded token. Easy enough.

Then I made a call using my own account.

Invoke-RestMethod -Uri "https://mycommunity.company.com/api.ashx/v2/user.xml?Username=$Username" -Headers @{ "Rest-User-Token" = $EncodedToken }

No errors and I got back a blob of XML content – I call that a success. I’m trying to up-level my skills and decided to instead use the JSON endpoint (same as above, but swap json instead of xml in the URI). The JSON content comes back in its own custom PSObject, and wasn’t buried within an XML object. I decided this was the way to go.

Storing the return as a variable, I could easily enumerate my user account details.

$MyUser = Invoke-RestMethod -Uri "https://mycommunity.company.com/api.ashx/v2/user.xml?Username=$Username" -Headers @{ Rest-User-Token: $EncodedToken }
$MyUser.User

Now I know that I have the skills necessary to make a call against the API and return valuable data – for my own or any other user I wanted to query. But I’d need to change the URI every single time.

Why bother with building functions?

Most of using this functionality will be repeating the exact same thing and only swapping out a few pieces of information (most notably the parameters passed to the URI). The authentication header, the community URL, and the base URI will remain the same for each call to this API.

Since this was also repeatable, I thought it would make sense to build a PowerShell function for this work. The original definition of this Get-VtUser function (for ‘Get Vertint/Telligent User’) looked a little like this:

function Get-VtUser ($CommunityUrl, $Token, $Username)
{
    $MyUser = Invoke-RestMethod -Uri ( $CommunityUrl + 'api.ashx/v2/user.xml?Username=' + $Username ) -Headers @{ 'Rest-User-Token' = $EncodedToken }
    $MyUser.User
}

Simple, easy, and to the point – call the API and return the User information. The returned content is the user information, but it’s all the user information. At least 80% of it is useless for most people. Additionally, I didn’t want to be the only person at my company who could do this work, so I needed to think about expanding the function.

I won’t bore you with all the iterations (there have been at least 15 of just this function), but eventually, I decided what I really needed was a bunch of functions to help with the administration work. The current version of this function is published here.

One function isn’t enough

When I really thought about it, one function (or even a small library of functions based around Users) wasn’t going to be enough. I needed to get information on posts, blogs, posts, and so much more if I didn’t want to be the only person doing this work.

So I started to build functions around points, groups, challenges, and forums. Then I had to collect those together in a place where I could functionally work with them.

Planning

As I said earlier, I am not a developer, so I don’t have scrum meetings or stand-ups, or other things, but what I do have is a little Project Management in my background. Building a list of requirements that I can tackle one at a time was something I’m capable of accomplishing.

My sketch of what I needed to build looked a little like this using traditional CRUD processes (and the associated acceptable PowerShell verbs):

  • User Management
    • Create -> New
    • Read -> Get (limited data returns and full data returns)
    • Update -> Set
    • Delete -> Remove
  • Points Management
    • Same as above
  • Challenge Management
    • Same as above
  • Group Management
    • Same as above

It can be a daunting list when I first looked at it, so I decided to build portions as I needed them. If you’d like to see how this looks now, you are welcome to clone my GitHub of vtPowerShell.

Once I get everything together and working as expected, then I’ll start on the next step about defining and building them properly as a PowerShell module.

Thanks for reading with me and if you have anything you’d like to contribute, please feel free to let me know!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.