Exploring Tanzu Mission Control API — Part II

Mike Carpendale
6 min readFeb 13

--

See over there….. that's where I’m going — Photo by Jason Abdilla on Unsplash

Becoming mission possible

Welcome to my series of ramblings ……. This is part II of my exploration into Tanzu Mission Control API. You can read the background in Part I here

I’m happy to report that after the help of Dean, Eknath, Morgan, and Corey — I can get the required data from TMC via API.

{
"clusterName": "sg-tkg-vsp-demo05",
"name": "k8s-counter-deployment",
"object": "Deployment",
"totalPods": null
}
{
"clusterName": "sg-tkg-vsp-demo05",
"name": "k8s-counter-deployment-5d48bb8988",
"object": "ReplicaSet",
"totalPods": null
}
{
"clusterName": "sg-tkg-vsp-demo05",
"name": "postgres",
"object": "Deployment",
"totalPods": null
}
{
"clusterName": "sg-tkg-vsp-demo05",
"name": "postgres-5c6d847dd",
"object": "ReplicaSet",
"totalPods": null
}
####
#AND
####
{
"clusterName": "sg-tkg-aws-demo2",
"name": "k8s-counter-deployment",
"object": "Deployment",
"totalPods": 3
}
{
"clusterName": "sg-tkg-aws-demo2",
"name": "k8s-counter-deployment-6dbc5d8b78",
"object": "ReplicaSet",
"totalPods": 3
}
{
"clusterName": "sg-tkg-aws-demo2",
"name": "postgres",
"object": "Deployment",
"totalPods": 1
}
{
"clusterName": "sg-tkg-aws-demo2",
"name": "postgres-7957478b7d",
"object": "ReplicaSet",
"totalPods": 1
}

I’m starting to feel like this will be possible….. Now to get it into my web page.

My web page has some buttons that will direct you to “other” pages, php pages where the code is “embedded” or “intermingled” that will kick off the magic of moving my cloud native app from on prem to a webscale cloud

the old view

I’m going to do a “part” redesign of the pages. I’m sure this can be done much better with an html page, JavaScript and AJAX……. but that is a future me problem.

  • the home page is developed with nicepage in html. It will eventually be a php page
  • It will pull in the status of the Workloads each time it loads with some “embedded” php code
the new interim view — home page with env status

On the new Home page, I the TMC API is pulling my data and it’s displayed in my table. You can see that the PODs are running in the ON-PREM env

Clicking on the failover button or tab, you navigate to the failover.php page, where the following happens;

  • “embedded” php code is executed to move my cloud native app from the ON-PREM env to AWS
  • these command results are echoed to the webpage so you can see what happened
  • Demo Environment Status table is updated (TMC API calls)
failover page — show env status — PODs now in the cloud

And well — Failback is exactly that — moving my stateful cloud-native app back to its ON-PREM env. No one should be accepting a one way failover…..

time to gets a busy with some code…….. Photo by Jeriden Villegas on Unsplash

So what do I need to do……… gets me a build’n …… first off is to convert these lines (from part I) into some php code.

refresh_token="replace with your Token"
access_token=$(curl -d "refresh_token=$refresh_token" https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/authorize | jq -r '.access_token')
curl -s 'searchScope.name=*' 'https://<your-name>.tmc.cloud.vmware.com/v1alpha1/clusters/*/objects?sort_by=fullName.clusterName%3Aascending%2CfullName.name%3Aascending&includeTotalCount=true&query=data.kind%3A%5B%27Deployment%27%2C+%27ReplicaSet%27%2C+%27StatefulSet%27%2C+%27DaemonSet%27%5D+AND+%28meta.namespace%3A%27*migration*%27%29+AND+%28fullName.clusterName%3A%27*vsp*%27%29&pagination.size=25&pagination.offset=0' -H "Authorization: Bearer $access_token" | jq '.objects[] | {clusterName: .fullName.clusterName, name: .fullName.name, object: .data.kind, totalPods: .data.aggregatedResources.totalPods}'
curl -s 'searchScope.name=*' 'https://<your-name>.tmc.cloud.vmware.com/v1alpha1/clusters/*/objects?sort_by=fullName.clusterName%3Aascending%2CfullName.name%3Aascending&includeTotalCount=true&query=data.kind%3A%5B%27Deployment%27%2C+%27ReplicaSet%27%2C+%27StatefulSet%27%2C+%27DaemonSet%27%5D+AND+%28meta.namespace%3A%27*migration*%27%29+AND+%28fullName.clusterName%3A%27*aws*%27%29&pagination.size=25&pagination.offset=0' -H "Authorization: Bearer $access_token" | jq '.objects[] | {clusterName: .fullName.clusterName, name: .fullName.name, object: .data.kind, totalPods: .data.aggregatedResources.totalPods}'

Off to ChatGPT I go and I end up with this after a few iterations.

<?php

$refresh_token = "replace with your Token";
$access_token_json = shell_exec("curl -s -d \"refresh_token=$refresh_token\" https://console.cloud.vmware.com/csp/gateway/am/api/auth/api-tokens/authorize");
$access_token_array = json_decode($access_token_json, true);
$access_token = $access_token_array['access_token'];
$vspcluster_json = shell_exec("curl -s 'https://<your-name>.tmc.cloud.vmware.com/v1alpha1/clusters/*/objects?sort_by=fullName.clusterName%3Aascending%2CfullName.name%3Aascending&includeTotalCount=true&query=data.kind%3A%5B%27Deployment%27%2C+%27ReplicaSet%27%2C+%27StatefulSet%27%2C+%27DaemonSet%27%5D+AND+%28meta.namespace%3A%27*migration*%27%29+AND+%28fullName.clusterName%3A%27*vsp*%27%29&pagination.size=25&pagination.offset=0' -H \"Authorization: Bearer $access_token\"");
// echo $cluster_json;
$vspcluster_array = json_decode($vspcluster_json, true);
$awscluster_json = shell_exec("curl -s 'https://<your-name>.tmc.cloud.vmware.com/v1alpha1/clusters/*/objects?sort_by=fullName.clusterName%3Aascending%2CfullName.name%3Aascending&includeTotalCount=true&query=data.kind%3A%5B%27Deployment%27%2C+%27ReplicaSet%27%2C+%27StatefulSet%27%2C+%27DaemonSet%27%5D+AND+%28meta.namespace%3A%27*migration*%27%29+AND+%28fullName.clusterName%3A%27*aws*%27%29&pagination.size=25&pagination.offset=0' -H \"Authorization: Bearer $access_token\"");
$awscluster_array = json_decode($awscluster_json, true);
//print_r($awscluster_array);

$vspoutput = "";
if (array_key_exists('objects', $vspcluster_array)) {
foreach($vspcluster_array['objects'] as $object) {
// echo "Cluster Name: " . $object['fullName']['clusterName'] . "\n";
$vspoutput .= "Name: " . $object['fullName']['name'] . "\n";
$vspoutput .= "object: " . $object['data']['kind'] . "\n";
// echo "totalPods: " . $object['data']['aggregatedResources']['totalPods'] . "\n";
if(array_key_exists('aggregatedResources', $object['data']) && array_key_exists('totalPods', $object['data']['aggregatedResources'])) {
$vspoutput .= "totalPods: " . $object['data']['aggregatedResources']['totalPods'] . "\n";
} else {
$vspoutput .= "totalPods: 0\n";
}
$vspoutput .= "\n";
}
} else {
$vspoutput .= "No objects found in the response\n";
}

// echo $vspoutput;

$awsoutput = "";
if (array_key_exists('objects', $awscluster_array)) {
foreach($awscluster_array['objects'] as $object) {
// echo "Cluster Name: " . $object['fullName']['clusterName'] . "\n";
$awsoutput .= "Name: " . $object['fullName']['name'] . "\n";
$awsoutput .= "object: " . $object['data']['kind'] . "\n";
// echo "totalPods: " . $object['data']['aggregatedResources']['totalPods'] . "\n";
if(array_key_exists('aggregatedResources', $object['data']) && array_key_exists('totalPods', $object['data']['aggregatedResources'])) {
$awsoutput .= "totalPods: " . $object['data']['aggregatedResources']['totalPods'] . "\n";
} else {
$awsoutput .= "totalPods: 0\n";
}
$awsoutput .= "\n";
}
} else {
$awsoutput .= "No objects found in the response\n";
}
// echo $awsoutput
?>

Hey ChatGPT can you document my code

This script retrieves information about objects (Deployment, ReplicaSet, StatefulSet, and DaemonSet) in VMware clusters. The information is obtained by making REST API calls to the VMware Tanzu Mission Control (TMC) API.

Here’s a step-by-step explanation of the code:

1. A refresh token is defined with a placeholder value.

2. A CURL command is executed to obtain an access token, by sending a request to the TMC API with the refresh token. The response is in JSON format, and it’s stored in the $access_token_json variable.

3. The JSON response is then decoded into an associative array using the json_decode() function, and the access_token value is extracted from the array and stored in the $access_token variable.

4. Two more CURL commands are executed to retrieve information about objects in two different types of clusters: vspand aws. These commands use the access token obtained in step 3 to authenticate the request. The results are stored in $vspcluster_json and $awscluster_json variables, respectively.

5. Both JSON responses are decoded into arrays using the json_decode() function, and stored in $vspcluster_array and $awscluster_array variables.

7. The code then checks if the objects key exists in each array, and if it does, it iterates over each object and prints its name, kind, and totalPods (if it exists). If the totalPods key exists in the current object, its value is printed, otherwise, it prints "totalPods not found". If the objects key doesn't exist, it prints "No objects found in the response".

Now let's get this data into my table — here’s how I’m doing that…… in 2 php sections

<thead class="u-custom-color-2 u-table-header u-table-header-1">
<tr style="height: 49px;">
<th class="u-border-1 u-border-custom-color-2 u-table-cell">On Prem</th>
<th class="u-border-1 u-border-custom-color-2 u-table-cell u-table-cell-2">Cloud</th>
</tr>
</thead>
<tbody class="u-custom-font u-table-body u-text-grey-80 u-table-body-1">
<tr style="height: 102px;">
<td class="u-border-1 u-border-grey-dark-1 u-custom-font u-heading-font u-table-cell">
<?php
$vsp_array = explode("\n", $vspoutput);
foreach($vsp_array as $vsp_line) {
echo $vsp_line . "<br>";
}
?>
</td>
<td class="u-border-1 u-border-grey-dark-1 u-custom-font u-heading-font u-table-cell">
<?php
$aws_array = explode("\n", $awsoutput);
foreach($aws_array as $aws_line) {
echo $aws_line . "<br>";
}
?>
</td>
Photo by Wil Stewart on Unsplash

And like that — I’m done…… for now — Tanzu Mission Control API exploration is successful.

Thanks for reading — happy API’ing
Mike

--

--

Mike Carpendale

Platform architect, digital infrastructure advocate, zwifter, coffee addict, hazy pale ale lover