Search code examples
chef-infraenvironmentjclouds

Creating new Environments with JClouds-Chef


I'm am trying to use the JClouds-Chef API to both bootstrap and configure newly-provisioned Linux VMs in our vCenter. Our DevOps Team (our "Chefs") have recently introduced the concept of Environments to all our recipes, and I was told that I now need to update my JClouds-Chef code to build new environments on the fly. Currently I have the following code, which simply specifies an existing Environment to use:

// Here, "node.getEnvironment()" might return "ourapp_dev" or "ourapp_test", etc.
bootstrapConfig bootstrapConfig = BootstrapConfig.builder()
    .environment(node.getEnvironment()).runList(runlist).build();

But now I have to create the Environment myself, on the fly; not use an existing one that is already available on our Chef server.

I was told I could use the Environment object to do this creation. And it certainly looks that way, given the way the API is set up. However I can't find any working examples, and not being a "Chef" myself, its tough for me to see the forest through the trees here.

Here's the environment I was told I would need to use as a template:

name "{appname}_dev"
description "{appname} Dev Environment"
cookbook_versions({
    "our_app" => "= 0.2.0",
    "our_logs" => "= 0.1.0"
})
default_attributes(
    "our_app" => {
        "port" => "{port}",
        "app_name" => "{appname}",
        "config_vars" => {
            "useFizz" => "true",
            "host" => "devourapp",
            "context" => "devourapp/{appname}"
        },
        "jar_file_url" => "http://ourartifactory/ourrepo/com/us/{appname}/%5BRELEASE%5D/{appname}-%5BRELEASE%5D.jar"
    },
    our_logs" => {
        "some_resource" => "{appname}",
        "log_server" => "logstash.example.com"
    }              
)

Apparently, anything in { } curly braces is a variable that I need to pass in some how. So for instance, {appname} might be fizzbuz, in which case the first line above would have to resolve to:

name "fizzbuzz_dev"

etc. I can determine these variable names ahead of time in Java code:

String appname = getAppName();
String port = getPort();
// etc.

The problem is that I can't figure out how to use the Environment API to reproduce the above config, especially when it comes to injecting appname and port as variables. Any ideas?


Solution

  • The cookbook versions can be set using the Environment builder object. It has a method that accepts a Map<String, String> you can use to configure them.

    The attributes are a little tricky. As the attribute structure is arbitrary, there is no practical way to represent them in a Java object. You have to use the attributes method in the Environment builder object, and put the root level attribute names as the keys, and a JsonBall with the literal json string as the value. Something like the following for a single attribute, but you can already provide the entire map directly to the attributes (plural) method:

    envBuilder.attribute("our_app", new JsonBall("{\"foo\":true}"));
    

    You'll have to manually build the json String with the appropriate values in it.