Question

I have an AWS EC2 instance deployed, and I need to find out its public IP. Howver, to know that I must first know the instance-id of my instance.

Objective:

  • I have a Java code running in my instance, and I want that code figure out the current IP or Instance-ID of the instance where it is being run.

After reading Amazon documentation I came up with a Java method that returns the IP of all instances, but this is not what I want, I want a method that returns only the instance-id or the public IP address of the running instance.

    /**
     * Returns a list with the public IPs of all the active instances, which are
     * returned by the {@link #getActiveInstances()} method.
     * 
     * @return  a list with the public IPs of all the active instances.
     * @see     #getActiveInstances()
     * */
    public List<String> getPublicIPs(){
        List<String> publicIpsList = new LinkedList<String>();

        //if there are no active instances, we return immediately to avoid extra 
        //computations.
        if(!areAnyActive())
            return publicIpsList;

        DescribeInstancesRequest request =  new DescribeInstancesRequest();
        request.setInstanceIds(instanceIds);

        DescribeInstancesResult result = ec2.describeInstances(request);
        List<Reservation> reservations = result.getReservations();

        List<Instance> instances;
        for(Reservation res : reservations){
            instances = res.getInstances();
            for(Instance ins : instances){
                LOG.info("PublicIP from " + ins.getImageId() + " is " + ins.getPublicIpAddress());
                publicIpsList.add(ins.getPublicIpAddress());
            }
        }

        return publicIpsList;
    }

In this code I have an array with the instance-ids of all active instances, but I do not know if they are "me" or not. So I assume that my first step would be to know who I am, and then to ask for my public IP address.

Is there a change I can do to the previous method to give me what I want? Is there a more efficient way of doing it?

Was it helpful?

Solution 4

I am not a java guy. However, my below ruby code does print the Instance ID and Public IP of the running instances as you needed:

ec2.describe_instances(
  filters:[
    {
      name: "instance-state-name",
      values: ["running"]
    }
  ]
).each do |resp|
  resp.reservations.each do |reservation|
    reservation.instances.each do |instance|
        puts instance.instance_id + " ---AND--- " + instance.public_ip_address
    end
  end
end

All you need to do is find out respective Methods/calls in JAVA SDK documentation. The code that you should be looking at is:

  filters:[
    {
      name: "instance-state-name",
      values: ["running"]
    }

In above block, I am filtering out only the running instances.

AND

resp.reservations.each do |reservation|
        reservation.instances.each do |instance|
            puts instance.instance_id + " ---AND--- " + instance.public_ip_address

In above code block, I am running 2 for loops and pulling instance.instance_id as well as instance.public_ip_address.

As JAVA SDK and Ruby SDK are both hitting the same AWS EC2 APIs, there must be similar settings in JAVA SDK.

Also, Your question is vague in the sense, are you running the JAVA code from the instance whose Instance id is needed? OR Are you running the java code from a different instance and want to pull the instance-ids of all the running instances?

UPDATE:

Updating the answers as the question has changed:

AWS provides meta-data service on each instance that is launched. You can poll the meta-data service locally to find out the needed information.

Form bash promp, below command provided the instance-id and the public IP address of the instance

$ curl -L http://169.254.169.254/latest/meta-data/instance-id

$ curl -L http://169.254.169.254/latest/meta-data/public-ipv4

You need to figure out how you will pull data from above URLs in java. At this point , you have enough information and this question is irrelevant with respect to AWS because now this is more of a JAVA question on how to poll above URLs.

OTHER TIPS

I would suggest/recommend the usage of the AWS SDK for Java.

// Resolve the instanceId
String instanceId = EC2MetadataUtils.getInstanceId();

// Resolve (first/primary) private IP
String privateAddress = EC2MetadataUtils.getInstanceInfo().getPrivateIp();

// Resolve public IP
AmazonEC2 client = AmazonEC2ClientBuilder.defaultClient();
String publicAddress = client.describeInstances(new DescribeInstancesRequest()
                                                    .withInstanceIds(instanceId))
                             .getReservations()
                             .stream()
                             .map(Reservation::getInstances)
                             .flatMap(List::stream)
                             .findFirst()
                             .map(Instance::getPublicIpAddress)
                             .orElse(null);

Unless Java8 is available, this will need more boilercode. But in the nutshell, that's it.

https://stackoverflow.com/a/30317951/525238 has already mentioned the EC2MetadataUtils, but this here includes working code also.

You want the com.amazonaws.util.EC2MetadataUtils class from the aws-java-sdk.

The following method will return the EC2 Instance ID.

public String retrieveInstanceId() throws IOException {
    String EC2Id = null;
    String inputLine;
    URL EC2MetaData = new URL("http://169.254.169.254/latest/meta-data/instance-id");
    URLConnection EC2MD = EC2MetaData.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(EC2MD.getInputStream()));
    while ((inputLine = in.readLine()) != null) {
        EC2Id = inputLine;
    }
    in.close();
    return EC2Id;
}

From here, you can then do the following to get information such as the IP address (in this example, the privateIP):

try {
    myEC2Id = retrieveInstanceId();
} catch (IOException e1) {
    e1.printStackTrace(getErrorStream());
}
DescribeInstancesRequest describeInstanceRequest = new DescribeInstancesRequest().withInstanceIds(myEC2Id);
DescribeInstancesResult describeInstanceResult = ec2.describeInstances(describeInstanceRequest);
System.out.println(describeInstanceResult.getReservations().get(0).getInstances().get(0).getPrivateIPAddress());

You can also use this to get all kinds of relevant information about the current instance the Java program is running on; just replace .getPrivateIPAddress() with the appropriate get command for the info you seek. List of available commands can can be found here.

Edit: For those that might shy away from using this due to the "unknown" URL; see Amazon's documentation on the topic, which points directly to this same URL; the only difference being they're doing it via cli rather than inside Java. http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

To answer the initial question of

I have an AWS EC2 instance deployed, and I need to find out its public IP.

You can do in Java using the AWS API:

EC2MetadataUtils.getData("/latest/meta-data/public-ipv4");

This will directly give you the public IP if one exists

You could use the metadata service to fetch this using HTTP: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html

ex:

GET http://169.254.169.254/latest/meta-data/instance-id

I was needing to do many operations with Amazon EC2. Then I implemented an utility class for this operations. Maybe it can be util to someone that arrive here. I implemented using AWS SDK for java version 2. The operations are:

  • Create machine;
  • Start machine;
  • Stop machine;
  • Reboot machine;
  • Delete machine (Terminate);
  • Describe machine;
  • Get Public IP from machine;

AmazonEC2 class:

import govbr.cloud.management.api.CloudManagementException;
import govbr.cloud.management.api.CloudServerMachine;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.core.exception.SdkClientException;
import software.amazon.awssdk.core.exception.SdkServiceException;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.Instance;
import software.amazon.awssdk.services.ec2.model.InstanceNetworkInterface;
import software.amazon.awssdk.services.ec2.model.InstanceType;
import software.amazon.awssdk.services.ec2.model.RebootInstancesRequest;
import software.amazon.awssdk.services.ec2.model.Reservation;
import software.amazon.awssdk.services.ec2.model.RunInstancesRequest;
import software.amazon.awssdk.services.ec2.model.RunInstancesResponse;
import software.amazon.awssdk.services.ec2.model.StartInstancesRequest;
import software.amazon.awssdk.services.ec2.model.StopInstancesRequest;
import software.amazon.awssdk.services.ec2.model.TerminateInstancesRequest;


public class AmazonEC2 {

    private final static String EC2_MESSAGE_ERROR = "A error occurred on the     Ec2.";
    private final static String CLIENT_MESSAGE_ERROR = "A error occurred in client side.";
    private final static String SERVER_MESSAGE_ERROR = "A error occurred in Amazon server.";
    private final static String UNEXPECTED_MESSAGE_ERROR = "Unexpected error occurred.";


    private Ec2Client buildDefaultEc2() {

        AwsCredentialsProvider credentials = AmazonCredentials.loadCredentialsFromFile();

        Ec2Client ec2 = Ec2Client.builder()
                .region(Region.SA_EAST_1)
                .credentialsProvider(credentials)                            
                .build();

        return ec2;
    }

    public String createMachine(String name, String amazonMachineId) 
                        throws CloudManagementException {
        try {
            if(amazonMachineId == null) {
                amazonMachineId = "ami-07b14488da8ea02a0";              
            }       

            Ec2Client ec2 = buildDefaultEc2();           

            RunInstancesRequest request = RunInstancesRequest.builder()
                    .imageId(amazonMachineId)
                    .instanceType(InstanceType.T1_MICRO)
                    .maxCount(1)
                    .minCount(1)
                    .build();

            RunInstancesResponse response = ec2.runInstances(request);

            Instance instance = null;

            if (response.reservation().instances().size() > 0) {
                instance = response.reservation().instances().get(0);
            }

            if(instance != null) {
                System.out.println("Machine created! Machine identifier: " 
                                    + instance.instanceId());
                return instance.instanceId();
            }

            return null;

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }       
    }

    public void startMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            StartInstancesRequest request = StartInstancesRequest.builder()
                                             .instanceIds(instanceId).build();
            ec2.startInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public void stopMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            StopInstancesRequest request = StopInstancesRequest.builder()
                                              .instanceIds(instanceId).build();
            ec2.stopInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public void rebootMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            RebootInstancesRequest request = RebootInstancesRequest.builder()
                                              .instanceIds(instanceId).build();
            ec2.rebootInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public void destroyMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();
            TerminateInstancesRequest request = TerminateInstancesRequest.builder()
       .instanceIds(instanceId).build();
            ec2.terminateInstances(request);

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public String getPublicIpAddress(String instanceId) throws CloudManagementException {
        try {

            Ec2Client ec2 = buildDefaultEc2();

            boolean done = false;

            DescribeInstancesRequest request = DescribeInstancesRequest.builder().build();

            while(!done) {
                DescribeInstancesResponse response = ec2.describeInstances(request);

                for(Reservation reservation : response.reservations()) {
                    for(Instance instance : reservation.instances()) {
                        if(instance.instanceId().equals(instanceId)) {
                            if(instance.networkInterfaces().size() > 0) {
                                InstanceNetworkInterface networkInterface = 
                                           instance.networkInterfaces().get(0);
                                String publicIp = networkInterface
                                                     .association().publicIp();
                                System.out.println("Machine found. Machine with Id " 
                                                   + instanceId 
                                                   + " has the follow public IP: " 
                                                   + publicIp);
                                return publicIp;
                            }                           
                        }
                    }
                }

                if(response.nextToken() == null) {
                    done = true;
                }
            }

            return null;

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

    public String describeMachine(String instanceId) {
        try {

            Ec2Client ec2 = buildDefaultEc2();          

            boolean done = false;

            DescribeInstancesRequest request = DescribeInstancesRequest.builder().build();

            while(!done) {
                DescribeInstancesResponse response = ec2.describeInstances(request);

                for(Reservation reservation : response.reservations()) {
                    for(Instance instance : reservation.instances()) {
                        if(instance.instanceId().equals(instanceId)) {                          
                            return "Found reservation with id " +
                                    instance.instanceId() +
                                    ", AMI " + instance.imageId() + 
                                    ", type " + instance.instanceType() + 
                                    ", state " + instance.state().name() + 
                                    "and monitoring state" + 
                                    instance.monitoring().state();                          
                        }
                    }
                }

                if(response.nextToken() == null) {
                    done = true;
                }
            }

            return null;

        } catch (Ec2Exception e) {          
            throw new CloudManagementException(EC2_MESSAGE_ERROR, e);   
        } catch (SdkClientException e) {
            throw new CloudManagementException(CLIENT_MESSAGE_ERROR, e);            
        } catch (SdkServiceException e) {
            throw new CloudManagementException(SERVER_MESSAGE_ERROR, e);            
        } catch (Exception e) {
            throw new CloudManagementException(UNEXPECTED_MESSAGE_ERROR, e);            
        }   
    }

}

AmazonCredentials class:

import java.io.InputStream;

import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.profiles.ProfileFile;
import software.amazon.awssdk.profiles.ProfileFile.Type;

public class AmazonCredentials {


public static AwsCredentialsProvider loadCredentialsFromFile() {
    InputStream profileInput = ClassLoader.getSystemResourceAsStream("credentials.profiles");

    ProfileFile profileFile = ProfileFile.builder()
            .content(profileInput)
            .type(Type.CREDENTIALS)
            .build();

    AwsCredentialsProvider profileProvider = ProfileCredentialsProvider.builder()
            .profileFile(profileFile)
            .build();

    return profileProvider;
}

}

CloudManagementException class:

public class CloudManagementException extends RuntimeException {

private static final long serialVersionUID = 1L;


public CloudManagementException(String message) {
    super(message);
}

public CloudManagementException(String message, Throwable cause) {
    super(message, cause);
}

}

credentials.profiles:

[default]
aws_access_key_id={your access key id here}
aws_secret_access_key={your secret access key here}

I hope help o/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top