Loading

How to write a PowerShell Module that exposes a RestAPI endpoint.

Yeah, of course I will be explaining this via the Nimble Storage PowerShell Toolkit, which is (IMHO) a great example of how to do this correctly. Perfect, well no, but its going down the right path.

The first step you will need is to get a hold of good documentation of how the RestAPI works on the particular thing you are writing a method to connect to. I would assume that you want to send encoded traffic as opposed to traffic in the clear, this means properly using credentials. Is so you will need to know at least how to form the connection request including your credentials, this will commonly return a token, and this token will be used to encode all further commands to the device.

If you examine the file ‘scripts’/helpers/ps1’ and look for the function ‘Connect-NSGroup‘ you will see how the token is obtained from the Nimble array. In this case the token is retrieved using the following $MyTokenReturnData=Invoke-RestMethod -Uri “https://10.10.10.50/v1/tokens” -method Post -body ((@data=@{useranme=’username’;password=’password’} | convertto-json

You then need to dig into this object to extract the token as such.

$MyToken=$MyTokenReturnData.data.session_token

For each subsequent Invoke-Rest you are going to want to include in the invoke-RestMethod the addition of the argument -header with the value of “@{‘X-Auth-Token’=$MyToken}”

Now that we have the basic Token taken care of, lets move on to how to implement a simple command, such as “Get-NSVolume“. We know that RestAPI uses a common CRUD type command set, meaning the options are commonly ‘Create, Read, Update, and Delete’. This is kind of in direct opposition to the RestAPI common methods, which are HTTP “Get, Post, Put, Delete, and Patch”. And since you know….Powershell, we want to map these logically to the common PowerShell verbs like “Get,Set,New, and Remove”.

In this case, to implement the Get-NSVolume command, Lets also assume that I want to make this call with no arguments. You will see from the command “Get-NSVolume” in the file Volumes.ps1 that if no parameters are set, I simply make the call to the helper function “Get-NimbleStorageAPIObjectList” function which lives in the helpers.ps1 file. This is because I found that ALL nimble objects behave this same way, and I want to the bulk of the code to be reusable. You will see from the Get-NimbleStorageAPIObjectList function that really all I do is make a call the the array using the Invoke-RestApi call to the path $BaseURI\v1\volumes and using method get, and the sub function Invoke-NimbleStorageRestAPI automatically adds the header, the command goes out very simply.

The data that is returned from this query includes the names of each volume with its ID. Since what I really want is the complete collection of these objects, I can then create a return object and make additional calls for each volume that was found as an additional call. This time however, the path will be invoke-restapi -method get -uri $BaseUri/volumes/id# and many details are returned for each volume.

As you can see, it makes it very easy to write simple code if you create your own version of the subcommands. in this example;

Get-NSVolume –> Calls Get-NimbleStorageAPIObjectList –> Invoke-NimbleStorageRestAPI.

each of these is more sub-functions is both more generic than the top level function, but each sub-level function adds something. i.e. The Get-NSVolume command knows that the object being acted upon is the Volume, so it passes that object name to the Get-NimbleStorageAPIObjectList API. This in turn knows how to query all the details for the many objects and return the collection. Additionally this function knows it is a GET command, so knows that the method to use should be “Read” and passes that along. The next level knows how to treat both read, update, remove, and create, but more importantly- it knows how to add the token header which none of the upper level functions need to know.\

Note that the Get-NSVolume command will look very similar to the Get-NSDisk command, and very similar to the Get-NSInitiatorGroup command. They all rely on these helper commands to add the know how to get things done.

I am going to go into much more detail on how this process works, and this methodology, and in fact we are using the method to write the SNIA Swordfish PowerShell Module commands as well. You will be able to follow the evolution of a PowerShell module written against an open standard live as it happens, additionally, if you are a PowerShell nut, you are welcome to join and help author some of this yourself.

Watch for the next session/blog which will go into more detail of how to include parameters