Skip to content
Merged
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 Down Expand Up @@ -245,5 +246,17 @@ public static Secret createSecret(String secretName) {
.build();
}

/**
* Returns a new test v3 extension config (ECDS), wrapping a no-op HTTP router filter.
*
* @param name name of the new extension config
*/
public static TypedExtensionConfig createExtensionConfig(String name) {
return TypedExtensionConfig.newBuilder()
.setName(name)
.setTypedConfig(Any.pack(Router.newBuilder().build()))
.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 @@ -46,6 +47,30 @@ public static Snapshot create(
Iterable<Secret> secrets,
String version) {

return create(clusters, endpoints, listeners, routes, secrets, Collections.emptySet(), version);
}

/**
* Returns a new {@link io.envoyproxy.controlplane.cache.v3.Snapshot} instance that is versioned uniformly across all
* resources, including ECDS extension configs.
*
* @param clusters the cluster resources in this snapshot
* @param endpoints the endpoint resources in this snapshot
* @param listeners the listener resources in this snapshot
* @param routes the route resources in this snapshot
* @param secrets the secret resources in this snapshot
* @param extensionConfigs the ECDS extension config resources in this snapshot
* @param version the version associated with all resources in this snapshot
*/
public static Snapshot create(
Iterable<Cluster> clusters,
Iterable<ClusterLoadAssignment> endpoints,
Iterable<Listener> listeners,
Iterable<RouteConfiguration> routes,
Iterable<Secret> secrets,
Iterable<TypedExtensionConfig> extensionConfigs,
String version) {

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

/**
Expand Down Expand Up @@ -84,6 +111,41 @@ public static Snapshot create(
Iterable<Secret> secrets,
String secretsVersion) {

return create(clusters, clustersVersion, endpoints, endpointsVersion, listeners, listenersVersion,
routes, routesVersion, secrets, secretsVersion, Collections.emptySet(), "");
}

/**
* Returns a new {@link io.envoyproxy.controlplane.cache.v3.Snapshot} instance that has separate versions for each
* resource type, including ECDS extension configs.
*
* @param clusters the cluster resources in this snapshot
* @param clustersVersion the version of the cluster resources
* @param endpoints the endpoint resources in this snapshot
* @param endpointsVersion the version of the endpoint resources
* @param listeners the listener resources in this snapshot
* @param listenersVersion the version of the listener resources
* @param routes the route resources in this snapshot
* @param routesVersion the version of the route resources
* @param secrets the secret resources in this snapshot
* @param secretsVersion the version of the secret resources
* @param extensionConfigs the ECDS extension config resources in this snapshot
* @param extensionConfigsVersion the version of the ECDS extension config resources
*/
public static Snapshot create(
Iterable<Cluster> clusters,
String clustersVersion,
Iterable<ClusterLoadAssignment> endpoints,
String endpointsVersion,
Iterable<Listener> listeners,
String listenersVersion,
Iterable<RouteConfiguration> routes,
String routesVersion,
Iterable<Secret> secrets,
String secretsVersion,
Iterable<TypedExtensionConfig> extensionConfigs,
String extensionConfigsVersion) {

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

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

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

/**
* 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 +260,8 @@ public Map<String, VersionedResource<?>> resources(String typeUrl) {
return (Map) routes().resources();
case SECRET:
return (Map) secrets().resources();
case EXTENSION_CONFIG:
return (Map) extensionConfigs().resources();
default:
return ImmutableMap.of();
}
Expand All @@ -213,6 +284,8 @@ public Map<String, VersionedResource<?>> versionedResources(ResourceType resourc
return (Map) routes().versionedResources();
case SECRET:
return (Map) secrets().versionedResources();
case EXTENSION_CONFIG:
return (Map) extensionConfigs().versionedResources();
default:
return ImmutableMap.of();
}
Expand Down Expand Up @@ -268,6 +341,8 @@ public String version(ResourceType resourceType, List<String> resourceNames) {
return routes().version(resourceNames);
case SECRET:
return secrets().version(resourceNames);
case EXTENSION_CONFIG:
return extensionConfigs().version(resourceNames);
default:
return "";
}
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 = "extensionConfig0";

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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static io.envoyproxy.controlplane.cache.Resources.V3.CLUSTER_TYPE_URL;
import static io.envoyproxy.controlplane.cache.Resources.V3.ENDPOINT_TYPE_URL;
import static io.envoyproxy.controlplane.cache.Resources.V3.EXTENSION_CONFIG_TYPE_URL;
import static io.envoyproxy.controlplane.cache.Resources.V3.LISTENER_TYPE_URL;
import static io.envoyproxy.controlplane.cache.Resources.V3.ROUTE_TYPE_URL;
import static io.envoyproxy.envoy.config.core.v3.ApiVersion.V3;
Expand All @@ -14,6 +15,7 @@
import io.envoyproxy.controlplane.cache.TestResources;
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 All @@ -29,6 +31,7 @@ public class SnapshotTest {
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 = "extensionConfig0";

private static final int ENDPOINT_PORT = ThreadLocalRandom.current().nextInt(10000, 20000);
private static final int LISTENER_PORT = ThreadLocalRandom.current().nextInt(20000, 30000);
Expand All @@ -41,6 +44,8 @@ public class SnapshotTest {
private static final RouteConfiguration ROUTE = TestResources.createRoute(ROUTE_NAME,
CLUSTER_NAME);
private static final Secret SECRET = TestResources.createSecret(SECRET_NAME);
private static final TypedExtensionConfig
EXTENSION_CONFIG = TestResources.createExtensionConfig(EXTENSION_CONFIG_NAME);

@Test
public void createSingleVersionSetsResourcesCorrectly() {
Expand Down Expand Up @@ -114,6 +119,58 @@ public void createSeparateVersionsSetsResourcesCorrectly() {
assertThat(snapshot.routes().version()).isEqualTo(routesVersion);
}

@Test
public void createSetsExtensionConfigsCorrectly() {
final String version = UUID.randomUUID().toString();

Snapshot snapshot = Snapshot.create(
ImmutableList.of(CLUSTER),
ImmutableList.of(ENDPOINT),
ImmutableList.of(LISTENER),
ImmutableList.of(ROUTE),
ImmutableList.of(SECRET),
ImmutableList.of(EXTENSION_CONFIG),
version);

assertThat(snapshot.extensionConfigs().resources())
.containsEntry(EXTENSION_CONFIG_NAME, EXTENSION_CONFIG)
.hasSize(1);
assertThat(snapshot.extensionConfigs().version()).isEqualTo(version);

assertThat(snapshot.resources(EXTENSION_CONFIG_TYPE_URL))
.containsEntry(EXTENSION_CONFIG_NAME, VersionedResource.create(EXTENSION_CONFIG))
.hasSize(1);
assertThat(snapshot.version(EXTENSION_CONFIG_TYPE_URL)).isEqualTo(version);

// The legacy create overload leaves the ECDS payload empty.
Snapshot withoutEcds = Snapshot.create(
ImmutableList.of(CLUSTER),
ImmutableList.of(ENDPOINT),
ImmutableList.of(LISTENER),
ImmutableList.of(ROUTE),
ImmutableList.of(SECRET),
version);
assertThat(withoutEcds.extensionConfigs().resources()).isEmpty();
}

@Test
public void createSeparateVersionsSetsExtensionConfigsCorrectly() {
final String extensionConfigsVersion = UUID.randomUUID().toString();

Snapshot snapshot = Snapshot.create(
ImmutableList.of(CLUSTER), UUID.randomUUID().toString(),
ImmutableList.of(ENDPOINT), UUID.randomUUID().toString(),
ImmutableList.of(LISTENER), UUID.randomUUID().toString(),
ImmutableList.of(ROUTE), UUID.randomUUID().toString(),
ImmutableList.of(SECRET), UUID.randomUUID().toString(),
ImmutableList.of(EXTENSION_CONFIG), extensionConfigsVersion);

assertThat(snapshot.extensionConfigs().resources())
.containsEntry(EXTENSION_CONFIG_NAME, EXTENSION_CONFIG)
.hasSize(1);
assertThat(snapshot.extensionConfigs().version()).isEqualTo(extensionConfigsVersion);
}

@Test
@SuppressWarnings("unchecked")
public void resourcesReturnsExpectedResources() {
Expand Down
Loading
Loading