diff options
author | Øyvind Grønnesby <oyving@yahooinc.com> | 2023-07-25 10:02:13 +0200 |
---|---|---|
committer | Øyvind Grønnesby <oyving@yahooinc.com> | 2023-07-25 10:20:48 +0200 |
commit | d678b4e8fe80c25118fd5aa1cf6353ef7a327eb7 (patch) | |
tree | a344fbd628a8ca6958ffd25d0607319f2c5e0f27 /controller-api | |
parent | b4126b644d2214564a9ed76c1c006b09454dbb6f (diff) | |
parent | 78a211072a21ec5f368b99bce19c1b703d98152d (diff) |
Merge branch 'master' into ogronnesby/billing-reporting
Diffstat (limited to 'controller-api')
29 files changed, 327 insertions, 423 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/DeploymentData.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/DeploymentData.java index b23b93cba78..f73aeb89f0e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/DeploymentData.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/application/v4/model/DeploymentData.java @@ -8,7 +8,7 @@ import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.vespa.athenz.api.AthenzDomain; import com.yahoo.vespa.hosted.controller.api.integration.billing.Quota; -import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificateMetadata; +import com.yahoo.vespa.hosted.controller.api.integration.certificates.EndpointCertificate; import com.yahoo.vespa.hosted.controller.api.integration.configserver.ContainerEndpoint; import com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken.DataplaneTokenVersions; import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretStore; @@ -36,7 +36,7 @@ public class DeploymentData { private final Supplier<InputStream> applicationPackage; private final Version platform; private final Set<ContainerEndpoint> containerEndpoints; - private final Supplier<Optional<EndpointCertificateMetadata>> endpointCertificateMetadata; + private final Supplier<Optional<EndpointCertificate>> endpointCertificate; private final Optional<DockerImage> dockerImageRepo; private final Optional<AthenzDomain> athenzDomain; private final Supplier<Quota> quota; @@ -48,7 +48,7 @@ public class DeploymentData { public DeploymentData(ApplicationId instance, ZoneId zone, Supplier<InputStream> applicationPackage, Version platform, Set<ContainerEndpoint> containerEndpoints, - Supplier<Optional<EndpointCertificateMetadata>> endpointCertificateMetadata, + Supplier<Optional<EndpointCertificate>> endpointCertificate, Optional<DockerImage> dockerImageRepo, Optional<AthenzDomain> athenzDomain, Supplier<Quota> quota, @@ -62,7 +62,7 @@ public class DeploymentData { this.applicationPackage = requireNonNull(applicationPackage); this.platform = requireNonNull(platform); this.containerEndpoints = Set.copyOf(requireNonNull(containerEndpoints)); - this.endpointCertificateMetadata = new Memoized<>(requireNonNull(endpointCertificateMetadata)); + this.endpointCertificate = new Memoized<>(requireNonNull(endpointCertificate)); this.dockerImageRepo = requireNonNull(dockerImageRepo); this.athenzDomain = athenzDomain; this.quota = new Memoized<>(requireNonNull(quota)); @@ -93,8 +93,8 @@ public class DeploymentData { return containerEndpoints; } - public Optional<EndpointCertificateMetadata> endpointCertificateMetadata() { - return endpointCertificateMetadata.get(); + public Optional<EndpointCertificate> endpointCertificate() { + return endpointCertificate.get(); } public Optional<DockerImage> dockerImageRepo() { diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java index 9a9c2af2d5d..820dc2ac573 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/AthenzDbMock.java @@ -96,6 +96,35 @@ public class AthenzDbMock { public boolean checkAccess(AthenzIdentity principal, String action, String resource) { return policies.values().stream().anyMatch(a -> a.matches(principal, action, resource)); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Domain domain = (Domain) o; + return isVespaTenant == domain.isVespaTenant && Objects.equals(name, domain.name) && Objects.equals(admins, domain.admins) && Objects.equals(tenantAdmins, domain.tenantAdmins) && Objects.equals(applications, domain.applications) && Objects.equals(services, domain.services) && Objects.equals(roles, domain.roles) && Objects.equals(policies, domain.policies) && Objects.equals(attributes, domain.attributes); + } + + @Override + public int hashCode() { + return Objects.hash(name, admins, tenantAdmins, applications, services, roles, policies, isVespaTenant, attributes); + } + + @Override + public String toString() { + return "Domain{" + + "name=" + name + + ", admins=" + admins + + ", tenantAdmins=" + tenantAdmins + + ", applications=" + applications + + ", services=" + services + + ", roles=" + roles + + ", policies=" + policies + + ", isVespaTenant=" + isVespaTenant + + ", attributes=" + attributes + + '}'; + } + } public static class Application { @@ -121,11 +150,30 @@ public class AthenzDbMock { public Service(boolean allowLaunch) { this.allowLaunch = allowLaunch; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Service service = (Service) o; + return allowLaunch == service.allowLaunch; + } + + @Override + public int hashCode() { + return Objects.hash(allowLaunch); + } + + @Override + public String toString() { + return allowLaunch ? "allowed" : "denied"; + } + } public static class Policy { private final String name; - final List<Assertion> assertions = new ArrayList<>(); + public final List<Assertion> assertions = new ArrayList<>(); public Policy(String name, String principal, String action, String resource) { this(name); @@ -158,6 +206,12 @@ public class AthenzDbMock { public int hashCode() { return Objects.hash(name, assertions); } + + @Override + public String toString() { + return name + ": " + assertions; + } + } public static class Assertion { @@ -203,6 +257,12 @@ public class AthenzDbMock { public int hashCode() { return Objects.hash(effect, role, action, resource); } + + @Override + public String toString() { + return asString(); + } + } public static class Role { @@ -228,5 +288,11 @@ public class AthenzDbMock { public int hashCode() { return Objects.hash(name); } + + @Override + public String toString() { + return name; + } + } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java index 94ed28778d7..9681b2b7326 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/athenz/ZmsClientMock.java @@ -145,7 +145,7 @@ public class ZmsClientMock implements ZmsClient { .map(d -> d.attributes) .map(attrs -> { if (attrs.containsKey("account")) { - return new AthenzDomainMeta((String)attrs.get("account"), domain.getName()); + return new AthenzDomainMeta((String) attrs.get("account"), (String) attrs.get("gcpProject"), domain.getName()); } return null; }) @@ -153,7 +153,7 @@ public class ZmsClientMock implements ZmsClient { } @Override - public void updateDomain(AthenzDomain domain, Map<String, Object> attributes) { + public void updateDomain(AthenzDomain domain, String mainKey, Map<String, Object> attributes) { if (!athenz.domains.containsKey(domain)) throw new IllegalStateException("Domain does not exist: " + domain.getName()); athenz.domains.get(domain).withAttributes(attributes); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java index aa0d9c75b81..75789c0989b 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/MockRoleService.java @@ -11,8 +11,9 @@ public class MockRoleService extends NoopRoleService { private List<TenantName> maintainedTenants; @Override - public void maintainRoles(List<TenantName> tenants) { + public double maintainRoles(List<TenantName> tenants) { maintainedTenants = List.copyOf(tenants); + return 1; } public List<TenantName> maintainedTenants() { diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java index 1ef1bc5106c..93a09b6c6bc 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/NoopRoleService.java @@ -34,7 +34,7 @@ public class NoopRoleService implements RoleService { public void deleteTenantPolicy(TenantName tenant, String policyName, String role) { } @Override - public void maintainRoles(List<TenantName> tenants) { } + public double maintainRoles(List<TenantName> tenants) { return 1; } @Override public void cleanupRoles(List<TenantName> tenants) { diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java index 0a35893a7c4..345545ab6f7 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/aws/RoleService.java @@ -26,7 +26,7 @@ public interface RoleService { /* * Maintain roles for the tenants in the system. Create missing roles, update trust. */ - void maintainRoles(List<TenantName> tenants); + double maintainRoles(List<TenantName> tenants); void cleanupRoles(List<TenantName> deletedTenants); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateMetadata.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificate.java index 02afbb6ace6..53d807b0139 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateMetadata.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificate.java @@ -5,20 +5,18 @@ import java.util.List; import java.util.Optional; /** - * This class is used for metadata about an application's endpoint certificate on the controller. - * <p> - * It has more properties than com.yahoo.config.model.api.EndpointCertificateMetadata. + * This holds information about an application's endpoint certificate. * * @author andreer */ -public record EndpointCertificateMetadata(String keyName, String certName, int version, long lastRequested, - String rootRequestId, // The id of the first request made for this certificate. Should not change. - Optional<String> leafRequestId, // The id of the last known request made for this certificate. Changes on refresh, may be outdated! - List<String> requestedDnsSans, String issuer, Optional<Long> expiry, - Optional<Long> lastRefreshed, Optional<String> randomizedId) { +public record EndpointCertificate(String keyName, String certName, int version, long lastRequested, + String rootRequestId, // The id of the first request made for this certificate. Should not change. + Optional<String> leafRequestId, // The id of the last known request made for this certificate. Changes on refresh, may be outdated! + List<String> requestedDnsSans, String issuer, Optional<Long> expiry, + Optional<Long> lastRefreshed, Optional<String> randomizedId) { - public EndpointCertificateMetadata withRandomizedId(String randomizedId) { - return new EndpointCertificateMetadata( + public EndpointCertificate withRandomizedId(String randomizedId) { + return new EndpointCertificate( this.keyName, this.certName, this.version, @@ -32,8 +30,8 @@ public record EndpointCertificateMetadata(String keyName, String certName, int v Optional.of(randomizedId)); } - public EndpointCertificateMetadata withKeyName(String keyName) { - return new EndpointCertificateMetadata( + public EndpointCertificate withKeyName(String keyName) { + return new EndpointCertificate( keyName, this.certName, this.version, @@ -47,8 +45,8 @@ public record EndpointCertificateMetadata(String keyName, String certName, int v this.randomizedId); } - public EndpointCertificateMetadata withCertName(String certName) { - return new EndpointCertificateMetadata( + public EndpointCertificate withCertName(String certName) { + return new EndpointCertificate( this.keyName, certName, this.version, @@ -62,8 +60,8 @@ public record EndpointCertificateMetadata(String keyName, String certName, int v this.randomizedId); } - public EndpointCertificateMetadata withVersion(int version) { - return new EndpointCertificateMetadata( + public EndpointCertificate withVersion(int version) { + return new EndpointCertificate( this.keyName, this.certName, version, @@ -77,8 +75,8 @@ public record EndpointCertificateMetadata(String keyName, String certName, int v this.randomizedId); } - public EndpointCertificateMetadata withLastRequested(long lastRequested) { - return new EndpointCertificateMetadata( + public EndpointCertificate withLastRequested(long lastRequested) { + return new EndpointCertificate( this.keyName, this.certName, this.version, @@ -92,8 +90,8 @@ public record EndpointCertificateMetadata(String keyName, String certName, int v this.randomizedId); } - public EndpointCertificateMetadata withLastRefreshed(long lastRefreshed) { - return new EndpointCertificateMetadata( + public EndpointCertificate withLastRefreshed(long lastRefreshed) { + return new EndpointCertificate( this.keyName, this.certName, this.version, @@ -107,8 +105,8 @@ public record EndpointCertificateMetadata(String keyName, String certName, int v this.randomizedId); } - public EndpointCertificateMetadata withRootRequestId(String rootRequestId) { - return new EndpointCertificateMetadata( + public EndpointCertificate withRootRequestId(String rootRequestId) { + return new EndpointCertificate( this.keyName, this.certName, this.version, @@ -122,8 +120,8 @@ public record EndpointCertificateMetadata(String keyName, String certName, int v this.randomizedId); } - public EndpointCertificateMetadata withLeafRequestId(Optional<String> leafRequestId) { - return new EndpointCertificateMetadata( + public EndpointCertificate withLeafRequestId(Optional<String> leafRequestId) { + return new EndpointCertificate( this.keyName, this.certName, this.version, diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateDetails.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateDetails.java index 3f5514dce8c..18565011d25 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateDetails.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateDetails.java @@ -4,28 +4,28 @@ package com.yahoo.vespa.hosted.controller.api.integration.certificates; import java.util.List; /** - * This record is used when requesting additional metadata about an application's endpoint certificate from the provider. + * This record is used when requesting additional details about an application's endpoint certificate from the provider. * * @author andreer */ public record EndpointCertificateDetails( - String request_id, + String requestId, String requestor, String status, - String ticket_id, - String athenz_domain, - List<EndpointCertificateRequestMetadata.DnsNameStatus> dnsnames, - String duration_sec, + String ticketId, + String athenzDomain, + List<EndpointCertificateRequest.DnsNameStatus> dnsNames, + String durationSec, String expiry, - String private_key_kgname, - String private_key_keyname, - String private_key_version, - String cert_key_kgname, - String cert_key_keyname, - String cert_key_version, - String create_time, - boolean expiry_protection, - String public_key_algo, + String privateKeyKgname, + String privateKeyKeyname, + String privateKeyVersion, + String certKeyKgname, + String certKeyKeyname, + String certKeyVersion, + String createTime, + boolean expiryProtection, + String publicKeyAlgo, String issuer, String serial -) { }
\ No newline at end of file +) { } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateException.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateException.java index a446a5382fb..7f4f22ced40 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateException.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateException.java @@ -1,6 +1,9 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.api.integration.certificates; +/** + * @author andreer + */ public class EndpointCertificateException extends RuntimeException { private final Type type; diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateMock.java deleted file mode 100644 index a0448e41b68..00000000000 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateMock.java +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.api.integration.certificates; - -import java.time.Instant; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -/** - * @author tokle - * @author andreer - */ -public class EndpointCertificateMock implements EndpointCertificateProvider { - - private final Map<String, List<String>> dnsNames = new HashMap<>(); - private final Map<String, EndpointCertificateMetadata> providerMetadata = new HashMap<>(); - - public List<String> dnsNamesOf(String rootRequestId) { - return Collections.unmodifiableList(dnsNames.getOrDefault(rootRequestId, List.of())); - } - - @Override - public EndpointCertificateMetadata requestCaSignedCertificate(String key, List<String> dnsNames, Optional<EndpointCertificateMetadata> currentMetadata, String algo, boolean useAlternativeProvider) { - String endpointCertificatePrefix = "vespa.tls.%s".formatted(key); - long epochSecond = Instant.now().getEpochSecond(); - long inAnHour = epochSecond + 3600; - String requestId = UUID.randomUUID().toString(); - this.dnsNames.put(requestId, dnsNames); - int version = currentMetadata.map(c -> currentMetadata.get().version()+1).orElse(0); - EndpointCertificateMetadata metadata = new EndpointCertificateMetadata(endpointCertificatePrefix + "-key", endpointCertificatePrefix + "-cert", version, 0, - currentMetadata.map(EndpointCertificateMetadata::rootRequestId).orElse(requestId), Optional.of(requestId), dnsNames, "mockCa", Optional.of(inAnHour), Optional.of(epochSecond), Optional.empty()); - currentMetadata.ifPresent(c -> providerMetadata.remove(c.leafRequestId().orElseThrow())); - providerMetadata.put(requestId, metadata); - return metadata; - } - - @Override - public List<EndpointCertificateRequestMetadata> listCertificates() { - - return providerMetadata.values().stream() - .map(p -> new EndpointCertificateRequestMetadata( - p.leafRequestId().orElse(p.rootRequestId()), - "requestor", - "ticketId", - "athenzDomain", - p.requestedDnsSans().stream() - .map(san -> new EndpointCertificateRequestMetadata.DnsNameStatus(san, "done")) - .toList(), - 3600, - "ok", - "2021-09-28T00:14:31.946562037Z", - p.expiry().orElseThrow(), - p.issuer(), - "rsa_2048" - )) - .toList(); - } - - @Override - public void deleteCertificate(String requestId) { - dnsNames.remove(requestId); - providerMetadata.remove(requestId); - } - - @Override - public EndpointCertificateDetails certificateDetails(String requestId) { - var metadata = providerMetadata.get(requestId); - - if(metadata==null) throw new RuntimeException("Unknown certificate request"); - - return new EndpointCertificateDetails(requestId, - "requestor", - "ok", - "ticket_id", - "athenz_domain", - metadata.requestedDnsSans().stream().map(name -> new EndpointCertificateRequestMetadata.DnsNameStatus(name, "done")).toList(), - "duration_sec", - "expiry", - metadata.keyName(), - metadata.keyName(), - "0", - metadata.certName(), - metadata.certName(), - "0", - "2021-09-28T00:14:31.946562037Z", - true, - "public_key_algo", - "issuer", - "serial"); - } -} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateProvider.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateProvider.java index 7c5268ea353..865abeac031 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateProvider.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateProvider.java @@ -11,9 +11,9 @@ import java.util.Optional; */ public interface EndpointCertificateProvider { - EndpointCertificateMetadata requestCaSignedCertificate(String endpointCertificatePrefix, List<String> dnsNames, Optional<EndpointCertificateMetadata> currentMetadata, String algo, boolean useAlternativeProvider); + EndpointCertificate requestCaSignedCertificate(String endpointCertificatePrefix, List<String> dnsNames, Optional<EndpointCertificate> currentCert, String algo, boolean useAlternativeProvider); - List<EndpointCertificateRequestMetadata> listCertificates(); + List<EndpointCertificateRequest> listCertificates(); void deleteCertificate(String requestId); diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateProviderMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateProviderMock.java new file mode 100644 index 00000000000..223eeb19a86 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateProviderMock.java @@ -0,0 +1,94 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.certificates; + +import java.time.Instant; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +/** + * @author tokle + * @author andreer + */ +public class EndpointCertificateProviderMock implements EndpointCertificateProvider { + + private final Map<String, List<String>> dnsNames = new HashMap<>(); + private final Map<String, EndpointCertificate> certificates = new HashMap<>(); + + public List<String> dnsNamesOf(String rootRequestId) { + return Collections.unmodifiableList(dnsNames.getOrDefault(rootRequestId, List.of())); + } + + @Override + public EndpointCertificate requestCaSignedCertificate(String key, List<String> dnsNames, Optional<EndpointCertificate> currentCert, String algo, boolean useAlternativeProvider) { + String endpointCertificatePrefix = "vespa.tls.%s".formatted(key); + long epochSecond = Instant.now().getEpochSecond(); + long inAnHour = epochSecond + 3600; + String requestId = UUID.randomUUID().toString(); + this.dnsNames.put(requestId, dnsNames); + int version = currentCert.map(c -> currentCert.get().version() + 1).orElse(0); + EndpointCertificate cert = new EndpointCertificate(endpointCertificatePrefix + "-key", endpointCertificatePrefix + "-cert", version, 0, + currentCert.map(EndpointCertificate::rootRequestId).orElse(requestId), Optional.of(requestId), dnsNames, "mockCa", Optional.of(inAnHour), Optional.of(epochSecond), Optional.empty()); + currentCert.ifPresent(c -> certificates.remove(c.leafRequestId().orElseThrow())); + certificates.put(requestId, cert); + return cert; + } + + @Override + public List<EndpointCertificateRequest> listCertificates() { + return certificates.values().stream() + .map(p -> new EndpointCertificateRequest( + p.leafRequestId().orElse(p.rootRequestId()), + "requestor", + "ticketId", + "athenzDomain", + p.requestedDnsSans().stream() + .map(san -> new EndpointCertificateRequest.DnsNameStatus(san, "done")) + .toList(), + 3600, + "ok", + "2021-09-28T00:14:31.946562037Z", + p.expiry().orElseThrow(), + p.issuer(), + "rsa_2048" + )) + .toList(); + } + + @Override + public void deleteCertificate(String requestId) { + dnsNames.remove(requestId); + certificates.remove(requestId); + } + + @Override + public EndpointCertificateDetails certificateDetails(String requestId) { + var request = certificates.get(requestId); + + if (request == null) throw new IllegalArgumentException("Unknown certificate request"); + + return new EndpointCertificateDetails(requestId, + "requestor", + "ok", + "ticket_id", + "athenz_domain", + request.requestedDnsSans().stream().map(name -> new EndpointCertificateRequest.DnsNameStatus(name, "done")).toList(), + "duration_sec", + "expiry", + request.keyName(), + request.keyName(), + "0", + request.certName(), + request.certName(), + "0", + "2021-09-28T00:14:31.946562037Z", + true, + "public_key_algo", + "issuer", + "serial"); + } + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateRequest.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateRequest.java new file mode 100644 index 00000000000..877f7ed64b0 --- /dev/null +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateRequest.java @@ -0,0 +1,18 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.api.integration.certificates; + +import java.util.List; + +/** + * This class is used for details about an application's endpoint certificate received from the certificate provider. + * + * @param createTime ISO 8601 + * @author andreer + */ +public record EndpointCertificateRequest(String requestId, String requestor, String ticketId, String athenzDomain, + List<DnsNameStatus> dnsNames, long durationSec, String status, + String createTime, long expiry, String issuer, String publicKeyAlgo) { + + public record DnsNameStatus(String dnsName, String status) {} + +} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateRequestMetadata.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateRequestMetadata.java deleted file mode 100644 index 339389105e6..00000000000 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateRequestMetadata.java +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.controller.api.integration.certificates; - -import java.util.List; -import java.util.Objects; - -/** - * This class is used for metadata about an application's endpoint certificate received from the certificate provider. - * - * @author andreer - */ -public class EndpointCertificateRequestMetadata { - - public EndpointCertificateRequestMetadata(String requestId, - String requestor, - String ticketId, - String athenzDomain, - List<DnsNameStatus> dnsNames, - long durationSec, - String status, - String createTime, - long expiry, - String issuer, - String publicKeyAlgo) { - this.requestId = requestId; - this.requestor = requestor; - this.ticketId = ticketId; - this.athenzDomain = athenzDomain; - this.dnsNames = dnsNames; - this.durationSec = durationSec; - this.status = status; - this.createTime = createTime; - this.expiry = expiry; - this.issuer = issuer; - this.publicKeyAlgo = publicKeyAlgo; - } - - public static class DnsNameStatus { - public final String dnsName; - public final String status; - - public DnsNameStatus(String dnsName, String status) { - this.dnsName = dnsName; - this.status = status; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DnsNameStatus that = (DnsNameStatus) o; - return dnsName.equals(that.dnsName) && status.equals(that.status); - } - - @Override - public int hashCode() { - return Objects.hash(dnsName, status); - } - - @Override - public String toString() { - return "DnsNameStatus{" + - "dnsName='" + dnsName + '\'' + - ", status='" + status + '\'' + - '}'; - } - } - - private final String requestId; - private final String requestor; - private final String ticketId; - private final String athenzDomain; - private final List<DnsNameStatus> dnsNames; - private final long durationSec; - private final String status; - private final String createTime; // ISO 8601 - private final long expiry; - private final String issuer; - private final String publicKeyAlgo; - - public String requestId() { - return requestId; - } - - public String requestor() { - return requestor; - } - - public String ticketId() { - return ticketId; - } - - public String athenzDomain() { - return athenzDomain; - } - - public List<DnsNameStatus> dnsNames() { - return dnsNames; - } - - public long durationSec() { - return durationSec; - } - - public String status() { - return status; - } - - public String createTime() { - return createTime; - } - - public long expiry() { - return expiry; - } - - public String issuer() { - return issuer; - } - - public String publicKeyAlgo() { - return publicKeyAlgo; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - EndpointCertificateRequestMetadata that = (EndpointCertificateRequestMetadata) o; - return durationSec == that.durationSec && - expiry == that.expiry && - requestId.equals(that.requestId) && - requestor.equals(that.requestor) && - ticketId.equals(that.ticketId) && - athenzDomain.equals(that.athenzDomain) && - dnsNames.equals(that.dnsNames) && - status.equals(that.status) && - createTime.equals(that.createTime) && - issuer.equals(that.issuer) && - publicKeyAlgo.equals(that.publicKeyAlgo); - } - - @Override - public int hashCode() { - return Objects.hash( - requestId, - requestor, - ticketId, - athenzDomain, - dnsNames, - durationSec, - status, - createTime, - expiry, - issuer, - publicKeyAlgo); - } - - @Override - public String toString() { - return "EndpointCertificateRequestMetadata{" + - "requestId='" + requestId + '\'' + - ", requestor='" + requestor + '\'' + - ", ticketId='" + ticketId + '\'' + - ", athenzDomain='" + athenzDomain + '\'' + - ", dnsNames=" + dnsNames + - ", durationSec=" + durationSec + - ", status='" + status + '\'' + - ", createTime='" + createTime + '\'' + - ", expiry=" + expiry + - ", issuer='" + issuer + '\'' + - ", publicKeyAlgo='" + publicKeyAlgo + '\'' + - '}'; - } -} diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidator.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidator.java index 0952fe587f9..b6bc8b9f129 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidator.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidator.java @@ -5,6 +5,9 @@ import com.yahoo.config.provision.zone.ZoneId; import java.util.List; +/** + * @author andreer + */ public interface EndpointCertificateValidator { - void validate(EndpointCertificateMetadata endpointCertificateMetadata, String serializedInstanceId, ZoneId zone, List<String> requiredNamesForZone); + void validate(EndpointCertificate endpointCertificate, String serializedInstanceId, ZoneId zone, List<String> requiredNamesForZone); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorImpl.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorImpl.java index cff61f1a50a..e09e2d096c2 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorImpl.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorImpl.java @@ -31,9 +31,9 @@ public class EndpointCertificateValidatorImpl implements EndpointCertificateVali } @Override - public void validate(EndpointCertificateMetadata endpointCertificateMetadata, String serializedInstanceId, ZoneId zone, List<String> requiredNamesForZone) { + public void validate(EndpointCertificate endpointCertificate, String serializedInstanceId, ZoneId zone, List<String> requiredNamesForZone) { try { - var pemEncodedEndpointCertificate = secretStore.getSecret(endpointCertificateMetadata.certName(), endpointCertificateMetadata.version()); + var pemEncodedEndpointCertificate = secretStore.getSecret(endpointCertificate.certName(), endpointCertificate.version()); if (pemEncodedEndpointCertificate == null) throw new EndpointCertificateException(EndpointCertificateException.Type.CERT_NOT_AVAILABLE, "Secret store returned null for certificate"); diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorMock.java index 6bdf9037dc1..428058315c9 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorMock.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/certificates/EndpointCertificateValidatorMock.java @@ -12,7 +12,7 @@ public class EndpointCertificateValidatorMock implements EndpointCertificateVali @Override public void validate( - EndpointCertificateMetadata endpointCertificateMetadata, + EndpointCertificate endpointCertificate, String serializedApplicationId, ZoneId zone, List<String> requiredNamesForZone) { diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java index 485bf627c87..71003b9d86e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/configserver/NodeRepository.java @@ -55,7 +55,7 @@ public interface NodeRepository { void upgrade(ZoneId zone, NodeType type, Version version, boolean allowDowngrade); /** Upgrade OS for all nodes of given type to a new version */ - void upgradeOs(ZoneId zone, NodeType type, Version version); + void upgradeOs(ZoneId zone, NodeType type, Version version, boolean allowDowngrade); /** Get target versions for upgrades in given zone */ TargetVersions targetVersionsOf(ZoneId zone); diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneToken.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneToken.java index f0cc87df1fe..76df5ce13dd 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneToken.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneToken.java @@ -1,6 +1,9 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken; +import java.time.Instant; +import java.util.Optional; + /** * Represents a generated data plane token. * @@ -8,5 +11,5 @@ package com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken; * * @author mortent */ -public record DataplaneToken(TokenId tokenId, FingerPrint fingerPrint, String tokenValue) { +public record DataplaneToken(TokenId tokenId, FingerPrint fingerPrint, String tokenValue, Optional<Instant> expiration) { } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneTokenVersions.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneTokenVersions.java index 618bfbc8a41..1ce558bd84e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneTokenVersions.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dataplanetoken/DataplaneTokenVersions.java @@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.controller.api.integration.dataplanetoken; import java.time.Instant; import java.util.List; +import java.util.Optional; /** * List of dataplane token versions of a token id. @@ -10,6 +11,7 @@ import java.util.List; * @author mortent */ public record DataplaneTokenVersions(TokenId tokenId, List<Version> tokenVersions) { - public record Version(FingerPrint fingerPrint, String checkAccessHash, Instant creationTime, String author) { + public record Version(FingerPrint fingerPrint, String checkAccessHash, Instant creationTime, + Optional<Instant> expiration, String author) { } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/maven/Metadata.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/maven/Metadata.java index dd80a2b3a9a..a0d3614ffc5 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/maven/Metadata.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/maven/Metadata.java @@ -5,9 +5,11 @@ import com.yahoo.component.Version; import com.yahoo.text.XML; import org.w3c.dom.Element; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import static java.util.Objects.requireNonNull; @@ -19,10 +21,12 @@ import static java.util.Objects.requireNonNull; public class Metadata { private final ArtifactId id; + private final Instant lastUpdated; private final List<Version> versions; - public Metadata(ArtifactId id, List<Version> versions) { + public Metadata(ArtifactId id, Instant lastUpdated, List<Version> versions) { this.id = requireNonNull(id); + this.lastUpdated = requireNonNull(lastUpdated); this.versions = versions.stream().sorted().toList(); } @@ -31,17 +35,25 @@ public class Metadata { Element metadata = XML.getDocument(xml).getDocumentElement(); ArtifactId id = new ArtifactId(XML.getValue(XML.getChild(metadata, "groupId")), XML.getValue(XML.getChild(metadata, "artifactId"))); + String lastUpdatedTimestamp = XML.getValue(XML.getChild(XML.getChild(metadata, "versioning"), "lastUpdated")); + Instant lastUpdated = Instant.from(DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneId.of("UTC")) + .parse(lastUpdatedTimestamp)); List<Version> versions = new ArrayList<>(); for (Element version : XML.getChildren(XML.getChild(XML.getChild(metadata, "versioning"), "versions"))) versions.add(Version.fromString(XML.getValue(version))); - return new Metadata(id, versions); + return new Metadata(id, lastUpdated, versions); } /** Id of the metadata this concerns. */ public ArtifactId id() { return id; } + /** When the list of versions was last updated. */ + Instant lastUpdated() { return lastUpdated; } + /** List of available versions of this, sorted by ascending version order. */ - public List<Version> versions() { return versions; } + public List<Version> versions(Instant availableAt) { + return versions.size() == 1 || availableAt.isAfter(lastUpdated.plusSeconds(10800)) ? versions : versions.subList(0, versions.size() - 1); + } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/GcpSecretStore.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/GcpSecretStore.java index 312bec1fd98..8432a582cad 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/GcpSecretStore.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/GcpSecretStore.java @@ -1,8 +1,14 @@ package com.yahoo.vespa.hosted.controller.api.integration.secrets; +import java.time.Duration; +import java.util.Optional; + public interface GcpSecretStore { - void createSecret(String secretName, String secret); + void setSecret(String secretName, Optional<Duration> expiry, String... accessorServiceAccounts); + + void addSecretVersion(String secretName, String secretValue); + + String getLatestSecretVersion(String secretName); - String getSecret(String secretName, int version); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopGcpSecretStore.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopGcpSecretStore.java index 9335a814f6c..ef35127e933 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopGcpSecretStore.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/secrets/NoopGcpSecretStore.java @@ -1,18 +1,21 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.api.integration.secrets; +import java.time.Duration; +import java.util.Optional; + /** * @author olaa */ public class NoopGcpSecretStore implements GcpSecretStore { @Override - public void createSecret(String secretName, String secret) { + public void setSecret(String secretName, Optional<Duration> expiry, String... accessorServiceAccounts) { } - } + @Override + public void addSecretVersion(String secretName, String secretValue) { } @Override - public String getSecret(String secretName, int version) { - return ""; - } + public String getLatestSecretVersion(String secretName) { return ""; } + } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMavenRepository.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMavenRepository.java index aad6b306662..f43ec795f92 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMavenRepository.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMavenRepository.java @@ -2,12 +2,17 @@ package com.yahoo.vespa.hosted.controller.api.integration.stubs; import com.yahoo.component.Version; +import com.yahoo.component.annotation.Inject; import com.yahoo.vespa.hosted.controller.api.integration.maven.ArtifactId; -import com.yahoo.vespa.hosted.controller.api.integration.maven.Metadata; import com.yahoo.vespa.hosted.controller.api.integration.maven.MavenRepository; +import com.yahoo.vespa.hosted.controller.api.integration.maven.Metadata; +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; /** * Mock repository for maven artifacts, that returns a static metadata. @@ -18,21 +23,31 @@ public class MockMavenRepository implements MavenRepository { public static final ArtifactId id = new ArtifactId("ai.vespa", "search"); + private final Clock clock; + private AtomicReference<Instant> lastUpdated; private final List<Version> versions = new ArrayList<>(); + @Inject public MockMavenRepository() { + this(Clock.fixed(Instant.EPOCH, ZoneId.of("UTC"))); + } + + public MockMavenRepository(Clock clock) { + this.clock = clock; + this.lastUpdated = new AtomicReference<>(clock.instant().minusSeconds(10801)); versions.addAll(List.of(Version.fromString("6.0"), Version.fromString("6.1"), Version.fromString("6.2"))); } public void addVersion(Version version) { + lastUpdated.set(clock.instant()); versions.add(version); } @Override public Metadata metadata() { - return new Metadata(id, versions); + return new Metadata(id, lastUpdated.get(), versions); } @Override diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/ChangeRequestSource.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/ChangeRequestSource.java index e5b3422b79b..0c43a3704df 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/ChangeRequestSource.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/ChangeRequestSource.java @@ -10,78 +10,13 @@ import static com.yahoo.vespa.hosted.controller.api.integration.vcmr.ChangeReque /** * @author olaa */ -public class ChangeRequestSource { - - private final String system; - private final String id; - private final Status status; - private final String url; - private final ZonedDateTime plannedStartTime; - private final ZonedDateTime plannedEndTime; - - - public ChangeRequestSource(String system, String id, String url, Status status, ZonedDateTime plannedStartTime, ZonedDateTime plannedEndTime) { - this.system = Objects.requireNonNull(system); - this.id = Objects.requireNonNull(id); - this.url = Objects.requireNonNull(url); - this.status = Objects.requireNonNull(status); - this.plannedStartTime = Objects.requireNonNull(plannedStartTime); - this.plannedEndTime = Objects.requireNonNull(plannedEndTime); - } - - public String getSystem() { - return system; - } - - public String getId() { - return id; - } - - public Status getStatus() { - return status; - } - - public String getUrl() { - return url; - } - - public ZonedDateTime getPlannedStartTime() { - return plannedStartTime; - } - - public ZonedDateTime getPlannedEndTime() { - return plannedEndTime; - } - - @Override - public String toString() { - return "ChangeRequestSource{" + - "system='" + system + '\'' + - ", id='" + id + '\'' + - ", status=" + status + - ", url='" + url + '\'' + - ", plannedStartTime=" + plannedStartTime + - ", plannedEndTime=" + plannedEndTime + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ChangeRequestSource that = (ChangeRequestSource) o; - return Objects.equals(system, that.system) && - Objects.equals(id, that.id) && - status == that.status && - Objects.equals(url, that.url) && - Objects.equals(plannedStartTime, that.plannedStartTime) && - Objects.equals(plannedEndTime, that.plannedEndTime); - } - - @Override - public int hashCode() { - return Objects.hash(system, id, status, url, plannedStartTime, plannedEndTime); - } +public record ChangeRequestSource(String system, + String id, + String url, + Status status, + ZonedDateTime plannedStartTime, + ZonedDateTime plannedEndTime, + String category) { public boolean isClosed() { return List.of(CLOSED, CANCELED, COMPLETE).contains(status); @@ -105,6 +40,7 @@ public class ChangeRequestSource { private Status status; private ZonedDateTime plannedStartTime; private ZonedDateTime plannedEndTime; + private String category; public Builder system(String system) { this.system = system; @@ -136,8 +72,13 @@ public class ChangeRequestSource { return this; } + public Builder category(String category) { + this.category = category; + return this; + } + public ChangeRequestSource build() { - return new ChangeRequestSource(system, id, url, status, plannedStartTime, plannedEndTime); + return new ChangeRequestSource(system, id, url, status, plannedStartTime, plannedEndTime, category); } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VcmrReport.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VcmrReport.java index 660f3c50556..89cf6f4b28d 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VcmrReport.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VcmrReport.java @@ -47,12 +47,12 @@ public class VcmrReport { * @return true if list of VCMRs is changed */ public boolean addVcmr(ChangeRequestSource source) { - var vcmr = new Vcmr(source.getId(), source.getStatus().name(), source.getPlannedStartTime(), source.getPlannedEndTime()); + var vcmr = new Vcmr(source.id(), source.status().name(), source.plannedStartTime(), source.plannedEndTime(), source.category()); if (vcmrs.contains(vcmr)) return false; // Remove to catch any changes in start/end time - removeVcmr(source.getId()); + removeVcmr(source.id()); return vcmrs.add(vcmr); } @@ -95,6 +95,7 @@ public class VcmrReport { public record Vcmr (@JsonProperty("id") String id, @JsonProperty("status") String status, @JsonProperty("plannedStartTime") ZonedDateTime plannedStartTime, - @JsonProperty("plannedEndTime") ZonedDateTime plannedEndTime) {} + @JsonProperty("plannedEndTime") ZonedDateTime plannedEndTime, + @JsonProperty("category") String category) {} } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VespaChangeRequest.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VespaChangeRequest.java index e0f867b97be..2771520e7fc 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VespaChangeRequest.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/vcmr/VespaChangeRequest.java @@ -3,7 +3,6 @@ package com.yahoo.vespa.hosted.controller.api.integration.vcmr; import com.yahoo.config.provision.zone.ZoneId; -import java.util.ArrayList; import java.util.List; import java.util.Objects; 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 1a8f4103659..6c603a1da7b 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 @@ -38,7 +38,8 @@ enum PathGroup { "/provision/v2/{*}", "/zone/v2/{*}", "/state/v1/{*}", - "/changemanagement/v1/{*}"), + "/changemanagement/v1/{*}", + "/application/v4/search/{*}"), /** Paths used for creating and reading user resources. */ user("/application/v4/user", diff --git a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/maven/MetadataTest.java b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/maven/MetadataTest.java index 4cec90eb48d..a6f7a5ee069 100644 --- a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/maven/MetadataTest.java +++ b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/maven/MetadataTest.java @@ -1,9 +1,12 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.controller.api.integration.maven; +import com.yahoo.collections.Iterables; import com.yahoo.component.Version; import org.junit.jupiter.api.Test; +import java.time.Instant; + import static org.junit.jupiter.api.Assertions.assertEquals; public class MetadataTest { @@ -13,8 +16,12 @@ public class MetadataTest { Metadata metadata = Metadata.fromXml(metadataXml); assertEquals("com.yahoo.vespa", metadata.id().groupId()); assertEquals("tenant-base", metadata.id().artifactId()); - assertEquals(Version.fromString("6.297.80"), metadata.versions().get(0)); - assertEquals(Version.fromString("7.61.10"), metadata.versions().get(metadata.versions().size() - 1)); + assertEquals(Instant.parse("2019-06-19T05:42:45.00Z"), metadata.lastUpdated()); + assertEquals(Version.fromString("6.297.80"), metadata.versions(metadata.lastUpdated()).get(0)); + assertEquals(Version.fromString("7.61.10"), Iterables.reversed(metadata.versions(metadata.lastUpdated().plusSeconds(10801))) + .iterator().next()); + assertEquals(Version.fromString("7.60.51"), Iterables.reversed(metadata.versions(metadata.lastUpdated().plusSeconds(10800))) + .iterator().next()); } private static final String metadataXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + |