diff options
author | jonmv <venstad@gmail.com> | 2023-02-01 16:27:48 +0100 |
---|---|---|
committer | jonmv <venstad@gmail.com> | 2023-02-01 16:27:48 +0100 |
commit | 4f76988e35d72006f29db1ba16e9610d70fe4864 (patch) | |
tree | 899ee2d768f690a755971a5e60ccd1ddb0266a3b /controller-api | |
parent | f6fdb2f2a5385881af69de5e760c11bc4ddae7c1 (diff) |
Run DNS challenges asynchronously, and check from job runner
Diffstat (limited to 'controller-api')
2 files changed, 57 insertions, 12 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MockVpcEndpointService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MockVpcEndpointService.java index f101339ed06..563b343dab5 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MockVpcEndpointService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MockVpcEndpointService.java @@ -3,32 +3,52 @@ package com.yahoo.vespa.hosted.controller.api.integration.dns; import ai.vespa.http.DomainName; import com.yahoo.config.provision.CloudAccount; import com.yahoo.vespa.hosted.controller.api.identifiers.ClusterId; +import com.yahoo.vespa.hosted.controller.api.integration.dns.Record.Type; +import java.time.Clock; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; /** * @author jonmv */ public class MockVpcEndpointService implements VpcEndpointService { - public interface Stub extends VpcEndpointService { - @Override default List<VpcEndpoint> getConnections(ClusterId clusterId, Optional<CloudAccount> account) { - return List.of(new VpcEndpoint("endpoint-1", "available")); - } - } + public final AtomicBoolean enabled = new AtomicBoolean(); + public final Map<RecordName, State> outcomes = new ConcurrentHashMap<>(); + + private final Clock clock; + private final NameService nameService; - public static final Stub empty = (name, cluster, account) -> Optional.empty(); + public MockVpcEndpointService(Clock clock, NameService nameService) { + this.clock = clock; + this.nameService = nameService; + } - public Stub delegate = empty; + @Override + public synchronized Optional<DnsChallenge> setPrivateDns(DomainName privateDnsName, ClusterId clusterId, Optional<CloudAccount> account) { + DnsChallenge challenge = new DnsChallenge(RecordName.from("challenge--" + privateDnsName.value()), + RecordData.from(account.map(CloudAccount::value).orElse("system")), + clusterId, + "service-id", + account, + clock.instant(), + State.pending); + return Optional.ofNullable(enabled.get() && nameService.findRecords(Type.TXT, challenge.name()).isEmpty() ? challenge : null); + } @Override - public Optional<DnsChallenge> setPrivateDns(DomainName privateDnsName, ClusterId clusterId, Optional<CloudAccount> account) { - return delegate.setPrivateDns(privateDnsName, clusterId, account); + public synchronized State process(DnsChallenge challenge) { + if (outcomes.containsKey(challenge.name())) return outcomes.get(challenge.name()); + if (nameService.findRecords(Type.TXT, challenge.name()).isEmpty()) throw new RuntimeException("No TXT record found for " + challenge.name()); + return State.done; } @Override - public List<VpcEndpoint> getConnections(ClusterId cluster, Optional<CloudAccount> account) { + public synchronized List<VpcEndpoint> getConnections(ClusterId cluster, Optional<CloudAccount> account) { return List.of(new VpcEndpoint("endpoint-1", "available")); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/VpcEndpointService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/VpcEndpointService.java index 5069a429b27..74459792987 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/VpcEndpointService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/VpcEndpointService.java @@ -4,20 +4,45 @@ import ai.vespa.http.DomainName; import com.yahoo.config.provision.CloudAccount; import com.yahoo.vespa.hosted.controller.api.identifiers.ClusterId; +import java.time.Instant; import java.util.List; import java.util.Optional; +import static java.util.Objects.requireNonNull; + /** * @author jonmv */ public interface VpcEndpointService { - /** Create a TXT record with this name and token, then run the trigger, to pass this challenge. */ - record DnsChallenge(RecordName name, RecordData data, Runnable trigger) { } + /** Create a TXT record with this name and token, and then complete the challenge. */ + record DnsChallenge(RecordName name, RecordData data, ClusterId clusterId, String serviceId, + Optional<CloudAccount> account, Instant createdAt, State state) { + + public DnsChallenge { + requireNonNull(name, "name must be non-null"); + requireNonNull(data, "data must be non-null"); + requireNonNull(clusterId, "clusterId must be non-null"); + requireNonNull(serviceId, "serviceId must be non-null"); + requireNonNull(account, "account must be non-null"); + requireNonNull(createdAt, "createdAt must be non-null"); + requireNonNull(state, "state must be non-null"); + } + + public DnsChallenge withState(State state) { + return new DnsChallenge(name, data, clusterId, serviceId, account, createdAt, state); + } + + } + + enum State { pending, ready, running, done } /** Sets the private DNS name for any VPC endpoint for the given cluster, potentially guarded by a challenge. */ Optional<DnsChallenge> setPrivateDns(DomainName privateDnsName, ClusterId clusterId, Optional<CloudAccount> account); + /** Attempts to complete the challenge, and returns the updated challenge state. */ + State process(DnsChallenge challenge); + /** A connection made to an endpoint service. */ record VpcEndpoint(String endpointId, String state) { } |