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:
Test workflow which calls Test javascript workflow and attempts to deserialise both objects:
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
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....
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.
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;
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);