| // 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.test; |
| |
| import static com.google.gerrit.k8s.operator.test.TestGerritCluster.CLUSTER_NAME; |
| import static java.util.concurrent.TimeUnit.MINUTES; |
| import static org.awaitility.Awaitility.await; |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.hamcrest.Matchers.notNullValue; |
| import static org.junit.jupiter.api.Assertions.assertTrue; |
| |
| import com.google.common.flogger.FluentLogger; |
| import com.google.gerrit.extensions.api.GerritApi; |
| import com.google.gerrit.k8s.operator.gerrit.Gerrit; |
| import com.google.gerrit.k8s.operator.gerrit.GerritConfigMapDependentResource; |
| import com.google.gerrit.k8s.operator.gerrit.GerritInitConfigMapDependentResource; |
| import com.google.gerrit.k8s.operator.gerrit.GerritSite; |
| import com.google.gerrit.k8s.operator.gerrit.GerritSpec; |
| import com.google.gerrit.k8s.operator.gerrit.GerritSpec.GerritMode; |
| import com.google.gerrit.k8s.operator.gerrit.ServiceDependentResource; |
| import com.urswolfer.gerrit.client.rest.GerritAuthData; |
| import com.urswolfer.gerrit.client.rest.GerritRestApiFactory; |
| import io.fabric8.kubernetes.api.model.ObjectMeta; |
| import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; |
| import io.fabric8.kubernetes.api.model.Quantity; |
| import io.fabric8.kubernetes.api.model.ResourceRequirementsBuilder; |
| import io.fabric8.kubernetes.api.model.Secret; |
| import io.fabric8.kubernetes.api.model.SecretBuilder; |
| import io.fabric8.kubernetes.client.KubernetesClient; |
| import java.util.Base64; |
| import java.util.Map; |
| import java.util.Set; |
| import org.eclipse.jgit.errors.ConfigInvalidException; |
| import org.eclipse.jgit.lib.Config; |
| |
| public class TestGerrit { |
| private static final FluentLogger logger = FluentLogger.forEnclosingClass(); |
| public static final String NAME = "gerrit"; |
| private static final String SECURE_CONFIG_SECRET_NAME = "gerrit-secret"; |
| private static final String DEFAULT_GERRIT_CONFIG = |
| "[gerrit]\n" |
| + " serverId = gerrit-1\n" |
| + "[index]\n" |
| + " type = LUCENE\n" |
| + "[auth]\n" |
| + " type = LDAP\n" |
| + "[ldap]\n" |
| + " server = ldap://openldap.openldap.svc.cluster.local:1389\n" |
| + " accountBase = dc=example,dc=org\n" |
| + " username = cn=admin,dc=example,dc=org\n" |
| + "[httpd]\n" |
| + " listenUrl = proxy-https://*:8080/\n" |
| + " requestLog = true\n" |
| + " gracefulStopTimeout = 1m\n" |
| + "[sshd]\n" |
| + " listenAddress = off\n" |
| + "[transfer]\n" |
| + " timeout = 120 s\n" |
| + "[user]\n" |
| + " name = Gerrit Code Review\n" |
| + " email = gerrit@example.com\n" |
| + " anonymousCoward = Unnamed User\n" |
| + "[cache]\n" |
| + " directory = cache\n" |
| + "[container]\n" |
| + " javaOptions = -Xmx4g"; |
| |
| private final KubernetesClient client; |
| private final String namespace; |
| private final GerritMode mode; |
| private final String ingress_domain; |
| |
| private Secret secureConfigSecret; |
| private Gerrit gerrit = new Gerrit(); |
| private Config config = defaultConfig(); |
| private Config secureConfig = new Config(); |
| |
| public TestGerrit( |
| KubernetesClient client, TestProperties testProps, String namespace, GerritMode mode) { |
| this.client = client; |
| this.namespace = namespace; |
| this.mode = mode; |
| this.ingress_domain = testProps.getIngressDomain(); |
| this.secureConfig.setString("ldap", null, "password", testProps.getLdapAdminPwd()); |
| } |
| |
| public TestGerrit(KubernetesClient client, TestProperties testProps, String namespace) { |
| this(client, testProps, namespace, GerritMode.PRIMARY); |
| } |
| |
| public void build() { |
| createGerritCR(); |
| createSecureConfig(); |
| } |
| |
| public void deploy() { |
| build(); |
| client.resource(secureConfigSecret).inNamespace(namespace).createOrReplace(); |
| client.resource(gerrit).inNamespace(namespace).createOrReplace(); |
| waitForGerritReadiness(); |
| } |
| |
| public GerritApi getGerritApiClient() { |
| return new GerritRestApiFactory() |
| .create( |
| new GerritAuthData.Basic( |
| String.format( |
| "http://%s.%s", ServiceDependentResource.getName(gerrit), ingress_domain))); |
| } |
| |
| public void modifyGerritConfig(String section, String key, String value) { |
| config.setString(section, null, key, value); |
| deploy(); |
| } |
| |
| public void modifySecureConfig(String section, String key, String value) { |
| secureConfig.setString(section, null, key, value); |
| createSecureConfig(); |
| client.resource(secureConfigSecret).inNamespace(namespace).createOrReplace(); |
| } |
| |
| public GerritSpec getSpec() { |
| return gerrit.getSpec(); |
| } |
| |
| public void setSpec(GerritSpec spec) { |
| gerrit.setSpec(spec); |
| deploy(); |
| } |
| |
| private static Config defaultConfig() { |
| Config cfg = new Config(); |
| try { |
| cfg.fromText(DEFAULT_GERRIT_CONFIG); |
| } catch (ConfigInvalidException e) { |
| throw new IllegalStateException("Illegal default test configuration."); |
| } |
| return cfg; |
| } |
| |
| private void createGerritCR() { |
| ObjectMeta gerritMeta = new ObjectMetaBuilder().withName(NAME).withNamespace(namespace).build(); |
| gerrit.setMetadata(gerritMeta); |
| GerritSpec gerritSpec = gerrit.getSpec(); |
| if (gerritSpec == null) { |
| gerritSpec = new GerritSpec(); |
| GerritSite site = new GerritSite(); |
| site.setSize(new Quantity("1Gi")); |
| gerritSpec.setSite(site); |
| gerritSpec.setResources( |
| new ResourceRequirementsBuilder() |
| .withRequests(Map.of("cpu", new Quantity("1"), "memory", new Quantity("5Gi"))) |
| .build()); |
| } |
| gerritSpec.setCluster(CLUSTER_NAME); |
| gerritSpec.setMode(mode); |
| gerritSpec.setConfigFiles(Map.of("gerrit.config", config.toText())); |
| gerritSpec.setSecrets(Set.of(SECURE_CONFIG_SECRET_NAME)); |
| |
| gerrit.setSpec(gerritSpec); |
| } |
| |
| private void createSecureConfig() { |
| secureConfigSecret = |
| new SecretBuilder() |
| .withNewMetadata() |
| .withNamespace(namespace) |
| .withName(SECURE_CONFIG_SECRET_NAME) |
| .endMetadata() |
| .withData( |
| Map.of( |
| "secure.config", |
| Base64.getEncoder().encodeToString(secureConfig.toText().getBytes()))) |
| .build(); |
| } |
| |
| private void waitForGerritReadiness() { |
| logger.atInfo().log("Waiting max 1 minutes for the configmaps to be created."); |
| await() |
| .atMost(1, MINUTES) |
| .untilAsserted( |
| () -> { |
| assertThat( |
| client |
| .configMaps() |
| .inNamespace(namespace) |
| .withName(GerritConfigMapDependentResource.getName(gerrit)) |
| .get(), |
| is(notNullValue())); |
| assertThat( |
| client |
| .configMaps() |
| .inNamespace(namespace) |
| .withName(GerritInitConfigMapDependentResource.getName(gerrit)) |
| .get(), |
| is(notNullValue())); |
| }); |
| |
| logger.atInfo().log("Waiting max 1 minutes for the Gerrit StatefulSet to be created."); |
| await() |
| .atMost(1, MINUTES) |
| .untilAsserted( |
| () -> { |
| assertThat( |
| client |
| .apps() |
| .statefulSets() |
| .inNamespace(namespace) |
| .withName(gerrit.getMetadata().getName()) |
| .get(), |
| is(notNullValue())); |
| }); |
| |
| logger.atInfo().log("Waiting max 1 minutes for the Gerrit Service to be created."); |
| await() |
| .atMost(1, MINUTES) |
| .untilAsserted( |
| () -> { |
| assertThat( |
| client |
| .services() |
| .inNamespace(namespace) |
| .withName(ServiceDependentResource.getName(gerrit)) |
| .get(), |
| is(notNullValue())); |
| }); |
| |
| logger.atInfo().log("Waiting max 2 minutes for the Gerrit StatefulSet to be ready."); |
| await() |
| .atMost(2, MINUTES) |
| .untilAsserted( |
| () -> { |
| assertTrue( |
| client |
| .apps() |
| .statefulSets() |
| .inNamespace(namespace) |
| .withName(gerrit.getMetadata().getName()) |
| .isReady()); |
| }); |
| } |
| } |