Question

I am using JClouds-Chef to:

  1. Bootstrap a newly-provisioned Linux VM; and then
  2. Run the chef-client on that node to configure it

It's important to note that all I'm currently configuring Chef with is a role (that's all it needs; everything else is set up on the Chef server for me):

public class ChefClient {
    public configure() {
        String vmIp = "myapp01.example.com";
        String vmSshUsername = "myuser";
        String vmSshPassword = "12345";

        String endpoint = "https://mychefserver.example.com";
        String client = "myuser";
        String validator = "chef-validator";
        String clientCredential = Files.toString(new File("C:\\Users\\myuser\\sandbox\\chef\\myuser.pem"), Charsets.UTF_8);
        String validatorCredential = Files.toString(new File("C:\\Users\\myuser\\sandbox\\chef\\chef-validator.pem"), Charsets.UTF_8);

        Properties props = new Properties();
        props.put(ChefProperties.CHEF_VALIDATOR_NAME, validator);
        props.put(ChefProperties.CHEF_VALIDATOR_CREDENTIAL, validatorCredential);
        props.put(Constants.PROPERTY_RELAX_HOSTNAME, "true");
        props.put(Constants.PROPERTY_TRUST_ALL_CERTS, "true");

        ChefContext ctx = ContextBuilder.newBuilder("chef")
            .endpoint(endpoint)
            .credentials(client, clientCredential)
            .overrides(props)
            .modules(ImmutableSet.of(new SshjSshClientModule())) //
            .buildView(ChefContext.class);
        ChefService chef = ctx.getChefService();

        List<String> runlist = new RunListBuilder().addRole("platformcontrol_dev").build();

        ArrayList<String> runList2 = new ArrayList<String>();
        for(String item : runlist) {
            runList2.add(item);
        }

        BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(runList2).build();

        chef.updateBootstrapConfigForGroup("jclouds-chef", bootstrapConfig);

        Statement bootstrap = chef.createBootstrapScriptForGroup("jclouds-chef");

        SshClient.Factory sshFactory = ctx.unwrap().utils()
            .injector().getInstance(Key.get(new TypeLiteral<SshClient.Factory>() {}));

        SshClient ssh = sshFactory.create(HostAndPort.fromParts(vmIp, 22),
            LoginCredentials.builder().user(vmSshUsername).password(vmSshPassword).build());

        ssh.connect();

        try {
            StringBuilder rawScript = new StringBuilder();

            Map<String, String> resolvedFunctions = ScriptBuilder.resolveFunctionDependenciesForStatements(
                new HashMap<String, String>(), ImmutableSet.of(bootstrap), OsFamily.UNIX);

            ScriptBuilder.writeFunctions(resolvedFunctions, OsFamily.UNIX, rawScript);
            rawScript.append(bootstrap.render(OsFamily.UNIX));

            ssh.put("/tmp/chef-bootstrap.sh", rawScript.toString());
            ExecResponse result = ssh.exec("bash /tmp/chef-bootstrap.sh");
        } catch(Throwable t) {
            println "Exception: " + t.message
        } finally {
            ssh.disconnect();
        }
    }
}

Our in-house "Chef" (our devops guy) now wants to add the concept of Chef "environments" to all our recipes in addition to the existing roles. This is so that we can specify environment-specific roles for each node. My question: does the JClouds-Chef API handle environments? If so, how might I modify the code to incorporate environment-specific roles?

Is it just as simple as:

BootstrapConfig bootstrapConfig = BootstrapConfig.builder()
    .environment("name-of-env-here?").runList(runList2).build();
Was it helpful?

Solution

Yes, it is that simple. That will tell the bootstrap script to register the node in the specified environment.

Take into account, though, that the environment must already exist in the Chef Server. If you want to create nodes in new environments, you can also create them programmatically as follows:

ChefApi api = ctx.unwrapApi(ChefApi.class);
if (api.getEnvironment("environment-name") == null) {
    Environment env = Environment.builder()
        .name("environment-name")
        .description("Some description")
        .build();
    api.createEnvironment(env);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top