Merge "Update Gerrit to 3.9.2"
diff --git a/Documentation/operator-api-reference.md b/Documentation/operator-api-reference.md
index 3ff6151..a4dc91a 100644
--- a/Documentation/operator-api-reference.md
+++ b/Documentation/operator-api-reference.md
@@ -8,6 +8,7 @@
- [Receiver](#receiver)
- [GitGarbageCollection](#gitgarbagecollection)
- [GerritNetwork](#gerritnetwork)
+ - [IncomingReplicationTask](#incomingreplicationtask)
- [GerritClusterSpec](#gerritclusterspec)
- [GerritClusterStatus](#gerritclusterstatus)
- [StorageConfig](#storageconfig)
@@ -54,6 +55,13 @@
- [GerritNetworkSpec](#gerritnetworkspec)
- [NetworkMember](#networkmember)
- [NetworkMemberWithSsh](#networkmemberwithssh)
+ - [ScheduledTasks](#scheduledtasks)
+ - [IncomingReplicationTaskTemplate](#incomingreplicationtasktemplate)
+ - [IncomingReplicationTaskTemplateSpec](#incomingreplicationtasktemplatespec)
+ - [IncomingReplicationConfig](#incomingreplicationconfig)
+ - [Remote](#remote)
+ - [Fetch](#fetch)
+ - [IncomingReplicationTaskSpec](#incomingreplicationtaskspec)
## General Remarks
@@ -68,7 +76,7 @@
---
**Group**: gerritoperator.google.com \
-**Version**: v1beta6 \
+**Version**: v1beta9 \
**Kind**: GerritCluster
---
@@ -85,7 +93,7 @@
Example:
```yaml
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritCluster
metadata:
name: gerrit
@@ -255,6 +263,12 @@
# Installs a packaged plugin
- name: delete-project
+ # Plugin with data files
+ - name: hooks
+ data:
+ secretRef: hooks
+ executable: false
+
# Downloads and installs a plugin
- name: javamelody
url: https://gerrit-ci.gerritforge.com/view/Plugins-stable-3.6/job/plugin-javamelody-bazel-master-stable-3.6/lastSuccessfulBuild/artifact/bazel-bin/plugins/javamelody/javamelody.jar
@@ -294,6 +308,10 @@
javaOptions = -Xms200m
javaOptions = -Xmx4g
+ envVars:
+ - name: GOOGLE_APPLICATION_CREDENTIALS
+ value: /var/gerrit/etc/gcp-credentials.json
+
secretRef: gerrit-secure-config
receiver:
@@ -359,6 +377,23 @@
httpPort: 80
credentialSecretRef: receiver-credentials
+
+ scheduledTasks:
+ incomingReplication:
+ - metadata:
+ name: github
+ spec:
+ schedule: "0 * * * *"
+ config:
+ remotes:
+ - name: github
+ url: https://github.com
+ fetch:
+ - remoteRepo: fabric8io/kubernetes-client
+ - remoteRepo: operator-framework/java-operator-sdk
+ localRepo: josdk
+ refSpec: "+refs/heads/master:refs/heads/github/master"
+ secretRef: github-repl-secret
```
## Gerrit
@@ -366,7 +401,7 @@
---
**Group**: gerritoperator.google.com \
-**Version**: v1beta6 \
+**Version**: v1beta9 \
**Kind**: Gerrit
---
@@ -383,7 +418,7 @@
Example:
```yaml
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: Gerrit
metadata:
name: gerrit
@@ -468,6 +503,12 @@
# Installs a plugin packaged into the gerrit.war file
- name: delete-project
+ # Plugin with data files
+ - name: hooks
+ data:
+ secretRef: hooks
+ executable: false
+
# Downloads and installs a plugin
- name: javamelody
url: https://gerrit-ci.gerritforge.com/view/Plugins-stable-3.6/job/plugin-javamelody-bazel-master-stable-3.6/lastSuccessfulBuild/artifact/bazel-bin/plugins/javamelody/javamelody.jar
@@ -509,6 +550,10 @@
javaOptions = -Xms200m
javaOptions = -Xmx4g
+ envVars:
+ - name: GOOGLE_APPLICATION_CREDENTIALS
+ value: /var/gerrit/etc/gcp-credentials.json
+
secretRef: gerrit-secure-config
serverId: ""
@@ -574,7 +619,7 @@
---
**Group**: gerritoperator.google.com \
-**Version**: v1beta6 \
+**Version**: v1beta9 \
**Kind**: Receiver
---
@@ -591,7 +636,7 @@
Example:
```yaml
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: Receiver
metadata:
name: receiver
@@ -702,7 +747,7 @@
---
**Group**: gerritoperator.google.com \
-**Version**: v1beta6 \
+**Version**: v1beta9 \
**Kind**: GitGarbageCollection
---
@@ -719,7 +764,7 @@
Example:
```yaml
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GitGarbageCollection
metadata:
name: gitgc
@@ -763,7 +808,7 @@
---
**Group**: gerritoperator.google.com \
-**Version**: v1beta6 \
+**Version**: v1beta9 \
**Kind**: GerritNetwork
---
@@ -779,7 +824,7 @@
Example:
```yaml
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit-network
@@ -807,6 +852,81 @@
httpPort: 29418
```
+## IncomingReplicationTask
+
+---
+
+**Group**: gerritoperator.google.com \
+**Version**: v1beta9 \
+**Kind**: IncomingReplicationTask
+
+---
+
+
+| Field | Type | Description |
+|---|---|---|
+| `apiVersion` | `String` | APIVersion of this resource |
+| `kind` | `String` | Kind of this resource |
+| `metadata` | [`ObjectMeta`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#objectmeta-v1-meta) | Metadata of the resource |
+| `spec` | [`IncomingReplicationTaskSpec`](#receiverspec) | Specification for IncomingReplicationTask |
+
+Example:
+
+```yaml
+apiVersion: "gerritoperator.google.com/v1beta9"
+kind: IncomingReplicationTask
+metadata:
+ name: incoming-repl-task
+spec:
+ config:
+ remotes:
+ - fetch:
+ - remoteRepo: fabric8io/kubernetes-client
+ name: github
+ timeout: 5m
+ url: https://github.com
+ schedule: '*/5 * * * *'
+ secretRef: incoming-repl-test
+
+ containerImages:
+ imagePullSecrets: []
+ imagePullPolicy: Always
+ gerritImages:
+ registry: docker.io
+ org: k8sgerrit
+ tag: latest
+ busyBox:
+ registry: docker.io
+ tag: latest
+
+ storage:
+ storageClasses:
+ readWriteOnce: default
+ readWriteMany: shared-storage
+ nfsWorkaround:
+ enabled: false
+ chownOnStartup: false
+ idmapdConfig: |-
+ [General]
+ Verbosity = 0
+ Domain = localdomain.com
+
+ [Mapping]
+ Nobody-User = nobody
+ Nobody-Group = nogroup
+
+ sharedStorage:
+ externalPVC:
+ enabled: false
+ claimName: ""
+ size: 1Gi
+ volumeName: ""
+ selector:
+ matchLabels:
+ volume-type: ssd
+ aws-availability-zone: us-east-1
+```
+
## GerritClusterSpec
| Field | Type | Description |
@@ -819,6 +939,7 @@
| `serverId` | `String` | The serverId to be used for all Gerrit instances (default: `<namespace>/<name>`) |
| `gerrits` | [`GerritTemplate`](#gerrittemplate)-Array | A list of Gerrit instances to be installed in the GerritCluster. Only a single primary Gerrit and a single Gerrit Replica is permitted. |
| `receiver` | [`ReceiverTemplate`](#receivertemplate) | A Receiver instance to be installed in the GerritCluster. |
+| `scheduledTasks` | [`ScheduledTasks`](#scheduledtasks) | Scheduled tasks to install into the GerritCluster |
## GerritClusterStatus
@@ -1013,6 +1134,7 @@
| `plugins` | [`GerritPlugin`](#gerritplugin)-Array | List of Gerrit plugins to install. These plugins can either be packaged in the Gerrit war-file or they will be downloaded. (optional) |
| `libs` | [`GerritModule`](#gerritmodule)-Array | List of Gerrit library modules to install. These lib modules will be downloaded. (optional) |
| `configFiles` | `Map<String, String>` | Configuration files for Gerrit that will be mounted into the Gerrit site's etc-directory (gerrit.config is mandatory) |
+| `envVars` | [`List<EnvVar>`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#envvar-v1-core) | Environment variables that will be set in the pod. (optional) |
| `secretRef` | `String` | Name of secret containing configuration files, e.g. secure.config, that will be mounted into the Gerrit site's etc-directory (optional) |
| `mode` | [`GerritMode`](#gerritmode) | In which mode Gerrit should be run. (default: PRIMARY) |
| `debug` | [`GerritDebugConfig`](#gerritdebugconfig) | Enable the debug-mode for Gerrit |
@@ -1052,6 +1174,7 @@
| Field | Type | Description |
|---|---|---|
| `secretRef` | `String` | Name of a secretRef. The secret will be mounted under the gerrit site's `data/$module_name` directory|
+| `executable` | `boolean` | Whether the mounted data files should have executable permissions (file mode 754 instead of 644). (default: false) |
## GerritPlugin
@@ -1219,3 +1342,59 @@
| Field | Type | Description |
|-----------|-------|-------------------|
| `sshPort` | `int` | Port used for SSH |
+
+## ScheduledTasks
+
+| Field | Type | Description |
+|---|---|---|
+| `incomingReplication` | [`IncomingReplicationTaskTemplate`](#incomingreplicationtasktemplate) | Scheduled task to fetch from remote git servers |
+
+## IncomingReplicationTaskTemplate
+
+| Field | Type | Description |
+|---|---|---|
+| `metadata` | [`ObjectMeta`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#objectmeta-v1-meta) | Metadata of the resource. A name is mandatory. Labels can optionally be defined. Other fields like the namespace are ignored. |
+| `spec` | [`IncomingReplicationTaskTemplateSpec`](#incomingreplicationtasktemplatespec) | Specification for IncomingReplicationTaskTemplate |
+
+## IncomingReplicationTaskTemplateSpec
+
+| Field | Type | Description |
+|---|---|---|
+| `schedule` | `String` | Schedule in which to execute the job |
+| `config` | [`IncomingReplicationConfig`](#incomingreplicationconfig) | Configuration of replication task |
+| `resources` | [`ResourceRequirements`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#resourcerequirements-v1-core) | Resource requirements for the GitGarbageCollection container |
+| `tolerations` | [`Toleration`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#toleration-v1-core)-Array | Pod tolerations (optional) |
+| `affinity` | [`Affinity`](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#affinity-v1-core) | Pod affinity (optional) |
+| `secretRef` | `String` | Name of the secret containing the .netrc file containing credentials for all remote git servers |
+
+## IncomingReplicationConfig
+
+| Field | Type | Description |
+|---|---|---|
+| `remotes` | [`List<Remote>`](#remote) | List of remotes from which to fetch |
+
+## Remote
+
+| Field | Type | Description |
+|---|---|---|
+| `name` | `String` | Name of the remote (mandatory) |
+| `url` | `String` | Base URL of the remote, e.g. `https://gerrit-review.googlesource.com/a` (mandatory) |
+| `timeout` | `String` | Timeout for the fetch (default: `5m`) |
+| `fetch` | [`List<Fetch>`](#fetch) | List of projects to fetch |
+
+## Fetch
+
+| Field | Type | Description |
+|---|---|---|
+| `remoteRepo` | `String` | Name of the remote repository (mandatory) |
+| `localRepo` | `String` | Name of the local repository (default: same as `remoteRepo`) |
+| `refSpec` | `String` | RefSpec to fetch (default: +refs/heads/*:refs/heads/{{remote.name}}/*) |
+
+## IncomingReplicationTaskSpec
+
+**Extends:** [`IncomingReplicationTaskTemplateSpec`](#incomingreplicationtasktemplatespec)
+
+| Field | Type | Description |
+|---|---|---|
+| `storage` | [`StorageConfig`](#storageconfig) | Storage used by GerritCluster |
+| `containerImages` | [`ContainerImageConfig`](#containerimageconfig) | Container images used inside GerritCluster |
diff --git a/Documentation/operator.md b/Documentation/operator.md
index 5fc952f..c225eff 100644
--- a/Documentation/operator.md
+++ b/Documentation/operator.md
@@ -17,6 +17,7 @@
3. [GitGarbageCollection](#gitgarbagecollection)
4. [Receiver](#receiver)
5. [GerritNetwork](#gerritnetwork)
+ 6. [IncomingReplicationTask](#incomingreplicationtask)
5. [Configuration of Gerrit](#configuration-of-gerrit)
## Development
@@ -286,6 +287,17 @@
The GerritNetwork CustomResource is not meant to be installed manually, but will
be created by the Gerrit Operator based on the GerritCluster CustomResource.
+### IncomingReplicationTask
+
+A regularly running task to fetch repositories from a different git server that
+is not necessarily a Gerrit to the local Gerrit. This job can also be used to
+fetch a subset of refs into an existing repository in Gerrit, e.g. branches from
+a forked repository could be fetched into a ref namespace of the fork residing
+in Gerrit.
+
+Only fetching via HTTP(S) is supported at the moment. SSH can't be used for
+fetches.
+
## Configuration of Gerrit
The operator takes care of all configuration in Gerrit that depends on the
diff --git a/b.sh b/b.sh
deleted file mode 100755
index 023e595..0000000
--- a/b.sh
+++ /dev/null
@@ -1 +0,0 @@
-find tmp/refs -type d -empty -mindepth 2 -delete -mmin +60
diff --git a/build b/build
index 92f7199..e4809c7 100755
--- a/build
+++ b/build
@@ -75,7 +75,7 @@
BUILD_ARGS="$BUILD_ARGS --build-arg HEALTHCHECK_JAR_URL=$HEALTHCHECK_JAR_URL"
fi
-export REV="$(git describe --always --dirty)"
+export REV="$(./get_version.sh --output K8SGERRIT)"
docker_build(){
IMAGE=$1
@@ -135,7 +135,7 @@
docker_build_gerrit_base
else
if test -z "$TAG"; then
- TAG="$(git describe --always --dirty)-unknown"
+ TAG="$REV-unknown"
fi
echo -e "\nNo Image containing Gerrit will be built." \
"The Gerrit-version can thus not be determinded." \
diff --git a/container-images/fetch-job/Dockerfile b/container-images/fetch-job/Dockerfile
new file mode 100644
index 0000000..e089da3
--- /dev/null
+++ b/container-images/fetch-job/Dockerfile
@@ -0,0 +1,13 @@
+ARG TAG=latest
+FROM base:${TAG}
+
+RUN apk update && \
+ apk add --no-cache yq
+
+COPY tools/* /var/tools/
+
+USER gerrit
+
+VOLUME ["/var/gerrit/git"]
+
+ENTRYPOINT ["/var/tools/fetch-job.sh"]
diff --git a/container-images/fetch-job/README.md b/container-images/fetch-job/README.md
new file mode 100644
index 0000000..67e4f09
--- /dev/null
+++ b/container-images/fetch-job/README.md
@@ -0,0 +1,34 @@
+# FetchJob container image
+
+Container to run a job that fetches from remote repositories to corresponding
+local repositories. Thi can be used to create copies of repositories hosted on
+other git servers in the local Gerrit. This is useful for backing up repositories
+or to have a copy of branches of a project that was forked in the local Gerrit.
+
+## Content
+
+* base image
+* `fetch-job.sh`: script executing the fetches
+
+## Start
+
+* execution of the provided `fetch-job.sh`
+
+## Configuration
+
+```yaml
+remotes:
+- name: example
+ url: https://example.com
+ timeout: 5m
+ fetch:
+ - remoteRepo: project1
+ - remoteRepo: project2
+ localRepo: local/project2
+ - remoteRepo: project3
+ localRepo: local/project3
+ refSpec: "+refs/heads/*:refs/heads/remote/*"
+```
+
+You will need to mount the credentials used to authenticate with remote servers
+to the container, e.g. by providing a .netrc file at `home/gerrit/.netrc`.
diff --git a/container-images/fetch-job/fetch-config.example.yaml b/container-images/fetch-job/fetch-config.example.yaml
new file mode 100644
index 0000000..46a1fea
--- /dev/null
+++ b/container-images/fetch-job/fetch-config.example.yaml
@@ -0,0 +1,11 @@
+remotes:
+- name: example
+ url: https://example.com
+ timeout: 5m
+ fetch:
+ - remoteRepo: project1
+ - remoteRepo: project2
+ localRepo: local/project2
+ - remoteRepo: project3
+ localRepo: local/project3
+ refSpec: +refs/heads/*:refs/heads/remote/*
diff --git a/container-images/fetch-job/tools/fetch-job.sh b/container-images/fetch-job/tools/fetch-job.sh
new file mode 100755
index 0000000..44c3d23
--- /dev/null
+++ b/container-images/fetch-job/tools/fetch-job.sh
@@ -0,0 +1,75 @@
+#!/bin/ash
+# Copyright (C) 2011, 2024 SAP SE
+#
+# 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.
+
+usage() {
+ me=`basename "$0"`
+ echo >&2 "Usage: $me [--config CONFIG_FILE]"
+ exit 1
+}
+
+GIT_HOME=/var/gerrit/git
+CONFIG_FILE=/var/gerrit/etc/incoming-replication.config.yaml
+
+while test $# -gt 0 ; do
+ case "$1" in
+ --help)
+ usage
+ ;;
+
+ --config)
+ shift
+ CONFIG_FILE=$1
+ shift
+ ;;
+
+ *)
+ break
+ esac
+done
+
+if ! test -f $CONFIG_FILE; then
+ echo "No config file has been found."
+ usage
+fi
+
+NUM_REMOTES=$(yq e '.remotes | length' "$CONFIG_FILE")
+for i in $(seq 0 $((NUM_REMOTES-1))); do
+ REMOTE=$(NUM_REMOTE=$i yq e '.remotes[env(NUM_REMOTE)]' "$CONFIG_FILE")
+ REMOTE_NAME="$(echo "$REMOTE" | yq e '.name' -)"
+ REMOTE_SERVER_URL="$(echo "$REMOTE" | yq e '.url' -)"
+ REMOTE_TIMEOUT="$(echo "$REMOTE" | yq e '.timeout' -)"
+
+ NUM_FETCHES=$(echo "$REMOTE" | yq e '.fetch | length' -)
+ for j in $(seq 0 $((NUM_FETCHES-1))); do
+ FETCH=$(echo "$REMOTE" | NUM_FETCH=$j yq e '.fetch[env(NUM_FETCH)]' -)
+ REMOTE_REPO="$(echo "$FETCH" | yq e '.remoteRepo' -)"
+
+ LOCAL_REPO="$(echo "$FETCH" | yq e '.localRepo' -)"
+ (test -z "$LOCAL_REPO" || [ "$LOCAL_REPO" = "null" ]) && LOCAL_REPO="$REMOTE_REPO"
+
+ REFSPEC="$(echo "$FETCH" | yq e '.refSpec' -)"
+ (test -z "$REFSPEC" || [ "$REFSPEC" = "null" ]) && REFSPEC="+refs/heads/*:refs/heads/$REMOTE_NAME/*"
+
+ REMOTE_URL="$REMOTE_SERVER_URL/$REMOTE_REPO"
+
+ GIT_DIR="--git-dir=$GIT_HOME/$LOCAL_REPO.git"
+ git $GIT_DIR config remote.$REMOTE_NAME.url $REMOTE_URL
+ git $GIT_DIR config --unset-all remote.$REMOTE_NAME.fetch
+ git $GIT_DIR config remote.$REMOTE_NAME.fetch $REFSPEC
+
+ echo "Fetching $REMOTE_REPO from $REMOTE_NAME"
+ timeout $REMOTE_TIMEOUT git $GIT_DIR fetch $REMOTE_NAME
+ done
+done
diff --git a/container-images/gerrit-base/Dockerfile b/container-images/gerrit-base/Dockerfile
index 33a61e8..221d273 100644
--- a/container-images/gerrit-base/Dockerfile
+++ b/container-images/gerrit-base/Dockerfile
@@ -29,7 +29,7 @@
RUN curl -f -k -o /var/plugins/global-refdb.jar ${GLOBAL_REFDB_URL}
# Download high-availability plugin
-ARG HA_JAR_URL=https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-high-availability-bazel-master/lastSuccessfulBuild/artifact/bazel-bin/plugins/high-availability/high-availability.jar
+ARG HA_JAR_URL=https://gerrit-ci.gerritforge.com/view/Plugins-stable-3.9/job/plugin-high-availability-bazel-stable-3.9/lastSuccessfulBuild/artifact/bazel-bin/plugins/high-availability/high-availability.jar
RUN curl -f -k -o /var/plugins/high-availability.jar ${HA_JAR_URL}
# Download zookeeper-refdb plugin
diff --git a/container-images/gerrit-init/Dockerfile b/container-images/gerrit-init/Dockerfile
index 70da7aa..53ef808 100644
--- a/container-images/gerrit-init/Dockerfile
+++ b/container-images/gerrit-init/Dockerfile
@@ -20,7 +20,6 @@
COPY config/* /var/config/
RUN mkdir -p /var/mnt/git \
- && mkdir -p /var/mnt/logs \
&& chown -R gerrit:users /var/mnt
USER gerrit
diff --git a/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/download_plugins.py b/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/download_plugins.py
index 2c9ace0..b401c11 100755
--- a/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/download_plugins.py
+++ b/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/download_plugins.py
@@ -91,6 +91,8 @@
required = []
if self.config.is_ha:
required.extend(REQUIRED_HA_LIBS)
+ elif self.config.refdb:
+ required.append("global-refdb")
LOG.info("Requiring libs: %s", required)
return required
diff --git a/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/init.py b/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/init.py
index 4931984..f5cb3f2 100755
--- a/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/init.py
+++ b/container-images/gerrit-init/tools/gerrit-initializer/initializer/tasks/init.py
@@ -103,12 +103,16 @@
LOG.info("No initialization required.")
return False
- def _ensure_symlink(self, src, target):
- if not os.path.exists(src):
- raise FileNotFoundError(f"Unable to find mounted dir: {src}")
+ def _symlink(self, src, target, required=True):
+ if os.path.islink(target) and not os.path.exists(os.readlink(target)):
+ LOG.warn(f"Removing broken symlink {target}")
+ os.unlink(target)
- if os.path.islink(target) and os.path.realpath(target) == src:
- return
+ if not os.path.exists(src):
+ if required:
+ raise FileNotFoundError(f"Unable to find mounted dir: {src}")
+ else:
+ return
if os.path.exists(target):
if os.path.isdir(target) and not os.path.islink(target):
@@ -119,16 +123,15 @@
os.symlink(src, target)
def _symlink_mounted_site_components(self):
- self._ensure_symlink(f"{MNT_PATH}/git", f"{self.site}/git")
- self._ensure_symlink(f"{MNT_PATH}/logs", f"{self.site}/logs")
+ self._symlink(f"{MNT_PATH}/git", f"{self.site}/git")
mounted_shared_dir = f"{MNT_PATH}/shared"
if not self.is_replica and os.path.exists(mounted_shared_dir):
- self._ensure_symlink(mounted_shared_dir, f"{self.site}/shared")
+ self._symlink(mounted_shared_dir, f"{self.site}/shared")
index_type = self.gerrit_config.get("index.type", default=IndexType.LUCENE.name)
if IndexType[index_type.upper()] is IndexType.ELASTICSEARCH:
- self._ensure_symlink(f"{MNT_PATH}/index", f"{self.site}/index")
+ self._symlink(f"{MNT_PATH}/index", f"{self.site}/index")
data_dir = f"{self.site}/data"
if os.path.exists(data_dir):
@@ -147,7 +150,7 @@
abs_path = os.path.join(data_dir, file_or_dir)
abs_mounted_path = os.path.join(mounted_data_dir, file_or_dir)
if os.path.isdir(abs_mounted_path):
- self._ensure_symlink(abs_mounted_path, abs_path)
+ self._symlink(abs_mounted_path, abs_path)
def _symlink_configuration(self):
etc_dir = f"{self.site}/etc"
@@ -160,7 +163,7 @@
if os.path.isfile(
os.path.join(f"{MNT_PATH}/etc/{config_type}", file_or_dir)
):
- self._ensure_symlink(
+ self._symlink(
os.path.join(f"{MNT_PATH}/etc/{config_type}", file_or_dir),
os.path.join(etc_dir, file_or_dir),
)
@@ -176,6 +179,11 @@
os.remove(full_path)
def execute(self):
+ # Required for migration away from NFS-based log storage, when using the
+ # Gerrit-Operator and to provide backwards compatibility for the helm-
+ # charts
+ self._symlink(f"{MNT_PATH}/logs", f"{self.site}/logs", required=False)
+
if not self.is_replica:
self._symlink_mounted_site_components()
elif not NoteDbValidator(MNT_PATH).check():
diff --git a/container-images/gerrit/Dockerfile b/container-images/gerrit/Dockerfile
index 6a2eebc..31f9374 100644
--- a/container-images/gerrit/Dockerfile
+++ b/container-images/gerrit/Dockerfile
@@ -2,3 +2,4 @@
FROM gerrit-base:${TAG}
COPY tools/* /var/tools/
+COPY etc/* /var/jvm/etc/
diff --git a/container-images/gerrit/etc/security.properties b/container-images/gerrit/etc/security.properties
new file mode 100644
index 0000000..8ee04e7
--- /dev/null
+++ b/container-images/gerrit/etc/security.properties
@@ -0,0 +1 @@
+networkaddress.cache.ttl=30
diff --git a/container-images/gerrit/tools/start b/container-images/gerrit/tools/start
index 688d544..d16fea8 100755
--- a/container-images/gerrit/tools/start
+++ b/container-images/gerrit/tools/start
@@ -22,6 +22,7 @@
fi
JAVA_OPTIONS=$(git config --file /var/gerrit/etc/gerrit.config --get-all container.javaOptions)
+JAVA_OPTIONS="$JAVA_OPTIONS -Djava.security.properties=/var/jvm/etc/security.properties"
JAVA_OPTIONS="$JAVA_OPTIONS -Dgerrit.instanceId=$POD_NAME"
java ${JAVA_OPTIONS} -jar /var/gerrit/bin/gerrit.war daemon \
-d /var/gerrit \
diff --git a/container-images/git-gc/tools/gc.sh b/container-images/git-gc/tools/gc.sh
index 911d3cf..a0ec890 100755
--- a/container-images/git-gc/tools/gc.sh
+++ b/container-images/git-gc/tools/gc.sh
@@ -119,6 +119,26 @@
done
}
+delete_stale_gc_lock()
+{
+ local PROJECT_DIR="$1"
+ OUT=$(find "$PROJECT_DIR" -name 'gc.pid' -type f -maxdepth 1 -mmin +720 -delete) && \
+ log "pruning stale 'gc.pid' lock file older than 12 hours:\n$OUT"
+}
+
+delete_empty_ref_dirs()
+{
+ PROJECT_DIR="$1"
+ find "$PROJECT_DIR/refs" -type d -empty -mindepth 2 -mmin +60 -delete
+}
+
+delete_stale_incoming_packs()
+{
+ local PROJECT_DIR="$1"
+ OUT=$(find "$PROJECT_DIR/objects" -maxdepth 1 \( -name 'incoming_*.pack' -o -name 'incoming_*.idx' \) -type f -mtime +1 -delete) && \
+ log "pruning stale 'incoming_*.pack' and 'incoming_*.idx' files older than 24 hours:\n$OUT"
+}
+
gc_project()
{
PROJECT_NAME="$@"
@@ -160,7 +180,9 @@
git --git-dir="$PROJECT_DIR" config gc.autodetach false
git --git-dir="$PROJECT_DIR" config gc.auto 0
git --git-dir="$PROJECT_DIR" config gc.autopacklimit 0
+ git --git-dir="$PROJECT_DIR" config gc.cruftPacks true
git --git-dir="$PROJECT_DIR" config gc.packrefs true
+ git --git-dir="$PROJECT_DIR" config gc.pruneExpire 2.weeks.ago
git --git-dir="$PROJECT_DIR" config gc.reflogexpire never
git --git-dir="$PROJECT_DIR" config gc.reflogexpireunreachable never
git --git-dir="$PROJECT_DIR" config receive.autogc false
@@ -168,14 +190,15 @@
git --git-dir="$PROJECT_DIR" config pack.window 250
git --git-dir="$PROJECT_DIR" config pack.depth 50
- OUT=$(git $GC_CONFIG --git-dir="$PROJECT_DIR" "$GC_COMMAND" --auto --prune $OPTS \
+ delete_stale_gc_lock "$PROJECT_DIR"
+
+ OUT=$(git $GC_CONFIG --git-dir="$PROJECT_DIR" "$GC_COMMAND" $OPTS \
|| date +"%D %r Failed: $PROJECT_NAME") \
&& log "$OUT"
delete_empty_ref_dirs "$PROJECT_DIR"
- OUT=$(find "$PROJECT_DIR/objects" -name 'incoming_*.pack' -type f -mtime +14 -delete) && \
- log "pruning stale 'incoming_*.pack' files older than 14 days:\n$OUT"
+ delete_stale_incoming_packs "$PROJECT_DIR"
if [ $DONOT_PACK_REFS_OPT -eq 0 ] ; then
local looseRefCount
@@ -189,12 +212,6 @@
OUT=$(date +"%D %r Finished: $PROJECT_NAME$LOG_OPTS") && log "$OUT"
}
-delete_empty_ref_dirs()
-{
- PROJECT_DIR="$1"
- find "$PROJECT_DIR/refs" -type d -empty -mindepth 2 -mmin +60 -delete
-}
-
###########################
# Main script starts here #
###########################
@@ -206,8 +223,8 @@
DONOT_WRITE_BITMAPS_OPT=0
DONOT_PACK_REFS_OPT=0
PRESERVE_PACKS_OPT=0
-# set auto gc options on the fly when git gc is triggered by cron
-GC_CONFIG="-c gc.auto=6700 -c gc.autoPackLimit=4"
+# optional additional git config options
+GC_CONFIG=""
while getopts 's:p:BRP?h' c
do
diff --git a/container-images/git-gc/tools/git-gc-preserve b/container-images/git-gc/tools/git-gc-preserve
index f658ae2..48cc9cf 100755
--- a/container-images/git-gc/tools/git-gc-preserve
+++ b/container-images/git-gc/tools/git-gc-preserve
@@ -92,11 +92,12 @@
# pack-0...2.pack to pack-0...2.old-pack
# pack-0...2.idx to pack-0...2.old-idx
get_preserved_packfile_name() { # packfile > preserved_packfile
- if [[ $1 == *.pack ]]; then
- echo "$(basename -- $1 .pack).old-pack"
- elif [[ $1 == *.idx ]]; then
- echo "$(basename -- $1 .idx).old-idx"
- fi
+ case "$1" in
+ *.pack)
+ echo "$(basename -- $1 .pack).old-pack";;
+ *.idx)
+ echo "$(basename -- $1 .idx).old-idx";;
+ esac
}
# main
@@ -107,6 +108,7 @@
shift
done
args=$(git rev-parse --sq-quote "$@")
+echo "git args: $args"
repopath=$(git rev-parse --git-dir)
if [ -z "$repopath" ]; then
diff --git a/container-images/publish_list b/container-images/publish_list
index d0b4826..5379e4a 100644
--- a/container-images/publish_list
+++ b/container-images/publish_list
@@ -16,5 +16,6 @@
echo "apache-git-http-backend" \
"gerrit-init" \
"gerrit" \
- "git-gc"
+ "git-gc" \
+ "fetch-job"
}
diff --git a/crd/current/gerritclusters.gerritoperator.google.com-v1.yml b/crd/current/gerritclusters.gerritoperator.google.com-v1.yml
index 49a6b13..e97e62f 100644
--- a/crd/current/gerritclusters.gerritoperator.google.com-v1.yml
+++ b/crd/current/gerritclusters.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerritcluster
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
@@ -854,6 +854,8 @@
properties:
secretRef:
type: string
+ executable:
+ type: boolean
type: object
type: object
type: array
@@ -870,6 +872,8 @@
properties:
secretRef:
type: string
+ executable:
+ type: boolean
type: object
type: object
type: array
@@ -877,6 +881,55 @@
additionalProperties:
type: string
type: object
+ envVars:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ valueFrom:
+ properties:
+ configMapKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
+ type: string
+ type: object
+ resourceFieldRef:
+ properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ type: object
+ type: object
+ type: array
secretRef:
type: string
mode:
@@ -1503,6 +1556,462 @@
enabled:
type: boolean
type: object
+ scheduledTasks:
+ properties:
+ incomingReplication:
+ items:
+ properties:
+ metadata:
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ type: object
+ creationTimestamp:
+ type: string
+ deletionGracePeriodSeconds:
+ type: integer
+ deletionTimestamp:
+ type: string
+ finalizers:
+ items:
+ type: string
+ type: array
+ generateName:
+ type: string
+ generation:
+ type: integer
+ labels:
+ additionalProperties:
+ type: string
+ type: object
+ managedFields:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ fieldsType:
+ type: string
+ fieldsV1:
+ type: object
+ manager:
+ type: string
+ operation:
+ type: string
+ subresource:
+ type: string
+ time:
+ type: string
+ type: object
+ type: array
+ name:
+ type: string
+ namespace:
+ type: string
+ ownerReferences:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ blockOwnerDeletion:
+ type: boolean
+ controller:
+ type: boolean
+ kind:
+ type: string
+ name:
+ type: string
+ uid:
+ type: string
+ type: object
+ type: array
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ uid:
+ type: string
+ type: object
+ spec:
+ properties:
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ type: object
+ type: array
+ type: object
type: object
status:
properties:
diff --git a/crd/current/gerritnetworks.gerritoperator.google.com-v1.yml b/crd/current/gerritnetworks.gerritoperator.google.com-v1.yml
index db2674e..8b5f2fc 100644
--- a/crd/current/gerritnetworks.gerritoperator.google.com-v1.yml
+++ b/crd/current/gerritnetworks.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerritnetwork
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
diff --git a/crd/current/gerrits.gerritoperator.google.com-v1.yml b/crd/current/gerrits.gerritoperator.google.com-v1.yml
index c634f9e..f579945 100644
--- a/crd/current/gerrits.gerritoperator.google.com-v1.yml
+++ b/crd/current/gerrits.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerrit
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
@@ -764,6 +764,8 @@
properties:
secretRef:
type: string
+ executable:
+ type: boolean
type: object
type: object
type: array
@@ -780,6 +782,8 @@
properties:
secretRef:
type: string
+ executable:
+ type: boolean
type: object
type: object
type: array
@@ -787,6 +791,55 @@
additionalProperties:
type: string
type: object
+ envVars:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ valueFrom:
+ properties:
+ configMapKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
+ type: string
+ type: object
+ resourceFieldRef:
+ properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ type: object
+ type: object
+ type: array
secretRef:
type: string
mode:
diff --git a/crd/current/gitgcs.gerritoperator.google.com-v1.yml b/crd/current/gitgcs.gerritoperator.google.com-v1.yml
index 9ceb6b9..393a0ce 100644
--- a/crd/current/gitgcs.gerritoperator.google.com-v1.yml
+++ b/crd/current/gitgcs.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gitgarbagecollection
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
diff --git a/crd/current/incomingreplicationtasks.gerritoperator.google.com-v1.yml b/crd/current/incomingreplicationtasks.gerritoperator.google.com-v1.yml
new file mode 100644
index 0000000..fd684f5
--- /dev/null
+++ b/crd/current/incomingreplicationtasks.gerritoperator.google.com-v1.yml
@@ -0,0 +1,538 @@
+# Generated by Fabric8 CRDGenerator, manual edits might get overwritten!
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ name: incomingreplicationtasks.gerritoperator.google.com
+spec:
+ group: gerritoperator.google.com
+ names:
+ kind: IncomingReplicationTask
+ plural: incomingreplicationtasks
+ singular: incomingreplicationtask
+ scope: Namespaced
+ versions:
+ - name: v1beta9
+ schema:
+ openAPIV3Schema:
+ properties:
+ spec:
+ properties:
+ containerImages:
+ properties:
+ imagePullPolicy:
+ type: string
+ imagePullSecrets:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ busyBox:
+ properties:
+ registry:
+ type: string
+ tag:
+ type: string
+ type: object
+ gerritImages:
+ properties:
+ registry:
+ type: string
+ org:
+ type: string
+ tag:
+ type: string
+ type: object
+ type: object
+ storage:
+ properties:
+ pluginCache:
+ properties:
+ enabled:
+ type: boolean
+ type: object
+ storageClasses:
+ properties:
+ readWriteOnce:
+ type: string
+ readWriteMany:
+ type: string
+ nfsWorkaround:
+ properties:
+ enabled:
+ type: boolean
+ chownOnStartup:
+ type: boolean
+ idmapdConfig:
+ type: string
+ type: object
+ type: object
+ sharedStorage:
+ properties:
+ externalPVC:
+ properties:
+ enabled:
+ type: boolean
+ claimName:
+ type: string
+ type: object
+ size:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ volumeName:
+ type: string
+ selector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ type: object
+ type: object
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ status:
+ properties:
+ apiVersion:
+ type: string
+ code:
+ type: integer
+ details:
+ properties:
+ causes:
+ items:
+ properties:
+ field:
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ type: object
+ type: array
+ group:
+ type: string
+ kind:
+ type: string
+ name:
+ type: string
+ retryAfterSeconds:
+ type: integer
+ uid:
+ type: string
+ type: object
+ kind:
+ type: string
+ message:
+ type: string
+ metadata:
+ properties:
+ continue:
+ type: string
+ remainingItemCount:
+ type: integer
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ type: object
+ reason:
+ type: string
+ status:
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/crd/current/receivers.gerritoperator.google.com-v1.yml b/crd/current/receivers.gerritoperator.google.com-v1.yml
index 0a206a6..f015fe9 100644
--- a/crd/current/receivers.gerritoperator.google.com-v1.yml
+++ b/crd/current/receivers.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: receiver
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
diff --git a/crd/deprecated/gerritclusters.gerritoperator.google.com-v1.yml b/crd/deprecated/gerritclusters.gerritoperator.google.com-v1.yml
index b0fb041..e920c6d 100644
--- a/crd/deprecated/gerritclusters.gerritoperator.google.com-v1.yml
+++ b/crd/deprecated/gerritclusters.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerritcluster
scope: Namespaced
versions:
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
@@ -877,6 +877,55 @@
additionalProperties:
type: string
type: object
+ envVars:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ valueFrom:
+ properties:
+ configMapKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
+ type: string
+ type: object
+ resourceFieldRef:
+ properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ type: object
+ type: object
+ type: array
secretRef:
type: string
mode:
@@ -1503,6 +1552,462 @@
enabled:
type: boolean
type: object
+ scheduledTasks:
+ properties:
+ incomingReplication:
+ items:
+ properties:
+ metadata:
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ type: object
+ creationTimestamp:
+ type: string
+ deletionGracePeriodSeconds:
+ type: integer
+ deletionTimestamp:
+ type: string
+ finalizers:
+ items:
+ type: string
+ type: array
+ generateName:
+ type: string
+ generation:
+ type: integer
+ labels:
+ additionalProperties:
+ type: string
+ type: object
+ managedFields:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ fieldsType:
+ type: string
+ fieldsV1:
+ type: object
+ manager:
+ type: string
+ operation:
+ type: string
+ subresource:
+ type: string
+ time:
+ type: string
+ type: object
+ type: array
+ name:
+ type: string
+ namespace:
+ type: string
+ ownerReferences:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ blockOwnerDeletion:
+ type: boolean
+ controller:
+ type: boolean
+ kind:
+ type: string
+ name:
+ type: string
+ uid:
+ type: string
+ type: object
+ type: array
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ uid:
+ type: string
+ type: object
+ spec:
+ properties:
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ type: object
+ type: array
+ type: object
type: object
status:
properties:
diff --git a/crd/deprecated/gerritnetworks.gerritoperator.google.com-v1.yml b/crd/deprecated/gerritnetworks.gerritoperator.google.com-v1.yml
index 93d0b10..f50e594 100644
--- a/crd/deprecated/gerritnetworks.gerritoperator.google.com-v1.yml
+++ b/crd/deprecated/gerritnetworks.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerritnetwork
scope: Namespaced
versions:
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
diff --git a/crd/deprecated/gerrits.gerritoperator.google.com-v1.yml b/crd/deprecated/gerrits.gerritoperator.google.com-v1.yml
index cb5e721..40eb075 100644
--- a/crd/deprecated/gerrits.gerritoperator.google.com-v1.yml
+++ b/crd/deprecated/gerrits.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerrit
scope: Namespaced
versions:
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
@@ -158,6 +158,8 @@
enabled:
type: boolean
type: object
+ sshdAdvertisedReadPort:
+ type: integer
serviceAccount:
type: string
tolerations:
@@ -785,6 +787,55 @@
additionalProperties:
type: string
type: object
+ envVars:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ valueFrom:
+ properties:
+ configMapKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
+ type: string
+ type: object
+ resourceFieldRef:
+ properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ type: object
+ type: object
+ type: array
secretRef:
type: string
mode:
diff --git a/crd/deprecated/gitgcs.gerritoperator.google.com-v1.yml b/crd/deprecated/gitgcs.gerritoperator.google.com-v1.yml
index 22f59e6..65e4072 100644
--- a/crd/deprecated/gitgcs.gerritoperator.google.com-v1.yml
+++ b/crd/deprecated/gitgcs.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gitgarbagecollection
scope: Namespaced
versions:
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
diff --git a/crd/deprecated/incomingreplicationtasks.gerritoperator.google.com-v1.yml b/crd/deprecated/incomingreplicationtasks.gerritoperator.google.com-v1.yml
new file mode 100644
index 0000000..f2d7628
--- /dev/null
+++ b/crd/deprecated/incomingreplicationtasks.gerritoperator.google.com-v1.yml
@@ -0,0 +1,538 @@
+# Generated by Fabric8 CRDGenerator, manual edits might get overwritten!
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ name: incomingreplicationtasks.gerritoperator.google.com
+spec:
+ group: gerritoperator.google.com
+ names:
+ kind: IncomingReplicationTask
+ plural: incomingreplicationtasks
+ singular: incomingreplicationtask
+ scope: Namespaced
+ versions:
+ - name: v1beta8
+ schema:
+ openAPIV3Schema:
+ properties:
+ spec:
+ properties:
+ containerImages:
+ properties:
+ imagePullPolicy:
+ type: string
+ imagePullSecrets:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ busyBox:
+ properties:
+ registry:
+ type: string
+ tag:
+ type: string
+ type: object
+ gerritImages:
+ properties:
+ registry:
+ type: string
+ org:
+ type: string
+ tag:
+ type: string
+ type: object
+ type: object
+ storage:
+ properties:
+ pluginCache:
+ properties:
+ enabled:
+ type: boolean
+ type: object
+ storageClasses:
+ properties:
+ readWriteOnce:
+ type: string
+ readWriteMany:
+ type: string
+ nfsWorkaround:
+ properties:
+ enabled:
+ type: boolean
+ chownOnStartup:
+ type: boolean
+ idmapdConfig:
+ type: string
+ type: object
+ type: object
+ sharedStorage:
+ properties:
+ externalPVC:
+ properties:
+ enabled:
+ type: boolean
+ claimName:
+ type: string
+ type: object
+ size:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ volumeName:
+ type: string
+ selector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ type: object
+ type: object
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ status:
+ properties:
+ apiVersion:
+ type: string
+ code:
+ type: integer
+ details:
+ properties:
+ causes:
+ items:
+ properties:
+ field:
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ type: object
+ type: array
+ group:
+ type: string
+ kind:
+ type: string
+ name:
+ type: string
+ retryAfterSeconds:
+ type: integer
+ uid:
+ type: string
+ type: object
+ kind:
+ type: string
+ message:
+ type: string
+ metadata:
+ properties:
+ continue:
+ type: string
+ remainingItemCount:
+ type: integer
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ type: object
+ reason:
+ type: string
+ status:
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
diff --git a/crd/deprecated/receivers.gerritoperator.google.com-v1.yml b/crd/deprecated/receivers.gerritoperator.google.com-v1.yml
index c31a2b5..d769814 100644
--- a/crd/deprecated/receivers.gerritoperator.google.com-v1.yml
+++ b/crd/deprecated/receivers.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: receiver
scope: Namespaced
versions:
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
diff --git a/get_version.sh b/get_version.sh
index f7b3585..ffeecc9 100755
--- a/get_version.sh
+++ b/get_version.sh
@@ -12,8 +12,62 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-REV=$(git describe --always --dirty)
-GERRIT_VERSION=$(docker run --platform=linux/amd64 --entrypoint "/bin/sh" gerrit-base:$REV \
- -c "java -jar /var/gerrit/bin/gerrit.war version")
-GERRIT_VERSION=$(echo "${GERRIT_VERSION##*$'\n'}" | cut -d' ' -f3 | tr -d '[:space:]')
-echo "$REV-$GERRIT_VERSION"
+usage() {
+ me=`basename "$0"`
+ echo >&2 "Usage: $me [--help] [--output (K8SGERRIT | GERRIT | COMBINED)]"
+ exit 1
+}
+
+OUTPUT="COMBINED"
+
+while test $# -gt 0 ; do
+ case "$1" in
+ --help)
+ usage
+ ;;
+
+ --output)
+ shift
+ OUTPUT=$1
+ shift
+ ;;
+
+ *)
+ break
+ esac
+done
+
+getK8sVersion() {
+ echo "$(git describe --always --dirty --abbrev=10)"
+}
+
+getGerritVersion() {
+ GERRIT_VERSION="$(
+ docker run \
+ --platform=linux/amd64 \
+ --entrypoint '/bin/sh' \
+ gerrit-base:$(getK8sVersion) \
+ -c 'java -jar /var/gerrit/bin/gerrit.war version'
+ )"
+ GERRIT_VERSION="$(
+ echo "${GERRIT_VERSION##*$'\n'}" \
+ | cut -d' ' -f3 \
+ | tr -d '[:space:]'
+ )"
+ echo "$GERRIT_VERSION"
+}
+
+case $OUTPUT in
+ K8SGERRIT)
+ echo "$(getK8sVersion)"
+ ;;
+ GERRIT)
+ echo "$(getGerritVersion)"
+ ;;
+ COMBINED)
+ echo "$(getK8sVersion)-$(getGerritVersion)"
+ ;;
+ *)
+ usage
+ ;;
+esac
diff --git a/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml
index d26fe79..93b7353 100644
--- a/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerritcluster
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
@@ -854,6 +854,8 @@
properties:
secretRef:
type: string
+ executable:
+ type: boolean
type: object
type: object
type: array
@@ -870,6 +872,8 @@
properties:
secretRef:
type: string
+ executable:
+ type: boolean
type: object
type: object
type: array
@@ -877,6 +881,55 @@
additionalProperties:
type: string
type: object
+ envVars:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ valueFrom:
+ properties:
+ configMapKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
+ type: string
+ type: object
+ resourceFieldRef:
+ properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ type: object
+ type: object
+ type: array
secretRef:
type: string
mode:
@@ -1503,6 +1556,462 @@
enabled:
type: boolean
type: object
+ scheduledTasks:
+ properties:
+ incomingReplication:
+ items:
+ properties:
+ metadata:
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ type: object
+ creationTimestamp:
+ type: string
+ deletionGracePeriodSeconds:
+ type: integer
+ deletionTimestamp:
+ type: string
+ finalizers:
+ items:
+ type: string
+ type: array
+ generateName:
+ type: string
+ generation:
+ type: integer
+ labels:
+ additionalProperties:
+ type: string
+ type: object
+ managedFields:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ fieldsType:
+ type: string
+ fieldsV1:
+ type: object
+ manager:
+ type: string
+ operation:
+ type: string
+ subresource:
+ type: string
+ time:
+ type: string
+ type: object
+ type: array
+ name:
+ type: string
+ namespace:
+ type: string
+ ownerReferences:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ blockOwnerDeletion:
+ type: boolean
+ controller:
+ type: boolean
+ kind:
+ type: string
+ name:
+ type: string
+ uid:
+ type: string
+ type: object
+ type: array
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ uid:
+ type: string
+ type: object
+ spec:
+ properties:
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ type: object
+ type: array
+ type: object
type: object
status:
properties:
@@ -1518,7 +2027,7 @@
storage: true
subresources:
status: {}
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
@@ -2382,6 +2891,55 @@
additionalProperties:
type: string
type: object
+ envVars:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ valueFrom:
+ properties:
+ configMapKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
+ type: string
+ type: object
+ resourceFieldRef:
+ properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ type: object
+ type: object
+ type: array
secretRef:
type: string
mode:
@@ -3008,6 +3566,462 @@
enabled:
type: boolean
type: object
+ scheduledTasks:
+ properties:
+ incomingReplication:
+ items:
+ properties:
+ metadata:
+ properties:
+ annotations:
+ additionalProperties:
+ type: string
+ type: object
+ creationTimestamp:
+ type: string
+ deletionGracePeriodSeconds:
+ type: integer
+ deletionTimestamp:
+ type: string
+ finalizers:
+ items:
+ type: string
+ type: array
+ generateName:
+ type: string
+ generation:
+ type: integer
+ labels:
+ additionalProperties:
+ type: string
+ type: object
+ managedFields:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ fieldsType:
+ type: string
+ fieldsV1:
+ type: object
+ manager:
+ type: string
+ operation:
+ type: string
+ subresource:
+ type: string
+ time:
+ type: string
+ type: object
+ type: array
+ name:
+ type: string
+ namespace:
+ type: string
+ ownerReferences:
+ items:
+ properties:
+ apiVersion:
+ type: string
+ blockOwnerDeletion:
+ type: boolean
+ controller:
+ type: boolean
+ kind:
+ type: string
+ name:
+ type: string
+ uid:
+ type: string
+ type: object
+ type: array
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ uid:
+ type: string
+ type: object
+ spec:
+ properties:
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ type: object
+ type: array
+ type: object
type: object
status:
properties:
diff --git a/helm-charts/gerrit-operator-crds/templates/gerritnetworks.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gerritnetworks.gerritoperator.google.com-v1.yml
index ef73154..3964f7e 100644
--- a/helm-charts/gerrit-operator-crds/templates/gerritnetworks.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gerritnetworks.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gerritnetwork
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
@@ -139,7 +139,7 @@
storage: true
subresources:
status: {}
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
diff --git a/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml
index 0ccabde..6cc88f9 100644
--- a/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml
@@ -13,7 +13,867 @@
singular: gerrit
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
+ schema:
+ openAPIV3Schema:
+ properties:
+ spec:
+ properties:
+ containerImages:
+ properties:
+ imagePullPolicy:
+ type: string
+ imagePullSecrets:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ busyBox:
+ properties:
+ registry:
+ type: string
+ tag:
+ type: string
+ type: object
+ gerritImages:
+ properties:
+ registry:
+ type: string
+ org:
+ type: string
+ tag:
+ type: string
+ type: object
+ type: object
+ storage:
+ properties:
+ pluginCache:
+ properties:
+ enabled:
+ type: boolean
+ type: object
+ storageClasses:
+ properties:
+ readWriteOnce:
+ type: string
+ readWriteMany:
+ type: string
+ nfsWorkaround:
+ properties:
+ enabled:
+ type: boolean
+ chownOnStartup:
+ type: boolean
+ idmapdConfig:
+ type: string
+ type: object
+ type: object
+ sharedStorage:
+ properties:
+ externalPVC:
+ properties:
+ enabled:
+ type: boolean
+ claimName:
+ type: string
+ type: object
+ size:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ volumeName:
+ type: string
+ selector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ type: object
+ type: object
+ ingress:
+ properties:
+ enabled:
+ type: boolean
+ host:
+ type: string
+ tlsEnabled:
+ type: boolean
+ ssh:
+ properties:
+ enabled:
+ type: boolean
+ type: object
+ type: object
+ refdb:
+ properties:
+ database:
+ enum:
+ - NONE
+ - ZOOKEEPER
+ - SPANNER
+ type: string
+ zookeeper:
+ properties:
+ connectString:
+ type: string
+ rootNode:
+ type: string
+ type: object
+ spanner:
+ properties:
+ projectName:
+ type: string
+ instance:
+ type: string
+ database:
+ type: string
+ type: object
+ type: object
+ serverId:
+ type: string
+ fluentBitSidecar:
+ properties:
+ image:
+ type: string
+ config:
+ type: string
+ enabled:
+ type: boolean
+ type: object
+ sshdAdvertisedReadPort:
+ type: integer
+ serviceAccount:
+ type: string
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ topologySpreadConstraints:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ matchLabelKeys:
+ items:
+ type: string
+ type: array
+ maxSkew:
+ type: integer
+ minDomains:
+ type: integer
+ nodeAffinityPolicy:
+ type: string
+ nodeTaintsPolicy:
+ type: string
+ topologyKey:
+ type: string
+ whenUnsatisfiable:
+ type: string
+ type: object
+ type: array
+ priorityClassName:
+ type: string
+ replicas:
+ type: integer
+ updatePartition:
+ type: integer
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ startupProbe:
+ properties:
+ exec:
+ properties:
+ command:
+ items:
+ type: string
+ type: array
+ type: object
+ failureThreshold:
+ type: integer
+ grpc:
+ properties:
+ port:
+ type: integer
+ service:
+ type: string
+ type: object
+ httpGet:
+ properties:
+ host:
+ type: string
+ httpHeaders:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ type: object
+ type: array
+ path:
+ type: string
+ port:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ scheme:
+ type: string
+ type: object
+ initialDelaySeconds:
+ type: integer
+ periodSeconds:
+ type: integer
+ successThreshold:
+ type: integer
+ tcpSocket:
+ properties:
+ host:
+ type: string
+ port:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ terminationGracePeriodSeconds:
+ type: integer
+ timeoutSeconds:
+ type: integer
+ type: object
+ readinessProbe:
+ properties:
+ exec:
+ properties:
+ command:
+ items:
+ type: string
+ type: array
+ type: object
+ failureThreshold:
+ type: integer
+ grpc:
+ properties:
+ port:
+ type: integer
+ service:
+ type: string
+ type: object
+ httpGet:
+ properties:
+ host:
+ type: string
+ httpHeaders:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ type: object
+ type: array
+ path:
+ type: string
+ port:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ scheme:
+ type: string
+ type: object
+ initialDelaySeconds:
+ type: integer
+ periodSeconds:
+ type: integer
+ successThreshold:
+ type: integer
+ tcpSocket:
+ properties:
+ host:
+ type: string
+ port:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ terminationGracePeriodSeconds:
+ type: integer
+ timeoutSeconds:
+ type: integer
+ type: object
+ livenessProbe:
+ properties:
+ exec:
+ properties:
+ command:
+ items:
+ type: string
+ type: array
+ type: object
+ failureThreshold:
+ type: integer
+ grpc:
+ properties:
+ port:
+ type: integer
+ service:
+ type: string
+ type: object
+ httpGet:
+ properties:
+ host:
+ type: string
+ httpHeaders:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ type: object
+ type: array
+ path:
+ type: string
+ port:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ scheme:
+ type: string
+ type: object
+ initialDelaySeconds:
+ type: integer
+ periodSeconds:
+ type: integer
+ successThreshold:
+ type: integer
+ tcpSocket:
+ properties:
+ host:
+ type: string
+ port:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ terminationGracePeriodSeconds:
+ type: integer
+ timeoutSeconds:
+ type: integer
+ type: object
+ gracefulStopTimeout:
+ type: integer
+ service:
+ properties:
+ sshPort:
+ type: integer
+ type:
+ type: string
+ httpPort:
+ type: integer
+ type: object
+ site:
+ properties:
+ size:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ plugins:
+ items:
+ properties:
+ installAsLibrary:
+ type: boolean
+ name:
+ type: string
+ url:
+ type: string
+ sha1:
+ type: string
+ data:
+ properties:
+ secretRef:
+ type: string
+ executable:
+ type: boolean
+ type: object
+ type: object
+ type: array
+ libs:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ sha1:
+ type: string
+ data:
+ properties:
+ secretRef:
+ type: string
+ executable:
+ type: boolean
+ type: object
+ type: object
+ type: array
+ configFiles:
+ additionalProperties:
+ type: string
+ type: object
+ envVars:
+ items:
+ properties:
+ name:
+ type: string
+ value:
+ type: string
+ valueFrom:
+ properties:
+ configMapKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
+ type: string
+ type: object
+ resourceFieldRef:
+ properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
+ name:
+ type: string
+ optional:
+ type: boolean
+ type: object
+ type: object
+ type: object
+ type: array
+ secretRef:
+ type: string
+ mode:
+ enum:
+ - PRIMARY
+ - REPLICA
+ type: string
+ debug:
+ properties:
+ enabled:
+ type: boolean
+ suspend:
+ type: boolean
+ type: object
+ type: object
+ status:
+ properties:
+ ready:
+ type: boolean
+ appliedConfigMapVersions:
+ additionalProperties:
+ type: string
+ type: object
+ appliedSecretVersions:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
@@ -787,811 +1647,55 @@
additionalProperties:
type: string
type: object
- secretRef:
- type: string
- mode:
- enum:
- - PRIMARY
- - REPLICA
- type: string
- debug:
- properties:
- enabled:
- type: boolean
- suspend:
- type: boolean
- type: object
- type: object
- status:
- properties:
- ready:
- type: boolean
- appliedConfigMapVersions:
- additionalProperties:
- type: string
- type: object
- appliedSecretVersions:
- additionalProperties:
- type: string
- type: object
- type: object
- type: object
- served: true
- storage: true
- subresources:
- status: {}
- - name: v1beta5
- schema:
- openAPIV3Schema:
- properties:
- spec:
- properties:
- containerImages:
- properties:
- imagePullPolicy:
- type: string
- imagePullSecrets:
- items:
- properties:
- name:
- type: string
- type: object
- type: array
- busyBox:
- properties:
- registry:
- type: string
- tag:
- type: string
- type: object
- gerritImages:
- properties:
- registry:
- type: string
- org:
- type: string
- tag:
- type: string
- type: object
- type: object
- storage:
- properties:
- pluginCache:
- properties:
- enabled:
- type: boolean
- type: object
- storageClasses:
- properties:
- readWriteOnce:
- type: string
- readWriteMany:
- type: string
- nfsWorkaround:
- properties:
- enabled:
- type: boolean
- chownOnStartup:
- type: boolean
- idmapdConfig:
- type: string
- type: object
- type: object
- sharedStorage:
- properties:
- externalPVC:
- properties:
- enabled:
- type: boolean
- claimName:
- type: string
- type: object
- size:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- volumeName:
- type: string
- selector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- type: object
- type: object
- ingress:
- properties:
- enabled:
- type: boolean
- host:
- type: string
- tlsEnabled:
- type: boolean
- ssh:
- properties:
- enabled:
- type: boolean
- type: object
- type: object
- refdb:
- properties:
- database:
- enum:
- - NONE
- - ZOOKEEPER
- - SPANNER
- type: string
- zookeeper:
- properties:
- connectString:
- type: string
- rootNode:
- type: string
- type: object
- spanner:
- properties:
- projectName:
- type: string
- instance:
- type: string
- database:
- type: string
- type: object
- type: object
- serverId:
- type: string
- fluentBitSidecar:
- properties:
- image:
- type: string
- config:
- type: string
- enabled:
- type: boolean
- type: object
- serviceAccount:
- type: string
- tolerations:
+ envVars:
items:
properties:
- effect:
+ name:
type: string
- key:
- type: string
- operator:
- type: string
- tolerationSeconds:
- type: integer
value:
type: string
- type: object
- type: array
- affinity:
- properties:
- nodeAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- preference:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchFields:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- type: object
- weight:
- type: integer
- type: object
- type: array
- requiredDuringSchedulingIgnoredDuringExecution:
- properties:
- nodeSelectorTerms:
- items:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchFields:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- type: object
- type: array
- type: object
- type: object
- podAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaces:
- items:
- type: string
- type: array
- topologyKey:
- type: string
- type: object
- weight:
- type: integer
- type: object
- type: array
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaces:
- items:
- type: string
- type: array
- topologyKey:
- type: string
- type: object
- type: array
- type: object
- podAntiAffinity:
- properties:
- preferredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- podAffinityTerm:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaces:
- items:
- type: string
- type: array
- topologyKey:
- type: string
- type: object
- weight:
- type: integer
- type: object
- type: array
- requiredDuringSchedulingIgnoredDuringExecution:
- items:
- properties:
- labelSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaceSelector:
- properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- namespaces:
- items:
- type: string
- type: array
- topologyKey:
- type: string
- type: object
- type: array
- type: object
- type: object
- topologySpreadConstraints:
- items:
- properties:
- labelSelector:
+ valueFrom:
properties:
- matchExpressions:
- items:
- properties:
- key:
- type: string
- operator:
- type: string
- values:
- items:
- type: string
- type: array
- type: object
- type: array
- matchLabels:
- additionalProperties:
- type: string
- type: object
- type: object
- matchLabelKeys:
- items:
- type: string
- type: array
- maxSkew:
- type: integer
- minDomains:
- type: integer
- nodeAffinityPolicy:
- type: string
- nodeTaintsPolicy:
- type: string
- topologyKey:
- type: string
- whenUnsatisfiable:
- type: string
- type: object
- type: array
- priorityClassName:
- type: string
- replicas:
- type: integer
- updatePartition:
- type: integer
- resources:
- properties:
- claims:
- items:
- properties:
- name:
- type: string
- type: object
- type: array
- limits:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- type: object
- requests:
- additionalProperties:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- type: object
- type: object
- startupProbe:
- properties:
- exec:
- properties:
- command:
- items:
- type: string
- type: array
- type: object
- failureThreshold:
- type: integer
- grpc:
- properties:
- port:
- type: integer
- service:
- type: string
- type: object
- httpGet:
- properties:
- host:
- type: string
- httpHeaders:
- items:
+ configMapKeyRef:
properties:
+ key:
+ type: string
name:
type: string
- value:
+ optional:
+ type: boolean
+ type: object
+ fieldRef:
+ properties:
+ apiVersion:
+ type: string
+ fieldPath:
type: string
type: object
- type: array
- path:
- type: string
- port:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- scheme:
- type: string
- type: object
- initialDelaySeconds:
- type: integer
- periodSeconds:
- type: integer
- successThreshold:
- type: integer
- tcpSocket:
- properties:
- host:
- type: string
- port:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- type: object
- terminationGracePeriodSeconds:
- type: integer
- timeoutSeconds:
- type: integer
- type: object
- readinessProbe:
- properties:
- exec:
- properties:
- command:
- items:
- type: string
- type: array
- type: object
- failureThreshold:
- type: integer
- grpc:
- properties:
- port:
- type: integer
- service:
- type: string
- type: object
- httpGet:
- properties:
- host:
- type: string
- httpHeaders:
- items:
+ resourceFieldRef:
properties:
+ containerName:
+ type: string
+ divisor:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ resource:
+ type: string
+ type: object
+ secretKeyRef:
+ properties:
+ key:
+ type: string
name:
type: string
- value:
- type: string
+ optional:
+ type: boolean
type: object
- type: array
- path:
- type: string
- port:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- scheme:
- type: string
- type: object
- initialDelaySeconds:
- type: integer
- periodSeconds:
- type: integer
- successThreshold:
- type: integer
- tcpSocket:
- properties:
- host:
- type: string
- port:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- type: object
- terminationGracePeriodSeconds:
- type: integer
- timeoutSeconds:
- type: integer
- type: object
- livenessProbe:
- properties:
- exec:
- properties:
- command:
- items:
- type: string
- type: array
- type: object
- failureThreshold:
- type: integer
- grpc:
- properties:
- port:
- type: integer
- service:
- type: string
- type: object
- httpGet:
- properties:
- host:
- type: string
- httpHeaders:
- items:
- properties:
- name:
- type: string
- value:
- type: string
- type: object
- type: array
- path:
- type: string
- port:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- scheme:
- type: string
- type: object
- initialDelaySeconds:
- type: integer
- periodSeconds:
- type: integer
- successThreshold:
- type: integer
- tcpSocket:
- properties:
- host:
- type: string
- port:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- type: object
- terminationGracePeriodSeconds:
- type: integer
- timeoutSeconds:
- type: integer
- type: object
- gracefulStopTimeout:
- type: integer
- service:
- properties:
- sshPort:
- type: integer
- type:
- type: string
- httpPort:
- type: integer
- type: object
- site:
- properties:
- size:
- anyOf:
- - type: integer
- - type: string
- x-kubernetes-int-or-string: true
- type: object
- plugins:
- items:
- properties:
- installAsLibrary:
- type: boolean
- name:
- type: string
- url:
- type: string
- sha1:
- type: string
- data:
- properties:
- secretRef:
- type: string
type: object
type: object
type: array
- libs:
- items:
- properties:
- name:
- type: string
- url:
- type: string
- sha1:
- type: string
- data:
- properties:
- secretRef:
- type: string
- type: object
- type: object
- type: array
- configFiles:
- additionalProperties:
- type: string
- type: object
secretRef:
type: string
mode:
diff --git a/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml
index b202d89..49f9768 100644
--- a/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: gitgarbagecollection
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
@@ -390,7 +390,7 @@
storage: true
subresources:
status: {}
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
diff --git a/helm-charts/gerrit-operator-crds/templates/incomingreplicationtasks.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/incomingreplicationtasks.gerritoperator.google.com-v1.yml
new file mode 100644
index 0000000..cd7a4ae
--- /dev/null
+++ b/helm-charts/gerrit-operator-crds/templates/incomingreplicationtasks.gerritoperator.google.com-v1.yml
@@ -0,0 +1,1063 @@
+# Generated by Fabric8 CRDGenerator, manual edits might get overwritten!
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ name: incomingreplicationtasks.gerritoperator.google.com
+spec:
+ group: gerritoperator.google.com
+ names:
+ kind: IncomingReplicationTask
+ plural: incomingreplicationtasks
+ singular: incomingreplicationtask
+ scope: Namespaced
+ versions:
+ - name: v1beta9
+ schema:
+ openAPIV3Schema:
+ properties:
+ spec:
+ properties:
+ containerImages:
+ properties:
+ imagePullPolicy:
+ type: string
+ imagePullSecrets:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ busyBox:
+ properties:
+ registry:
+ type: string
+ tag:
+ type: string
+ type: object
+ gerritImages:
+ properties:
+ registry:
+ type: string
+ org:
+ type: string
+ tag:
+ type: string
+ type: object
+ type: object
+ storage:
+ properties:
+ pluginCache:
+ properties:
+ enabled:
+ type: boolean
+ type: object
+ storageClasses:
+ properties:
+ readWriteOnce:
+ type: string
+ readWriteMany:
+ type: string
+ nfsWorkaround:
+ properties:
+ enabled:
+ type: boolean
+ chownOnStartup:
+ type: boolean
+ idmapdConfig:
+ type: string
+ type: object
+ type: object
+ sharedStorage:
+ properties:
+ externalPVC:
+ properties:
+ enabled:
+ type: boolean
+ claimName:
+ type: string
+ type: object
+ size:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ volumeName:
+ type: string
+ selector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ type: object
+ type: object
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ status:
+ properties:
+ apiVersion:
+ type: string
+ code:
+ type: integer
+ details:
+ properties:
+ causes:
+ items:
+ properties:
+ field:
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ type: object
+ type: array
+ group:
+ type: string
+ kind:
+ type: string
+ name:
+ type: string
+ retryAfterSeconds:
+ type: integer
+ uid:
+ type: string
+ type: object
+ kind:
+ type: string
+ message:
+ type: string
+ metadata:
+ properties:
+ continue:
+ type: string
+ remainingItemCount:
+ type: integer
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ type: object
+ reason:
+ type: string
+ status:
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+ - name: v1beta8
+ schema:
+ openAPIV3Schema:
+ properties:
+ spec:
+ properties:
+ containerImages:
+ properties:
+ imagePullPolicy:
+ type: string
+ imagePullSecrets:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ busyBox:
+ properties:
+ registry:
+ type: string
+ tag:
+ type: string
+ type: object
+ gerritImages:
+ properties:
+ registry:
+ type: string
+ org:
+ type: string
+ tag:
+ type: string
+ type: object
+ type: object
+ storage:
+ properties:
+ pluginCache:
+ properties:
+ enabled:
+ type: boolean
+ type: object
+ storageClasses:
+ properties:
+ readWriteOnce:
+ type: string
+ readWriteMany:
+ type: string
+ nfsWorkaround:
+ properties:
+ enabled:
+ type: boolean
+ chownOnStartup:
+ type: boolean
+ idmapdConfig:
+ type: string
+ type: object
+ type: object
+ sharedStorage:
+ properties:
+ externalPVC:
+ properties:
+ enabled:
+ type: boolean
+ claimName:
+ type: string
+ type: object
+ size:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ volumeName:
+ type: string
+ selector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ type: object
+ type: object
+ schedule:
+ type: string
+ config:
+ properties:
+ remotes:
+ items:
+ properties:
+ name:
+ type: string
+ url:
+ type: string
+ timeout:
+ type: string
+ fetch:
+ items:
+ properties:
+ remoteRepo:
+ type: string
+ localRepo:
+ type: string
+ refSpec:
+ type: string
+ required:
+ - remoteRepo
+ type: object
+ type: array
+ required:
+ - name
+ - url
+ type: object
+ type: array
+ required:
+ - remotes
+ type: object
+ resources:
+ properties:
+ claims:
+ items:
+ properties:
+ name:
+ type: string
+ type: object
+ type: array
+ limits:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ requests:
+ additionalProperties:
+ anyOf:
+ - type: integer
+ - type: string
+ x-kubernetes-int-or-string: true
+ type: object
+ type: object
+ tolerations:
+ items:
+ properties:
+ effect:
+ type: string
+ key:
+ type: string
+ operator:
+ type: string
+ tolerationSeconds:
+ type: integer
+ value:
+ type: string
+ type: object
+ type: array
+ affinity:
+ properties:
+ nodeAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ preference:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ properties:
+ nodeSelectorTerms:
+ items:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchFields:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ type: object
+ type: array
+ type: object
+ type: object
+ podAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ podAntiAffinity:
+ properties:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ podAffinityTerm:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ weight:
+ type: integer
+ type: object
+ type: array
+ requiredDuringSchedulingIgnoredDuringExecution:
+ items:
+ properties:
+ labelSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaceSelector:
+ properties:
+ matchExpressions:
+ items:
+ properties:
+ key:
+ type: string
+ operator:
+ type: string
+ values:
+ items:
+ type: string
+ type: array
+ type: object
+ type: array
+ matchLabels:
+ additionalProperties:
+ type: string
+ type: object
+ type: object
+ namespaces:
+ items:
+ type: string
+ type: array
+ topologyKey:
+ type: string
+ type: object
+ type: array
+ type: object
+ type: object
+ secretRef:
+ type: string
+ required:
+ - schedule
+ - config
+ type: object
+ status:
+ properties:
+ apiVersion:
+ type: string
+ code:
+ type: integer
+ details:
+ properties:
+ causes:
+ items:
+ properties:
+ field:
+ type: string
+ message:
+ type: string
+ reason:
+ type: string
+ type: object
+ type: array
+ group:
+ type: string
+ kind:
+ type: string
+ name:
+ type: string
+ retryAfterSeconds:
+ type: integer
+ uid:
+ type: string
+ type: object
+ kind:
+ type: string
+ message:
+ type: string
+ metadata:
+ properties:
+ continue:
+ type: string
+ remainingItemCount:
+ type: integer
+ resourceVersion:
+ type: string
+ selfLink:
+ type: string
+ type: object
+ reason:
+ type: string
+ status:
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
diff --git a/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml
index bb2601e..864f018 100644
--- a/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml
@@ -13,7 +13,7 @@
singular: receiver
scope: Namespaced
versions:
- - name: v1beta6
+ - name: v1beta9
schema:
openAPIV3Schema:
properties:
@@ -653,7 +653,7 @@
storage: true
subresources:
status: {}
- - name: v1beta5
+ - name: v1beta8
schema:
openAPIV3Schema:
properties:
diff --git a/helm-charts/gerrit-operator/templates/rbac.yaml b/helm-charts/gerrit-operator/templates/rbac.yaml
index 8c890c4..0c4d91d 100644
--- a/helm-charts/gerrit-operator/templates/rbac.yaml
+++ b/helm-charts/gerrit-operator/templates/rbac.yaml
@@ -89,6 +89,7 @@
- "gateways"
- "virtualservices"
- "destinationrules"
+ - "serviceentries"
verbs:
- '*'
- apiGroups:
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/Constants.java b/operator/src/main/java/com/google/gerrit/k8s/operator/Constants.java
index 96d538e..f9dd36a 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/Constants.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/Constants.java
@@ -17,7 +17,14 @@
import com.google.inject.AbstractModule;
public class Constants extends AbstractModule {
- public static final String VERSION = "v1beta6";
+ public static final String VERSION = "v1beta9";
public static final String[] CUSTOM_RESOURCES =
- new String[] {"GerritCluster", "Gerrit", "Receiver", "GerritNetwork", "GitGarbageCollection"};
+ new String[] {
+ "GerritCluster",
+ "Gerrit",
+ "Receiver",
+ "GerritNetwork",
+ "GitGarbageCollection",
+ "IncomingReplicationTask"
+ };
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/Main.java b/operator/src/main/java/com/google/gerrit/k8s/operator/Main.java
index 8fc1428..4eab034 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/Main.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/Main.java
@@ -19,13 +19,18 @@
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
+import io.javaoperatorsdk.operator.OperatorException;
public class Main {
public static void main(String[] args) throws Exception {
- Injector injector = Guice.createInjector(Stage.PRODUCTION, new OperatorModule());
- injector.getInstance(HttpServer.class).start();
- injector.getInstance(ValidationWebhookConfigs.class).apply();
- injector.getInstance(GerritOperator.class).start();
+ try {
+ Injector injector = Guice.createInjector(Stage.PRODUCTION, new OperatorModule());
+ injector.getInstance(HttpServer.class).start();
+ injector.getInstance(ValidationWebhookConfigs.class).apply();
+ injector.getInstance(GerritOperator.class).start();
+ } catch (OperatorException e) {
+ System.exit(1);
+ }
}
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/OperatorModule.java b/operator/src/main/java/com/google/gerrit/k8s/operator/OperatorModule.java
index 3e61528..2c229fb 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/OperatorModule.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/OperatorModule.java
@@ -21,6 +21,7 @@
import com.google.gerrit.k8s.operator.network.GerritNetworkReconcilerProvider;
import com.google.gerrit.k8s.operator.receiver.ReceiverReconciler;
import com.google.gerrit.k8s.operator.server.ServerModule;
+import com.google.gerrit.k8s.operator.tasks.incomingrepl.IncomingReplicationTaskReconciler;
import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;
import io.fabric8.kubernetes.client.Config;
@@ -46,6 +47,7 @@
reconcilers.addBinding().to(GerritClusterReconciler.class);
reconcilers.addBinding().to(GerritReconciler.class);
reconcilers.addBinding().to(GitGarbageCollectionReconciler.class);
+ reconcilers.addBinding().to(IncomingReplicationTaskReconciler.class);
reconcilers.addBinding().to(ReceiverReconciler.class);
reconcilers.addBinding().toProvider(GerritNetworkReconcilerProvider.class);
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritCluster.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritCluster.java
index ec4adba..36c0fd9 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritCluster.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritCluster.java
@@ -142,20 +142,6 @@
}
@JsonIgnore
- public static VolumeMount getLogsVolumeMount() {
- return getLogsVolumeMount("/var/mnt/logs");
- }
-
- @JsonIgnore
- public static VolumeMount getLogsVolumeMount(String mountPath) {
- return new VolumeMountBuilder()
- .withName(SHARED_VOLUME_NAME)
- .withSubPathExpr("logs/$(POD_NAME)")
- .withMountPath(mountPath)
- .build();
- }
-
- @JsonIgnore
public static Volume getNfsImapdConfigVolume() {
return new VolumeBuilder()
.withName(NFS_IDMAPD_CONFIG_VOLUME_NAME)
@@ -193,7 +179,6 @@
ContainerImageConfig imageConfig,
List<VolumeMount> additionalVolumeMounts) {
List<VolumeMount> volumeMounts = new ArrayList<>();
- volumeMounts.add(getLogsVolumeMount());
volumeMounts.add(getGitRepositoriesVolumeMount());
volumeMounts.addAll(additionalVolumeMounts);
@@ -219,7 +204,6 @@
.withImage(imageConfig.getBusyBox().getBusyBoxImage())
.withCommand(List.of("sh", "-c"))
.withArgs(args.toString().trim())
- .withEnv(getPodNameEnvVar())
.withVolumeMounts(volumeMounts)
.build();
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritClusterSpec.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritClusterSpec.java
index 6dffd0b..3451fa0 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritClusterSpec.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/GerritClusterSpec.java
@@ -35,6 +35,7 @@
private List<GerritTemplate> gerrits = new ArrayList<>();
private ReceiverTemplate receiver;
private FluentBitSidecarConfig fluentBitSidecar = new FluentBitSidecarConfig();
+ private ScheduledTasks scheduledTasks = new ScheduledTasks();
public GerritStorageConfig getStorage() {
return storage;
@@ -100,10 +101,26 @@
this.fluentBitSidecar = fluentBitSidecar;
}
+ public ScheduledTasks getScheduledTasks() {
+ return scheduledTasks;
+ }
+
+ public void setScheduledTasks(ScheduledTasks scheduledTasks) {
+ this.scheduledTasks = scheduledTasks;
+ }
+
@Override
public int hashCode() {
return Objects.hash(
- containerImages, fluentBitSidecar, gerrits, ingress, receiver, refdb, serverId, storage);
+ containerImages,
+ fluentBitSidecar,
+ gerrits,
+ ingress,
+ receiver,
+ refdb,
+ scheduledTasks,
+ serverId,
+ storage);
}
@Override
@@ -118,6 +135,7 @@
&& Objects.equals(ingress, other.ingress)
&& Objects.equals(receiver, other.receiver)
&& Objects.equals(refdb, other.refdb)
+ && Objects.equals(scheduledTasks, other.scheduledTasks)
&& Objects.equals(serverId, other.serverId)
&& Objects.equals(storage, other.storage);
}
@@ -140,6 +158,8 @@
+ receiver
+ ", fluentBitSidecar="
+ fluentBitSidecar
+ + ", scheduledTasks="
+ + scheduledTasks
+ "]";
}
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/ScheduledTasks.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/ScheduledTasks.java
new file mode 100644
index 0000000..3651d32
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/cluster/ScheduledTasks.java
@@ -0,0 +1,51 @@
+// Copyright (C) 2024 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.api.model.cluster;
+
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTaskTemplate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class ScheduledTasks {
+ private List<IncomingReplicationTaskTemplate> incomingReplication = new ArrayList<>();
+
+ public List<IncomingReplicationTaskTemplate> getIncomingReplication() {
+ return incomingReplication;
+ }
+
+ public void setIncomingReplication(List<IncomingReplicationTaskTemplate> incomingReplTasks) {
+ this.incomingReplication = incomingReplTasks;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(incomingReplication);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ ScheduledTasks other = (ScheduledTasks) obj;
+ return Objects.equals(incomingReplication, other.incomingReplication);
+ }
+
+ @Override
+ public String toString() {
+ return "ScheduledTasks [incomingReplTasks=" + incomingReplication + "]";
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritModuleData.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritModuleData.java
index 94d7441..5f48c3a 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritModuleData.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritModuleData.java
@@ -18,6 +18,7 @@
public class GerritModuleData {
private String secretRef;
+ private boolean executable;
public String getSecretRef() {
return secretRef;
@@ -27,9 +28,17 @@
this.secretRef = secretRef;
}
+ public boolean isExecutable() {
+ return executable;
+ }
+
+ public void setExecutable(boolean executable) {
+ this.executable = executable;
+ }
+
@Override
public int hashCode() {
- return Objects.hash(secretRef);
+ return Objects.hash(executable, secretRef);
}
@Override
@@ -38,11 +47,11 @@
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
GerritModuleData other = (GerritModuleData) obj;
- return Objects.equals(secretRef, other.secretRef);
+ return executable == other.executable && Objects.equals(secretRef, other.secretRef);
}
@Override
public String toString() {
- return "GerritModuleData [secretRef=" + secretRef + "]";
+ return "GerritModuleData [secretRef=" + secretRef + ", executable=" + executable + "]";
}
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplate.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplate.java
index 0fb2212..a2abc4c 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplate.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplate.java
@@ -78,7 +78,9 @@
gerritSpec.setIngress(ingressConfig);
gerritSpec.setServerId(getServerId(gerritCluster));
gerritSpec.setFluentBitSidecar(gerritCluster.getSpec().getFluentBitSidecar());
- if (getSpec().isHighlyAvailablePrimary()) {
+
+ if (gerritCluster.getSpec().getGerrits().stream()
+ .anyMatch(g -> g.getSpec().getMode().equals(GerritMode.PRIMARY))) {
GlobalRefDbConfig refdb = gerritCluster.getSpec().getRefdb();
if (refdb.getZookeeper() != null && refdb.getZookeeper().getRootNode() == null) {
refdb
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplateSpec.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplateSpec.java
index de0bfaa..55fe3b6 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplateSpec.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/gerrit/GerritTemplateSpec.java
@@ -17,6 +17,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.gerrit.k8s.operator.api.model.shared.HttpSshServiceConfig;
import io.fabric8.kubernetes.api.model.Affinity;
+import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.ResourceRequirements;
import io.fabric8.kubernetes.api.model.Toleration;
import io.fabric8.kubernetes.api.model.TopologySpreadConstraint;
@@ -52,6 +53,7 @@
private List<GerritPlugin> plugins = List.of();
private List<GerritModule> libs = List.of();
private Map<String, String> configFiles = Map.of();
+ private List<EnvVar> envVars = List.of();
private String secretRef;
private GerritMode mode = GerritMode.PRIMARY;
@@ -83,6 +85,7 @@
this.plugins = templateSpec.plugins;
this.libs = templateSpec.libs;
this.configFiles = templateSpec.configFiles;
+ this.envVars = templateSpec.envVars;
this.secretRef = templateSpec.secretRef;
this.mode = templateSpec.mode;
@@ -236,6 +239,14 @@
this.configFiles = configFiles;
}
+ public List<EnvVar> getEnvVars() {
+ return envVars;
+ }
+
+ public void setEnvVars(List<EnvVar> envVars) {
+ this.envVars = envVars;
+ }
+
public String getSecretRef() {
return secretRef;
}
@@ -276,6 +287,7 @@
affinity,
configFiles,
debug,
+ envVars,
gracefulStopTimeout,
libs,
livenessProbe,
@@ -303,6 +315,7 @@
GerritTemplateSpec other = (GerritTemplateSpec) obj;
return Objects.equals(affinity, other.affinity)
&& Objects.equals(configFiles, other.configFiles)
+ && Objects.equals(envVars, other.envVars)
&& Objects.equals(debug, other.debug)
&& gracefulStopTimeout == other.gracefulStopTimeout
&& Objects.equals(libs, other.libs)
@@ -359,6 +372,8 @@
+ libs
+ ", configFiles="
+ configFiles
+ + ", envVars="
+ + envVars
+ ", secretRef="
+ secretRef
+ ", mode="
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/Fetch.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/Fetch.java
new file mode 100644
index 0000000..ef71847
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/Fetch.java
@@ -0,0 +1,75 @@
+// Copyright (C) 2024 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.api.model.tasks.incomingrepl;
+
+import io.fabric8.generator.annotation.Required;
+import java.util.Objects;
+
+public class Fetch {
+ @Required private String remoteRepo;
+ private String localRepo;
+ private String refSpec;
+
+ public String getRemoteRepo() {
+ return remoteRepo;
+ }
+
+ public void setRemoteRepo(String remoteRepo) {
+ this.remoteRepo = remoteRepo;
+ }
+
+ public String getLocalRepo() {
+ return localRepo;
+ }
+
+ public void setLocalRepo(String localRepo) {
+ this.localRepo = localRepo;
+ }
+
+ public String getRefSpec() {
+ return refSpec;
+ }
+
+ public void setRefSpec(String refSpec) {
+ this.refSpec = refSpec;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(localRepo, refSpec, remoteRepo);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ Fetch other = (Fetch) obj;
+ return Objects.equals(localRepo, other.localRepo)
+ && Objects.equals(refSpec, other.refSpec)
+ && Objects.equals(remoteRepo, other.remoteRepo);
+ }
+
+ @Override
+ public String toString() {
+ return "Fetch [remoteRepo="
+ + remoteRepo
+ + ", localRepo="
+ + localRepo
+ + ", refSpec="
+ + refSpec
+ + "]";
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationConfig.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationConfig.java
new file mode 100644
index 0000000..5328e8a
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationConfig.java
@@ -0,0 +1,51 @@
+// Copyright (C) 2024 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.api.model.tasks.incomingrepl;
+
+import io.fabric8.generator.annotation.Required;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class IncomingReplicationConfig {
+ @Required private List<Remote> remotes = new ArrayList<>();
+
+ public List<Remote> getRemotes() {
+ return remotes;
+ }
+
+ public void setRemotes(List<Remote> remotes) {
+ this.remotes = remotes;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(remotes);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ IncomingReplicationConfig other = (IncomingReplicationConfig) obj;
+ return Objects.equals(remotes, other.remotes);
+ }
+
+ @Override
+ public String toString() {
+ return "IncomingReplicationConfig [remotes=" + remotes + "]";
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTask.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTask.java
new file mode 100644
index 0000000..cf62009
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTask.java
@@ -0,0 +1,35 @@
+// Copyright (C) 2024 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.api.model.tasks.incomingrepl;
+
+import com.google.gerrit.k8s.operator.Constants;
+import io.fabric8.kubernetes.api.model.Namespaced;
+import io.fabric8.kubernetes.api.model.Status;
+import io.fabric8.kubernetes.client.CustomResource;
+import io.fabric8.kubernetes.model.annotation.Group;
+import io.fabric8.kubernetes.model.annotation.Version;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+@Group("gerritoperator.google.com")
+@Version(Constants.VERSION)
+public class IncomingReplicationTask extends CustomResource<IncomingReplicationTaskSpec, Status>
+ implements Namespaced {
+ private static final long serialVersionUID = 1L;
+
+ public String toString() {
+ return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskSpec.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskSpec.java
new file mode 100644
index 0000000..73a1774
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskSpec.java
@@ -0,0 +1,70 @@
+// Copyright (C) 2024 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.api.model.tasks.incomingrepl;
+
+import com.google.gerrit.k8s.operator.api.model.shared.ContainerImageConfig;
+import com.google.gerrit.k8s.operator.api.model.shared.GerritStorageConfig;
+import java.util.Objects;
+
+public class IncomingReplicationTaskSpec extends IncomingReplicationTaskTemplateSpec {
+ private ContainerImageConfig containerImages = new ContainerImageConfig();
+ private GerritStorageConfig storage = new GerritStorageConfig();
+
+ public IncomingReplicationTaskSpec() {}
+
+ public IncomingReplicationTaskSpec(IncomingReplicationTaskTemplateSpec templateSpec) {
+ super(templateSpec);
+ }
+
+ public ContainerImageConfig getContainerImages() {
+ return containerImages;
+ }
+
+ public void setContainerImages(ContainerImageConfig containerImages) {
+ this.containerImages = containerImages;
+ }
+
+ public GerritStorageConfig getStorage() {
+ return storage;
+ }
+
+ public void setStorage(GerritStorageConfig storage) {
+ this.storage = storage;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(containerImages, storage);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ IncomingReplicationTaskSpec other = (IncomingReplicationTaskSpec) obj;
+ return Objects.equals(containerImages, other.containerImages)
+ && Objects.equals(storage, other.storage);
+ }
+
+ @Override
+ public String toString() {
+ return "IncomingReplicationTaskSpec [containerImages="
+ + containerImages
+ + ", storage="
+ + storage
+ + "]";
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskTemplate.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskTemplate.java
new file mode 100644
index 0000000..81b499a
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskTemplate.java
@@ -0,0 +1,95 @@
+// Copyright (C) 2024 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.api.model.tasks.incomingrepl;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
+import io.fabric8.kubernetes.api.model.KubernetesResource;
+import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
+import java.util.Objects;
+
+@JsonDeserialize(using = com.fasterxml.jackson.databind.JsonDeserializer.None.class)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({"metadata", "spec"})
+public class IncomingReplicationTaskTemplate implements KubernetesResource {
+
+ private static final long serialVersionUID = 1L;
+
+ @JsonProperty("metadata")
+ private ObjectMeta metadata;
+
+ @JsonProperty("spec")
+ private IncomingReplicationTaskTemplateSpec spec;
+
+ public ObjectMeta getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(ObjectMeta metadata) {
+ this.metadata = metadata;
+ }
+
+ public IncomingReplicationTaskTemplateSpec getSpec() {
+ return spec;
+ }
+
+ public void setSpec(IncomingReplicationTaskTemplateSpec spec) {
+ this.spec = spec;
+ }
+
+ @JsonIgnore
+ public IncomingReplicationTask toIncomingReplicationTask(GerritCluster gerritCluster) {
+ IncomingReplicationTaskSpec incomingReplicationTaskSpec = new IncomingReplicationTaskSpec(spec);
+ incomingReplicationTaskSpec.setContainerImages(gerritCluster.getSpec().getContainerImages());
+ incomingReplicationTaskSpec.setStorage(gerritCluster.getSpec().getStorage());
+ IncomingReplicationTask incomingReplTask = new IncomingReplicationTask();
+ incomingReplTask.setSpec(incomingReplicationTaskSpec);
+ incomingReplTask.setMetadata(getIncomingReplicationTaskMetadata(gerritCluster));
+ return incomingReplTask;
+ }
+
+ @JsonIgnore
+ private ObjectMeta getIncomingReplicationTaskMetadata(GerritCluster gerritCluster) {
+ return new ObjectMetaBuilder()
+ .withName(getMetadata().getName())
+ .withLabels(getMetadata().getLabels())
+ .withNamespace(gerritCluster.getMetadata().getNamespace())
+ .build();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(metadata, spec);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ IncomingReplicationTaskTemplate other = (IncomingReplicationTaskTemplate) obj;
+ return Objects.equals(metadata, other.metadata) && Objects.equals(spec, other.spec);
+ }
+
+ @Override
+ public String toString() {
+ return "IncomingReplicationTaskTemplate [metadata=" + metadata + ", spec=" + spec + "]";
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskTemplateSpec.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskTemplateSpec.java
new file mode 100644
index 0000000..eda52dd
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/IncomingReplicationTaskTemplateSpec.java
@@ -0,0 +1,127 @@
+// Copyright (C) 2024 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.api.model.tasks.incomingrepl;
+
+import io.fabric8.generator.annotation.Required;
+import io.fabric8.kubernetes.api.model.Affinity;
+import io.fabric8.kubernetes.api.model.ResourceRequirements;
+import io.fabric8.kubernetes.api.model.Toleration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class IncomingReplicationTaskTemplateSpec {
+ @Required private String schedule;
+ @Required private IncomingReplicationConfig config;
+ private ResourceRequirements resources;
+ private List<Toleration> tolerations = new ArrayList<>();
+ private Affinity affinity;
+ private String secretRef;
+
+ public IncomingReplicationTaskTemplateSpec() {}
+
+ public IncomingReplicationTaskTemplateSpec(IncomingReplicationTaskTemplateSpec spec) {
+ this.schedule = spec.getSchedule();
+ this.config = spec.getConfig();
+ this.resources = spec.getResources();
+ this.tolerations = spec.getTolerations();
+ this.affinity = spec.getAffinity();
+ this.secretRef = spec.getSecretRef();
+ }
+
+ public String getSchedule() {
+ return schedule;
+ }
+
+ public void setSchedule(String schedule) {
+ this.schedule = schedule;
+ }
+
+ public IncomingReplicationConfig getConfig() {
+ return config;
+ }
+
+ public void setConfig(IncomingReplicationConfig config) {
+ this.config = config;
+ }
+
+ public ResourceRequirements getResources() {
+ return resources;
+ }
+
+ public void setResources(ResourceRequirements resources) {
+ this.resources = resources;
+ }
+
+ public List<Toleration> getTolerations() {
+ return tolerations;
+ }
+
+ public void setTolerations(List<Toleration> tolerations) {
+ this.tolerations = tolerations;
+ }
+
+ public Affinity getAffinity() {
+ return affinity;
+ }
+
+ public void setAffinity(Affinity affinity) {
+ this.affinity = affinity;
+ }
+
+ public String getSecretRef() {
+ return secretRef;
+ }
+
+ public void setSecretRef(String secretRef) {
+ this.secretRef = secretRef;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(affinity, config, resources, schedule, tolerations, secretRef);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ IncomingReplicationTaskTemplateSpec other = (IncomingReplicationTaskTemplateSpec) obj;
+ return Objects.equals(affinity, other.affinity)
+ && Objects.equals(config, other.config)
+ && Objects.equals(resources, other.resources)
+ && Objects.equals(schedule, other.schedule)
+ && Objects.equals(tolerations, other.tolerations)
+ && Objects.equals(secretRef, other.secretRef);
+ }
+
+ @Override
+ public String toString() {
+ return "IncomingReplicationTaskSpec [schedule="
+ + schedule
+ + ", remote="
+ + config
+ + ", resources="
+ + resources
+ + ", tolerations="
+ + tolerations
+ + ", affinity="
+ + affinity
+ + ", secretRef="
+ + secretRef
+ + "]";
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/Remote.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/Remote.java
new file mode 100644
index 0000000..a4f3dd9
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/tasks/incomingrepl/Remote.java
@@ -0,0 +1,81 @@
+// Copyright (C) 2024 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.api.model.tasks.incomingrepl;
+
+import io.fabric8.generator.annotation.Required;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class Remote {
+ @Required private String name;
+ @Required private String url;
+ private String timeout = "5m";
+ private List<Fetch> fetch = new ArrayList<>();
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(String timeout) {
+ this.timeout = timeout;
+ }
+
+ public List<Fetch> getFetch() {
+ return fetch;
+ }
+
+ public void setFetch(List<Fetch> fetch) {
+ this.fetch = fetch;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(fetch, name, timeout, url);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ Remote other = (Remote) obj;
+ return Objects.equals(fetch, other.fetch)
+ && Objects.equals(name, other.name)
+ && Objects.equals(timeout, other.timeout)
+ && Objects.equals(url, other.url);
+ }
+
+ @Override
+ public String toString() {
+ return "Remote [name=" + name + ", url=" + url + ", time=" + timeout + ", fetch=" + fetch + "]";
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java
index 5ea9e66..587c53f 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java
@@ -16,6 +16,7 @@
import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_GERRIT_EVENT_SOURCE;
import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE;
+import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE;
import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_RECEIVER_EVENT_SOURCE;
import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CM_EVENT_SOURCE;
import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.PVC_EVENT_SOURCE;
@@ -27,10 +28,12 @@
import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
import com.google.gerrit.k8s.operator.api.model.receiver.Receiver;
import com.google.gerrit.k8s.operator.api.model.receiver.ReceiverTemplate;
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask;
import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerrit;
import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritCondition;
import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritNetwork;
import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritNetworkCondition;
+import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedIncomingReplicationTask;
import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedReceiver;
import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedReceiverCondition;
import com.google.gerrit.k8s.operator.cluster.dependent.NfsIdmapdConfigMap;
@@ -81,6 +84,9 @@
type = ClusterManagedGerritNetwork.class,
reconcilePrecondition = ClusterManagedGerritNetworkCondition.class,
useEventSourceWithName = CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE),
+ @Dependent(
+ type = ClusterManagedIncomingReplicationTask.class,
+ useEventSourceWithName = CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE),
})
public class GerritClusterReconciler
implements Reconciler<GerritCluster>, EventSourceInitializer<GerritCluster> {
@@ -90,6 +96,8 @@
public static final String CLUSTER_MANAGED_RECEIVER_EVENT_SOURCE = "cluster-managed-receiver";
public static final String CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE =
"cluster-managed-gerrit-network";
+ public static final String CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE =
+ "cluster-managed-incoming-repl-task";
@Override
public Map<String, EventSource> prepareEventSources(EventSourceContext<GerritCluster> context) {
@@ -113,6 +121,12 @@
new InformerEventSource<>(
InformerConfiguration.from(GerritNetwork.class, context).build(), context);
+ InformerEventSource<IncomingReplicationTask, GerritCluster>
+ clusterManagedIncomingReplTaskEventSource =
+ new InformerEventSource<>(
+ InformerConfiguration.from(IncomingReplicationTask.class, context).build(),
+ context);
+
Map<String, EventSource> eventSources = new HashMap<>();
eventSources.put(CM_EVENT_SOURCE, cmEventSource);
eventSources.put(PVC_EVENT_SOURCE, pvcEventSource);
@@ -120,6 +134,8 @@
eventSources.put(CLUSTER_MANAGED_RECEIVER_EVENT_SOURCE, clusterManagedReceiverEventSource);
eventSources.put(
CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE, clusterManagedGerritNetworkEventSource);
+ eventSources.put(
+ CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE, clusterManagedIncomingReplTaskEventSource);
return eventSources;
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerrit.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerrit.java
index d7d871c..7603c30 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerrit.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerrit.java
@@ -17,7 +17,7 @@
import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
import com.google.gerrit.k8s.operator.api.model.gerrit.GerritTemplate;
-import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import com.google.gerrit.k8s.operator.util.KubernetesDependentCustomResource;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource;
@@ -25,8 +25,7 @@
import java.util.Map;
import java.util.Set;
-public class ClusterManagedGerrit
- extends CRUDReconcileAddKubernetesDependentResource<Gerrit, GerritCluster>
+public class ClusterManagedGerrit extends KubernetesDependentCustomResource<Gerrit, GerritCluster>
implements Deleter<GerritCluster>, BulkDependentResource<Gerrit, GerritCluster> {
public ClusterManagedGerrit() {
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerritNetwork.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerritNetwork.java
index aa3a228..d6c1e5c 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerritNetwork.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedGerritNetwork.java
@@ -22,7 +22,7 @@
import com.google.gerrit.k8s.operator.api.model.network.NetworkMember;
import com.google.gerrit.k8s.operator.api.model.network.NetworkMemberWithSsh;
import com.google.gerrit.k8s.operator.api.model.receiver.ReceiverTemplate;
-import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import com.google.gerrit.k8s.operator.util.KubernetesDependentCustomResource;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
@@ -30,7 +30,7 @@
@KubernetesDependent
public class ClusterManagedGerritNetwork
- extends CRUDReconcileAddKubernetesDependentResource<GerritNetwork, GerritCluster> {
+ extends KubernetesDependentCustomResource<GerritNetwork, GerritCluster> {
public static final String NAME_SUFFIX = "gerrit-network";
public ClusterManagedGerritNetwork() {
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedIncomingReplicationTask.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedIncomingReplicationTask.java
new file mode 100644
index 0000000..a822a36
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedIncomingReplicationTask.java
@@ -0,0 +1,63 @@
+// Copyright (C) 2023 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.dependent;
+
+import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask;
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTaskTemplate;
+import com.google.gerrit.k8s.operator.util.KubernetesDependentCustomResource;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
+import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+@KubernetesDependent
+public class ClusterManagedIncomingReplicationTask
+ extends KubernetesDependentCustomResource<IncomingReplicationTask, GerritCluster>
+ implements Deleter<GerritCluster>,
+ BulkDependentResource<IncomingReplicationTask, GerritCluster> {
+
+ public ClusterManagedIncomingReplicationTask() {
+ super(IncomingReplicationTask.class);
+ }
+
+ @Override
+ public Map<String, IncomingReplicationTask> desiredResources(
+ GerritCluster primary, Context<GerritCluster> context) {
+ Map<String, IncomingReplicationTask> incomingReplTasks = new HashMap<>();
+ for (IncomingReplicationTaskTemplate incomingReplTaskTemplate :
+ primary.getSpec().getScheduledTasks().getIncomingReplication()) {
+ IncomingReplicationTask incomingReplTask =
+ incomingReplTaskTemplate.toIncomingReplicationTask(primary);
+ incomingReplTasks.put(incomingReplTask.getMetadata().getName(), incomingReplTask);
+ }
+ return incomingReplTasks;
+ }
+
+ @Override
+ public Map<String, IncomingReplicationTask> getSecondaryResources(
+ GerritCluster primary, Context<GerritCluster> context) {
+ Set<IncomingReplicationTask> incomingReplTasks =
+ context.getSecondaryResources(IncomingReplicationTask.class);
+ Map<String, IncomingReplicationTask> result = new HashMap<>(incomingReplTasks.size());
+ for (IncomingReplicationTask incomingReplTask : incomingReplTasks) {
+ result.put(incomingReplTask.getMetadata().getName(), incomingReplTask);
+ }
+ return result;
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedReceiver.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedReceiver.java
index 14e7e87..33e533d 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedReceiver.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/ClusterManagedReceiver.java
@@ -16,11 +16,11 @@
import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
import com.google.gerrit.k8s.operator.api.model.receiver.Receiver;
-import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import com.google.gerrit.k8s.operator.util.KubernetesDependentCustomResource;
import io.javaoperatorsdk.operator.api.reconciler.Context;
public class ClusterManagedReceiver
- extends CRUDReconcileAddKubernetesDependentResource<Receiver, GerritCluster> {
+ extends KubernetesDependentCustomResource<Receiver, GerritCluster> {
public ClusterManagedReceiver() {
super(Receiver.class);
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/FluentBitConfigMap.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/FluentBitConfigMap.java
deleted file mode 100644
index 4e4757f..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/FluentBitConfigMap.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2024 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.dependent;
-
-import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
-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.Map;
-
-@KubernetesDependent(resourceDiscriminator = FluentBitConfigMapDiscriminator.class)
-public class FluentBitConfigMap extends CRUDKubernetesDependentResource<ConfigMap, Gerrit> {
-
- public FluentBitConfigMap() {
- super(ConfigMap.class);
- }
-
- public static String getName(Gerrit gerrit) {
- return String.format("%s-fluentbit-configmap", gerrit.getMetadata().getName());
- }
-
- @Override
- protected ConfigMap desired(Gerrit gerrit, Context<Gerrit> context) {
- String customConfig = gerrit.getSpec().getFluentBitSidecar().getConfig();
- String config =
- """
- [SERVICE]
- Parsers_file parsers-multiline.conf
- [INPUT]
- Name tail
- Path /var/mnt/logs/*log
- Tag <log_name>
- Tag_Regex ^\\/var\\/mnt\\/logs\\/(?<log_name>[^*]+)
- Multiline.parser gerrit-multiline
- Buffer_Chunk_Size 10M
- Buffer_Max_Size 10M\n
- """
- + customConfig;
- String multilineParser =
- """
- [MULTILINE_PARSER]
- Name gerrit-multiline
- Type regex
- Flush_timeout 1000
- Rule "start_state" "/\\[\\d{4}-\\d{2}-\\d{2}(.*?)\\](.*)/" "cont"
- Rule "cont" "^(?!\\[)(.*)" "cont"
- """;
-
- return new ConfigMapBuilder()
- .withApiVersion("v1")
- .withNewMetadata()
- .withName(getName(gerrit))
- .withNamespace(gerrit.getMetadata().getNamespace())
- .withLabels(
- GerritCluster.getLabels(
- gerrit.getMetadata().getName(), getName(gerrit), this.getClass().getSimpleName()))
- .endMetadata()
- .withData(
- Map.ofEntries(
- Map.entry("fluent-bit.conf", config),
- Map.entry("parsers-multiline.conf", multilineParser)))
- .build();
- }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java
index 1ba060e..b5ad4b6 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java
@@ -19,7 +19,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
import com.google.gerrit.k8s.operator.api.model.gerrit.GerritStatus;
-import com.google.gerrit.k8s.operator.cluster.dependent.FluentBitConfigMap;
+import com.google.gerrit.k8s.operator.gerrit.dependent.FluentBitConfigMap;
import com.google.gerrit.k8s.operator.gerrit.dependent.GerritConfigMap;
import com.google.gerrit.k8s.operator.gerrit.dependent.GerritInitConfigMap;
import com.google.gerrit.k8s.operator.gerrit.dependent.GerritService;
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/config/GerritConfigBuilder.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/config/GerritConfigBuilder.java
index 2753ef9..0ad04e2 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/config/GerritConfigBuilder.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/config/GerritConfigBuilder.java
@@ -20,6 +20,7 @@
import com.google.common.collect.ImmutableList;
import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
import com.google.gerrit.k8s.operator.api.model.gerrit.GerritTemplateSpec.GerritMode;
+import com.google.gerrit.k8s.operator.api.model.shared.GlobalRefDbConfig.RefDatabase;
import com.google.gerrit.k8s.operator.api.model.shared.IngressConfig;
import java.util.ArrayList;
import java.util.HashSet;
@@ -73,12 +74,16 @@
requiredOptions.add(new RequiredOption<String>("gerrit", "serverId", serverId));
}
- if (gerrit.getSpec().isHighlyAvailablePrimary()) {
+ if ((!gerrit.getSpec().getRefdb().getDatabase().equals(RefDatabase.NONE)
+ && gerrit.getSpec().getMode().equals(GerritMode.PRIMARY))
+ || gerrit.getSpec().isHighlyAvailablePrimary()) {
requiredOptions.add(
new RequiredOption<Set<String>>(
"gerrit",
"installModule",
Set.of("com.gerritforge.gerrit.globalrefdb.validation.LibModule")));
+ }
+ if (gerrit.getSpec().isHighlyAvailablePrimary()) {
requiredOptions.add(
new RequiredOption<Set<String>>(
"gerrit",
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMap.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMap.java
new file mode 100644
index 0000000..8544688
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMap.java
@@ -0,0 +1,122 @@
+// Copyright (C) 2024 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.gerrit.dependent;
+
+import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
+import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
+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.Map;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
+
+@KubernetesDependent(resourceDiscriminator = FluentBitConfigMapDiscriminator.class)
+public class FluentBitConfigMap extends CRUDKubernetesDependentResource<ConfigMap, Gerrit> {
+ private static final String FLUENT_BIT_SERVICE_CONFIG =
+ """
+ [SERVICE]
+ Parsers_file parsers.conf
+ Storage.path /var/mnt/logs/flb-storage/
+ """;
+ private static final String FLUENT_BIT_TEXT_LOG_INPUT =
+ """
+ [INPUT]
+ Name tail
+ Storage.type filesystem
+ Path /var/mnt/logs/*_log
+ Tag <log_name>
+ Tag_Regex ^\\/var\\/mnt\\/logs\\/(?<log_name>[^*]+)
+ Multiline.parser gerrit-multiline
+ Buffer_Chunk_Size 10M
+ Buffer_Max_Size 10M\n
+ """;
+ private static final String FLUENT_BIT_JSON_LOG_INPUT =
+ """
+ [INPUT]
+ Name tail
+ Storage.type filesystem
+ Path /var/mnt/logs/*_log.json
+ Tag <log_name>
+ Tag_Regex ^\\/var\\/mnt\\/logs\\/(?<log_name>.+)
+ Parser jsonLog
+ Buffer_Chunk_Size 10M
+ Buffer_Max_Size 10M\n
+ """;
+ private static final String MULTILINE_PARSER_CONFIG =
+ """
+ [MULTILINE_PARSER]
+ Name gerrit-multiline
+ Type regex
+ Flush_timeout 1000
+ Rule "start_state" "/\\[\\d{4}-\\d{2}-\\d{2}(.*?)\\](.*)/" "cont"
+ Rule "cont" "^(?!\\[)(.*)" "cont"
+ """;
+ private static final String JSON_PARSER_CONFIG =
+ """
+ [PARSER]
+ Name jsonLog
+ Format json
+ """;
+
+ public FluentBitConfigMap() {
+ super(ConfigMap.class);
+ }
+
+ public static String getName(Gerrit gerrit) {
+ return String.format("%s-fluentbit-configmap", gerrit.getMetadata().getName());
+ }
+
+ @Override
+ protected ConfigMap desired(Gerrit gerrit, Context<Gerrit> context) {
+ String customConfig = gerrit.getSpec().getFluentBitSidecar().getConfig();
+
+ Config gerritConfig = new Config();
+ try {
+ gerritConfig.fromText(gerrit.getSpec().getConfigFiles().get("gerrit.config"));
+ } catch (ConfigInvalidException e) {
+ throw new IllegalStateException("Failed to parse gerrit.config.", e);
+ }
+
+ String config = FLUENT_BIT_SERVICE_CONFIG;
+ String parserConfig = "";
+ if (gerritConfig.getBoolean("log", "textLogging", true)) {
+ config = config + FLUENT_BIT_TEXT_LOG_INPUT;
+ parserConfig = parserConfig + MULTILINE_PARSER_CONFIG;
+ }
+
+ if (gerritConfig.getBoolean("log", "jsonLogging", false)) {
+ config = config + FLUENT_BIT_JSON_LOG_INPUT;
+ parserConfig = parserConfig + JSON_PARSER_CONFIG;
+ }
+ config = config + customConfig;
+
+ return new ConfigMapBuilder()
+ .withApiVersion("v1")
+ .withNewMetadata()
+ .withName(getName(gerrit))
+ .withNamespace(gerrit.getMetadata().getNamespace())
+ .withLabels(
+ GerritCluster.getLabels(
+ gerrit.getMetadata().getName(), getName(gerrit), this.getClass().getSimpleName()))
+ .endMetadata()
+ .withData(
+ Map.ofEntries(
+ Map.entry("fluent-bit.conf", config), Map.entry("parsers.conf", parserConfig)))
+ .build();
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/FluentBitConfigMapDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMapDiscriminator.java
similarity index 96%
rename from operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/FluentBitConfigMapDiscriminator.java
rename to operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMapDiscriminator.java
index 0c2684b..88e8255 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/FluentBitConfigMapDiscriminator.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMapDiscriminator.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.k8s.operator.cluster.dependent;
+package com.google.gerrit.k8s.operator.gerrit.dependent;
import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
import io.fabric8.kubernetes.api.model.ConfigMap;
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java
index b4a8859..c0204d3 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java
@@ -58,7 +58,7 @@
}
public static String getName(Gerrit gerrit) {
- return gerrit.getMetadata().getName();
+ return getName(gerrit.getMetadata().getName());
}
public static String getName(String gerritName) {
@@ -66,11 +66,11 @@
}
public static String getName(GerritTemplate gerrit) {
- return gerrit.getMetadata().getName();
+ return getName(gerrit.getMetadata().getName());
}
public static String getHostname(Gerrit gerrit) {
- return getHostname(gerrit.getMetadata().getName(), gerrit.getMetadata().getNamespace());
+ return getHostname(getName(gerrit), gerrit.getMetadata().getNamespace());
}
public static String getHostname(String name, String namespace) {
@@ -82,12 +82,16 @@
"http://%s:%s", getHostname(gerrit), gerrit.getSpec().getService().getHttpPort());
}
- public static Map<String, String> getLabels(Gerrit gerrit) {
+ public Map<String, String> getLabels(Gerrit gerrit) {
return GerritCluster.getLabels(
- gerrit.getMetadata().getName(), "gerrit-service", GerritReconciler.class.getSimpleName());
+ gerrit.getMetadata().getName(), getComponentName(), GerritReconciler.class.getSimpleName());
}
- private static List<ServicePort> getServicePorts(Gerrit gerrit) {
+ protected String getComponentName() {
+ return "gerrit-service";
+ }
+
+ protected static List<ServicePort> getServicePorts(Gerrit gerrit) {
List<ServicePort> ports = new ArrayList<>();
ports.add(
new ServicePortBuilder()
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritStatefulSet.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritStatefulSet.java
index 6cc91b1..5e86085 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritStatefulSet.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritStatefulSet.java
@@ -21,7 +21,6 @@
import com.google.gerrit.k8s.operator.api.model.gerrit.GerritModuleData;
import com.google.gerrit.k8s.operator.api.model.shared.ContainerImageConfig;
import com.google.gerrit.k8s.operator.api.model.shared.NfsWorkaroundConfig;
-import com.google.gerrit.k8s.operator.cluster.dependent.FluentBitConfigMap;
import com.google.gerrit.k8s.operator.gerrit.GerritReconciler;
import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
import io.fabric8.kubernetes.api.model.Container;
@@ -122,7 +121,7 @@
stsBuilder
.withApiVersion("apps/v1")
.withNewMetadata()
- .withName(gerrit.getMetadata().getName())
+ .withName(getName(gerrit))
.withNamespace(gerrit.getMetadata().getNamespace())
.withLabels(getLabels(gerrit))
.endMetadata()
@@ -172,7 +171,7 @@
.withNewPreStop()
.withNewExec()
.withCommand(
- "/bin/ash/", "-c", "kill -2 $(pidof java) && tail --pid=$(pidof java) -f /dev/null")
+ "/bin/ash", "-c", "kill -2 $(pidof java) && tail --pid=$(pidof java) -f /dev/null")
.endExec()
.endPreStop()
.endLifecycle()
@@ -206,6 +205,14 @@
return stsBuilder.build();
}
+ public static String getName(Gerrit gerrit) {
+ return getName(gerrit.getMetadata().getName());
+ }
+
+ public static String getName(String gerritName) {
+ return gerritName;
+ }
+
private static String getComponentName(String gerritName) {
return String.format("gerrit-statefulset-%s", gerritName);
}
@@ -265,6 +272,7 @@
.withName(md.getSecretRef())
.withNewSecret()
.withSecretName(md.getSecretRef())
+ .withDefaultMode(md.isExecutable() ? 0754 : 0644)
.endSecret()
.build());
}
@@ -296,7 +304,6 @@
volumeMounts.add(GerritCluster.getHAShareVolumeMount());
}
volumeMounts.add(GerritCluster.getGitRepositoriesVolumeMount());
- volumeMounts.add(GerritCluster.getLogsVolumeMount());
volumeMounts.add(
new VolumeMountBuilder()
.withName("gerrit-config")
@@ -351,7 +358,12 @@
.withMountPath("/fluent-bit/etc/")
.build());
- volumeMounts.add(GerritCluster.getLogsVolumeMount());
+ volumeMounts.add(
+ new VolumeMountBuilder()
+ .withName(SITE_VOLUME_NAME)
+ .withSubPath("logs")
+ .withMountPath("/var/mnt/logs")
+ .build());
return volumeMounts;
}
@@ -378,6 +390,8 @@
private List<EnvVar> getEnvVars(Gerrit gerrit) {
List<EnvVar> envVars = new ArrayList<>();
envVars.add(GerritCluster.getPodNameEnvVar());
+ envVars.addAll(gerrit.getSpec().getEnvVars());
+
if (gerrit.getSpec().isHighlyAvailablePrimary()) {
envVars.add(
new EnvVarBuilder()
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionCronJob.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionCronJob.java
index fc1bddb..24364d7 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionCronJob.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionCronJob.java
@@ -122,7 +122,6 @@
private Container buildGitGcContainer(GitGarbageCollection gitGc, GerritCluster gerritCluster) {
List<VolumeMount> volumeMounts = new ArrayList<>();
volumeMounts.add(GerritCluster.getGitRepositoriesVolumeMount("/var/gerrit/git"));
- volumeMounts.add(GerritCluster.getLogsVolumeMount("/var/log/git"));
if (gerritCluster.getSpec().getStorage().getStorageClasses().getNfsWorkaround().isEnabled()
&& gerritCluster
@@ -146,7 +145,6 @@
.getGerritImages()
.getFullImageName("git-gc"))
.withResources(gitGc.getSpec().getResources())
- .withEnv(GerritCluster.getPodNameEnvVar())
.withVolumeMounts(volumeMounts);
ArrayList<String> args = new ArrayList<>();
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java
index 3bd1e61..b67760a 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java
@@ -35,6 +35,7 @@
import com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterMappingReceiverGET;
import com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterTLSContext;
import com.google.gerrit.k8s.operator.network.ambassador.dependent.LoadBalanceCondition;
+import com.google.gerrit.k8s.operator.network.ambassador.dependent.ReceiverGETMappingCondition;
import com.google.gerrit.k8s.operator.network.ambassador.dependent.ReceiverMappingCondition;
import com.google.gerrit.k8s.operator.network.ambassador.dependent.SingleMappingCondition;
import com.google.gerrit.k8s.operator.network.ambassador.dependent.TLSContextCondition;
@@ -132,7 +133,7 @@
@Dependent(
name = GERRIT_MAPPING_RECEIVER_GET,
type = GerritClusterMappingReceiverGET.class,
- reconcilePrecondition = ReceiverMappingCondition.class,
+ reconcilePrecondition = ReceiverGETMappingCondition.class,
useEventSourceWithName = MAPPING_EVENT_SOURCE),
@Dependent(
name = GERRIT_TLS_CONTEXT,
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java
index e32ef23..ac56422 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java
@@ -49,10 +49,17 @@
gerritNetwork, GERRIT_MAPPING_RECEIVER, this.getClass().getSimpleName()))
.endMetadata()
.withNewSpecLike(getCommonSpec(gerritNetwork, receiverServiceName))
- .withPrefix(PROJECTS_URL_PATTERN + "|" + RECEIVE_PACK_URL_PATTERN)
- .withPrefixRegex(true)
+ .withPrefix(getPrefix(gerritNetwork))
+ .withPrefixRegex(gerritNetwork.hasGerritReplica())
.endSpec()
.build();
return mapping;
}
+
+ private String getPrefix(GerritNetwork gerritNetwork) {
+ if (gerritNetwork.hasGerritReplica()) {
+ return PROJECTS_URL_PATTERN + "|" + RECEIVE_PACK_URL_PATTERN;
+ }
+ return "/";
+ }
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioCondition.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/ReceiverGETMappingCondition.java
similarity index 70%
rename from operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioCondition.java
rename to operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/ReceiverGETMappingCondition.java
index 95fe2f0..13aada0 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioCondition.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/ReceiverGETMappingCondition.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 The Android Open Source Project
+// Copyright (C) 2024 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.
@@ -12,23 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.k8s.operator.network.istio.dependent;
+package com.google.gerrit.k8s.operator.network.ambassador.dependent;
import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.fabric8.istio.api.networking.v1beta1.VirtualService;
+import io.getambassador.v2.Mapping;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
-public class GerritIstioCondition implements Condition<VirtualService, GerritNetwork> {
+public class ReceiverGETMappingCondition implements Condition<Mapping, GerritNetwork> {
@Override
public boolean isMet(
- DependentResource<VirtualService, GerritNetwork> dependentResource,
+ DependentResource<Mapping, GerritNetwork> dependentResource,
GerritNetwork gerritNetwork,
Context<GerritNetwork> context) {
return gerritNetwork.getSpec().getIngress().isEnabled()
- && (gerritNetwork.hasGerrits() || gerritNetwork.hasReceiver());
+ && gerritNetwork.hasGerritReplica()
+ && gerritNetwork.hasReceiver();
}
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngress.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngress.java
index 0201eea..bed92db 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngress.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngress.java
@@ -14,7 +14,6 @@
package com.google.gerrit.k8s.operator.network.ingress.dependent;
-import static com.google.gerrit.k8s.operator.api.model.network.GerritNetwork.SESSION_COOKIE_NAME;
import static com.google.gerrit.k8s.operator.network.Constants.GERRIT_FORBIDDEN_URL_PATTERN;
import static com.google.gerrit.k8s.operator.network.Constants.PROJECTS_URL_PATTERN;
import static com.google.gerrit.k8s.operator.network.Constants.RECEIVE_PACK_URL_PATTERN;
@@ -38,6 +37,7 @@
import io.fabric8.kubernetes.api.model.networking.v1.ServiceBackendPortBuilder;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -47,6 +47,8 @@
public class GerritClusterIngress
extends CRUDReconcileAddKubernetesDependentResource<Ingress, GerritNetwork> {
public static final String INGRESS_NAME = "gerrit-ingress";
+ public static final String SESSION_COOKIE_NAME = "Gerrit_Session";
+ public static final Duration SESSION_COOKIE_TTL = Duration.ofSeconds(3600L);
public GerritClusterIngress() {
super(Ingress.class);
@@ -100,7 +102,7 @@
gerritNetwork.getMetadata().getNamespace(),
svcName);
}
- if (gerritNetwork.hasReceiver()) {
+ if (gerritNetwork.hasReceiver() && gerritNetwork.hasGerritReplica()) {
String svcName = ReceiverService.getName(gerritNetwork.getSpec().getReceiver().getName());
configSnippet =
createNginxConfigSnippetGerritReplicaRouting(
@@ -117,8 +119,12 @@
annotations.put("nginx.ingress.kubernetes.io/affinity", "cookie");
annotations.put("nginx.ingress.kubernetes.io/session-cookie-name", SESSION_COOKIE_NAME);
annotations.put("nginx.ingress.kubernetes.io/session-cookie-path", "/");
- annotations.put("nginx.ingress.kubernetes.io/session-cookie-max-age", "60");
- annotations.put("nginx.ingress.kubernetes.io/session-cookie-expires", "60");
+ annotations.put(
+ "nginx.ingress.kubernetes.io/session-cookie-max-age",
+ String.valueOf(SESSION_COOKIE_TTL.getSeconds()));
+ annotations.put(
+ "nginx.ingress.kubernetes.io/session-cookie-expires",
+ String.valueOf(SESSION_COOKIE_TTL.getSeconds()));
return annotations;
}
@@ -253,18 +259,22 @@
ServiceBackendPort port =
new ServiceBackendPortBuilder().withName(ReceiverService.HTTP_PORT_NAME).build();
- for (String path : List.of(PROJECTS_URL_PATTERN, RECEIVE_PACK_URL_PATTERN)) {
- paths.add(
- new HTTPIngressPathBuilder()
- .withPathType("Prefix")
- .withPath(path)
- .withNewBackend()
- .withNewService()
- .withName(svcName)
- .withPort(port)
- .endService()
- .endBackend()
- .build());
+ HTTPIngressPathBuilder builder =
+ new HTTPIngressPathBuilder()
+ .withPathType("Prefix")
+ .withNewBackend()
+ .withNewService()
+ .withName(svcName)
+ .withPort(port)
+ .endService()
+ .endBackend();
+
+ if (gerritNetwork.hasGerritReplica()) {
+ for (String path : List.of(PROJECTS_URL_PATTERN, RECEIVE_PACK_URL_PATTERN)) {
+ paths.add(builder.withPath(path).build());
+ }
+ } else {
+ paths.add(builder.withPath("/").build());
}
return paths;
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java
index fb1c65c..9d0a509 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java
@@ -15,16 +15,18 @@
package com.google.gerrit.k8s.operator.network.istio;
import static com.google.gerrit.k8s.operator.network.istio.GerritIstioReconciler.ISTIO_DESTINATION_RULE_EVENT_SOURCE;
+import static com.google.gerrit.k8s.operator.network.istio.GerritIstioReconciler.ISTIO_SERVICE_ENTRIES_EVENT_SOURCE;
import static com.google.gerrit.k8s.operator.network.istio.GerritIstioReconciler.ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE;
import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
import com.google.gerrit.k8s.operator.network.GerritClusterIngressCondition;
import com.google.gerrit.k8s.operator.network.istio.dependent.GerritClusterIstioGateway;
-import com.google.gerrit.k8s.operator.network.istio.dependent.GerritIstioCondition;
import com.google.gerrit.k8s.operator.network.istio.dependent.GerritIstioDestinationRule;
+import com.google.gerrit.k8s.operator.network.istio.dependent.GerritIstioServiceEntries;
import com.google.gerrit.k8s.operator.network.istio.dependent.GerritIstioVirtualService;
import com.google.inject.Singleton;
import io.fabric8.istio.api.networking.v1beta1.DestinationRule;
+import io.fabric8.istio.api.networking.v1beta1.ServiceEntry;
import io.fabric8.istio.api.networking.v1beta1.VirtualService;
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Context;
@@ -45,16 +47,21 @@
@Dependent(
name = "gerrit-destination-rules",
type = GerritIstioDestinationRule.class,
- reconcilePrecondition = GerritIstioCondition.class,
+ reconcilePrecondition = GerritClusterIngressCondition.class,
useEventSourceWithName = ISTIO_DESTINATION_RULE_EVENT_SOURCE),
@Dependent(
+ name = "gerrit-service-entries",
+ type = GerritIstioServiceEntries.class,
+ reconcilePrecondition = GerritClusterIngressCondition.class,
+ useEventSourceWithName = ISTIO_SERVICE_ENTRIES_EVENT_SOURCE),
+ @Dependent(
name = "gerrit-istio-gateway",
type = GerritClusterIstioGateway.class,
reconcilePrecondition = GerritClusterIngressCondition.class),
@Dependent(
name = "gerrit-istio-virtual-service",
type = GerritIstioVirtualService.class,
- reconcilePrecondition = GerritIstioCondition.class,
+ reconcilePrecondition = GerritClusterIngressCondition.class,
dependsOn = {"gerrit-istio-gateway"},
useEventSourceWithName = ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE)
})
@@ -62,6 +69,8 @@
implements Reconciler<GerritNetwork>, EventSourceInitializer<GerritNetwork> {
public static final String ISTIO_DESTINATION_RULE_EVENT_SOURCE =
"gerrit-cluster-istio-destination-rule";
+ public static final String ISTIO_SERVICE_ENTRIES_EVENT_SOURCE =
+ "gerrit-cluster-istio-service-entries";
public static final String ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE =
"gerrit-cluster-istio-virtual-service";
@@ -71,12 +80,17 @@
new InformerEventSource<>(
InformerConfiguration.from(DestinationRule.class, context).build(), context);
+ InformerEventSource<ServiceEntry, GerritNetwork> gerritIstioServiceEntriesEventSource =
+ new InformerEventSource<>(
+ InformerConfiguration.from(ServiceEntry.class, context).build(), context);
+
InformerEventSource<VirtualService, GerritNetwork> virtualServiceEventSource =
new InformerEventSource<>(
InformerConfiguration.from(VirtualService.class, context).build(), context);
Map<String, EventSource> eventSources = new HashMap<>();
eventSources.put(ISTIO_DESTINATION_RULE_EVENT_SOURCE, gerritIstioDestinationRuleEventSource);
+ eventSources.put(ISTIO_SERVICE_ENTRIES_EVENT_SOURCE, gerritIstioServiceEntriesEventSource);
eventSources.put(ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE, virtualServiceEventSource);
return eventSources;
}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioAndPrimaryGerritCondition.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioAndPrimaryGerritCondition.java
deleted file mode 100644
index 0960fdf..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioAndPrimaryGerritCondition.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2023 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.network.istio.dependent;
-
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.fabric8.istio.api.networking.v1beta1.VirtualService;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
-import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
-
-public class GerritIstioAndPrimaryGerritCondition
- implements Condition<VirtualService, GerritNetwork> {
-
- @Override
- public boolean isMet(
- DependentResource<VirtualService, GerritNetwork> dependentResource,
- GerritNetwork gerritNetwork,
- Context<GerritNetwork> context) {
-
- return gerritNetwork.getSpec().getIngress().isEnabled()
- && (gerritNetwork.hasGerrits() || gerritNetwork.hasReceiver());
- }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java
index 04cf05c..b3f75ef 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java
@@ -14,9 +14,6 @@
package com.google.gerrit.k8s.operator.network.istio.dependent;
-import static com.google.gerrit.k8s.operator.api.model.network.GerritNetwork.SESSION_COOKIE_NAME;
-import static com.google.gerrit.k8s.operator.api.model.network.GerritNetwork.SESSION_COOKIE_TTL;
-
import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
import com.google.gerrit.k8s.operator.api.model.gerrit.GerritTemplate;
import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
@@ -76,12 +73,7 @@
.withNewLoadBalancer()
.withNewLoadBalancerSettingsConsistentHashLbPolicy()
.withNewConsistentHash()
- .withNewLoadBalancerSettingsConsistentHashLBHttpCookieKey()
- .withNewHttpCookie()
- .withName(SESSION_COOKIE_NAME)
- .withTtl(SESSION_COOKIE_TTL)
- .endHttpCookie()
- .endLoadBalancerSettingsConsistentHashLBHttpCookieKey()
+ .withNewLoadBalancerSettingsConsistentHashLBUseSourceIpKey(true)
.endConsistentHash()
.endLoadBalancerSettingsConsistentHashLbPolicy()
.endLoadBalancer()
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioServiceEntries.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioServiceEntries.java
new file mode 100644
index 0000000..ed75855
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioServiceEntries.java
@@ -0,0 +1,119 @@
+// Copyright (C) 2024 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.network.istio.dependent;
+
+import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
+import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
+import com.google.gerrit.k8s.operator.gerrit.dependent.GerritService;
+import com.google.gerrit.k8s.operator.gerrit.dependent.GerritStatefulSet;
+import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import io.fabric8.istio.api.networking.v1beta1.PortBuilder;
+import io.fabric8.istio.api.networking.v1beta1.ServiceEntry;
+import io.fabric8.istio.api.networking.v1beta1.ServiceEntryBuilder;
+import io.fabric8.istio.api.networking.v1beta1.ServiceEntryLocation;
+import io.fabric8.istio.api.networking.v1beta1.ServiceEntryResolution;
+import io.fabric8.kubernetes.api.model.apps.StatefulSet;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
+import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class GerritIstioServiceEntries
+ extends CRUDReconcileAddKubernetesDependentResource<ServiceEntry, GerritNetwork>
+ implements Deleter<GerritNetwork>, BulkDependentResource<ServiceEntry, GerritNetwork> {
+
+ public GerritIstioServiceEntries() {
+ super(ServiceEntry.class);
+ }
+
+ private ServiceEntry desired(String podName, GerritNetwork gerritNetwork) {
+ String namespace = gerritNetwork.getMetadata().getNamespace();
+ return new ServiceEntryBuilder()
+ .withNewMetadata()
+ .withName(podName)
+ .withNamespace(namespace)
+ .withLabels(
+ GerritCluster.getLabels(
+ gerritNetwork.getMetadata().getName(), podName, this.getClass().getSimpleName()))
+ .endMetadata()
+ .withNewSpec()
+ .withLocation(ServiceEntryLocation.MESH_INTERNAL)
+ .withResolution(ServiceEntryResolution.DNS)
+ .withHosts(
+ getServiceHost(
+ podName,
+ GerritService.getName(gerritNetwork.getSpec().getPrimaryGerrit().getName()),
+ namespace))
+ .withPorts(
+ List.of(
+ new PortBuilder()
+ .withName("ssh-primary")
+ .withNumber(gerritNetwork.getSpec().getPrimaryGerrit().getSshPort())
+ .withProtocol("TCP")
+ .build(),
+ new PortBuilder()
+ .withName("http")
+ .withNumber(gerritNetwork.getSpec().getPrimaryGerrit().getHttpPort())
+ .withProtocol("HTTP")
+ .build()))
+ .endSpec()
+ .build();
+ }
+
+ private String getServiceHost(String podName, String serviceName, String namespace) {
+ return String.format("%s.%s.%s.svc.cluster.local", podName, serviceName, namespace);
+ }
+
+ @Override
+ public Map<String, ServiceEntry> desiredResources(
+ GerritNetwork gerritNetwork, Context<GerritNetwork> context) {
+ Map<String, ServiceEntry> serviceEntries = new HashMap<>();
+ if (gerritNetwork.hasPrimaryGerrit()) {
+ String primaryGerritName = gerritNetwork.getSpec().getPrimaryGerrit().getName();
+
+ StatefulSet sts =
+ context
+ .getClient()
+ .resources(StatefulSet.class)
+ .inNamespace(gerritNetwork.getMetadata().getNamespace())
+ .withName(GerritStatefulSet.getName(primaryGerritName))
+ .get();
+
+ if (sts == null) {
+ return serviceEntries;
+ }
+
+ for (int i = 0; i < sts.getSpec().getReplicas(); i++) {
+ String podName = String.format("%s-%d", primaryGerritName, i);
+ serviceEntries.put(podName, desired(podName, gerritNetwork));
+ }
+ }
+ return serviceEntries;
+ }
+
+ @Override
+ public Map<String, ServiceEntry> getSecondaryResources(
+ GerritNetwork gerritNetwork, Context<GerritNetwork> context) {
+ Set<ServiceEntry> serviceEntries = context.getSecondaryResources(ServiceEntry.class);
+ Map<String, ServiceEntry> result = new HashMap<>(serviceEntries.size());
+ for (ServiceEntry se : serviceEntries) {
+ result.put(se.getMetadata().getName(), se);
+ }
+ return result;
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java
index d2ba41b..a504ab7 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java
@@ -84,10 +84,15 @@
String namespace = gerritNetwork.getMetadata().getNamespace();
List<HTTPRoute> routes = new ArrayList<>();
if (gerritNetwork.hasReceiver()) {
- routes.add(
+ HTTPRouteBuilder receiverRouteBuilder =
new HTTPRouteBuilder()
- .withName("receiver-" + gerritNetwork.getSpec().getReceiver().getName())
- .withMatch(getReceiverMatches())
+ .withName("receiver-" + gerritNetwork.getSpec().getReceiver().getName());
+ if (gerritNetwork.hasGerritReplica()) {
+ receiverRouteBuilder = receiverRouteBuilder.withMatch(getReceiverMatches());
+ }
+
+ routes.add(
+ receiverRouteBuilder
.withRoute(
getReceiverHTTPDestination(gerritNetwork.getSpec().getReceiver(), namespace))
.build());
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/dependent/ReceiverDeployment.java b/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/dependent/ReceiverDeployment.java
index 9f5fc0c..f1102ae 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/dependent/ReceiverDeployment.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/dependent/ReceiverDeployment.java
@@ -106,7 +106,6 @@
.getContainerImages()
.getGerritImages()
.getFullImageName("apache-git-http-backend"))
- .withEnv(GerritCluster.getPodNameEnvVar())
.withPorts(getContainerPorts(receiver))
.withResources(receiver.getSpec().getResources())
.withReadinessProbe(receiver.getSpec().getReadinessProbe())
@@ -163,7 +162,6 @@
private Set<VolumeMount> getVolumeMounts(Receiver receiver, boolean isInitContainer) {
Set<VolumeMount> volumeMounts = new HashSet<>();
volumeMounts.add(GerritCluster.getGitRepositoriesVolumeMount("/var/gerrit/git"));
- volumeMounts.add(GerritCluster.getLogsVolumeMount("/var/log/apache2"));
volumeMounts.add(
new VolumeMountBuilder()
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/IncomingReplicationTaskReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/IncomingReplicationTaskReconciler.java
new file mode 100644
index 0000000..48d7abb
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/IncomingReplicationTaskReconciler.java
@@ -0,0 +1,45 @@
+// Copyright (C) 2024 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.tasks.incomingrepl;
+
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask;
+import com.google.gerrit.k8s.operator.tasks.incomingrepl.dependent.IncomingReplicationTaskConfigMap;
+import com.google.gerrit.k8s.operator.tasks.incomingrepl.dependent.IncomingReplicationTaskCronJob;
+import com.google.inject.Singleton;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
+import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
+import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
+
+@Singleton
+@ControllerConfiguration(
+ dependents = {
+ @Dependent(
+ name = "incoming-repl-task-configmap",
+ type = IncomingReplicationTaskConfigMap.class),
+ @Dependent(
+ name = "incoming-repl-task-cronjob",
+ type = IncomingReplicationTaskCronJob.class,
+ dependsOn = "incoming-repl-task-configmap")
+ })
+public class IncomingReplicationTaskReconciler implements Reconciler<IncomingReplicationTask> {
+
+ @Override
+ public UpdateControl<IncomingReplicationTask> reconcile(
+ IncomingReplicationTask incomingRepl, Context<IncomingReplicationTask> context) {
+ return UpdateControl.noUpdate();
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskConfigMap.java b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskConfigMap.java
new file mode 100644
index 0000000..341bdc6
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskConfigMap.java
@@ -0,0 +1,75 @@
+// Copyright (C) 2024 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.tasks.incomingrepl.dependent;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask;
+import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
+import io.javaoperatorsdk.operator.OperatorException;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Map;
+
+@KubernetesDependent
+public class IncomingReplicationTaskConfigMap
+ extends CRUDReconcileAddKubernetesDependentResource<ConfigMap, IncomingReplicationTask> {
+ public static final String CONFIG_FILE_NAME = "incoming-replication.config.yaml";
+
+ public IncomingReplicationTaskConfigMap() {
+ super(ConfigMap.class);
+ }
+
+ @Override
+ public ConfigMap desired(
+ IncomingReplicationTask incomingReplTask, Context<IncomingReplicationTask> context) {
+ Map<String, String> labels =
+ GerritCluster.getLabels(
+ incomingReplTask.getMetadata().getName(),
+ getName(incomingReplTask),
+ this.getClass().getSimpleName());
+
+ return new ConfigMapBuilder()
+ .withApiVersion("v1")
+ .withNewMetadata()
+ .withName(getName(incomingReplTask))
+ .withNamespace(incomingReplTask.getMetadata().getNamespace())
+ .withLabels(labels)
+ .endMetadata()
+ .withData(Map.of(CONFIG_FILE_NAME, getConfigAsString(incomingReplTask)))
+ .build();
+ }
+
+ public static String getName(IncomingReplicationTask incomingReplTask) {
+ return String.format("%s-configmap", incomingReplTask.getMetadata().getName());
+ }
+
+ private String getConfigAsString(IncomingReplicationTask incomingReplTask) {
+ StringWriter writer = new StringWriter();
+ try {
+ new ObjectMapper(new YAMLFactory())
+ .writeValue(writer, incomingReplTask.getSpec().getConfig());
+ } catch (IOException e) {
+ throw new OperatorException(
+ "Failed to write configuration for incoming replication task.", e);
+ }
+ return writer.toString();
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskCronJob.java b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskCronJob.java
new file mode 100644
index 0000000..96dbc62
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskCronJob.java
@@ -0,0 +1,234 @@
+// Copyright (C) 2024 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.tasks.incomingrepl.dependent;
+
+import static com.google.gerrit.k8s.operator.tasks.incomingrepl.dependent.IncomingReplicationTaskConfigMap.CONFIG_FILE_NAME;
+
+import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
+import com.google.gerrit.k8s.operator.api.model.shared.ContainerImageConfig;
+import com.google.gerrit.k8s.operator.api.model.shared.NfsWorkaroundConfig;
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask;
+import com.google.gerrit.k8s.operator.tasks.incomingrepl.IncomingReplicationTaskReconciler;
+import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import io.fabric8.kubernetes.api.model.Container;
+import io.fabric8.kubernetes.api.model.ContainerBuilder;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.Volume;
+import io.fabric8.kubernetes.api.model.VolumeBuilder;
+import io.fabric8.kubernetes.api.model.VolumeMount;
+import io.fabric8.kubernetes.api.model.VolumeMountBuilder;
+import io.fabric8.kubernetes.api.model.batch.v1.CronJob;
+import io.fabric8.kubernetes.api.model.batch.v1.CronJobBuilder;
+import io.fabric8.kubernetes.api.model.batch.v1.JobTemplateSpec;
+import io.fabric8.kubernetes.api.model.batch.v1.JobTemplateSpecBuilder;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class IncomingReplicationTaskCronJob
+ extends CRUDReconcileAddKubernetesDependentResource<CronJob, IncomingReplicationTask> {
+ private static final String CONFIGMAP_VOLUME_NAME = "incoming-repl-config";
+
+ public IncomingReplicationTaskCronJob() {
+ super(CronJob.class);
+ }
+
+ @Override
+ protected CronJob desired(
+ IncomingReplicationTask incomingReplTask, Context<IncomingReplicationTask> context) {
+ String ns = incomingReplTask.getMetadata().getNamespace();
+ String name = incomingReplTask.getMetadata().getName();
+ Map<String, String> labels = getLabels(incomingReplTask);
+
+ List<Container> initContainers = new ArrayList<>();
+ NfsWorkaroundConfig nfsWorkaround =
+ incomingReplTask.getSpec().getStorage().getStorageClasses().getNfsWorkaround();
+ if (nfsWorkaround.isEnabled() && nfsWorkaround.isChownOnStartup()) {
+ boolean hasIdmapdConfig =
+ incomingReplTask
+ .getSpec()
+ .getStorage()
+ .getStorageClasses()
+ .getNfsWorkaround()
+ .getIdmapdConfig()
+ != null;
+ ContainerImageConfig images = incomingReplTask.getSpec().getContainerImages();
+
+ initContainers.add(GerritCluster.createNfsInitContainer(hasIdmapdConfig, images));
+ }
+
+ JobTemplateSpec gitGcJobTemplate =
+ new JobTemplateSpecBuilder()
+ .withNewSpec()
+ .withNewTemplate()
+ .withNewMetadata()
+ .withAnnotations(
+ Map.of(
+ "sidecar.istio.io/inject",
+ "false",
+ "cluster-autoscaler.kubernetes.io/safe-to-evict",
+ "false"))
+ .withLabels(labels)
+ .endMetadata()
+ .withNewSpec()
+ .withTolerations(incomingReplTask.getSpec().getTolerations())
+ .withAffinity(incomingReplTask.getSpec().getAffinity())
+ .addAllToImagePullSecrets(
+ incomingReplTask.getSpec().getContainerImages().getImagePullSecrets())
+ .withRestartPolicy("OnFailure")
+ .withNewSecurityContext()
+ .withFsGroup(100L)
+ .endSecurityContext()
+ .addAllToInitContainers(initContainers)
+ .addToContainers(buildTaskContainer(incomingReplTask))
+ .withVolumes(getVolumes(incomingReplTask))
+ .endSpec()
+ .endTemplate()
+ .endSpec()
+ .build();
+
+ return new CronJobBuilder()
+ .withApiVersion("batch/v1")
+ .withNewMetadata()
+ .withNamespace(ns)
+ .withName(name)
+ .withLabels(labels)
+ .endMetadata()
+ .withNewSpec()
+ .withSchedule(incomingReplTask.getSpec().getSchedule())
+ .withConcurrencyPolicy("Forbid")
+ .withJobTemplate(gitGcJobTemplate)
+ .endSpec()
+ .build();
+ }
+
+ private static String getComponentName(String incomingReplTaskName) {
+ return String.format("task-incoming-replication-%s", incomingReplTaskName);
+ }
+
+ private static Map<String, String> getLabels(IncomingReplicationTask incomingReplTask) {
+ String name = incomingReplTask.getMetadata().getName();
+ return GerritCluster.getLabels(
+ name, getComponentName(name), IncomingReplicationTaskReconciler.class.getSimpleName());
+ }
+
+ private Container buildTaskContainer(IncomingReplicationTask incomingReplTask) {
+
+ ContainerBuilder taskContainerBuilder =
+ new ContainerBuilder()
+ .withName("incoming-replication")
+ .withImagePullPolicy(
+ incomingReplTask.getSpec().getContainerImages().getImagePullPolicy())
+ .withImage(
+ incomingReplTask
+ .getSpec()
+ .getContainerImages()
+ .getGerritImages()
+ .getFullImageName("fetch-job"))
+ .withResources(incomingReplTask.getSpec().getResources())
+ .withVolumeMounts(getVolumeMounts(incomingReplTask));
+
+ return taskContainerBuilder.build();
+ }
+
+ private List<VolumeMount> getVolumeMounts(IncomingReplicationTask incomingReplTask) {
+ List<VolumeMount> volumeMounts = new ArrayList<>();
+ volumeMounts.add(GerritCluster.getGitRepositoriesVolumeMount("/var/gerrit/git"));
+
+ volumeMounts.add(
+ new VolumeMountBuilder()
+ .withName(CONFIGMAP_VOLUME_NAME)
+ .withSubPath(CONFIG_FILE_NAME)
+ .withMountPath("/var/gerrit/etc/" + CONFIG_FILE_NAME)
+ .build());
+
+ if (incomingReplTask.getSpec().getStorage().getStorageClasses().getNfsWorkaround().isEnabled()
+ && incomingReplTask
+ .getSpec()
+ .getStorage()
+ .getStorageClasses()
+ .getNfsWorkaround()
+ .getIdmapdConfig()
+ != null) {
+ volumeMounts.add(GerritCluster.getNfsImapdConfigVolumeMount());
+ }
+
+ String secretRef = incomingReplTask.getSpec().getSecretRef();
+ if (secretRef != null && !secretRef.isBlank()) {
+ Secret secret =
+ client
+ .resources(Secret.class)
+ .inNamespace(incomingReplTask.getMetadata().getNamespace())
+ .withName(secretRef)
+ .get();
+ if (secret != null && secret.getData().containsKey(".netrc")) {
+ volumeMounts.add(
+ new VolumeMountBuilder()
+ .withName(secretRef)
+ .withSubPath(".netrc")
+ .withMountPath("/home/gerrit/.netrc")
+ .build());
+ }
+ }
+ return volumeMounts;
+ }
+
+ private List<Volume> getVolumes(IncomingReplicationTask incomingReplTask) {
+ List<Volume> volumes = new ArrayList<>();
+
+ volumes.add(
+ GerritCluster.getSharedVolume(
+ incomingReplTask.getSpec().getStorage().getSharedStorage().getExternalPVC()));
+
+ volumes.add(
+ new VolumeBuilder()
+ .withName(CONFIGMAP_VOLUME_NAME)
+ .withNewConfigMap()
+ .withName(IncomingReplicationTaskConfigMap.getName(incomingReplTask))
+ .endConfigMap()
+ .build());
+
+ if (incomingReplTask
+ .getSpec()
+ .getStorage()
+ .getStorageClasses()
+ .getNfsWorkaround()
+ .isEnabled()) {
+ if (incomingReplTask
+ .getSpec()
+ .getStorage()
+ .getStorageClasses()
+ .getNfsWorkaround()
+ .getIdmapdConfig()
+ != null) {
+ volumes.add(GerritCluster.getNfsImapdConfigVolume());
+ }
+ }
+
+ String secretRef = incomingReplTask.getSpec().getSecretRef();
+ if (secretRef != null && !secretRef.isBlank()) {
+ volumes.add(
+ new VolumeBuilder()
+ .withName(secretRef)
+ .withNewSecret()
+ .withSecretName(secretRef)
+ .endSecret()
+ .build());
+ }
+
+ return volumes;
+ }
+}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/util/KubernetesDependentCustomResource.java b/operator/src/main/java/com/google/gerrit/k8s/operator/util/KubernetesDependentCustomResource.java
new file mode 100644
index 0000000..e0f7782
--- /dev/null
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/util/KubernetesDependentCustomResource.java
@@ -0,0 +1,84 @@
+// Copyright (C) 2024 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.util;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.fabric8.kubernetes.api.model.Namespaced;
+import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.fabric8.kubernetes.client.dsl.Resource;
+import io.javaoperatorsdk.operator.api.reconciler.Context;
+import io.javaoperatorsdk.operator.processing.dependent.Matcher.Result;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.GenericKubernetesResourceMatcher;
+import io.javaoperatorsdk.operator.processing.dependent.kubernetes.GenericResourceUpdatePreProcessor;
+import io.javaoperatorsdk.operator.processing.event.ResourceID;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class KubernetesDependentCustomResource<
+ R extends HasMetadata, P extends HasMetadata>
+ extends CRUDReconcileAddKubernetesDependentResource<R, P> {
+
+ private static final Logger log =
+ LoggerFactory.getLogger(KubernetesDependentCustomResource.class);
+
+ public KubernetesDependentCustomResource(Class<R> resourceType) {
+ super(resourceType);
+ }
+
+ protected R setApiVersionAnnotation(R updated, P primary) {
+ ObjectMeta meta = updated.getMetadata();
+ Map<String, String> actualAnnotations = meta.getAnnotations();
+ actualAnnotations.put("gerritoperator.google.com/apiVersion", primary.getApiVersion());
+ meta.setAnnotations(actualAnnotations);
+ updated.setMetadata(meta);
+ return updated;
+ }
+
+ @Override
+ public Result<R> match(R actualResource, R desired, P primary, Context<P> context) {
+ return GenericKubernetesResourceMatcher.match(desired, actualResource, true, true);
+ }
+
+ @Override
+ public R create(R target, P primary, Context<P> context) {
+ return prepare(setApiVersionAnnotation(target, primary), primary, "Creating").create();
+ }
+
+ @Override
+ public R update(R actual, R target, P primary, Context<P> context) {
+ R updatedActual =
+ GenericResourceUpdatePreProcessor.processorFor(resourceType())
+ .replaceSpecOnActual(actual, target, context);
+ updatedActual = setApiVersionAnnotation(updatedActual, primary);
+ return prepare(updatedActual, primary, "Updating").replace();
+ }
+
+ protected Resource<R> prepare(R desired, P primary, String actionName) {
+ log.debug(
+ "{} target resource with type: {}, with id: {}",
+ actionName,
+ desired.getClass(),
+ ResourceID.fromResource(desired));
+
+ desired.addOwnerReference(primary);
+
+ if (desired instanceof Namespaced) {
+ return client.resource(desired).inNamespace(desired.getMetadata().getNamespace());
+ } else {
+ return client.resource(desired);
+ }
+ }
+}
diff --git a/operator/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.model.KubernetesResource b/operator/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.model.KubernetesResource
index 8fa0944..e9714a5 100644
--- a/operator/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.model.KubernetesResource
+++ b/operator/src/main/resources/META-INF/services/io.fabric8.kubernetes.api.model.KubernetesResource
@@ -1,5 +1,6 @@
com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster
com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit
com.google.gerrit.k8s.operator.api.model.gitgc.GitGarbageCollection
+com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask
com.google.gerrit.k8s.operator.api.model.receiver.Receiver
com.google.gerrit.k8s.operator.api.model.network.GerritNetwork
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterAmbassadorTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterAmbassadorTest.java
index ae97807..d9dd075 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterAmbassadorTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterAmbassadorTest.java
@@ -120,6 +120,9 @@
GerritClusterMappingReceiver.class.getName(), "mapping_receiver.yaml",
GerritClusterMappingReceiverGET.class.getName(), "mappingGET_receiver.yaml")),
Arguments.of(
+ "../../gerritnetwork_receiver.yaml",
+ Map.of(GerritClusterMappingReceiver.class.getName(), "mapping_receiver_only.yaml")),
+ Arguments.of(
"../../gerritnetwork_receiver_replica_tls.yaml",
Map.of(
GerritClusterMapping.class.getName(), "mapping_replica.yaml",
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngressTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngressTest.java
index 123a5e1..ced3985 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngressTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/network/ingress/dependent/GerritClusterIngressTest.java
@@ -45,6 +45,7 @@
Arguments.of("../../gerritnetwork_primary_replica.yaml", "ingress_primary_replica.yaml"),
Arguments.of("../../gerritnetwork_primary.yaml", "ingress_primary.yaml"),
Arguments.of("../../gerritnetwork_replica.yaml", "ingress_replica.yaml"),
+ Arguments.of("../../gerritnetwork_receiver.yaml", "ingress_receiver.yaml"),
Arguments.of("../../gerritnetwork_receiver_replica.yaml", "ingress_receiver_replica.yaml"),
Arguments.of(
"../../gerritnetwork_receiver_replica_tls.yaml", "ingress_receiver_replica_tls.yaml"));
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioTest.java
index 52d9a77..43e0ae8 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioTest.java
@@ -61,6 +61,8 @@
Arguments.of(
"../../gerritnetwork_replica.yaml", "gateway.yaml", "virtualservice_replica.yaml"),
Arguments.of(
+ "../../gerritnetwork_receiver.yaml", "gateway.yaml", "virtualservice_receiver.yaml"),
+ Arguments.of(
"../../gerritnetwork_receiver_replica.yaml",
"gateway.yaml",
"virtualservice_receiver_replica.yaml"),
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskTest.java
new file mode 100644
index 0000000..1b64cff
--- /dev/null
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskTest.java
@@ -0,0 +1,111 @@
+// Copyright (C) 2024 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.tasks.incomingrepl.dependent;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
+import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask;
+import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedIncomingReplicationTask;
+import io.fabric8.kubernetes.api.model.ConfigMap;
+import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.api.model.SecretBuilder;
+import io.fabric8.kubernetes.api.model.batch.v1.CronJob;
+import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.javaoperatorsdk.operator.ReconcilerUtils;
+import java.net.HttpURLConnection;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.junit.Rule;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+@TestInstance(Lifecycle.PER_CLASS)
+public class IncomingReplicationTaskTest {
+ @Rule public KubernetesServer kubernetesServer = new KubernetesServer();
+
+ @BeforeAll
+ public void setup() throws Exception {
+ kubernetesServer.before();
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideYamlManifests")
+ public void expectedIncomingReplicationTaskComponentsCreated(
+ String inputGerritCluster,
+ String expectedIncomingReplTask,
+ String expectedCronJob,
+ String expectedConfigMap)
+ throws Exception {
+ GerritCluster input =
+ ReconcilerUtils.loadYaml(GerritCluster.class, this.getClass(), inputGerritCluster);
+ IncomingReplicationTask expectedReplTask =
+ ReconcilerUtils.loadYaml(
+ IncomingReplicationTask.class, this.getClass(), expectedIncomingReplTask);
+ IncomingReplicationTask incomingReplTask =
+ new ClusterManagedIncomingReplicationTask()
+ .desiredResources(input, null)
+ .get(expectedReplTask.getMetadata().getName());
+ assertThat(incomingReplTask).isEqualTo(expectedReplTask);
+
+ Secret testSecret =
+ new SecretBuilder()
+ .withNewMetadata()
+ .withName(expectedReplTask.getSpec().getSecretRef())
+ .withNamespace(expectedReplTask.getMetadata().getNamespace())
+ .endMetadata()
+ .withData(Map.of(".netrc", "c2VjcmV0Cg=="))
+ .build();
+
+ kubernetesServer
+ .expect()
+ .get()
+ .withPath(
+ String.format(
+ "/api/v1/namespaces/%s/secrets/%s",
+ incomingReplTask.getMetadata().getNamespace(),
+ incomingReplTask.getSpec().getSecretRef()))
+ .andReturn(HttpURLConnection.HTTP_OK, testSecret)
+ .always();
+
+ IncomingReplicationTaskCronJob incomingReplicationTaskCronJob =
+ new IncomingReplicationTaskCronJob();
+ incomingReplicationTaskCronJob.setKubernetesClient(kubernetesServer.getClient());
+ CronJob cronJob = incomingReplicationTaskCronJob.desired(incomingReplTask, null);
+
+ assertThat(cronJob)
+ .isEqualTo(ReconcilerUtils.loadYaml(CronJob.class, this.getClass(), expectedCronJob));
+
+ IncomingReplicationTaskConfigMap incomingReplicationTaskConfigMap =
+ new IncomingReplicationTaskConfigMap();
+ ConfigMap configMap = incomingReplicationTaskConfigMap.desired(incomingReplTask, null);
+
+ assertThat(configMap)
+ .isEqualTo(ReconcilerUtils.loadYaml(ConfigMap.class, this.getClass(), expectedConfigMap));
+ }
+
+ private static Stream<Arguments> provideYamlManifests() {
+ return Stream.of(
+ Arguments.of(
+ "../gerritcluster_incomingrepl.yaml",
+ "../incomingrepltask.yaml",
+ "incomingrepl_cronjob.yaml",
+ "incomingrepl_configmap.yaml"));
+ }
+}
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/test/AbstractGerritOperatorE2ETest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/test/AbstractGerritOperatorE2ETest.java
index 2c43790..84087a8 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/test/AbstractGerritOperatorE2ETest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/test/AbstractGerritOperatorE2ETest.java
@@ -26,6 +26,7 @@
import com.google.gerrit.k8s.operator.network.GerritNetworkReconcilerProvider;
import com.google.gerrit.k8s.operator.network.IngressType;
import com.google.gerrit.k8s.operator.receiver.ReceiverReconciler;
+import com.google.gerrit.k8s.operator.tasks.incomingrepl.IncomingReplicationTaskReconciler;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretBuilder;
import io.fabric8.kubernetes.client.Config;
@@ -64,6 +65,7 @@
.withReconciler(new GitGarbageCollectionReconciler(client))
.withReconciler(new ReceiverReconciler(client))
.withReconciler(getGerritNetworkReconciler())
+ .withReconciler(new IncomingReplicationTaskReconciler())
.build();
@BeforeEach
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_primary.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_primary.yaml
index d659bdc..7a3872c 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_primary.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_primary.yaml
@@ -1,7 +1,9 @@
-apiVersion: gerritoperator.google.com/v1beta5
+apiVersion: gerritoperator.google.com/v1beta9
kind: Gerrit
metadata:
name: gerrit
+ annotations:
+ gerritoperator.google.com/apiVersion: gerritoperator.google.com/v1beta9
spec:
configFiles: {}
containerImages:
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_replica.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_replica.yaml
index 82bc522..2ace26e 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_replica.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/cluster/dependent/gerrit_replica.yaml
@@ -1,7 +1,9 @@
-apiVersion: gerritoperator.google.com/v1beta5
+apiVersion: gerritoperator.google.com/v1beta9
kind: Gerrit
metadata:
name: gerrit-replica
+ annotations:
+ gerritoperator.google.com/apiVersion: gerritoperator.google.com/v1beta9
spec:
configFiles: {}
containerImages:
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_default.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_default.yaml
index ebc04e6..cc0e75a 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_default.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_default.yaml
@@ -14,7 +14,7 @@
annotations:
app.kubernetes.io/managed-by: gerrit-operator
ownerReferences:
- - apiVersion: gerritoperator.google.com/v1beta6
+ - apiVersion: gerritoperator.google.com/v1beta9
kind: GitGarbageCollection
name: gitgc
uid: abcd1234
@@ -65,18 +65,10 @@
limits:
cpu: 100m
memory: 256Mi
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
volumeMounts:
- name: shared
subPath: git
mountPath: /var/gerrit/git
- - name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/log/git
volumes:
- name: shared
persistentVolumeClaim:
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_nfs_workaround.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_nfs_workaround.yaml
index ac30455..164f74b 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_nfs_workaround.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_nfs_workaround.yaml
@@ -14,7 +14,7 @@
annotations:
app.kubernetes.io/managed-by: gerrit-operator
ownerReferences:
- - apiVersion: gerritoperator.google.com/v1beta6
+ - apiVersion: gerritoperator.google.com/v1beta9
kind: GitGarbageCollection
name: gitgc
uid: abcd1234
@@ -62,17 +62,9 @@
- sh
- -c
args:
- - chown -R 1000:100 /var/mnt/logs /var/mnt/git
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
+ - chown -R 1000:100 /var/mnt/git
volumeMounts:
- name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/mnt/logs
- - name: shared
subPath: git
mountPath: /var/mnt/git
- name: nfs-config
@@ -89,18 +81,10 @@
limits:
cpu: 100m
memory: 256Mi
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
volumeMounts:
- name: shared
subPath: git
mountPath: /var/gerrit/git
- - name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/log/git
- name: nfs-config
subPath: idmapd.conf
mountPath: /etc/idmapd.conf
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_options_enabled.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_options_enabled.yaml
index b9780f5..de4fdd2 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_options_enabled.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_all_options_enabled.yaml
@@ -14,7 +14,7 @@
annotations:
app.kubernetes.io/managed-by: gerrit-operator
ownerReferences:
- - apiVersion: gerritoperator.google.com/v1beta6
+ - apiVersion: gerritoperator.google.com/v1beta9
kind: GitGarbageCollection
name: gitgc
uid: abcd1234
@@ -69,18 +69,10 @@
- -B
- -R
- -P
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
volumeMounts:
- name: shared
subPath: git
mountPath: /var/gerrit/git
- - name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/log/git
volumes:
- name: shared
persistentVolumeClaim:
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_default.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_default.yaml
index 68d68ca..92888a1 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_default.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_default.yaml
@@ -14,7 +14,7 @@
annotations:
app.kubernetes.io/managed-by: gerrit-operator
ownerReferences:
- - apiVersion: gerritoperator.google.com/v1beta6
+ - apiVersion: gerritoperator.google.com/v1beta9
kind: GitGarbageCollection
name: gitgc
uid: abcd1234
@@ -70,18 +70,10 @@
- test
- -p
- example
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
volumeMounts:
- name: shared
subPath: git
mountPath: /var/gerrit/git
- - name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/log/git
volumes:
- name: shared
persistentVolumeClaim:
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_options_enabled.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_options_enabled.yaml
index 7458352..83d6aa9 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_options_enabled.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/dependent/cronjob_selected_options_enabled.yaml
@@ -14,7 +14,7 @@
annotations:
app.kubernetes.io/managed-by: gerrit-operator
ownerReferences:
- - apiVersion: gerritoperator.google.com/v1beta6
+ - apiVersion: gerritoperator.google.com/v1beta9
kind: GitGarbageCollection
name: gitgc
uid: abcd1234
@@ -73,18 +73,10 @@
- -B
- -R
- -P
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
volumeMounts:
- name: shared
subPath: git
mountPath: /var/gerrit/git
- - name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/log/git
volumes:
- name: shared
persistentVolumeClaim:
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_minimal.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_minimal.yaml
index b35e286..85296b4 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_minimal.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_minimal.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritCluster
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_nfs_workaround.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_nfs_workaround.yaml
index 90b796a..827522b 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_nfs_workaround.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gerritcluster_nfs_workaround.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritCluster
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_default.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_default.yaml
index 0131865..7b72bd7 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_default.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_default.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GitGarbageCollection
metadata:
name: gitgc
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_options_enabled.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_options_enabled.yaml
index eb7f260..9b819f7 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_options_enabled.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_all_options_enabled.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GitGarbageCollection
metadata:
name: gitgc
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_default.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_default.yaml
index 59cabb6..e1dd468 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_default.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_default.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GitGarbageCollection
metadata:
name: gitgc
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_options_enabled.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_options_enabled.yaml
index 7eb0955..2669a38 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_options_enabled.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gitgc/gitgc_selected_options_enabled.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GitGarbageCollection
metadata:
name: gitgc
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ambassador/dependent/mapping_receiver_only.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ambassador/dependent/mapping_receiver_only.yaml
new file mode 100644
index 0000000..661bdc3
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ambassador/dependent/mapping_receiver_only.yaml
@@ -0,0 +1,15 @@
+apiVersion: getambassador.io/v2
+kind: Mapping
+metadata:
+ name: gerrit-mapping-receiver
+ namespace: gerrit
+spec:
+ ambassador_id:
+ - my-id-1
+ - my-id-2
+ bypass_auth: true
+ rewrite: ""
+ host: example.com
+ prefix: /
+ prefix_regex: false
+ service: receiver:48081
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary.yaml
index 88998fa..5c389fe 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica.yaml
index 97010f8..3bd9826 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_ssh.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_ssh.yaml
index 1a0bb09..7c133c1 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_ssh.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_ssh.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_tls.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_tls.yaml
index efa6391..11df2a1 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_tls.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_replica_tls.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_ssh.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_ssh.yaml
index 5f3fe8b..716469a 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_ssh.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_primary_ssh.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver.yaml
new file mode 100644
index 0000000..2bfc142
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver.yaml
@@ -0,0 +1,16 @@
+apiVersion: "gerritoperator.google.com/v1beta7"
+kind: GerritNetwork
+metadata:
+ name: gerrit
+ namespace: gerrit
+spec:
+ ingress:
+ enabled: true
+ host: example.com
+ tls:
+ enabled: false
+ ambassador:
+ id: ["my-id-1", "my-id-2"]
+ receiver:
+ name: receiver
+ httpPort: 48081
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica.yaml
index e5ee023..c3a0f2c 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_ssh.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_ssh.yaml
index f209621..3da5e14 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_ssh.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_ssh.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_tls.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_tls.yaml
index ce39a7d..b834c38 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_tls.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_receiver_replica_tls.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica.yaml
index d016aa5..6d344b7 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica_ssh.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica_ssh.yaml
index eafa0ee..2005379 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica_ssh.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/gerritnetwork_replica_ssh.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: GerritNetwork
metadata:
name: gerrit
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary.yaml
index a45192b..09dce08 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary.yaml
@@ -14,8 +14,8 @@
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-name: Gerrit_Session
nginx.ingress.kubernetes.io/session-cookie-path: /
- nginx.ingress.kubernetes.io/session-cookie-max-age: 60
- nginx.ingress.kubernetes.io/session-cookie-expires: 60
+ nginx.ingress.kubernetes.io/session-cookie-max-age: 3600
+ nginx.ingress.kubernetes.io/session-cookie-expires: 3600
spec:
rules:
- host: example.com
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica.yaml
index e0cecf1..91b9acd 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica.yaml
@@ -19,8 +19,8 @@
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-name: Gerrit_Session
nginx.ingress.kubernetes.io/session-cookie-path: /
- nginx.ingress.kubernetes.io/session-cookie-max-age: 60
- nginx.ingress.kubernetes.io/session-cookie-expires: 60
+ nginx.ingress.kubernetes.io/session-cookie-max-age: 3600
+ nginx.ingress.kubernetes.io/session-cookie-expires: 3600
spec:
rules:
- host: example.com
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica_tls.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica_tls.yaml
index e0aa83e..76a8de3 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica_tls.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_primary_replica_tls.yaml
@@ -19,8 +19,8 @@
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-name: Gerrit_Session
nginx.ingress.kubernetes.io/session-cookie-path: /
- nginx.ingress.kubernetes.io/session-cookie-max-age: 60
- nginx.ingress.kubernetes.io/session-cookie-expires: 60
+ nginx.ingress.kubernetes.io/session-cookie-max-age: 3600
+ nginx.ingress.kubernetes.io/session-cookie-expires: 3600
spec:
tls:
- hosts:
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver.yaml
new file mode 100644
index 0000000..ff9b4e4
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver.yaml
@@ -0,0 +1,25 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: gerrit-ingress
+ namespace: gerrit
+ annotations:
+ nginx.ingress.kubernetes.io/use-regex: true
+ kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/affinity: cookie
+ nginx.ingress.kubernetes.io/session-cookie-name: Gerrit_Session
+ nginx.ingress.kubernetes.io/session-cookie-path: /
+ nginx.ingress.kubernetes.io/session-cookie-max-age: 3600
+ nginx.ingress.kubernetes.io/session-cookie-expires: 3600
+spec:
+ rules:
+ - host: example.com
+ http:
+ paths:
+ - pathType: Prefix
+ path: "/"
+ backend:
+ service:
+ name: receiver
+ port:
+ name: http
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica.yaml
index 093dac7..0964004 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica.yaml
@@ -9,8 +9,8 @@
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-name: Gerrit_Session
nginx.ingress.kubernetes.io/session-cookie-path: /
- nginx.ingress.kubernetes.io/session-cookie-max-age: 60
- nginx.ingress.kubernetes.io/session-cookie-expires: 60
+ nginx.ingress.kubernetes.io/session-cookie-max-age: 3600
+ nginx.ingress.kubernetes.io/session-cookie-expires: 3600
nginx.ingress.kubernetes.io/configuration-snippet: |-
if ($args ~ service=git-receive-pack){
set $proxy_upstream_name "gerrit-receiver-http";
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica_tls.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica_tls.yaml
index 839827b..f132986 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica_tls.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_receiver_replica_tls.yaml
@@ -9,8 +9,8 @@
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-name: Gerrit_Session
nginx.ingress.kubernetes.io/session-cookie-path: /
- nginx.ingress.kubernetes.io/session-cookie-max-age: 60
- nginx.ingress.kubernetes.io/session-cookie-expires: 60
+ nginx.ingress.kubernetes.io/session-cookie-max-age: 3600
+ nginx.ingress.kubernetes.io/session-cookie-expires: 3600
nginx.ingress.kubernetes.io/configuration-snippet: |-
if ($args ~ service=git-receive-pack){
set $proxy_upstream_name "gerrit-receiver-http";
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_replica.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_replica.yaml
index 07dfe7d..3513c84 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_replica.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/ingress/dependent/ingress_replica.yaml
@@ -9,8 +9,8 @@
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-name: Gerrit_Session
nginx.ingress.kubernetes.io/session-cookie-path: /
- nginx.ingress.kubernetes.io/session-cookie-max-age: 60
- nginx.ingress.kubernetes.io/session-cookie-expires: 60
+ nginx.ingress.kubernetes.io/session-cookie-max-age: 3600
+ nginx.ingress.kubernetes.io/session-cookie-expires: 3600
spec:
rules:
- host: example.com
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/network/istio/dependent/virtualservice_receiver.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/istio/dependent/virtualservice_receiver.yaml
new file mode 100644
index 0000000..cb7330f
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/network/istio/dependent/virtualservice_receiver.yaml
@@ -0,0 +1,17 @@
+apiVersion: networking.istio.io/v1beta1
+kind: VirtualService
+metadata:
+ name: gerrit-gerrit-http-virtual-service
+ namespace: gerrit
+spec:
+ hosts:
+ - example.com
+ gateways:
+ - gerrit/gerrit-istio-gateway
+ http:
+ - name: receiver-receiver
+ route:
+ - destination:
+ port:
+ number: 48081
+ host: receiver.gerrit.svc.cluster.local
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml
index 4857152..2257380 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml
@@ -65,11 +65,6 @@
- name: apache-git-http-backend
imagePullPolicy: Always
image: docker.io/k8sgerrit/apache-git-http-backend:latest
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
ports:
- name: http
containerPort: 80
@@ -100,9 +95,6 @@
failureThreshold: 3
volumeMounts:
- - name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/log/apache2
- name: apache-credentials
mountPath: /var/apache/credentials/.htpasswd
subPath: .htpasswd
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml
index 92d0752..53b3c87 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml
@@ -43,11 +43,6 @@
- name: apache-git-http-backend
imagePullPolicy: Always
image: docker.io/k8sgerrit/apache-git-http-backend:latest
- env:
- - name: POD_NAME
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
ports:
- name: http
containerPort: 80
@@ -61,9 +56,6 @@
port: 80
volumeMounts:
- - name: shared
- subPathExpr: "logs/$(POD_NAME)"
- mountPath: /var/log/apache2
- name: apache-credentials
mountPath: /var/apache/credentials/.htpasswd
subPath: .htpasswd
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver.yaml
index d6689dd..06f62cb 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: Receiver
metadata:
name: receiver
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver_minimal.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver_minimal.yaml
index 4e0be0f..57f10ef 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver_minimal.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/receiver_minimal.yaml
@@ -1,4 +1,4 @@
-apiVersion: "gerritoperator.google.com/v1beta6"
+apiVersion: "gerritoperator.google.com/v1beta9"
kind: Receiver
metadata:
name: receiver
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/incomingrepl_configmap.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/incomingrepl_configmap.yaml
new file mode 100644
index 0000000..9b322d2
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/incomingrepl_configmap.yaml
@@ -0,0 +1,25 @@
+apiVersion: v1
+kind: ConfigMap
+data:
+ incoming-replication.config.yaml: |
+ ---
+ remotes:
+ - name: "github"
+ url: "https://github.com"
+ timeout: "5m"
+ fetch:
+ - remoteRepo: "fabric8io/kubernetes-client"
+ localRepo: "kubernetes-client"
+ refSpec: "+refs/heads/*:refs/heads/remote/*"
+
+metadata:
+ name: incoming-replication-test-configmap
+ namespace: gerrit
+ labels:
+ app.kubernetes.io/managed-by: gerrit-operator
+ app.kubernetes.io/name: gerrit
+ app.kubernetes.io/part-of: incoming-replication-test
+ app.kubernetes.io/created-by: IncomingReplicationTaskConfigMap
+ app.kubernetes.io/instance: incoming-replication-test
+ app.kubernetes.io/version: unknown
+ app.kubernetes.io/component: incoming-replication-test-configmap
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/incomingrepl_cronjob.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/incomingrepl_cronjob.yaml
new file mode 100644
index 0000000..01c8aa8
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/incomingrepl_cronjob.yaml
@@ -0,0 +1,59 @@
+apiVersion: batch/v1
+kind: CronJob
+metadata:
+ name: incoming-replication-test
+ namespace: gerrit
+ labels:
+ app.kubernetes.io/managed-by: gerrit-operator
+ app.kubernetes.io/name: gerrit
+ app.kubernetes.io/part-of: incoming-replication-test
+ app.kubernetes.io/created-by: IncomingReplicationTaskReconciler
+ app.kubernetes.io/instance: incoming-replication-test
+ app.kubernetes.io/version: unknown
+ app.kubernetes.io/component: task-incoming-replication-incoming-replication-test
+spec:
+ schedule: "*/5 * * * *"
+ concurrencyPolicy: Forbid
+ jobTemplate:
+ spec:
+ template:
+ metadata:
+ annotations:
+ sidecar.istio.io/inject: false
+ cluster-autoscaler.kubernetes.io/safe-to-evict: false
+ labels:
+ app.kubernetes.io/managed-by: gerrit-operator
+ app.kubernetes.io/name: gerrit
+ app.kubernetes.io/part-of: incoming-replication-test
+ app.kubernetes.io/created-by: IncomingReplicationTaskReconciler
+ app.kubernetes.io/instance: incoming-replication-test
+ app.kubernetes.io/version: unknown
+ app.kubernetes.io/component: task-incoming-replication-incoming-replication-test
+ spec:
+ restartPolicy: OnFailure
+ securityContext:
+ fsGroup: 100
+ containers:
+ - name: incoming-replication
+ imagePullPolicy: Always
+ image: docker.io/k8sgerrit/fetch-job:latest
+ volumeMounts:
+ - name: shared
+ subPath: git
+ mountPath: /var/gerrit/git
+ - name: incoming-repl-config
+ subPath: incoming-replication.config.yaml
+ mountPath: /var/gerrit/etc/incoming-replication.config.yaml
+ - name: incoming-repl-secret
+ subPath: .netrc
+ mountPath: /home/gerrit/.netrc
+ volumes:
+ - name: shared
+ persistentVolumeClaim:
+ claimName: shared-pvc
+ - name: incoming-repl-config
+ configMap:
+ name: incoming-replication-test-configmap
+ - name: incoming-repl-secret
+ secret:
+ secretName: incoming-repl-secret
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/gerritcluster_incomingrepl.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/gerritcluster_incomingrepl.yaml
new file mode 100644
index 0000000..397ecf6
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/gerritcluster_incomingrepl.yaml
@@ -0,0 +1,35 @@
+apiVersion: "gerritoperator.google.com/v1beta9"
+kind: GerritCluster
+metadata:
+ name: gerrit
+ namespace: gerrit
+spec:
+ containerImages: {}
+
+ storage:
+ storageClasses:
+ readWriteOnce: default
+ readWriteMany: shared-storage
+ sharedStorage:
+ size: 1Gi
+ volumeName: "vol"
+ selector:
+ matchLabels:
+ volume-type: ssd
+ aws-availability-zone: us-east-1
+
+ scheduledTasks:
+ incomingReplication:
+ - metadata:
+ name: incoming-replication-test
+ spec:
+ schedule: "*/5 * * * *"
+ config:
+ remotes:
+ - name: github
+ url: https://github.com
+ fetch:
+ - remoteRepo: fabric8io/kubernetes-client
+ localRepo: kubernetes-client
+ refSpec: +refs/heads/*:refs/heads/remote/*
+ secretRef: incoming-repl-secret
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/incomingrepltask.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/incomingrepltask.yaml
new file mode 100644
index 0000000..0d10a52
--- /dev/null
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/tasks/incomingrepl/incomingrepltask.yaml
@@ -0,0 +1,49 @@
+apiVersion: "gerritoperator.google.com/v1beta9"
+kind: IncomingReplicationTask
+metadata:
+ name: incoming-replication-test
+ namespace: gerrit
+spec:
+ config:
+ remotes:
+ - fetch:
+ - remoteRepo: fabric8io/kubernetes-client
+ localRepo: kubernetes-client
+ refSpec: +refs/heads/*:refs/heads/remote/*
+ name: github
+ timeout: 5m
+ url: https://github.com
+ schedule: '*/5 * * * *'
+ secretRef: incoming-repl-test
+ containerImages:
+ busyBox:
+ registry: docker.io
+ tag: latest
+ gerritImages:
+ org: k8sgerrit
+ registry: docker.io
+ tag: latest
+ imagePullPolicy: Always
+ imagePullSecrets: []
+ storage:
+ pluginCache:
+ enabled: false
+ sharedStorage:
+ externalPVC:
+ claimName: gerrit-shared-pvc
+ enabled: true
+ size: 1500Gi
+ storageClasses:
+ nfsWorkaround:
+ chownOnStartup: false
+ enabled: false
+ idmapdConfig: |-
+ [General]
+ Verbosity = 0
+ Domain = localdomain.com
+
+ [Mapping]
+ Nobody-User = nobody
+ Nobody-Group = nogroup
+ readWriteMany: nfs-client
+ readWriteOnce: gce-sc-fast