Skip to content

Commit

Permalink
Merge pull request #640 from tbak/master
Browse files Browse the repository at this point in the history
1.x Bug fixes and minor cleanups
  • Loading branch information
tbak committed Sep 15, 2015
2 parents 9fe7120 + 79e4dcd commit b7d96ae
Show file tree
Hide file tree
Showing 11 changed files with 468 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,32 +1,30 @@
package com.netflix.discovery;

import com.google.inject.AbstractModule;
import com.netflix.appinfo.CloudInstanceConfig;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
import com.netflix.archaius.Config;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaArchaius2ClientConfig;

/**
* Add this module to your project to enable Eureka client and registration
*
*
* @author elandau
*
*/
public final class EurekaArchaius2Module extends AbstractModule {
@Override
protected void configure() {
requireBinding(Config.class);
// Bindings for eureka
bind(EurekaInstanceConfig.class).to(EurekaInstanceConfig.class);

// Bindings for eureka
bind(EurekaInstanceConfig.class).to(CloudInstanceConfig.class);
bind(EurekaArchaius2ClientConfig.class).to(EurekaArchaius2ClientConfig.class);
bind(InstanceInfo.class).toProvider(EurekaConfigBasedInstanceInfoProvider.class);
bind(EurekaClient.class).to(DiscoveryClient.class);
}

@Override
public boolean equals(Object obj) {
return EurekaArchaius2Module.class.equals(obj.getClass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -25,14 +25,14 @@ protected JerseyEurekaHttpClient(String serviceUrl) {
this.serviceUrl = serviceUrl;
}

protected abstract ApacheHttpClient4 getJerseyApacheClient();
protected abstract Client getJerseyClient();

@Override
public HttpResponse<Void> register(InstanceInfo info) {
String urlPath = "apps/" + info.getAppName();
ClientResponse response = null;
try {
Builder resourceBuilder = getJerseyApacheClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
Builder resourceBuilder = getJerseyClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
addExtraHeaders(resourceBuilder);
response = resourceBuilder
.header("Accept-Encoding", "gzip")
Expand All @@ -53,10 +53,10 @@ public HttpResponse<Void> register(InstanceInfo info) {

@Override
public HttpResponse<Void> cancel(String appName, String id) {
String urlPath = "apps/" + appName + "/" + id;
String urlPath = "apps/" + appName + '/' + id;
ClientResponse response = null;
try {
Builder resourceBuilder = getJerseyApacheClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
Builder resourceBuilder = getJerseyClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
addExtraHeaders(resourceBuilder);
response = resourceBuilder.delete(ClientResponse.class);
return HttpResponse.responseWith(response.getStatus());
Expand All @@ -75,7 +75,7 @@ public HttpResponse<InstanceInfo> sendHeartBeat(String appName, String id, Insta
String urlPath = "apps/" + appName + '/' + id;
ClientResponse response = null;
try {
WebResource webResource = getJerseyApacheClient().resource(serviceUrl)
WebResource webResource = getJerseyClient().resource(serviceUrl)
.path(urlPath)
.queryParam("status", info.getStatus().toString())
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString());
Expand All @@ -100,7 +100,7 @@ public HttpResponse<Void> statusUpdate(String appName, String id, InstanceStatus
String urlPath = "apps/" + appName + "/" + id + "/status";
ClientResponse response = null;
try {
Builder requestBuilder = getJerseyApacheClient().resource(serviceUrl)
Builder requestBuilder = getJerseyClient().resource(serviceUrl)
.path(urlPath)
.queryParam("value", newStatus.name())
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
Expand All @@ -123,7 +123,7 @@ public HttpResponse<Void> deleteStatusOverride(String appName, String id, Instan
String urlPath = "apps/" + appName + '/' + id + "/status";
ClientResponse response = null;
try {
Builder requestBuilder = getJerseyApacheClient().resource(serviceUrl)
Builder requestBuilder = getJerseyClient().resource(serviceUrl)
.path(urlPath)
.queryParam("lastDirtyTimestamp", info.getLastDirtyTimestamp().toString())
.getRequestBuilder();
Expand All @@ -145,7 +145,7 @@ public HttpResponse<Applications> getApplications() {
String urlPath = "apps/";
ClientResponse response = null;
try {
Builder requestBuilder = getJerseyApacheClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
Builder requestBuilder = getJerseyClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
addExtraHeaders(requestBuilder);
response = requestBuilder.accept(MediaType.APPLICATION_JSON_TYPE).get(ClientResponse.class);

Expand All @@ -169,7 +169,7 @@ public HttpResponse<Applications> getDelta() {
String urlPath = "apps/delta";
ClientResponse response = null;
try {
Builder requestBuilder = getJerseyApacheClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
Builder requestBuilder = getJerseyClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
addExtraHeaders(requestBuilder);
response = requestBuilder.accept(MediaType.APPLICATION_JSON_TYPE).get(ClientResponse.class);

Expand All @@ -193,7 +193,7 @@ public HttpResponse<InstanceInfo> getInstance(String appName, String id) {
String urlPath = "apps/" + appName + '/' + id;
ClientResponse response = null;
try {
Builder requestBuilder = getJerseyApacheClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
Builder requestBuilder = getJerseyClient().resource(serviceUrl).path(urlPath).getRequestBuilder();
addExtraHeaders(requestBuilder);
response = requestBuilder.accept(MediaType.APPLICATION_JSON_TYPE).get(ClientResponse.class);

Expand All @@ -214,7 +214,7 @@ public HttpResponse<InstanceInfo> getInstance(String appName, String id) {

@Override
public void shutdown() {
getJerseyApacheClient().destroy();
getJerseyClient().destroy();
}

protected void addExtraHeaders(Builder webResource) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
/*
* Copyright 2015 Netflix, Inc.
*
* Licensed 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 com.netflix.discovery.util;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.InstanceInfo.ActionType;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import com.netflix.discovery.util.EurekaEntityTransformers.Transformer;

/**
* Collection of functions operating on {@link Applications} and {@link Application} data
* structures. The functions are organized into groups with common prefix name:
* <ul>
* <li>select - queries over Eureka entity objects</li>
* <li>to - Eureka entity object transformers</li>
* <li>copy - copy Eureka entities, with aggregated {@link InstanceInfo} objects copied by reference</li>
* <li>deepCopy - copy Eureka entities, with aggregated {@link InstanceInfo} objects copied by value</li>
* <li>merge - merge two identical data structures</li>
* <li>count - statistical functions</li>
* </ul>
*
* @author Tomasz Bak
*/
public final class EurekaEntityFunctions {

private EurekaEntityFunctions() {
}

public static Set<String> selectApplicationNames(Applications applications) {
Set<String> result = new HashSet<>();
for (Application app : applications.getRegisteredApplications()) {
result.add(app.getName());
}
return result;
}

public static Map<String, InstanceInfo> selectInstancesMappedById(Application application) {
Map<String, InstanceInfo> result = new HashMap<>();
for (InstanceInfo instance : application.getInstances()) {
result.put(instance.getId(), instance);
}
return result;
}

public static InstanceInfo selectInstance(Applications applications, String id) {
for (Application application : applications.getRegisteredApplications()) {
for (InstanceInfo instance : application.getInstances()) {
if (instance.getId().equals(id)) {
return instance;
}
}
}
return null;
}

public static InstanceInfo selectInstance(Applications applications, String appName, String id) {
Application application = applications.getRegisteredApplications(appName);
if (application != null) {
for (InstanceInfo instance : application.getInstances()) {
if (instance.getId().equals(id)) {
return instance;
}
}
}
return null;
}

public static Map<String, Application> toApplicationMap(List<InstanceInfo> instances) {
Map<String, Application> applicationMap = new HashMap<String, Application>();
for (InstanceInfo instance : instances) {
String appName = instance.getAppName();
Application application = applicationMap.get(appName);
if (application == null) {
applicationMap.put(appName, application = new Application(appName));
}
application.addInstance(instance);
}
return applicationMap;
}

public static Applications toApplications(Map<String, Application> applicationMap) {
Applications applications = new Applications();
for (Application application : applicationMap.values()) {
applications.addApplication(application);
}
return updateMeta(applications);
}

public static Applications toApplications(InstanceInfo... instances) {
return toApplications(Arrays.asList(instances));
}

public static Applications toApplications(List<InstanceInfo> instances) {
Applications result = new Applications();
for (InstanceInfo instance : instances) {
Application app = result.getRegisteredApplications(instance.getAppName());
if (app == null) {
app = new Application(instance.getAppName());
result.addApplication(app);
}
app.addInstance(instance);
}
return updateMeta(result);
}

public static Applications copyApplications(Applications source) {
Applications result = new Applications();
copyApplications(source, result);
return updateMeta(result);
}

public static void copyApplications(Applications source, Applications result) {
if(source != null) {
for (Application app : source.getRegisteredApplications()) {
result.addApplication(new Application(app.getName(), app.getInstances()));
}
}
}

public static Application copyApplication(Application application) {
Application copy = new Application(application.getName());
for (InstanceInfo instance : application.getInstances()) {
copy.addInstance(instance);
}
return copy;
}

public static void copyApplication(Application source, Application result) {
if(source != null) {
for (InstanceInfo instance : source.getInstances()) {
result.addInstance(instance);
}
}
}

public static void copyInstances(List<InstanceInfo> instances, Applications result) {
if (instances != null) {
for (InstanceInfo instance : instances) {
Application app = result.getRegisteredApplications(instance.getAppName());
if (app == null) {
app = new Application(instance.getAppName());
result.addApplication(app);
}
app.addInstance(instance);
}
}
}

public static InstanceInfo copyInstance(InstanceInfo original, ActionType actionType) {
InstanceInfo copy = new InstanceInfo(original);
copy.setActionType(actionType);
return copy;
}

public static void deepCopyApplication(Application source, Application result, Transformer<InstanceInfo> transformer) {
for (InstanceInfo instance : source.getInstances()) {
InstanceInfo copy = transformer.apply(instance);
if (copy == instance) {
copy = new InstanceInfo(instance);
}
result.addInstance(copy);
}
}

public static Application deepCopyApplication(Application source) {
Application result = new Application(source.getName());
deepCopyApplication(source, result, EurekaEntityTransformers.<InstanceInfo>identity());
return result;
}

public static Applications deepCopyApplications(Applications source) {
Applications result = new Applications();
for (Application application : source.getRegisteredApplications()) {
result.addApplication(deepCopyApplication(application));
}
return updateMeta(result);
}

public static Applications mergeApplications(Applications first, Applications second) {
Set<String> firstNames = selectApplicationNames(first);
Set<String> secondNames = selectApplicationNames(second);
Set<String> allNames = new HashSet<String>(firstNames);
allNames.addAll(secondNames);

Applications merged = new Applications();
for (String appName : allNames) {
if (firstNames.contains(appName)) {
if (secondNames.contains(appName)) {
merged.addApplication(mergeApplication(first.getRegisteredApplications(appName), second.getRegisteredApplications(appName)));
} else {
merged.addApplication(copyApplication(first.getRegisteredApplications(appName)));
}
} else {
merged.addApplication(copyApplication(second.getRegisteredApplications(appName)));
}
}
return updateMeta(merged);
}

public static Application mergeApplication(Application first, Application second) {
if (!first.getName().equals(second.getName())) {
throw new IllegalArgumentException("Cannot merge applications with different names");
}
Application merged = copyApplication(first);
for (InstanceInfo instance : second.getInstances()) {
switch (instance.getActionType()) {
case ADDED:
case MODIFIED:
merged.addInstance(instance);
break;
case DELETED:
merged.removeInstance(instance);
}
}
return merged;
}

public static Applications updateMeta(Applications applications) {
applications.setVersion(1L);
applications.setAppsHashCode(applications.getReconcileHashCode());
return applications;
}

public static int countInstances(Applications applications) {
int count = 0;
for (Application application : applications.getRegisteredApplications()) {
count += application.getInstances().size();
}
return count;
}
}
Loading

0 comments on commit b7d96ae

Please sign in to comment.