summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java4
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionTest.java6
-rw-r--r--container-core/src/main/java/com/yahoo/restapi/Path.java1
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java95
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java5
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java1
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiHandler.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandler.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiHandler.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiHandler.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java12
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java25
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java1
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/responses/discovery/instance_api.json10
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java18
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java2
-rw-r--r--zookeeper-server/zookeeper-server-3.6.2/pom.xml12
-rw-r--r--zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaZooKeeperAdminImpl.java3
30 files changed, 111 insertions, 148 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java
index 909a29fd0a3..2bd343fc230 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionValidator.java
@@ -97,10 +97,10 @@ public class IndexedHierarchicDistributionValidator {
}
if (totalReadyCopies % groupCount != 0) {
throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Expected equal amount of ready copies per group, but " +
- totalReadyCopies + " ready copies is specified with " + groupCount + " groups");
+ totalReadyCopies + " ready copies is specified with " + groupCount + " groups");
}
if (totalReadyCopies == 0) {
- System.err.println(getErrorMsgPrefix(clusterName) + "Warning. No ready copies configured. At least one is recommended.");
+ throw new IllegalArgumentException(getErrorMsgPrefix(clusterName) + "Warning. No ready copies configured. At least one is recommended.");
}
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionTest.java
index 80ab6745b79..3be592e54e7 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/content/IndexedHierarchicDistributionTest.java
@@ -254,10 +254,4 @@ public class IndexedHierarchicDistributionTest {
getTwoGroupsCluster(4, 2, "2|*");
}
- @Test
- public void allowNoReadyCopies() throws Exception {
- // The active one should be indexed anyhow. Setting up no ready copies
- getTwoGroupsCluster(4, 0, "2|*");
- }
-
}
diff --git a/container-core/src/main/java/com/yahoo/restapi/Path.java b/container-core/src/main/java/com/yahoo/restapi/Path.java
index 23a791e7532..9fc924adbe2 100644
--- a/container-core/src/main/java/com/yahoo/restapi/Path.java
+++ b/container-core/src/main/java/com/yahoo/restapi/Path.java
@@ -46,6 +46,7 @@ public class Path {
this(uri, "");
}
+ // TODO (freva): Remove, used by factory
public Path(URI uri, String optionalPrefix) {
this.optionalPrefix = optionalPrefix;
this.pathString = uri.getRawPath();
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
index 72210ec26ed..a0da8cbddba 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/PathGroup.java
@@ -6,7 +6,6 @@ import com.yahoo.restapi.Path;
import java.net.URI;
import java.util.EnumSet;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -21,13 +20,11 @@ import java.util.Set;
enum PathGroup {
/** Paths exclusive to operators (including read), used for system management. */
- classifiedOperator(PathPrefix.api,
- "/configserver/v1/{*}",
+ classifiedOperator("/configserver/v1/{*}",
"/deployment/v1/{*}"),
/** Paths used for system management by operators. */
- operator(PathPrefix.none,
- "/controller/v1/{*}",
+ operator("/controller/v1/{*}",
"/flags/v1/{*}",
"/loadbalancers/v1/{*}",
"/nodes/v2/{*}",
@@ -42,61 +39,51 @@ enum PathGroup {
"/changemanagement/v1/{*}"),
/** Paths used for creating and reading user resources. */
- user(PathPrefix.api,
- "/application/v4/user",
+ user("/application/v4/user",
"/athenz/v1/{*}"),
/** Paths used for creating tenants with proper access control. */
tenant(Matcher.tenant,
- PathPrefix.api,
"/application/v4/tenant/{tenant}"),
/** Paths used for user management on the tenant level. */
tenantUsers(Matcher.tenant,
- PathPrefix.api,
"/user/v1/tenant/{tenant}"),
/** Paths used by tenant administrators. */
tenantInfo(Matcher.tenant,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/",
"/application/v4/tenant/{tenant}/info/",
"/routing/v1/status/tenant/{tenant}/{*}"),
tenantKeys(Matcher.tenant,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/key/"),
+ tenantArchiveAccess(Matcher.tenant,
+ "/application/v4/tenant/{tenant}/archive-access"),
billingToken(Matcher.tenant,
- PathPrefix.api,
"/billing/v1/tenant/{tenant}/token"),
billingInstrument(Matcher.tenant,
- PathPrefix.api,
"/billing/v1/tenant/{tenant}/instrument/{*}"),
billingPlan(Matcher.tenant,
- PathPrefix.api,
"/billing/v1/tenant/{tenant}/plan/{*}"),
billingCollection(Matcher.tenant,
- PathPrefix.api,
"/billing/v1/tenant/{tenant}/collection/{*}"),
billingList(Matcher.tenant,
- PathPrefix.api,
"/billing/v1/tenant/{tenant}/billing/{*}"),
applicationKeys(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/key/"),
/** Path for the base application resource. */
application(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}",
"/application/v4/tenant/{tenant}/application/{application}/instance/",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}"),
@@ -104,13 +91,11 @@ enum PathGroup {
/** Paths used for user management on the application level. */
applicationUsers(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/user/v1/tenant/{tenant}/application/{application}"),
/** Paths used by application administrators. */
applicationInfo(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/package",
"/application/v4/tenant/{tenant}/application/{application}/compile-version",
"/application/v4/tenant/{tenant}/application/{application}/deployment",
@@ -139,7 +124,6 @@ enum PathGroup {
developmentRestart(Matcher.tenant,
Matcher.application,
Matcher.instance,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/environment/dev/region/{region}/restart",
"/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/environment/perf/region/{region}/restart",
"/application/v4/tenant/{tenant}/application/{application}/environment/dev/region/{region}/instance/{instance}/restart",
@@ -149,7 +133,6 @@ enum PathGroup {
/** Path used to restart production nodes. */
productionRestart(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/prod/region/{region}/restart",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/test/region/{region}/restart",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/staging/region/{region}/restart",
@@ -160,7 +143,6 @@ enum PathGroup {
/** Path used to manipulate reindexing status. */
reindexing(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/{environment}/region/{region}/reindex",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/{environment}/region/{region}/reindexing"),
@@ -168,7 +150,6 @@ enum PathGroup {
developmentDeployment(Matcher.tenant,
Matcher.application,
Matcher.instance,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/deploy/{job}",
"/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/environment/dev/region/{region}",
"/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/environment/dev/region/{region}/deploy",
@@ -185,7 +166,6 @@ enum PathGroup {
/** Paths used for production deployments. */
productionDeployment(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/prod/region/{region}",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/prod/region/{region}/deploy",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/environment/test/region/{region}",
@@ -202,84 +182,76 @@ enum PathGroup {
/** Paths used for continuous deployment to production. */
submission(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/submit",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/submit"),
/** Paths used for other tasks by build services. */ // TODO: This will vanish.
buildService(Matcher.tenant,
Matcher.application,
- PathPrefix.api,
"/application/v4/tenant/{tenant}/application/{application}/jobreport",
"/application/v4/tenant/{tenant}/application/{application}/instance/{ignored}/jobreport"),
/** Paths which contain (not very strictly) classified information about customers. */
- classifiedTenantInfo(PathPrefix.api,
- "/application/v4/",
+ classifiedTenantInfo("/application/v4/",
"/application/v4/tenant/"),
/** Paths which contain (not very strictly) classified information about, e.g., customers. */
- classifiedInfo(PathPrefix.none,
- "/",
+ classifiedInfo("/",
"/d/{*}"),
/** Paths providing public information. */
- publicInfo(PathPrefix.api,
- "/user/v1/user", // Information about who you are.
+ publicInfo("/user/v1/user", // Information about who you are.
"/badge/v1/{*}", // Badges for deployment jobs.
"/zone/v1/{*}"), // Lists environment and regions.
/** Paths used for deploying system-wide feature flags. */
- systemFlagsDeploy(PathPrefix.none, "/system-flags/v1/deploy"),
+ systemFlagsDeploy("/system-flags/v1/deploy"),
/** Paths used for "dry-running" system-wide feature flags. */
- systemFlagsDryrun(PathPrefix.none, "/system-flags/v1/dryrun"),
+ systemFlagsDryrun("/system-flags/v1/dryrun"),
/** Paths used for receiving payment callbacks */
- paymentProcessor(PathPrefix.none, "/payment/notification"),
+ paymentProcessor("/payment/notification"),
/** Paths used for invoice management */
- hostedAccountant(PathPrefix.api,
- "/billing/v1/invoice/{*}",
- "/billing/v1/billing"),
+ hostedAccountant("/billing/v1/invoice/{*}",
+ "/billing/v1/billing"),
/** Path used for listing endpoint certificate request info */
- endpointCertificateRequestInfo(PathPrefix.none, "/certificateRequests/"),
+ endpointCertificateRequestInfo("/certificateRequests/"),
/** Path used for secret store management */
- secretStore(Matcher.tenant, PathPrefix.api, "/application/v4/tenant/{tenant}/secret-store/{*}");
+ secretStore(Matcher.tenant, "/application/v4/tenant/{tenant}/secret-store/{*}");
final List<String> pathSpecs;
- final PathPrefix prefix;
final List<Matcher> matchers;
- PathGroup(PathPrefix prefix, String... pathSpecs) {
- this(List.of(), prefix, List.of(pathSpecs));
+ PathGroup(String... pathSpecs) {
+ this(List.of(), List.of(pathSpecs));
}
- PathGroup(Matcher first, PathPrefix prefix, String... pathSpecs) {
- this(List.of(first), prefix, List.of(pathSpecs));
+ PathGroup(Matcher first, String... pathSpecs) {
+ this(List.of(first), List.of(pathSpecs));
}
- PathGroup(Matcher first, Matcher second, PathPrefix prefix, String... pathSpecs) {
- this(List.of(first, second), prefix, List.of(pathSpecs));
+ PathGroup(Matcher first, Matcher second, String... pathSpecs) {
+ this(List.of(first, second), List.of(pathSpecs));
}
- PathGroup(Matcher first, Matcher second, Matcher third, PathPrefix prefix, String... pathSpecs) {
- this(List.of(first, second, third), prefix, List.of(pathSpecs));
+ PathGroup(Matcher first, Matcher second, Matcher third, String... pathSpecs) {
+ this(List.of(first, second, third), List.of(pathSpecs));
}
/** Creates a new path group, if the given context matchers are each present exactly once in each of the given specs. */
- PathGroup(List<Matcher> matchers, PathPrefix prefix, List<String> pathSpecs) {
+ PathGroup(List<Matcher> matchers, List<String> pathSpecs) {
this.matchers = matchers;
- this.prefix = prefix;
this.pathSpecs = pathSpecs;
}
/** Returns path if it matches any spec in this group, with match groups set by the match. */
private Optional<Path> get(URI uri) {
- Path matcher = new Path(uri, prefix.prefix);
+ Path matcher = new Path(uri);
for (String spec : pathSpecs) // Iterate to be sure the Path's state is that of the match.
if (matcher.matches(spec)) return Optional.of(matcher);
return Optional.empty();
@@ -352,21 +324,4 @@ enum PathGroup {
}
- /**
- * The valid prefixes of paths in a {@link PathGroup}. Provides flexibility in cases where paths are made available
- * under a non-root path.
- */
- enum PathPrefix {
-
- none(""),
- api("/api");
-
- private final String prefix;
-
- PathPrefix(String prefix) {
- this.prefix = Objects.requireNonNull(prefix);
- }
-
- }
-
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java
index ad739d16ff8..b48e786c178 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/Policy.java
@@ -72,6 +72,11 @@ enum Policy {
.on(PathGroup.tenant, PathGroup.tenantInfo, PathGroup.tenantUsers, PathGroup.applicationUsers)
.in(SystemName.all())),
+ /** Access to set and unset archive access role under a tenant. */
+ tenantArchiveAccessManagement(Privilege.grant(Action.update, Action.delete)
+ .on(PathGroup.tenantArchiveAccess)
+ .in(SystemName.all())),
+
/** Access to create application under a certain tenant. */
applicationCreate(Privilege.grant(Action.create)
.on(PathGroup.application)
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java
index aeb5419b682..a0ee0fe3548 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/role/RoleDefinition.java
@@ -63,6 +63,7 @@ public enum RoleDefinition {
administrator(Policy.tenantUpdate,
Policy.tenantManager,
Policy.tenantDelete,
+ Policy.tenantArchiveAccessManagement,
Policy.applicationManager,
Policy.keyRevokal,
Policy.paymentInstrumentRead,
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index e5ada9365f0..ca080078328 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -154,8 +154,6 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
private static final ObjectMapper jsonMapper = new ObjectMapper();
- private static final String OPTIONAL_PREFIX = "/api";
-
private final Controller controller;
private final AccessControlRequests accessControlRequests;
private final TestConfigSerializer testConfigSerializer;
@@ -178,7 +176,7 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
@Override
public HttpResponse handle(HttpRequest request) {
try {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
switch (request.getMethod()) {
case GET: return handleGET(path, request);
case PUT: return handlePUT(path, request);
@@ -1985,6 +1983,8 @@ public class ApplicationApiHandler extends LoggingRequestHandler {
toSlime(tenantQuota, usedQuota, object.setObject("quota"));
+ cloudTenant.archiveAccessRole().ifPresent(role -> object.setString("archiveAccessRole", role));
+
break;
}
default: throw new IllegalArgumentException("Unexpected tenant type '" + tenant.type() + "'.");
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiHandler.java
index d10a4879bf5..26c4bf6292a 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiHandler.java
@@ -37,7 +37,6 @@ import java.util.logging.Logger;
public class AthenzApiHandler extends LoggingRequestHandler {
private final static Logger log = Logger.getLogger(AthenzApiHandler.class.getName());
- private static final String OPTIONAL_PREFIX = "/api";
private final AthenzFacade athenz;
private final AthenzDomain sandboxDomain;
@@ -70,7 +69,7 @@ public class AthenzApiHandler extends LoggingRequestHandler {
}
private HttpResponse get(HttpRequest request) {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
if (path.matches("/athenz/v1")) return root(request);
if (path.matches("/athenz/v1/domains")) return domainList(request);
if (path.matches("/athenz/v1/properties")) return properties();
@@ -80,7 +79,7 @@ public class AthenzApiHandler extends LoggingRequestHandler {
}
private HttpResponse post(HttpRequest request) {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
if (path.matches("/athenz/v1/user")) return signup(request);
return ErrorResponse.notFoundError(String.format("No '%s' handler at '%s'", request.getMethod(),
request.getUri().getPath()));
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
index 88191bc836b..c56c2e93f65 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
@@ -5,7 +5,6 @@ import com.yahoo.config.provision.TenantName;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.container.jdisc.HttpResponse;
import com.yahoo.container.jdisc.LoggingRequestHandler;
-import com.yahoo.container.logging.AccessLog;
import com.yahoo.restapi.ErrorResponse;
import com.yahoo.restapi.JacksonJsonResponse;
import com.yahoo.restapi.MessageResponse;
@@ -55,7 +54,6 @@ import java.util.stream.Collectors;
*/
public class BillingApiHandler extends LoggingRequestHandler {
- private static final String OPTIONAL_PREFIX = "/api";
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private final BillingController billingController;
@@ -73,7 +71,7 @@ public class BillingApiHandler extends LoggingRequestHandler {
@Override
public HttpResponse handle(HttpRequest request) {
try {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
String userId = userIdOrThrow(request);
switch (request.getMethod()) {
case GET:
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandler.java
index f65f7534476..1bb3b1c5de8 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandler.java
@@ -33,7 +33,6 @@ public class ConfigServerApiHandler extends AuditLoggingRequestHandler {
private static final ZoneId CONTROLLER_ZONE = ZoneId.from("prod", "controller");
private static final URI CONTROLLER_URI = URI.create("https://localhost:4443/");
- private static final String OPTIONAL_PREFIX = "/api";
private static final List<String> WHITELISTED_APIS = List.of("/flags/v1/", "/nodes/v2/", "/orchestrator/v1/");
private final ZoneRegistry zoneRegistry;
@@ -70,7 +69,7 @@ public class ConfigServerApiHandler extends AuditLoggingRequestHandler {
}
private HttpResponse get(HttpRequest request) {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
if (path.matches("/configserver/v1")) {
return root(request);
}
@@ -78,7 +77,7 @@ public class ConfigServerApiHandler extends AuditLoggingRequestHandler {
}
private HttpResponse proxy(HttpRequest request) {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
if ( ! path.matches("/configserver/v1/{environment}/{region}/{*}")) {
return ErrorResponse.notFoundError("Nothing at " + path);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java
index da13a84a3d4..552e22e9a2c 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiHandler.java
@@ -49,8 +49,6 @@ import static java.util.stream.Collectors.toUnmodifiableMap;
@SuppressWarnings("unused") // Injected
public class DeploymentApiHandler extends LoggingRequestHandler {
- private static final String OPTIONAL_PREFIX = "/api";
-
private final Controller controller;
public DeploymentApiHandler(LoggingRequestHandler.Context parentCtx, Controller controller) {
@@ -77,7 +75,7 @@ public class DeploymentApiHandler extends LoggingRequestHandler {
}
private HttpResponse handleGET(HttpRequest request) {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
if (path.matches("/deployment/v1/")) return root(request);
return ErrorResponse.notFoundError("Nothing at " + path);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiHandler.java
index f26477beb3b..828e7e63483 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiHandler.java
@@ -42,7 +42,6 @@ import java.util.stream.Collectors;
*/
public class RoutingApiHandler extends AuditLoggingRequestHandler {
- private static final String OPTIONAL_PREFIX = "/api";
private final Controller controller;
public RoutingApiHandler(Context ctx, Controller controller) {
@@ -53,7 +52,7 @@ public class RoutingApiHandler extends AuditLoggingRequestHandler {
@Override
public HttpResponse auditAndHandle(HttpRequest request) {
try {
- var path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ var path = new Path(request.getUri());
switch (request.getMethod()) {
case GET: return get(path, request);
case POST: return post(path);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java
index e097b82b7d0..039e9b64df7 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiHandler.java
@@ -64,7 +64,6 @@ import java.util.stream.Collectors;
public class UserApiHandler extends LoggingRequestHandler {
private final static Logger log = Logger.getLogger(UserApiHandler.class.getName());
- private static final String optionalPrefix = "/api";
private final UserManagement users;
private final Controller controller;
@@ -83,7 +82,7 @@ public class UserApiHandler extends LoggingRequestHandler {
@Override
public HttpResponse handle(HttpRequest request) {
try {
- Path path = new Path(request.getUri(), optionalPrefix);
+ Path path = new Path(request.getUri());
switch (request.getMethod()) {
case GET: return handleGET(path, request);
case POST: return handlePOST(path, request);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiHandler.java
index abbbbef82c7..fd6dfa61180 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiHandler.java
@@ -29,8 +29,6 @@ import java.util.stream.Collectors;
@SuppressWarnings("unused")
public class ZoneApiHandler extends LoggingRequestHandler {
- private static final String OPTIONAL_PREFIX = "/api";
-
private final ZoneRegistry zoneRegistry;
public ZoneApiHandler(LoggingRequestHandler.Context parentCtx, ServiceRegistry serviceRegistry) {
@@ -57,7 +55,7 @@ public class ZoneApiHandler extends LoggingRequestHandler {
}
private HttpResponse get(HttpRequest request) {
- Path path = new Path(request.getUri(), OPTIONAL_PREFIX);
+ Path path = new Path(request.getUri());
if (path.matches("/zone/v1")) {
return root(request);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
index b5126b7973b..4f9702669dd 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/tenant/CloudTenant.java
@@ -12,6 +12,7 @@ import java.time.Instant;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
+import java.util.regex.Pattern;
/**
* A paying tenant in a Vespa cloud service.
@@ -20,6 +21,8 @@ import java.util.Optional;
*/
public class CloudTenant extends Tenant {
+ private static final Pattern VALID_ARCHIVE_ACCESS_ROLE_PATTERN = Pattern.compile("arn:aws:iam::\\d{12}:.+");
+
private final Optional<Principal> creator;
private final BiMap<PublicKey, Principal> developerKeys;
private final TenantInfo info;
@@ -36,6 +39,9 @@ public class CloudTenant extends Tenant {
this.info = Objects.requireNonNull(info);
this.tenantSecretStores = tenantSecretStores;
this.archiveAccessRole = archiveAccessRole;
+ if (!archiveAccessRole.map(role -> VALID_ARCHIVE_ACCESS_ROLE_PATTERN.matcher(role).matches()).orElse(true))
+ throw new IllegalArgumentException(String.format("Invalid archive access role '%s': Must match expected pattern: '%s'",
+ archiveAccessRole.get(), VALID_ARCHIVE_ACCESS_ROLE_PATTERN.pattern()));
}
/** Creates a tenant with the given name, provided it passes validation. */
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java
index 9790c8244c8..e123c4cca62 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java
@@ -120,7 +120,7 @@ public class TenantSerializerTest {
new TenantSecretStore("ss1", "123", "role1"),
new TenantSecretStore("ss2", "124", "role2")
),
- Optional.of("role3")
+ Optional.of("arn:aws:iam::123456789012:role/my-role")
);
CloudTenant serialized = (CloudTenant) serializer.tenantFrom(serializer.toSlime(tenant));
assertEquals(tenant.info(), serialized.info());
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
index 2bf6eb39089..10f143a8e96 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ContainerTester.java
@@ -142,12 +142,16 @@ public class ContainerTester {
expectedStatusCode);
}
- public void assertResponse(Supplier<Request> requestSupplier, Consumer<Response> responseAssertion, int expectedStatusCode) {
+ public void assertResponse(Supplier<Request> requestSupplier, ConsumerThrowingException<Response> responseAssertion, int expectedStatusCode) {
var request = requestSupplier.get();
FilterResult filterResult = invokeSecurityFilters(request);
request = filterResult.request;
Response response = filterResult.response != null ? filterResult.response : container.handleRequest(request);
- responseAssertion.accept(response);
+ try {
+ responseAssertion.accept(response);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
assertEquals("Status code", expectedStatusCode, response.getStatus());
}
@@ -203,5 +207,9 @@ public class ContainerTester {
}
}
+ @FunctionalInterface
+ public interface ConsumerThrowingException<T> {
+ void accept(T t) throws Exception;
+ }
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java
index b935f8cbbe4..538e98c4c83 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerCloudTest.java
@@ -36,14 +36,11 @@ public class ControllerContainerCloudTest extends ControllerContainerTest {
" <handler id='com.yahoo.vespa.hosted.controller.restapi.application.ApplicationApiHandler'>\n" +
" <binding>http://*/application/v4/*</binding>\n" +
- " <binding>http://*/api/application/v4/*</binding>\n" +
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.zone.v1.ZoneApiHandler'>\n" +
" <binding>http://*/zone/v1</binding>\n" +
" <binding>http://*/zone/v1/*</binding>\n" +
- " <binding>http://*/api/zone/v1</binding>\n" +
- " <binding>http://*/api/zone/v1/*</binding>\n" +
" </handler>\n" +
" <http>\n" +
@@ -88,6 +85,7 @@ public class ControllerContainerCloudTest extends ControllerContainerTest {
public RequestBuilder principal(String principal) { this.principal = new SimplePrincipal(principal); return this; }
public RequestBuilder user(User user) { this.user = user; return this; }
public RequestBuilder roles(Set<Role> roles) { this.roles = roles; return this; }
+ public RequestBuilder roles(Role... roles) { return roles(Set.of(roles)); }
@Override
public Request get() {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
index 50123e497dc..e92c229d4bc 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
@@ -75,7 +75,6 @@ public class ControllerContainerTest {
" <component id='com.yahoo.vespa.hosted.controller.api.integration.stubs.MockUserManagement'/>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.deployment.DeploymentApiHandler'>\n" +
" <binding>http://*/deployment/v1/*</binding>\n" +
- " <binding>http://*/api/deployment/v1/*</binding>\n" +
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.deployment.BadgeApiHandler'>\n" +
" <binding>http://*/badge/v1/*</binding>\n" +
@@ -93,8 +92,6 @@ public class ControllerContainerTest {
" <handler id='com.yahoo.vespa.hosted.controller.restapi.configserver.ConfigServerApiHandler'>\n" +
" <binding>http://*/configserver/v1</binding>\n" +
" <binding>http://*/configserver/v1/*</binding>\n" +
- " <binding>http://*/api/configserver/v1</binding>\n" +
- " <binding>http://*/api/configserver/v1/*</binding>\n" +
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.flags.AuditedFlagsHandler'>\n" +
" <binding>http://*/flags/v1</binding>\n" +
@@ -102,11 +99,9 @@ public class ControllerContainerTest {
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.user.UserApiHandler'>\n" +
" <binding>http://*/user/v1/*</binding>\n" +
- " <binding>http://*/api/user/v1/*</binding>\n" +
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.routing.RoutingApiHandler'>\n" +
" <binding>http://*/routing/v1/*</binding>\n" +
- " <binding>http://*/api/routing/v1/*</binding>\n" +
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.changemanagement.ChangeManagementApiHandler'>\n" +
" <binding>http://*/changemanagement/v1/*</binding>\n" +
@@ -128,7 +123,6 @@ public class ControllerContainerTest {
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.athenz.AthenzApiHandler'>\n" +
" <binding>http://*/athenz/v1/*</binding>\n" +
- " <binding>http://*/api/athenz/v1/*</binding>\n" +
" </handler>\n" +
" <handler id='com.yahoo.vespa.hosted.controller.restapi.zone.v1.ZoneApiHandler'>\n" +
" <binding>http://*/zone/v1</binding>\n" +
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
index 51e63d5b4cf..4fb91639daa 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
@@ -34,6 +34,8 @@ import static com.yahoo.application.container.handler.Request.Method.POST;
import static com.yahoo.application.container.handler.Request.Method.PUT;
import static com.yahoo.vespa.hosted.controller.restapi.application.ApplicationApiTest.createApplicationSubmissionData;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
@@ -195,6 +197,29 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
assertEquals(0, tenant.tenantSecretStores().size());
}
+ @Test
+ public void archive_uri_test() {
+ tester.assertResponse(request("/application/v4/tenant/scoober", GET).roles(Role.reader(tenantName)),
+ (response) -> assertFalse(response.getBodyAsString().contains("archiveAccessRole")),
+ 200);
+ tester.assertResponse(request("/application/v4/tenant/scoober/archive-access", PUT)
+ .data("{\"role\":\"dummy\"}").roles(Role.administrator(tenantName)),
+ "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Invalid archive access role 'dummy': Must match expected pattern: 'arn:aws:iam::\\\\d{12}:.+'\"}", 400);
+
+ tester.assertResponse(request("/application/v4/tenant/scoober/archive-access", PUT)
+ .data("{\"role\":\"arn:aws:iam::123456789012:role/my-role\"}").roles(Role.administrator(tenantName)),
+ "{\"message\":\"Archive access role set to 'arn:aws:iam::123456789012:role/my-role' for tenant scoober.\"}", 200);
+ tester.assertResponse(request("/application/v4/tenant/scoober", GET).roles(Role.reader(tenantName)),
+ (response) -> assertTrue(response.getBodyAsString().contains("\"archiveAccessRole\":\"arn:aws:iam::123456789012:role/my-role\"")),
+ 200);
+
+ tester.assertResponse(request("/application/v4/tenant/scoober/archive-access", DELETE).roles(Role.administrator(tenantName)),
+ "{\"message\":\"Archive access role removed for tenant scoober.\"}", 200);
+ tester.assertResponse(request("/application/v4/tenant/scoober", GET).roles(Role.reader(tenantName)),
+ (response) -> assertFalse(response.getBodyAsString().contains("archiveAccessRole")),
+ 200);
+ }
+
private ApplicationPackageBuilder prodBuilder() {
return new ApplicationPackageBuilder()
.instances("default")
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java
index 8d3f2d584b8..bf67e06db21 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/athenz/AthenzApiTest.java
@@ -49,7 +49,7 @@ public class AthenzApiTest extends ControllerContainerTest {
new File("property-list.json"));
// POST user signup
- tester.assertResponse(authenticatedRequest("http://localhost:8080/api/athenz/v1/user", "", Request.Method.POST),
+ tester.assertResponse(authenticatedRequest("http://localhost:8080/athenz/v1/user", "", Request.Method.POST),
"{\"message\":\"User 'bob' added to admin role of 'vespa.vespa.tenants.sandbox'\"}");
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java
index c414a3680fc..519c3f56976 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/configserver/ConfigServerApiHandlerTest.java
@@ -66,7 +66,7 @@ public class ConfigServerApiHandlerTest extends ControllerContainerTest {
assertLastRequest("https://cfg.prod.us-north-1.test.vip:4443/", "PUT");
// DELETE /configserver/v1/prod/us-north-1/nodes/v2/node/node1
- tester.assertResponse(operatorRequest("http://localhost:8080/api/configserver/v1/prod/controller/nodes/v2/node/node1",
+ tester.assertResponse(operatorRequest("http://localhost:8080/configserver/v1/prod/controller/nodes/v2/node/node1",
"", Request.Method.DELETE), "ok");
assertLastRequest("https://localhost:4443/", "DELETE");
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java
index f3c24458e6e..3d07b5d51d4 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/deployment/DeploymentApiTest.java
@@ -74,7 +74,6 @@ public class DeploymentApiTest extends ControllerContainerTest {
tester.controller().updateVersionStatus(censorConfigServers(VersionStatus.compute(tester.controller())));
tester.assertResponse(operatorRequest("http://localhost:8080/deployment/v1/"), new File("root.json"));
- tester.assertResponse(operatorRequest("http://localhost:8080/api/deployment/v1/"), new File("root.json"));
}
private VersionStatus censorConfigServers(VersionStatus versionStatus) {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java
index 0a9e2dac49e..b1bd7df059c 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/RoutingApiTest.java
@@ -77,12 +77,6 @@ public class RoutingApiTest extends ControllerContainerTest {
tester.assertResponse(operatorRequest("http://localhost:8080/routing/v1/status/environment/", "",
Request.Method.GET),
new File("discovery/environment.json"));
-
- // GET instance with api prefix (test that the /api prefix works)
- tester.assertResponse(authenticatedRequest("http://localhost:8080/api/routing/v1/status/tenant/t1/application/a1/instance/default/",
- "",
- Request.Method.GET),
- new File("discovery/instance_api.json"));
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/responses/discovery/instance_api.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/responses/discovery/instance_api.json
deleted file mode 100644
index a9e789d9fe9..00000000000
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/routing/responses/discovery/instance_api.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "resources": [
- {
- "url": "http://localhost:8080/api/routing/v1/status/tenant/t1/application/a1/instance/default/environment/prod/region/us-east-3/"
- },
- {
- "url": "http://localhost:8080/api/routing/v1/status/tenant/t1/application/a1/instance/default/environment/prod/region/us-west-1/"
- }
- ]
-} \ No newline at end of file
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java
index 3a63caf52cd..acd481030e2 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiOnPremTest.java
@@ -62,7 +62,7 @@ public class UserApiOnPremTest extends ControllerContainerTest {
}
private Request createUserRequest(User user, AthenzIdentity identity) {
- Request request = new Request("http://localhost:8080/api/user/v1/user");
+ Request request = new Request("http://localhost:8080/user/v1/user");
Map<String, String> userAttributes = new HashMap<>();
userAttributes.put("email", user.email());
if (user.name() != null)
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java
index dc765e01d4e..1ad705be0b7 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/user/UserApiTest.java
@@ -57,11 +57,6 @@ public class UserApiTest extends ControllerContainerCloudTest {
.roles(operator),
"[]");
- // GET at application/v4/tenant is available also under the /api prefix.
- tester.assertResponse(request("/api/application/v4/tenant")
- .roles(operator),
- "[]");
-
// POST a tenant is not available to everyone.
tester.assertResponse(request("/application/v4/tenant/my-tenant", POST)
.data("{\"token\":\"hello\"}"),
@@ -129,11 +124,6 @@ public class UserApiTest extends ControllerContainerCloudTest {
.roles(Set.of(Role.administrator(id.tenant()))),
new File("application-roles.json"));
- // GET application role information is available also under the /api prefix.
- tester.assertResponse(request("/api/user/v1/tenant/my-tenant/application/my-app")
- .roles(Set.of(Role.administrator(id.tenant()))),
- new File("application-roles.json"));
-
// POST a pem deploy key
tester.assertResponse(request("/application/v4/tenant/my-tenant/application/my-app/key", POST)
.roles(Set.of(Role.developer(id.tenant())))
@@ -223,7 +213,7 @@ public class UserApiTest extends ControllerContainerCloudTest {
Set<Role> operator = Set.of(Role.hostedOperator(), Role.hostedSupporter(), Role.hostedAccountant());
User user = new User("dev@domail", "Joe Developer", "dev", null);
- tester.assertResponse(request("/api/user/v1/user")
+ tester.assertResponse(request("/user/v1/user")
.roles(operator)
.user(user),
new File("user-without-applications.json"));
@@ -246,13 +236,13 @@ public class UserApiTest extends ControllerContainerCloudTest {
controller.createApplication("sandbox", "app2", "dev");
// Should still be empty because none of the roles explicitly refer to any of the applications
- tester.assertResponse(request("/api/user/v1/user")
+ tester.assertResponse(request("/user/v1/user")
.roles(operator)
.user(user),
new File("user-without-applications.json"));
// Empty applications because tenant dummy does not exist
- tester.assertResponse(request("/api/user/v1/user")
+ tester.assertResponse(request("/user/v1/user")
.roles(Set.of(Role.administrator(TenantName.from("tenant1")),
Role.developer(TenantName.from("tenant2")),
Role.developer(TenantName.from("sandbox")),
@@ -274,7 +264,7 @@ public class UserApiTest extends ControllerContainerCloudTest {
controller.createTenant("tenant1", Tenant.Type.cloud);
tester.assertResponse(
- request("/api/user/v1/user").user(user),
+ request("/user/v1/user").user(user),
new File("user-without-trial-capacity-cloud.json"));
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java
index d5031267b27..a8845fa92a3 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/zone/v1/ZoneApiTest.java
@@ -52,7 +52,7 @@ public class ZoneApiTest extends ControllerContainerCloudTest {
new File("prod.json"));
// GET /zone/v1/environment/dev/default
- tester.assertResponse(request("/api/zone/v1/environment/dev/default")
+ tester.assertResponse(request("/zone/v1/environment/dev/default")
.roles(everyone),
new File("default-for-region.json"));
}
diff --git a/zookeeper-server/zookeeper-server-3.6.2/pom.xml b/zookeeper-server/zookeeper-server-3.6.2/pom.xml
index 522bc71df97..04f8b012b09 100644
--- a/zookeeper-server/zookeeper-server-3.6.2/pom.xml
+++ b/zookeeper-server/zookeeper-server-3.6.2/pom.xml
@@ -18,6 +18,18 @@
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>com.yahoo.vespa</groupId>
+ <artifactId>zookeeper-client-common</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <!-- Don't use ZK version from zookeeper-client-common -->
+ <groupId>org.apache.zookeeper</groupId>
+ <artifactId>zookeeper</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.2</version>
diff --git a/zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaZooKeeperAdminImpl.java b/zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaZooKeeperAdminImpl.java
index 8ae30942d55..d92527fb5fd 100644
--- a/zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaZooKeeperAdminImpl.java
+++ b/zookeeper-server/zookeeper-server-3.6.2/src/main/java/com/yahoo/vespa/zookeeper/VespaZooKeeperAdminImpl.java
@@ -1,6 +1,7 @@
// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.zookeeper;
+import com.yahoo.vespa.zookeeper.client.ZkClientConfigBuilder;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.admin.ZooKeeperAdmin;
@@ -45,7 +46,7 @@ public class VespaZooKeeperAdminImpl implements VespaZooKeeperAdmin {
private ZooKeeperAdmin createAdmin(String connectionSpec) throws IOException {
return new ZooKeeperAdmin(connectionSpec, (int) sessionTimeout().toMillis(),
- (event) -> log.log(Level.INFO, event.toString()));
+ (event) -> log.log(Level.INFO, event.toString()), new ZkClientConfigBuilder().toConfig());
}
private static boolean retryOn(KeeperException e) {