VMware Cloud Community
probo
Enthusiast
Enthusiast

vCO and JSON

A plan of mine when I started building a vCO environment was to integrate it with Puppet, so when we built VMs we could define configuration information that Puppet could use to build the system.

This was after months of searching around investigating other products like The Foreman and such.

How I do this is by reading and writing JSON to a file which is read by Hiera and fed into Puppet. Eventually we'll start using a key-value store like CouchDB, this is early days in our implementation.

However a huge problem I'm facing is the how vCO runs JavaScript, parameters passed into or out of a workflow are converted into Java objects and then back into JavaScript. From what I gather you're meant to use Properties as a object type that acts like JavaScript Objects, but it won't convert into JSON.

When trying to pass JavaScript Objects between Workflows using an Any type the same issue occurs, the object is converted to a Java type then back into JavaScript which clobbers it.

Take two example workflows:

Test javascript which creates two objects, one a flat JSON string converted to an Object and one an Object created use new Object(). It deserialises both objects and logs the output:

JSON-vCO-1.JPG

Test workflow which calls Test javascript workflow and attempts to deserialise both objects:

JSON-vCO-2.JPG

The output log is:

[2014-10-16 22:01:07.657] [I] {"a":{"b":"c"}}

[2014-10-16 22:01:07.658] [I] {"a":{"b":"c"}}

[2014-10-16 22:01:07.711] [I] {}

[2014-10-16 22:01:07.712] [I] {}

So both objects successfully deserialise in the initial workflow but once they're passed to the second workflow they can't be deserialised

4 Replies
Burke-
VMware Employee
VMware Employee

Yes, you'll need to .stringify BEFORE leaving the scriptable task/action that creates your JS object, then .parse the string when you bring it back into another scriptable task, action, or workflow. I'm not sure why we don't just serialize/deserialize JS objects....

If my answer resolved or helped you, please mark it as Correct or Helpful to award points. Thank you!

Visit http://www.vcoteam.info & http://blogs.vmware.com/orchestrator
for vRealize Orchestrator tips and tutorials - @TechnicalValues on Twitter
stumpr
Virtuoso
Virtuoso

Been like that for years, haven't been able to build objects and pass them around.  And doesn't stringify break on custom methods (too lazy to test, just remembering)?  Would be good to see that capability.  Lot easier to use custom objects as code logic vs doing properties object parsing.

Reuben Stump | http://www.virtuin.com | @ReubenStump
probo
Enthusiast
Enthusiast

Rather than serializing the object before it leaves a workflow and deserializing it later I've created an action that converts a Properties object into a true JavaScript object. It takes a Properties value (named prop) as input and returns an Any type value as output. Here's the code

var keys = prop.keys;

var object = new Object();

for(var i in keys) {

  switch(System.getObjectType(keys[i])) {

       case "Properties":

            object[keys[i]] = new Object(prop.get(keys[i]));

       case "Array":

            object[keys[i]] = new Array(prop.get(keys[i]));

       default:

            object[keys[i]] = prop.get(keys[i]);

  }

}

return object;

0 Kudos
probo
Enthusiast
Enthusiast

For those playing along at home I realised my JS wasn't well written and didn't support more than two levels of nested Properties. Here's the new code.

function propertyToObject (property) {

  var object = new Object();

  if(System.getObjectType(property) != "Properties") {

       return property;

  }

  for(var key in property) {

       switch(System.getObjectType(property.get(key))) {

            case "Properties":

                 object[key] = propertyToObject(property.get(key));

                 break;

            case "Array":

                 var array = new Array();

                 property.get(key).forEach(function(v, i, a) {

                      array.push(propertyToObject(v));

                 })

                 object[key] = array;

                 break;

            default:

                 object[key] = property.get(key);

       }

  }

  return object;

}

return propertyToObject(prop);

0 Kudos