All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yahoo.vespa.hosted.controller.routing.RoutingPolicy Maven / Gradle / Ivy

There is a newer version: 8.253.3
Show newest version
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.routing;

import com.google.common.collect.ImmutableSortedSet;
import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.zone.RoutingMethod;
import com.yahoo.text.Text;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import com.yahoo.vespa.hosted.controller.application.Endpoint;
import com.yahoo.vespa.hosted.controller.application.Endpoint.Port;
import com.yahoo.vespa.hosted.controller.application.EndpointId;
import com.yahoo.vespa.hosted.controller.application.SystemApplication;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

/**
 * Represents the DNS routing policy for a {@link com.yahoo.vespa.hosted.controller.application.Deployment}.
 *
 * @author mortent
 * @author mpolden
 */
public class RoutingPolicy {

    private final RoutingPolicyId id;
    private final HostName canonicalName;
    private final Optional dnsZone;
    private final Set instanceEndpoints;
    private final Set applicationEndpoints;
    private final Status status;

    /** DO NOT USE. Public for serialization purposes */
    public RoutingPolicy(RoutingPolicyId id, HostName canonicalName, Optional dnsZone,
                         Set instanceEndpoints, Set applicationEndpoints, Status status) {
        this.id = Objects.requireNonNull(id, "id must be non-null");
        this.canonicalName = Objects.requireNonNull(canonicalName, "canonicalName must be non-null");
        this.dnsZone = Objects.requireNonNull(dnsZone, "dnsZone must be non-null");
        this.instanceEndpoints = ImmutableSortedSet.copyOf(Objects.requireNonNull(instanceEndpoints, "instanceEndpoints must be non-null"));
        this.applicationEndpoints = ImmutableSortedSet.copyOf(Objects.requireNonNull(applicationEndpoints, "applicationEndpoints must be non-null"));
        this.status = Objects.requireNonNull(status, "status must be non-null");
    }

    /** The ID of this */
    public RoutingPolicyId id() {
        return id;
    }

    /** The canonical name for the load balancer this applies to (rhs of a CNAME or ALIAS record) */
    public HostName canonicalName() {
        return canonicalName;
    }

    /** DNS zone for the load balancer this applies to, if any. Used when creating ALIAS records. */
    public Optional dnsZone() {
        return dnsZone;
    }

    /** The instance-level endpoints this participates in */
    public Set instanceEndpoints() {
        return instanceEndpoints;
    }

    /** The application-level endpoints  this participates in */
    public Set applicationEndpoints() {
        return applicationEndpoints;
    }

    /** Returns the status of this */
    public Status status() {
        return status;
    }

    /** Returns whether this policy applies to given deployment */
    public boolean appliesTo(DeploymentId deployment) {
        return id.owner().equals(deployment.applicationId()) &&
               id.zone().equals(deployment.zoneId());
    }

    /** Returns a copy of this with status set to given status */
    public RoutingPolicy with(Status status) {
        return new RoutingPolicy(id, canonicalName, dnsZone, instanceEndpoints, applicationEndpoints, status);
    }

    /** Returns the zone endpoints of this */
    public List zoneEndpointsIn(SystemName system, RoutingMethod routingMethod, ZoneRegistry zoneRegistry) {
        Optional infraEndpoint = SystemApplication.matching(id.owner())
                                                            .flatMap(app -> app.endpointIn(id.zone(), zoneRegistry));
        if (infraEndpoint.isPresent()) {
            return List.of(infraEndpoint.get());
        }
        DeploymentId deployment = new DeploymentId(id.owner(), id.zone());
        List endpoints = new ArrayList<>();
        endpoints.add(endpoint(routingMethod).target(id.cluster(), deployment).in(system));
        // Add legacy endpoint
        if (routingMethod == RoutingMethod.shared) {
            endpoints.add(endpoint(routingMethod).target(id.cluster(), deployment)
                                                 .on(Port.tls(4443))
                                                 .legacy()
                                                 .in(system));
        }
        return endpoints;
    }

    /** Returns the region endpoint of this */
    public Endpoint regionEndpointIn(SystemName system, RoutingMethod routingMethod) {
        return endpoint(routingMethod).targetRegion(id.cluster(), id.zone()).in(system);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        RoutingPolicy that = (RoutingPolicy) o;
        return id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public String toString() {
        return Text.format("%s [instance endpoints: %s, application endpoints: %s%s], %s owned by %s, in %s", canonicalName,
                           instanceEndpoints, applicationEndpoints,
                           dnsZone.map(z -> ", DNS zone: " + z).orElse(""), id.cluster(), id.owner().toShortString(),
                           id.zone().value());
    }

    private Endpoint.EndpointBuilder endpoint(RoutingMethod routingMethod) {
        return Endpoint.of(id.owner())
                       .on(Port.fromRoutingMethod(routingMethod))
                       .routingMethod(routingMethod);
    }

    /** The status of a routing policy */
    public static class Status {

        private final boolean active;
        private final RoutingStatus routingStatus;

        /** DO NOT USE. Public for serialization purposes */
        public Status(boolean active, RoutingStatus routingStatus) {
            this.active = active;
            this.routingStatus = Objects.requireNonNull(routingStatus, "globalRouting must be non-null");
        }

        /** Returns whether this is considered active according to the load balancer status */
        public boolean isActive() {
            return active;
        }

        /** Return status of routing */
        public RoutingStatus routingStatus() {
            return routingStatus;
        }

        /** Returns a copy of this with routing status changed */
        public Status with(RoutingStatus routingStatus) {
            return new Status(active, routingStatus);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Status status = (Status) o;
            return active == status.active &&
                   routingStatus.equals(status.routingStatus);
        }

        @Override
        public int hashCode() {
            return Objects.hash(active, routingStatus);
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy