Write Attributes (Use Case)

I have been recently working with a customer that has a unique use case for XaaS. They are deploying some specific instances which i will get to in another post to deep dive into that.

I wanted to utilize the write attributes to maintain a state file for the XaaS instance.

The definition of write attributes is “Add arbitrary values to the Attributes map of the target resource”
Task Types.

In this particular example I need to keep the following items in mind:

  1. there are multiple things that get deployed with this XaaS instance
  2. the end user could add to the XaaS and add additional capabilities.
  3. the end user gets an email of what was deployed with this initial provisioning of the instance.
  4. the end user also gets an email of the updated instance details.
  5. i needed a way to track what was deployed and how to delete it when the tear down phase kicks off.

In our docs, you will see mention to the following: Ensure that the RESULT TYPE value for the Task returning a JSON map is set to “JSON”. Keep in mind that the result type takes the standard out and puts that into the result type that you can then reference in write attributes task type.

I showed the customer like look heres me tracking the data using the write attributes. They said thats awesome, but i also want to see the standard out data and all the logging tracked with the instance.

Well that created a new set of challenges, because in reality I can’t pass all of my log data in json output to the write attributes task type. I needed a way to only pass specific data from my standard out into the write attributes and it needed to be in json format.

Workflow

The provision phase has 6 steps. The 3 we are going to focus on are the first 3.

Nested Lab Deployment

This is the main script that prints the json that I want and all the log data that i need to pass on to the write attributes.

Write Attributes Parsing ( the purpose of the post)

Here i take the standard out of Nested Lab Deployment and look for specific keys to grab the data between those two lines and store that and pass it along to step 3.

Write Attributes to Instance Payload

Here I parsed data from the previous task and wrote that to the instance map in the expected format.

Nested Lab Deployment (Sample output and Configuration)

The output of the nested lab deployment contains a ton of data. It helps the end user / IT admins understand whats happening and how to troubleshoot the XaaS instance.

Configuration

Instead of Result Type = Json - I set it to Single Value. This allows me to take the entire output and push that to the parsing phase to clean up the data and only extract what i am looking for.

Also note the code is write attribparse, we will reference this in the follow on script.

Sample Output of Nested Lab Deployment.

In the output you can see that before the ----json_object_start---- there is a ton of log data.

....
2023-09-14 19:34:34,373:154:morpheus_utils:add_tag_number_of_hosts:ERROR:Tags not added successfully
2023-09-14 19:34:34,373:155:morpheus_utils:add_tag_number_of_hosts:ERROR:401
2023-09-14 19:34:34,373:156:morpheus_utils:add_tag_number_of_hosts:ERROR:{"error":"invalid_token","error_description":"Access token expired: **********************"}
----json_object_start----
{
    "esxi": [
        {
            "esxiInstanceName": "C566000010",
            "esxiHostname": "C566000010",
            "esxiIpAddress": "********",
            "esxiNetmask": "********",
            "esxiGateway": "********",
            "esxiDns": "********",
            "esxiNtp": "********",
            "esxiSsh": "True",
            "esxiSyslog": "",
            "destination_vcenter": "vc1",
            "network_pool_id": 1000,
            "network_name": "Testing",
            "nestedESXivCPU": "2",
            "nestedESXivMEM": "4096",
            "ova_path": "somepath"
        }
    ],
    "vcenter": [
        {
            "json_config_path": "/tmp/C56600001.json",
            "hostname": "********",
            "username": "administrator@vsphere.local",
            "network_name": "Testing",
            "datacenter": "Testing",
            "datastore": "Testing",
            "target": "Testing",
            "deployment_option": "tiny",
            "name": "C56600001vc",
            "next_ips": "********",
            "vcNetmask": "********",
            "vcGateway": "********",
            "dns_servers": "********",
            "ssh_enable": true,
            "domain_name": "vsphere.local",
            "ceip_enabled": false,
            "destination_vcenter": "vc1",
            "network_pool_id": 1000
        }
    ],
    "storage": []
}
----json_object_end----

Write Attributes Parsing ( the purpose of the post)

Configuration

If we look at the config notice the Result Type = JSON. This will utilize the code below and print that in a way that can be consumed by the Write Attributes Task.

Also note the Code as this will be whats part of the write attributes task type.

Sample Python Script of Write Attributes Parsing.

Here we take the output from the previous task and we search for the start token and the end token and print everything in between for the next task to consume.

def extract_json_content(text):

	start_token = "----json_object_start----"
	end_token = "----json_object_end----"

	start_index = text.find(start_token)
	end_index = text.find(end_token)

	if start_index == -1 or end_index == -1 or start_index >= end_index:
		return None # Return None if the start or end token is not found, or if start comes after end

	return text[start_index + len(start_token):end_index].strip()

output = morpheus['results']['writeattribparse'] # This is the code from the previous task.  
parsed = extract_json_content(output)
print(parsed) # We print parsed output to store it in the result type for the next task to consume.  

Write Attributes to Instance Payload

Now that we have the data parsed properly - we need to write attributes to the instance map for later consumption.

Below is the configuration I used for the write attributes task. It adds to the map the json from the previous task to the map and adds it to an element named instances. You could change the element to whatever suits your needs. My example provisions out specific ovas and they are tied to instances so it made sense to keep that all mapped under the same element. You could always add to that and add other elements like as examples:

{
  "instances": <%=results.parsedattributes?.encodeAsJSON()%>,
  "firewalls": <%=results.fwparsedattrib?.encodeAsJSON()%>,
  "storage": <%=results.storageparsedattrib?.encodeAsJSON()%>
}

You would need tasks assigned to that workflow that capture those items and their respective codes, but the possibility is there to add that.

Why do I even care?

Well great question - this is keeping a running state that i can reference in other tasks and automation that can then reference this instance map and perform more automation on. Write attributes is not limited to XaaS instances either - you could use this for a whole host of other uses on new instances that are provisioned.

Theres a better way to do that

I am absolutely positive my code and my example is not the only way to achieve this. The benefit of Morpheus is there isn’t always only one way to do something. Could you write some cool groovy, shell, powershell, and other automation workflow and automation? Absolutely! We welcome and love the feedback and collaboration! Post your examples!

6 Likes

Great write up :+1: