blob: c38abca404d926a2d6dad5eeb04d1bbfe47c50fe [file] [log] [blame]
/*
* 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);
}
}