In the past few posts in this series, I’ve tackled how to perform basic authentication and use the GET method to pull down data. Now, I’ll dive into some of the methods available for sending data to a RESTful API endpoint by way of PowerShell code. The idea is to give you a head start on how to structure the API calls so that you can write your own. I’ll be using a Rubrik cluster as my endpoint, but again – any RESTful endpoint should be similar in nature. It’s just the body content format and supported methods that should vary from solution to solution.
Creating Objects with POST
The first method we’ll cover is POST, which I previewed back in the basic authentication article. This method tells an endpoint that something new is to be created and the response from the server will indicate both the status of the API call and a response with details on the activity. POST is not idempotent nor is it safe, meaning multiple requests yield varying results and data is modified.
It’s important to differentiate between the call status versus the response content. You could, for example, successfully contact the RESTful endpoint and receive a status code of 200 which means “OK.” However, the call itself may fail because the server has a blocking task or is otherwise unable to fulfill your request. The details on the issue would reside in the response content. Because of this, you should not base the success or failure of an operational solely on the API status code. You can, however, use the status code to determine if the call was even submitted to the server. A complete list of status codes can be found on Wikipedia here.
Let’s get to the code. I’m going to perform a simple POST request that asks a Rubrik cluster to take an on-demand backup of a virtual machine. All I need is the VM ID, which is a combination of the vCenter UUID and VM’s MOID, and the URI of the collection (/job/type/backup in this example). For brevity’s sake, I’ve pulled the VM information and have included it below.
# Required API Variables $uri = 'https://brik1.rubrik.demo:443/job/type/backup' $body = @{ vmId = '0b046b24-3fdb-4b33-b0c8-670fa1e96075-vm-6409' } # RESTful API Call $r = Invoke-WebRequest -Uri $uri -Headers $global:RubrikHead -Method Post -Body (ConvertTo-Json -InputObject $body)
The code above takes the ID of a single VM, stores it in a hashtable, and then submits that in JSON format to the collection URI stored in $uri. Because I used Invoke-WebRequest, I can also check the status code and status description of the API call by querying the $r variable where the call results are stored. In this case, the status code is 200 and the status description is OK. Thus, the endpoint received the request.
Because Rubrik formats data using JSON, digging deeper into the response content requires a conversion from JSON back into a PowerShell System.Object. To do this, use ConvertFrom-Json. Note that I could have also used Invoke-RestMethod to pull the content directly, but then I would not have the status codes I showed earlier. I consider that a deal breaker.
ConvertFrom-Json $r.Content status description ------ ----------- Success CREATE_SNAPSHOT_0b046b24-3fdb-4b33:::0
The content information comes directly from the server, and indicates that the request was successful while also supplying a job ID corresponding to the on-demand backup request. This can be referenced to track the job within the system, if desired.
In this particular case, both the API call and server response indicate that the request was successful. Checking the activity log in Rubrik verifies this.
Next, we’ll look at how to update the data within an object.
Updating Objects with PUT
From my experience, the PUT method is primarily used to update an object’s content. However, there are instances where PUT is used to create an object. PUT is idempotent but not safe, meaning multiple requests yield identical results and data is modified.
One of my largest complaints with the PUT method is that it requires that you send over the entire list of object properties, even if you just want to update one or a few properties. Meaning, if an object has twenty properties, you have to send over a body that contains all twenty properties- even if you want to modify one of them. I commonly ran into this challenge with VMware’s NSX API, requiring me to first GET an object’s properties, read them in, and then send back the properties (with one or two modified) using a PUT. If you fail to send over a property when using PUT, the API will assume the value is null and subsequently set the property’s value to null.
Here’s an example of what a PUT would look like to VMware NSX. Note that NSX uses XML format for body contents, not JSON.
# Required API Variables $uri = 'https://nsx1.glacier.local:443/api/2.0/vdn/controller/cluster' $body = '<controllerConfig> <sslEnabled>true</sslEnabled> </controllerConfig>' # RESTful API Call $r = Invoke-WebRequest -Uri $uri -Method Post -Body $body -ContentType 'application/xml'
Rubrik doesn’t use the PUT method, choosing to instead embrace the PATCH method.
Updating Partial Objects with PATCH
I’ve written about using PATCH in a prior post. The syntax is identical to a PUT, but the resource will only update properties that are included in the body contents. Meaning, if you have a resource that contains twenty properties, but only wish to update one of the properties, you can PATCH a single property. I’ve found that this avoids the need to GET property details because we’re only interested making a change to one or more properties and already know what their new values should be. It doesn’t completely eliminate using GET for instances where I need to apply logic to current property values, but is still very handy and a much more efficient transfer of data to the endpoint.
PATCH is not idempotent nor is it safe, meaning multiple requests yield varying results and data is modified.
Let’s say that you want to update the protection policy – Rubrik calls this an SLA Domain – for a virtual machine. Looking at the model schema of /vm/{id} reveals a number of properties that can be updated. I’ve added a blue arrow to show where the property list resides.
According to Rubrik’s Swagger-UI, there are three properties listed that can be updated. However, I only want to change the SLA Domain (slaDomainId) property. Using PATCH, this is simple. I only need to provide the slaDomainId key-value pair to the body, convert it to JSON, and send it to the VM’s resource ID. Below is a sample bit of code.
# Required API Variables $uri = 'https://brik1.rubrik.demo:443/vm/0b046b24-3fdb-4b33-b0c8-670fa1e96075-vm-6409' $body = @{ slaDomainId = 'GOLD_aa4c5eee-51d6-4901-aeb4-5ba44f7f65cc' } # RESTful API Call $r = Invoke-WebRequest -Uri $uri -Headers $global:RubrikHead -Method PATCH -Body (ConvertTo-Json -InputObject $body)
The resulting response content shows all of the details outlined in the response class from Swagger-UI. I can see that my VM has been placed in the Gold SLA Domain without altering the other properties that I didn’t specify in the PATCH request.
ConvertFrom-Json $r.Content id : 0b046b24-3fdb-4b33-b0c8-670fa1e96075-vm-6409 managedId : VirtualMachine:::0b046b24-3fdb-4b33-b0c8-670fa1e96075-vm-6409 moid : vm-6409 name : SE-CWAHL-WIN powerStatus : poweredOn slaDomain : @{id=GOLD_aa4c5eee-51d6-4901-aeb4-5ba44f7f65cc; primaryClusterUuid=6bd222b3-f416-475b-a93c-227859dba170; name=Gold; frequencies=System.Object[]; replicationSpecs=System.Object[]; isDefault=True; uiColor=#f8c044}
Note that not all APIs will support PATCH, so you may be stuck using GETs and PUTs to read-then-modify resource properties. Either check your vendor’s API documentation, use an API explorer, or try using the OPTIONS method if you’re really, really lucky.
Congratulations, you should now know how to use the three RESTful API methods that can create or update objects and their respective properties! Wield this great power for the glory of your data center and remember to be responsible with your PUTs. 🙂