/** 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); } } }
/** * Set the application name of the instance.This is mostly used in querying of instances. * * @param appName the application name. * @return the instance info builder. */ public Builder setAppName(String appName) { result.appName = appName; if (result.appName != null) { result.appName = result.appName.toUpperCase(); } return this; }
@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"); } }
public Applications toApplications() { Map<String, Application> appsByName = new HashMap<>(); Iterator<InstanceInfo> it = serviceIterator(); while (it.hasNext()) { InstanceInfo instanceInfo = it.next(); Application instanceApp = appsByName.get(instanceInfo.getAppName()); if (instanceApp == null) { instanceApp = new Application(instanceInfo.getAppName()); appsByName.put(instanceInfo.getAppName(), instanceApp); } instanceApp.addInstance(instanceInfo); } // Do not pass application list to the constructor, as it does not initialize properly // Applications // data structure. Applications applications = new Applications(); for (Application app : appsByName.values()) { applications.addApplication(app); } applications.setAppsHashCode(applications.getReconcileHashCode()); return applications; }
/** * Enabled or disable secure/non-secure ports . * * @param type Secure or Non-Secure. * @param isEnabled true if enabled. * @return the instance builder. */ public Builder enablePort(PortType type, boolean isEnabled) { if (type == PortType.SECURE) { result.isSecurePortEnabled = isEnabled; } else { result.isUnsecurePortEnabled = isEnabled; } return this; }
private String fetchFortuneServiceUrl() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("FORTUNE-SERVICE", false); logger.debug("instanceID: {}", instance.getId()); String fortuneServiceUrl = instance.getHomePageUrl(); logger.debug("fortune service url: {}", fortuneServiceUrl); return fortuneServiceUrl; }
/** * Sets the absolute home page {@link URL} for this instance. The users can provide the <code> * homePageUrlPath</code> if the home page resides in the same instance talking to discovery, * else in the cases where the instance is a proxy for some other server, it can provide the * full {@link URL}. If the full {@link URL} is provided it takes precedence. * * <p>The full {@link URL} should follow the format http://${netflix.appinfo.hostname}:7001/ * where the value ${netflix.appinfo.hostname} is replaced at runtime. * * @param relativeUrl the relative url path of the home page. * @param explicitUrl - The full {@link URL} for the home page * @return the instance builder. */ public Builder setHomePageUrl(String relativeUrl, String explicitUrl) { String hostNameInterpolationExpression = "${" + namespace + "hostname}"; if (explicitUrl != null) { result.homePageUrl = explicitUrl.replace(hostNameInterpolationExpression, result.hostName); } else if (relativeUrl != null) { result.homePageUrl = HTTP_PROTOCOL + result.hostName + COLON + result.port + relativeUrl; } return this; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; InstanceInfo other = (InstanceInfo) obj; if (getId() == null) { if (other.getId() != null) return false; } else if (!getId().equals(other.getId())) return false; return true; }
private boolean isReplicaAvailable(String myAppName, String url) { try { String givenHostName = new URI(url).getHost(); Application app = PeerAwareInstanceRegistry.getInstance().getApplication(myAppName, false); for (InstanceInfo info : app.getInstances()) { if (info.getHostName().equals(givenHostName)) { return true; } } } catch (Throwable e) { logger.error("Could not determine if the replica is available ", e); } return false; }
public Applications takeDelta(int count) { if (currentIt == null) { currentIt = serviceIterator(); allApplications = new Applications(); } List<InstanceInfo> instanceBatch = new ArrayList<InstanceInfo>(); for (int i = 0; i < count; i++) { InstanceInfo next = currentIt.next(); next.setActionType(ActionType.ADDED); instanceBatch.add(next); } Applications nextBatch = EurekaEntityFunctions.toApplications(toApplicationMap(instanceBatch)); allApplications = mergeApplications(allApplications, nextBatch); nextBatch.setAppsHashCode(allApplications.getAppsHashCode()); return nextBatch; }
private List<DiscoveryEnabledServer> obtainServersViaDiscovery() { List<DiscoveryEnabledServer> serverList = new ArrayList<DiscoveryEnabledServer>(); DiscoveryClient discoveryClient = DiscoveryManager.getInstance().getDiscoveryClient(); if (discoveryClient == null) { return new ArrayList<DiscoveryEnabledServer>(); } if (vipAddresses != null) { for (String vipAddress : vipAddresses.split(",")) { // if targetRegion is null, it will be interpreted as the same region of client List<InstanceInfo> listOfinstanceInfo = discoveryClient.getInstancesByVipAddress(vipAddress, isSecure, targetRegion); for (InstanceInfo ii : listOfinstanceInfo) { if (ii.getStatus().equals(InstanceStatus.UP)) { if (shouldUseOverridePort) { if (logger.isDebugEnabled()) { logger.debug( "Overriding port on client name: " + clientName + " to " + overridePort); } // copy is necessary since the InstanceInfo builder just uses the original reference, // and we don't want to corrupt the global eureka copy of the object which may be // used by other clients in our system InstanceInfo copy = new InstanceInfo(ii); if (isSecure) { ii = new InstanceInfo.Builder(copy).setSecurePort(overridePort).build(); } else { ii = new InstanceInfo.Builder(copy).setPort(overridePort).build(); } } DiscoveryEnabledServer des = new DiscoveryEnabledServer(ii, isSecure); des.setZone(DiscoveryClient.getZone(ii)); serverList.add(des); } } if (serverList.size() > 0 && prioritizeVipAddressBasedServers) { break; // if the current vipAddress has servers, we dont use subsequent vipAddress based // servers } } } return serverList; }
@Test public void testMiniAppGet() throws Exception { Response response = applicationResource.getApplication( Version.V2.name(), MediaType.APPLICATION_JSON, EurekaAccept.compact.name()); String json = String.valueOf(response.getEntity()); DecoderWrapper decoder = CodecWrappers.getDecoder(CodecWrappers.LegacyJacksonJson.class); Application decodedApp = decoder.decode(json, Application.class); // assert false as one is mini, so should NOT equal assertThat(EurekaEntityComparators.equal(testApplication, decodedApp), is(false)); for (InstanceInfo instanceInfo : testApplication.getInstances()) { InstanceInfo decodedInfo = decodedApp.getByInstanceId(instanceInfo.getId()); assertThat(EurekaEntityComparators.equalMini(instanceInfo, decodedInfo), is(true)); } }
/** * 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; }
/** * Sets the fully qualified hostname of this running instance.This is mostly used in * constructing the {@link URL} for communicating with the instance. * * @param hostName the host name of the instance. * @return the {@link InstanceInfo} builder. */ public Builder setHostName(String hostName) { String existingHostName = result.hostName; result.hostName = hostName; if ((existingHostName != null) && !(hostName.equals(existingHostName))) { refreshStatusPageUrl() .refreshHealthCheckUrl() .refreshVIPAddress() .refreshSecureVIPAddress(); } return this; }
public String getNextServiceFromEureka(String serviceName) throws ServiceNotFoundException { // vipAddress of the Webapp service - Check acmeair-webapp.properties file String vipAddress = serviceName; InstanceInfo nextServerInfo = null; try { nextServerInfo = DiscoveryManager.getInstance() .getDiscoveryClient() .getNextServerFromEureka(vipAddress, false); } catch (Exception e) { System.out.println("Cannot get an instance of " + vipAddress + "to talk to from eureka : "); e.printStackTrace(); throw new ServiceNotFoundException(); } // return nextServerInfo.getIPAddr() + ":" + nextServerInfo.getPort(); // Assume default port return nextServerInfo.getIPAddr(); }
public void y() { InstanceInfo info = InstanceInfo.Builder.newBuilder() .setStatus(InstanceStatus.UP) .setAppName("testopenam") .setHostName("localhost") .setPort(8080) .setVIPAddress("testopenam") // .setMetadata(new HashMap() {{put("instanceId", "openam1");}}) .setDataCenterInfo(new InstanceIdDataCenterInfo("openam1")) .setHomePageUrl( "/OpenAM-12.0.0/isAlive.jsp", "http://localhost:8080/OpenAM-12.0.0/isAlive.jsp") .setStatusPageUrl( "/OpenAM-12.0.0/isAlive.jsp", "http://localhost:8080/OpenAM-12.0.0/isAlive.jsp") .setHealthCheckUrls( "/OpenAM-12.0.0/isAlive.jsp", "http://localhost:8080/OpenAM-12.0.0/isAlive.jsp", null) .build(); info.getId(); PeerAwareInstanceRegistry.getInstance().register(info, false); }
/** * Sets the absolute health check {@link URL} for this instance for both secure and non-secure * communication The users can provide the <code>healthCheckUrlPath</code> if the healthcheck * page resides in the same instance talking to discovery, else in the cases where the instance * is a proxy for some other server, it can provide the full {@link URL}. If the full {@link * URL} is provided it takes precedence. * * <p>The full {@link URL} should follow the format * http://${netflix.appinfo.hostname}:7001/healthcheck where the value * ${netflix.appinfo.hostname} is replaced at runtime. * * @param relativeUrl - The {@link URL} path for healthcheck page for this instance. * @param explicitUrl - The full {@link URL} for the healthcheck page. * @param secureExplicitUrl the full secure explicit url of the healthcheck page. * @return the instance builder */ public Builder setHealthCheckUrls( String relativeUrl, String explicitUrl, String secureExplicitUrl) { String hostNameInterpolationExpression = "${" + namespace + "hostname}"; result.healthCheckRelativeUrl = relativeUrl; result.healthCheckExplicitUrl = explicitUrl; result.healthCheckSecureExplicitUrl = secureExplicitUrl; if (explicitUrl != null) { result.healthCheckUrl = explicitUrl.replace(hostNameInterpolationExpression, result.hostName); } else if (result.isUnsecurePortEnabled) { result.healthCheckUrl = HTTP_PROTOCOL + result.hostName + COLON + result.port + relativeUrl; } if (secureExplicitUrl != null) { result.secureHealthCheckUrl = secureExplicitUrl.replace(hostNameInterpolationExpression, result.hostName); } else if (result.isSecurePortEnabled) { result.secureHealthCheckUrl = HTTPS_PROTOCOL + result.hostName + COLON + result.securePort + relativeUrl; } return this; }
@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)); }
/** * Set the instance lease information. * * @param info the lease information for this instance. */ public void setLeaseInfo(LeaseInfo info) { result.leaseInfo = info; }
/** * Sets the Secure Virtual Internet Protocol address for this instance. The address should * follow the format <hostname:port> This address needs to be resolved into a real address for * communicating with this instance. * * @param secureVIPAddress the secure VIP address of the instance. * @return - Builder instance */ public Builder setSecureVIPAddress(String secureVIPAddress) { result.secureVipAddressUnresolved = secureVIPAddress; result.secureVipAddress = resolveDeploymentContextBasedVipAddresses(secureVIPAddress); return this; }
public static ReplicationInstance newReplicationInstanceOf(Action action, InstanceInfo instance) { switch (action) { case Register: return new ReplicationInstance( instance.getAppName(), instance.getId(), System.currentTimeMillis(), null, instance.getStatus().name(), instance, action); case Cancel: return new ReplicationInstance( instance.getAppName(), instance.getId(), System.currentTimeMillis(), null, null, null, action); case Heartbeat: return new ReplicationInstance( instance.getAppName(), instance.getId(), System.currentTimeMillis(), InstanceStatus.OUT_OF_SERVICE.name(), instance.getStatus().name(), instance, action); case StatusUpdate: return new ReplicationInstance( instance.getAppName(), instance.getId(), System.currentTimeMillis(), InstanceStatus.OUT_OF_SERVICE.name(), null, null, action); case DeleteStatusOverride: return new ReplicationInstance( instance.getAppName(), instance.getId(), System.currentTimeMillis(), InstanceStatus.OUT_OF_SERVICE.name(), null, null, action); } throw new IllegalStateException("Unexpected action " + action); }
@Deprecated public Builder setCountryId(int id) { result.countryId = id; return this; }
/** * Sets the datacenter information. * * @param datacenter the datacenter information for where this instance is running. * @return the {@link InstanceInfo} builder. */ public Builder setDataCenterInfo(DataCenterInfo datacenter) { result.dataCenterInfo = datacenter; return this; }
/** * 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); } }
/** * Sets the secure port that is used to service requests. * * @param port the secure port that is used to service requests. * @return the {@link InstanceInfo} builder. */ public Builder setSecurePort(int port) { result.securePort = port; return this; }
/** * Replace the existing metadata map with a new one. * * @param mt the new metadata name. * @return instance info builder. */ public Builder setMetadata(Map<String, String> mt) { result.metadata = mt; return this; }
/** * Sets the Virtual Internet Protocol address for this instance. The address should follow the * format <code><hostname:port></code> This address needs to be resolved into a real address for * communicating with this instance. * * @param vipAddress - The Virtual Internet Protocol address of this instance. * @return the instance builder. */ public Builder setVIPAddress(String vipAddress) { result.vipAddressUnresolved = vipAddress; result.vipAddress = resolveDeploymentContextBasedVipAddresses(vipAddress); return this; }
public String getStatus(InstanceInfo info) { return info.getStatus().name(); }
/* * (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); }
/** * Sets the AWS ASG name for this instance. * * @param asgName the asg name for this instance. * @return the instance info builder. */ public Builder setASGName(String asgName) { result.asgName = asgName; return this; }