diff options
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) { |