org.jclouds.examples.google.lb.MainApp.java Source code

Java tutorial

Introduction

Here is the source code for org.jclouds.examples.google.lb.MainApp.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.jclouds.examples.google.lb;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;

import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.domain.Credentials;
import org.jclouds.googlecloud.GoogleCredentialsFromJson;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.GoogleComputeEngineProviderMetadata;
import org.jclouds.googlecomputeengine.domain.Firewall;
import org.jclouds.googlecomputeengine.domain.ForwardingRule;
import org.jclouds.googlecomputeengine.domain.Metadata;
import org.jclouds.googlecomputeengine.domain.NewInstance;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.features.InstanceApi;
import org.jclouds.googlecomputeengine.features.OperationApi;
import org.jclouds.googlecomputeengine.options.FirewallOptions;
import org.jclouds.googlecomputeengine.options.ForwardingRuleCreationOptions;
import org.jclouds.googlecomputeengine.options.HttpHealthCheckCreationOptions;
import org.jclouds.googlecomputeengine.options.TargetPoolCreationOptions;

import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Files;
import com.google.inject.Injector;

/**
 * Demonstrates the use of {@link ComputeService}.
 * <p/>
 * Usage is:
 * {@code java MainApp provider identity credential groupName (add|exec|run|destroy)}
 * if {@code exec} is used, the following parameter is a command, which should
 * be passed in quotes
 * if {@code run} is used, the following parameter is a file to execute.
 */
public class MainApp {

    public static enum Action {
        CREATE, REQUEST, DESTROY, DELETE_STARTUP_SCRIPT
    }

    public static String DEFAULT_ZONE = "us-central1-b";
    public static String DEFAULT_REGION = "us-central1";
    public static String DEFAULT_MACHINE_TYPE = "n1-standard-1";
    public static URI DEFAULT_IMAGE_URL = URI.create(
            "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/backports-debian-7-wheezy-v20150325");
    public static String FIREWALL_TAG = "allow-tcp-port-80";
    public static String STARTUP_SCRIPT = "apt-get update && apt-get install -y apache2 && hostname > /var/www/index.html";

    public static int NUM_INSTANCES = 3;

    public static int PARAMETERS = 2;
    public static String INVALID_SYNTAX = "Invalid number of parameters. Syntax is: json_key_path (create|request|destroy|delete_startup_script)";

    public static void main(String[] args) {
        if (args.length < PARAMETERS)
            throw new IllegalArgumentException(INVALID_SYNTAX);

        String jsonKeyFile = args[0];
        Action action = Action.valueOf(args[1].toUpperCase());

        // Read in JSON key.
        String fileContents = null;
        try {
            fileContents = Files.toString(new File(jsonKeyFile), Charset.defaultCharset());
        } catch (IOException ex) {
            System.out.println("Error Reading the Json key file. Please check the provided path is correct.");
            System.exit(1);
        }

        Supplier<Credentials> credentialSupplier = new GoogleCredentialsFromJson(fileContents);

        // This demonstrates how to initialize a ComputeServiceContext using json key files.
        ComputeServiceContext context = ContextBuilder.newBuilder("google-compute-engine")
                .credentialsSupplier(credentialSupplier).buildView(ComputeServiceContext.class);

        Credentials credentials = credentialSupplier.get();

        GoogleComputeEngineApi googleApi = createGoogleComputeEngineApi(credentials.identity,
                credentials.credential);

        String project_name = googleApi.project().get().name();
        System.out.printf("Sucessfully Authenticated to project %s\n", project_name);

        InstanceApi instanceApi = googleApi.instancesInZone(DEFAULT_ZONE);

        switch (action) {
        case CREATE: {
            Metadata metadata = googleApi.project().get().commonInstanceMetadata();
            if (metadata.get("startup-script") != null && metadata.get("startup-script") != STARTUP_SCRIPT) {

                System.out.println("Project already has a startup script, exiting to avoid overwriting it.");
                System.exit(1);
            }
            System.out.println("Updating startup script");
            metadata.put("startup-script", STARTUP_SCRIPT);
            Operation operation = googleApi.project().setCommonInstanceMetadata(metadata);
            OperationApi operationsApi = googleApi.operations();
            WaitForOperation(operationsApi, operation);

            URI networkURL = googleApi.networks().get("default").selfLink();
            if (networkURL == null) {
                System.out.println(
                        "Your project does not have a default network. Please recreate the default network or try again with a new project");
                System.exit(1);
            }
            System.out.println("Creating:");

            // Add firewall rule to allow TCP on port 80
            FirewallOptions options = new FirewallOptions()
                    .addAllowedRule(Firewall.Rule.create("tcp", ImmutableList.of("80")))
                    .sourceRanges(ImmutableList.of("0.0.0.0/0"));
            //.addTargetTag(FIREWALL_TAG);
            operation = googleApi.firewalls().createInNetwork("jclouds-lb-firewall-tcp-80", networkURL, options);
            System.out.println(" - firewall");
            WaitForOperation(operationsApi, operation);

            URI machineTypeURL = googleApi.machineTypesInZone(DEFAULT_ZONE).get(DEFAULT_MACHINE_TYPE).selfLink();

            // Make requests to create instances.
            ArrayList<Operation> operations = new ArrayList<Operation>();
            for (int i = 0; i < NUM_INSTANCES; i++) {
                Operation o = instanceApi.create(NewInstance.create("jclouds-lb-instance-" + i, machineTypeURL,
                        networkURL, DEFAULT_IMAGE_URL));
                System.out.println(" - instance");
                operations.add(o);
            }

            ArrayList<URI> instances = new ArrayList<URI>();
            for (Operation op : operations) {
                WaitForOperation(operationsApi, op);
                instances.add(op.targetLink());
            }

            // Create Health Check
            HttpHealthCheckCreationOptions healthCheckOptions = new HttpHealthCheckCreationOptions.Builder()
                    .checkIntervalSec(1).timeoutSec(1).buildWithDefaults();
            operation = googleApi.httpHeathChecks().insert("jclouds-lb-healthcheck", healthCheckOptions);
            System.out.println(" - http health check");
            WaitForOperation(operationsApi, operation);
            URI healthCheckURI = googleApi.httpHeathChecks().get("jclouds-lb-healthcheck").selfLink();

            // Create Target Pool
            TargetPoolCreationOptions targetPoolOptions = new TargetPoolCreationOptions.Builder(
                    "jclouds-lb-target-pool").healthChecks(ImmutableList.of(healthCheckURI)).instances(instances)
                            .build();
            Operation targetPoolOperation = googleApi.targetPoolsInRegion(DEFAULT_REGION).create(targetPoolOptions);
            System.out.println(" - target pool");
            WaitForOperation(operationsApi, targetPoolOperation);

            // Create Forwarding Rule
            ForwardingRuleCreationOptions forwardingOptions = new ForwardingRuleCreationOptions.Builder()
                    .ipProtocol(ForwardingRule.IPProtocol.TCP).target(targetPoolOperation.targetLink()).build();
            operation = googleApi.forwardingRulesInRegion(DEFAULT_REGION).create("jclouds-lb-forwarding",
                    forwardingOptions);
            System.out.println(" - forwarding rule");
            WaitForOperation(operationsApi, operation);

            String ipAddress = googleApi.forwardingRulesInRegion(DEFAULT_REGION).get("jclouds-lb-forwarding")
                    .ipAddress();
            System.out.println("Ready to recieve traffic at " + ipAddress);

            break;
        }
        case REQUEST: {
            // Find the created forwarding rule.
            ForwardingRule forwardingRule = googleApi.forwardingRulesInRegion(DEFAULT_REGION)
                    .get("jclouds-lb-forwarding");
            if (forwardingRule == null) {
                System.out.println("jclouds-lb-forwarding rule does not exist. Have you successfully run create?");
                System.exit(1);
            }
            String ipAddress = googleApi.forwardingRulesInRegion(DEFAULT_REGION).get("jclouds-lb-forwarding")
                    .ipAddress();
            System.out.printf("Found the forwarding rule! Try executing 'while true; do curl -m1 %s; done'\n",
                    ipAddress);

            break;
        }
        case DELETE_STARTUP_SCRIPT: {
            System.out.println("removing startup script from project metadata");
            DeleteStartupScript(googleApi);
            break;
        }
        case DESTROY: {
            // Delete Forwarding Rule
            googleApi.forwardingRulesInRegion(DEFAULT_REGION).delete("jclouds-lb-forwarding");

            // Delete Target Pool
            googleApi.targetPoolsInRegion(DEFAULT_REGION).delete("jclouds-lb-target-pool");

            // Delete Health Check
            googleApi.httpHeathChecks().delete("jclouds-lb-healthcheck");

            // Delete Instances
            ArrayList<Operation> operations = new ArrayList<Operation>();
            for (int i = 0; i < NUM_INSTANCES; i++) {
                Operation o = instanceApi.delete("jclouds-lb-instance-" + i);
                operations.add(o);
            }

            // Delete Firewall Rule
            googleApi.firewalls().delete("jclouds-lb-firewall-tcp-80");

            // Delete Startup Script
            DeleteStartupScript(googleApi);

            System.out.println("ran cleanup");
            break;
        }
        }
    }

    public static void DeleteStartupScript(GoogleComputeEngineApi googleApi) {
        Metadata metadata = googleApi.project().get().commonInstanceMetadata();
        metadata.remove("startup-script");
        googleApi.project().setCommonInstanceMetadata(metadata);
    }

    public static int WaitForOperation(OperationApi api, Operation operation) {
        int timeout = 60; // seconds
        int time = 0;

        while (operation.status() != Operation.Status.DONE) {
            if (time >= timeout) {
                return 1;
            }
            time++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            operation = api.get(operation.selfLink());
        }
        //TODO: Check for errors.
        return 0;
    }

    // This function demonstrates how to get an instance of the GoogleComputeEngineApi.
    private static GoogleComputeEngineApi createGoogleComputeEngineApi(String identity, String credential) {
        ContextBuilder contextBuilder = ContextBuilder
                .newBuilder(GoogleComputeEngineProviderMetadata.builder().build())
                .credentials(identity, credential);
        Injector injector = contextBuilder.buildInjector();
        return injector.getInstance(GoogleComputeEngineApi.class);
    }
}