Skip to content

cache+server: add support for ECDS Fixes #430 #431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static io.envoyproxy.controlplane.cache.Resources.ApiVersion.V3;
import static io.envoyproxy.controlplane.cache.Resources.ResourceType.CLUSTER;
import static io.envoyproxy.controlplane.cache.Resources.ResourceType.ENDPOINT;
import static io.envoyproxy.controlplane.cache.Resources.ResourceType.EXTENSION_CONFIG;
import static io.envoyproxy.controlplane.cache.Resources.ResourceType.LISTENER;
import static io.envoyproxy.controlplane.cache.Resources.ResourceType.ROUTE;
import static io.envoyproxy.controlplane.cache.Resources.ResourceType.SECRET;
Expand All @@ -16,6 +17,7 @@
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.core.v3.TypedExtensionConfig;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.listener.v3.Filter;
import io.envoyproxy.envoy.config.listener.v3.FilterChain;
Expand All @@ -42,7 +44,8 @@ public enum ResourceType {
ENDPOINT,
LISTENER,
ROUTE,
SECRET
SECRET,
EXTENSION_CONFIG
}

public enum ApiVersion {
Expand All @@ -66,18 +69,21 @@ public static class V3 {
"type.googleapis.com/envoy.config.route.v3" + ".RouteConfiguration";
public static final String SECRET_TYPE_URL =
"type.googleapis.com/envoy.extensions" + ".transport_sockets.tls.v3.Secret";
public static final String EXTENSION_CONFIG_TYPE_URL =
"type.googleapis.com/envoy.config.core.v3" + ".TypedExtensionConfig";

public static final List<String> TYPE_URLS =
ImmutableList.of(
CLUSTER_TYPE_URL,
ENDPOINT_TYPE_URL,
LISTENER_TYPE_URL,
ROUTE_TYPE_URL,
SECRET_TYPE_URL);
SECRET_TYPE_URL,
EXTENSION_CONFIG_TYPE_URL);
}

public static final List<ResourceType> RESOURCE_TYPES_IN_ORDER =
ImmutableList.of(CLUSTER, ENDPOINT, LISTENER, ROUTE, SECRET);
ImmutableList.of(CLUSTER, ENDPOINT, LISTENER, ROUTE, SECRET, EXTENSION_CONFIG);

public static final Map<String, ResourceType> TYPE_URLS_TO_RESOURCE_TYPE =
new ImmutableMap.Builder<String, ResourceType>()
Expand All @@ -86,6 +92,7 @@ public static class V3 {
.put(Resources.V3.LISTENER_TYPE_URL, LISTENER)
.put(Resources.V3.ROUTE_TYPE_URL, ROUTE)
.put(Resources.V3.SECRET_TYPE_URL, SECRET)
.put(Resources.V3.EXTENSION_CONFIG_TYPE_URL, EXTENSION_CONFIG)
.build();

public static final Map<String, Class<? extends Message>> RESOURCE_TYPE_BY_URL =
Expand All @@ -95,6 +102,7 @@ public static class V3 {
.put(Resources.V3.LISTENER_TYPE_URL, Listener.class)
.put(Resources.V3.ROUTE_TYPE_URL, RouteConfiguration.class)
.put(Resources.V3.SECRET_TYPE_URL, Secret.class)
.put(Resources.V3.EXTENSION_CONFIG_TYPE_URL, TypedExtensionConfig.class)
.build();

/**
Expand Down Expand Up @@ -123,6 +131,10 @@ public static String getResourceName(Message resource) {
return ((Secret) resource).getName();
}

if (resource instanceof TypedExtensionConfig) {
return ((TypedExtensionConfig) resource).getName();
}

return "";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.envoyproxy.envoy.config.core.v3.GrpcService;
import io.envoyproxy.envoy.config.core.v3.SocketAddress;
import io.envoyproxy.envoy.config.core.v3.SocketAddress.Protocol;
import io.envoyproxy.envoy.config.core.v3.TypedExtensionConfig;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.endpoint.v3.Endpoint;
import io.envoyproxy.envoy.config.endpoint.v3.LbEndpoint;
Expand All @@ -29,6 +30,7 @@
import io.envoyproxy.envoy.extensions.filters.http.router.v3.Router;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager;
import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.CodecType;
import io.envoyproxy.envoy.extensions.filters.network.thrift_proxy.filters.header_to_metadata.v3.HeaderToMetadata;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.Secret;
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.TlsCertificate;

Expand Down Expand Up @@ -245,5 +247,17 @@ public static Secret createSecret(String secretName) {
.build();
}

/**
* Returns a new test v3 secret.
*
* @param configName name of the new config
*/
public static TypedExtensionConfig createExtensionConfig(String configName) {
return TypedExtensionConfig.newBuilder()
.setName(configName)
.setTypedConfig(Any.pack(HeaderToMetadata.getDefaultInstance()))
.build();
}

private TestResources() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.envoyproxy.controlplane.cache.SnapshotResources;
import io.envoyproxy.controlplane.cache.VersionedResource;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.core.v3.TypedExtensionConfig;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
Expand Down Expand Up @@ -44,6 +45,7 @@ public static Snapshot create(
Iterable<Listener> listeners,
Iterable<RouteConfiguration> routes,
Iterable<Secret> secrets,
Iterable<TypedExtensionConfig> extensions,
String version) {

return new AutoValue_Snapshot(
Expand All @@ -56,7 +58,9 @@ public static Snapshot create(
SnapshotResources
.create(generateSnapshotResourceIterable(routes), version),
SnapshotResources
.create(generateSnapshotResourceIterable(secrets), version));
.create(generateSnapshotResourceIterable(secrets), version),
SnapshotResources
.create(generateSnapshotResourceIterable(extensions), version));
}

/**
Expand All @@ -82,7 +86,9 @@ public static Snapshot create(
Iterable<RouteConfiguration> routes,
String routesVersion,
Iterable<Secret> secrets,
String secretsVersion) {
String secretsVersion,
Iterable<TypedExtensionConfig> extensions,
String extensionsVersion) {

// TODO(snowp): add a builder alternative
return new AutoValue_Snapshot(
Expand All @@ -95,7 +101,9 @@ public static Snapshot create(
SnapshotResources
.create(generateSnapshotResourceIterable(routes), routesVersion),
SnapshotResources.create(generateSnapshotResourceIterable(secrets),
secretsVersion));
secretsVersion),
SnapshotResources.create(generateSnapshotResourceIterable(extensions),
extensionsVersion));
}

/**
Expand All @@ -105,7 +113,8 @@ public static Snapshot create(
*/
public static Snapshot createEmpty(String version) {
return create(Collections.emptySet(), Collections.emptySet(),
Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), version);
Collections.emptySet(), Collections.emptySet(), Collections.emptySet(),
Collections.emptySet(), version);
}

/**
Expand Down Expand Up @@ -133,6 +142,11 @@ public static Snapshot createEmpty(String version) {
*/
public abstract SnapshotResources<Secret> secrets();

/**
* Returns all extensions config items in the ECDS payload.
*/
public abstract SnapshotResources<TypedExtensionConfig> extensions();

/**
* Asserts that all dependent resources are included in the snapshot. All EDS resources are listed by name in CDS
* resources, and all RDS resources are listed by name in LDS resources.
Expand Down Expand Up @@ -191,6 +205,8 @@ public Map<String, VersionedResource<?>> resources(String typeUrl) {
return (Map) routes().resources();
case SECRET:
return (Map) secrets().resources();
case EXTENSION_CONFIG:
return (Map) extensions().resources();
default:
return ImmutableMap.of();
}
Expand All @@ -213,6 +229,8 @@ public Map<String, VersionedResource<?>> versionedResources(ResourceType resourc
return (Map) routes().versionedResources();
case SECRET:
return (Map) secrets().versionedResources();
case EXTENSION_CONFIG:
return (Map) extensions().versionedResources();
default:
return ImmutableMap.of();
}
Expand Down Expand Up @@ -268,6 +286,8 @@ public String version(ResourceType resourceType, List<String> resourceNames) {
return routes().version(resourceNames);
case SECRET:
return secrets().version(resourceNames);
case EXTENSION_CONFIG:
return extensions().version(resourceNames);
default:
return "";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.google.protobuf.Message;
import com.google.type.Color;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.core.v3.TypedExtensionConfig;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
Expand All @@ -31,6 +32,7 @@ public class ResourcesTest {
private static final String LISTENER_NAME = "v3listener";
private static final String ROUTE_NAME = "v3route";
private static final String SECRET_NAME = "v3secret";
private static final String EXTENSION_CONFIG_NAME = "v3extension_config";

private static final int ENDPOINT_PORT = ThreadLocalRandom.current().nextInt(10000, 20000);
private static final int LISTENER_PORT = ThreadLocalRandom.current().nextInt(20000, 30000);
Expand All @@ -47,6 +49,9 @@ public class ResourcesTest {
private static final VersionedResource<Secret> SECRET = VersionedResource.create(
TestResources.createSecret(SECRET_NAME),
UUID.randomUUID().toString());
private static final VersionedResource<TypedExtensionConfig> EXTENSION_CONFIG = VersionedResource.create(
TestResources.createExtensionConfig(EXTENSION_CONFIG_NAME),
UUID.randomUUID().toString());

@Test
public void getResourceNameReturnsExpectedNameForValidResourceMessage() {
Expand All @@ -56,7 +61,8 @@ public void getResourceNameReturnsExpectedNameForValidResourceMessage() {
ENDPOINT, CLUSTER_NAME,
LISTENER, LISTENER_NAME,
ROUTE, ROUTE_NAME,
SECRET, SECRET_NAME);
SECRET, SECRET_NAME,
EXTENSION_CONFIG, EXTENSION_CONFIG_NAME);

cases.forEach(
(resource, expectedName) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.envoyproxy.controlplane.cache.XdsRequest;
import io.envoyproxy.envoy.config.cluster.v3.Cluster;
import io.envoyproxy.envoy.config.core.v3.Node;
import io.envoyproxy.envoy.config.core.v3.TypedExtensionConfig;
import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment;
import io.envoyproxy.envoy.config.listener.v3.Listener;
import io.envoyproxy.envoy.config.route.v3.RouteConfiguration;
Expand All @@ -40,6 +41,7 @@ public class SimpleCacheTest {
private static final String LISTENER_NAME = "listener0";
private static final String ROUTE_NAME = "route0";
private static final String SECRET_NAME = "secret0";
private static final String EXTENSION_CONFIG_NAME = "extension_config0";

private static final String VERSION1 = UUID.randomUUID().toString();
private static final String VERSION2 = UUID.randomUUID().toString();
Expand All @@ -50,6 +52,7 @@ public class SimpleCacheTest {
ImmutableList.of(Listener.newBuilder().setName(LISTENER_NAME).build()),
ImmutableList.of(RouteConfiguration.newBuilder().setName(ROUTE_NAME).build()),
ImmutableList.of(Secret.newBuilder().setName(SECRET_NAME).build()),
ImmutableList.of(TypedExtensionConfig.newBuilder().setName(EXTENSION_CONFIG_NAME).build()),
VERSION1);

private static final Snapshot SNAPSHOT2 = Snapshot.create(
Expand All @@ -58,6 +61,7 @@ public class SimpleCacheTest {
ImmutableList.of(Listener.newBuilder().setName(LISTENER_NAME).build()),
ImmutableList.of(RouteConfiguration.newBuilder().setName(ROUTE_NAME).build()),
ImmutableList.of(Secret.newBuilder().setName(SECRET_NAME).build()),
ImmutableList.of(TypedExtensionConfig.newBuilder().setName(EXTENSION_CONFIG_NAME).build()),
VERSION2);

private static final Snapshot MULTIPLE_RESOURCES_SNAPSHOT2 = Snapshot.create(
Expand All @@ -68,6 +72,7 @@ public class SimpleCacheTest {
ImmutableList.of(Listener.newBuilder().setName(LISTENER_NAME).build()),
ImmutableList.of(RouteConfiguration.newBuilder().setName(ROUTE_NAME).build()),
ImmutableList.of(Secret.newBuilder().setName(SECRET_NAME).build()),
ImmutableList.of(TypedExtensionConfig.newBuilder().setName(EXTENSION_CONFIG_NAME).build()),
VERSION2);

private static void assertThatWatchIsOpenWithNoResponses(WatchAndTracker watchAndTracker) {
Expand Down Expand Up @@ -297,7 +302,8 @@ public void successfullyWatchAllResourceTypesWithSetBeforeWatchWithRequestVersio
Resources.V3.CLUSTER_TYPE_URL, Resources.V3.ENDPOINT_TYPE_URL,
Resources.V3.ENDPOINT_TYPE_URL, Resources.V3.LISTENER_TYPE_URL,
Resources.V3.LISTENER_TYPE_URL, ROUTE_TYPE_URL, ROUTE_TYPE_URL,
Resources.V3.SECRET_TYPE_URL, Resources.V3.SECRET_TYPE_URL);
Resources.V3.SECRET_TYPE_URL, Resources.V3.SECRET_TYPE_URL,
Resources.V3.EXTENSION_CONFIG_TYPE_URL, Resources.V3.EXTENSION_CONFIG_TYPE_URL);
}

@Test
Expand Down Expand Up @@ -460,7 +466,8 @@ public void watchesAreReleasedAfterCancel() {
public void watchIsLeftOpenIfNotRespondedImmediately() {
SimpleCache<String> cache = new SimpleCache<>(new SingleNodeGroup());
cache.setSnapshot(SingleNodeGroup.GROUP, Snapshot.create(
ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), VERSION1));
ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(),
ImmutableList.of(), VERSION1));

ResponseTracker responseTracker = new ResponseTracker();
Watch watch = cache.createWatch(
Expand Down
Loading