@Test public void testBadRegistrationOfDataCenterInfo() throws Exception { try { // test 400 when configured to return client error ConfigurationManager.getConfigInstance() .setProperty("eureka.experimental.registration.validation.dataCenterInfoId", "true"); InstanceInfo instanceInfo = spy(InstanceInfoGenerator.takeOne()); when(instanceInfo.getDataCenterInfo()).thenReturn(new TestDataCenterInfo()); Response response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(400)); // test backfill of data for AmazonInfo ConfigurationManager.getConfigInstance() .setProperty("eureka.experimental.registration.validation.dataCenterInfoId", "false"); instanceInfo = spy(InstanceInfoGenerator.takeOne()); assertThat(instanceInfo.getDataCenterInfo(), instanceOf(AmazonInfo.class)); ((AmazonInfo) instanceInfo.getDataCenterInfo()) .getMetadata() .remove(AmazonInfo.MetaDataKey.instanceId.getName()); // clear the Id response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(204)); } finally { ConfigurationManager.getConfigInstance() .clearProperty("eureka.experimental.registration.validation.dataCenterInfoId"); } }
/** Unbind the EIP that this instance is associated with. */ public void unbindEIP() throws Exception { InstanceInfo myInfo = applicationInfoManager.getInfo(); String myPublicIP = null; if (myInfo != null && myInfo.getDataCenterInfo().getName() == Name.Amazon) { myPublicIP = ((AmazonInfo) myInfo.getDataCenterInfo()).get(MetaDataKey.publicIpv4); if (myPublicIP == null) { logger.info("Instance is not associated with an EIP. Will not try to unbind"); return; } try { AmazonEC2 ec2Service = getEC2Service(); DescribeAddressesRequest describeAddressRequest = new DescribeAddressesRequest().withPublicIps(myPublicIP); DescribeAddressesResult result = ec2Service.describeAddresses(describeAddressRequest); if ((result.getAddresses() != null) && (!result.getAddresses().isEmpty())) { Address eipAddress = result.getAddresses().get(0); DisassociateAddressRequest dissociateRequest = new DisassociateAddressRequest(); String domain = eipAddress.getDomain(); if ("vpc".equals(domain)) { dissociateRequest.setAssociationId(eipAddress.getAssociationId()); } else { dissociateRequest.setPublicIp(eipAddress.getPublicIp()); } ec2Service.disassociateAddress(dissociateRequest); logger.info("Dissociated the EIP {} from this instance", myPublicIP); } } catch (Throwable e) { throw new RuntimeException("Cannot dissociate address from this instance", e); } } }
/** * Checks if an EIP is already bound to the instance. * * @return true if an EIP is bound, false otherwise */ public boolean isEIPBound() { InstanceInfo myInfo = applicationInfoManager.getInfo(); String myInstanceId = ((AmazonInfo) myInfo.getDataCenterInfo()).get(MetaDataKey.instanceId); String myZone = ((AmazonInfo) myInfo.getDataCenterInfo()).get(MetaDataKey.availabilityZone); String myPublicIP = ((AmazonInfo) myInfo.getDataCenterInfo()).get(MetaDataKey.publicIpv4); Collection<String> candidateEIPs = getCandidateEIPs(myInstanceId, myZone); for (String eipEntry : candidateEIPs) { if (eipEntry.equals(myPublicIP)) { logger.info( "My instance {} seems to be already associated with the public ip {}", myInstanceId, myPublicIP); return true; } } return false; }
@Test public void testBadRegistration() throws Exception { InstanceInfo instanceInfo = spy(InstanceInfoGenerator.takeOne()); when(instanceInfo.getId()).thenReturn(null); Response response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(400)); instanceInfo = spy(InstanceInfoGenerator.takeOne()); when(instanceInfo.getHostName()).thenReturn(null); response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(400)); instanceInfo = spy(InstanceInfoGenerator.takeOne()); when(instanceInfo.getAppName()).thenReturn(""); response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(400)); instanceInfo = spy(InstanceInfoGenerator.takeOne()); when(instanceInfo.getAppName()).thenReturn(applicationResource.getName() + "extraExtra"); response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(400)); instanceInfo = spy(InstanceInfoGenerator.takeOne()); when(instanceInfo.getDataCenterInfo()).thenReturn(null); response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(400)); instanceInfo = spy(InstanceInfoGenerator.takeOne()); when(instanceInfo.getDataCenterInfo()) .thenReturn( new DataCenterInfo() { @Override public Name getName() { return null; } }); response = applicationResource.addInstance(instanceInfo, false + ""); assertThat(response.getStatus(), is(400)); }
/** * Checks if an EIP is bound and optionally binds the EIP. * * <p>The list of EIPs are arranged with the EIPs allocated in the zone first followed by other * EIPs. * * <p>If an EIP is already bound to this instance this method simply returns. Otherwise, this * method tries to find an unused EIP based on information from AWS. If it cannot find any unused * EIP this method, it will be retried for a specified interval. * * <p>One of the following scenarios can happen here : * * <p>1) If the instance is already bound to an EIP as deemed by AWS, no action is taken. 2) If an * EIP is already bound to another instance as deemed by AWS, that EIP is skipped. 3) If an EIP is * not already bound to an instance and if this instance is not bound to an EIP, then the EIP is * bound to this instance. */ public void bindEIP() { InstanceInfo myInfo = applicationInfoManager.getInfo(); String myInstanceId = ((AmazonInfo) myInfo.getDataCenterInfo()).get(MetaDataKey.instanceId); String myZone = ((AmazonInfo) myInfo.getDataCenterInfo()).get(MetaDataKey.availabilityZone); Collection<String> candidateEIPs = getCandidateEIPs(myInstanceId, myZone); AmazonEC2 ec2Service = getEC2Service(); boolean isMyinstanceAssociatedWithEIP = false; Address selectedEIP = null; for (String eipEntry : candidateEIPs) { try { String associatedInstanceId; // Check with AWS, if this EIP is already been used by another instance DescribeAddressesRequest describeAddressRequest = new DescribeAddressesRequest().withPublicIps(eipEntry); DescribeAddressesResult result = ec2Service.describeAddresses(describeAddressRequest); if ((result.getAddresses() != null) && (!result.getAddresses().isEmpty())) { Address eipAddress = result.getAddresses().get(0); associatedInstanceId = eipAddress.getInstanceId(); // This EIP is not used by any other instance, hence mark it for selection if it is not // already marked. if (((associatedInstanceId == null) || (associatedInstanceId.isEmpty()))) { if (selectedEIP == null) { selectedEIP = eipAddress; } } else if (isMyinstanceAssociatedWithEIP = (associatedInstanceId.equals(myInstanceId))) { // This EIP is associated with an instance, check if this is the same as the current // instance. // If it is the same, stop searching for an EIP as this instance is already associated // with an // EIP selectedEIP = eipAddress; break; } else { // The EIP is used by some other instance, hence skip it logger.warn( "The selected EIP {} is associated with another instance {} according to AWS," + " hence skipping this", eipEntry, associatedInstanceId); } } } catch (Throwable t) { logger.error("Failed to bind elastic IP: {} to {}", eipEntry, myInstanceId, t); } } if (null != selectedEIP) { String publicIp = selectedEIP.getPublicIp(); // Only bind if the EIP is not already associated if (!isMyinstanceAssociatedWithEIP) { AssociateAddressRequest associateAddressRequest = new AssociateAddressRequest().withInstanceId(myInstanceId); String domain = selectedEIP.getDomain(); if ("vpc".equals(domain)) { associateAddressRequest.setAllocationId(selectedEIP.getAllocationId()); } else { associateAddressRequest.setPublicIp(publicIp); } ec2Service.associateAddress(associateAddressRequest); logger.info( "\n\n\nAssociated {} running in zone: {} to elastic IP: {}", myInstanceId, myZone, publicIp); } logger.info( "My instance {} seems to be already associated with the EIP {}", myInstanceId, publicIp); } else { logger.info( "No EIP is free to be associated with this instance. Candidate EIPs are: {}", candidateEIPs); } }
/* * (non-Javadoc) * * @see * com.thoughtworks.xstream.converters.Converter#marshal(java.lang.Object * , com.thoughtworks.xstream.io.HierarchicalStreamWriter, * com.thoughtworks.xstream.converters.MarshallingContext) */ @Override public void marshal( Object source, HierarchicalStreamWriter writer, MarshallingContext context) { InstanceInfo info = (InstanceInfo) source; if (info.getInstanceId() != null) { writer.startNode(ELEM_INSTANCE_ID); writer.setValue(info.getInstanceId()); writer.endNode(); } writer.startNode(ELEM_HOST); writer.setValue(info.getHostName()); writer.endNode(); writer.startNode(ELEM_APP); writer.setValue(info.getAppName()); writer.endNode(); writer.startNode(ELEM_IP); writer.setValue(info.getIPAddr()); writer.endNode(); if (!("unknown".equals(info.getSID()) || "na".equals(info.getSID()))) { writer.startNode(ELEM_SID); writer.setValue(info.getSID()); writer.endNode(); } writer.startNode(ELEM_STATUS); writer.setValue(getStatus(info)); writer.endNode(); writer.startNode(ELEM_OVERRIDDEN_STATUS); writer.setValue(info.getOverriddenStatus().name()); writer.endNode(); writer.startNode(ELEM_PORT); writer.addAttribute(ATTR_ENABLED, String.valueOf(info.isPortEnabled(PortType.UNSECURE))); writer.setValue(String.valueOf(info.getPort())); writer.endNode(); writer.startNode(ELEM_SECURE_PORT); writer.addAttribute(ATTR_ENABLED, String.valueOf(info.isPortEnabled(PortType.SECURE))); writer.setValue(String.valueOf(info.getSecurePort())); writer.endNode(); writer.startNode(ELEM_COUNTRY_ID); writer.setValue(String.valueOf(info.getCountryId())); writer.endNode(); if (info.getDataCenterInfo() != null) { writer.startNode(NODE_DATACENTER); // This is needed for backward compat. for now. if (info.getDataCenterInfo().getName() == Name.Amazon) { writer.addAttribute("class", "com.netflix.appinfo.AmazonInfo"); } else { writer.addAttribute("class", "com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo"); } context.convertAnother(info.getDataCenterInfo()); writer.endNode(); } if (info.getLeaseInfo() != null) { writer.startNode(NODE_LEASE); context.convertAnother(info.getLeaseInfo()); writer.endNode(); } if (info.getMetadata() != null) { writer.startNode(NODE_METADATA); // for backward compat. for now if (info.getMetadata().size() == 0) { writer.addAttribute("class", "java.util.Collections$EmptyMap"); } context.convertAnother(info.getMetadata()); writer.endNode(); } autoMarshalEligible(source, writer); }