blob: 9d3aabd68c0035222da8617dd56805cfc674f1df [file] [log] [blame]
// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.k8s.operator.cluster;
import com.google.gerrit.k8s.operator.gerrit.Gerrit;
import com.google.gerrit.k8s.operator.gerrit.ServiceDependentResource;
import com.google.gerrit.k8s.operator.receiver.Receiver;
import com.google.gerrit.k8s.operator.receiver.ReceiverServiceDependentResource;
import io.fabric8.kubernetes.api.model.networking.v1.HTTPIngressPath;
import io.fabric8.kubernetes.api.model.networking.v1.HTTPIngressPathBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.IngressBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.IngressRule;
import io.fabric8.kubernetes.api.model.networking.v1.IngressRuleBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.IngressTLS;
import io.fabric8.kubernetes.api.model.networking.v1.IngressTLSBuilder;
import io.fabric8.kubernetes.api.model.networking.v1.ServiceBackendPort;
import io.fabric8.kubernetes.api.model.networking.v1.ServiceBackendPortBuilder;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@KubernetesDependent(labelSelector = "app.kubernetes.io/component=gerrit-ingress")
public class GerritIngress extends CRUDKubernetesDependentResource<Ingress, GerritCluster> {
public static final String INGRESS_NAME = "gerrit-ingress";
public GerritIngress() {
super(Ingress.class);
}
@Override
protected Ingress desired(GerritCluster gerritCluster, Context<GerritCluster> context) {
List<Gerrit> gerrits =
client
.resources(Gerrit.class)
.inNamespace(gerritCluster.getMetadata().getNamespace())
.list()
.getItems()
.stream()
.filter(gerrit -> GerritCluster.isMemberPartOfCluster(gerrit.getSpec(), gerritCluster))
.collect(Collectors.toList());
List<Receiver> receivers =
client
.resources(Receiver.class)
.inNamespace(gerritCluster.getMetadata().getNamespace())
.list()
.getItems()
.stream()
.filter(r -> GerritCluster.isMemberPartOfCluster(r.getSpec(), gerritCluster))
.collect(Collectors.toList());
List<String> hosts = new ArrayList<>();
List<IngressRule> ingressRules = new ArrayList<>();
for (Receiver receiver : receivers) {
ingressRules.add(getReceiverIngressRule(gerritCluster, receiver));
hosts.add(getFullHostname(receiver.getMetadata().getName(), gerritCluster));
}
ingressRules.addAll(getGerritIngressRules(gerritCluster, gerrits));
for (Gerrit gerrit : gerrits) {
hosts.add(getFullHostname(gerrit.getMetadata().getName(), gerritCluster));
}
Ingress gerritIngress =
new IngressBuilder()
.withNewMetadata()
.withName("gerrit-ingress")
.withNamespace(gerritCluster.getMetadata().getNamespace())
.withLabels(gerritCluster.getLabels("gerrit-ingress", this.getClass().getSimpleName()))
.withAnnotations(gerritCluster.getSpec().getIngress().getAnnotations())
.endMetadata()
.withNewSpec()
.withTls(getIngressTLS(gerritCluster, hosts))
.withRules(ingressRules)
.endSpec()
.build();
return gerritIngress;
}
private IngressTLS getIngressTLS(GerritCluster gerritCluster, List<String> hosts) {
if (gerritCluster.getSpec().getIngress().getTls().isEnabled()) {
return new IngressTLSBuilder()
.withHosts(hosts)
.withSecretName(gerritCluster.getSpec().getIngress().getTls().getSecret())
.build();
}
return new IngressTLS();
}
private List<IngressRule> getGerritIngressRules(
GerritCluster gerritCluster, List<Gerrit> gerrits) {
List<IngressRule> ingressRules = new ArrayList<>();
for (Gerrit gerrit : gerrits) {
String gerritSvcName = ServiceDependentResource.getName(gerrit);
ingressRules.add(
new IngressRuleBuilder()
.withHost(getFullHostname(gerritSvcName, gerritCluster))
.withNewHttp()
.withPaths(getGerritHTTPIngressPath(gerritSvcName))
.endHttp()
.build());
}
return ingressRules;
}
private IngressRule getReceiverIngressRule(GerritCluster gerritCluster, Receiver receiver) {
return new IngressRuleBuilder()
.withHost(getFullHostname(receiver.getMetadata().getName(), gerritCluster))
.withNewHttp()
.withPaths(getReceiverIngressPaths(ReceiverServiceDependentResource.getName(receiver)))
.endHttp()
.build();
}
public HTTPIngressPath getGerritHTTPIngressPath(String svcName) {
ServiceBackendPort port =
new ServiceBackendPortBuilder().withName(ServiceDependentResource.HTTP_PORT_NAME).build();
return new HTTPIngressPathBuilder()
.withPathType("Prefix")
.withPath("/")
.withNewBackend()
.withNewService()
.withName(svcName)
.withPort(port)
.endService()
.endBackend()
.build();
}
public List<HTTPIngressPath> getReceiverIngressPaths(String svcName) {
List<HTTPIngressPath> paths = new ArrayList<>();
ServiceBackendPort port =
new ServiceBackendPortBuilder()
.withName(ReceiverServiceDependentResource.HTTP_PORT_NAME)
.build();
for (String path : Set.of("/a/projects", "/new", "/git")) {
paths.add(
new HTTPIngressPathBuilder()
.withPathType("Prefix")
.withPath(path)
.withNewBackend()
.withNewService()
.withName(svcName)
.withPort(port)
.endService()
.endBackend()
.build());
}
return paths;
}
public static String getFullHostname(String svcName, GerritCluster gerritCluster) {
return String.format("%s.%s", svcName, gerritCluster.getSpec().getIngress().getHost());
}
}