Skip to content

Commit c528161

Browse files
committed
Kubernetes Operator for Nessie
1 parent 7cf65f0 commit c528161

23 files changed

+1720
-0
lines changed

Diff for: gradle/libs.versions.toml

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ quarkus-bom = { module = "io.quarkus.platform:quarkus-bom", version.ref = "quark
148148
quarkus-cassandra-bom = { module = "io.quarkus.platform:quarkus-cassandra-bom", version.ref = "quarkus" }
149149
quarkus-google-cloud-services-bom = { module = "io.quarkus.platform:quarkus-google-cloud-services-bom", version.ref = "quarkus" }
150150
quarkus-logging-sentry = { module = "io.quarkiverse.loggingsentry:quarkus-logging-sentry", version = "2.0.4" }
151+
# references io.quarkiverse.operatorsdk:quarkus-operator-sdk:6.4.0, too old
152+
# TODO switch when quarkus 3.7 is released
153+
# quarkus-operator-sdk-bom = { module = "io.quarkus.platform:quarkus-operator-sdk-bom", version.ref = "quarkus" }
154+
quarkus-operator-sdk-bom = { module = "io.quarkiverse.operatorsdk:quarkus-operator-sdk-bom", version = "6.5.1" }
151155
rest-assured = { module = "io.rest-assured:rest-assured", version = "5.4.0" }
152156
rocksdb-jni = { module = "org.rocksdb:rocksdbjni", version = "8.9.1" }
153157
scala-library-v212 = { module = "org.scala-lang:scala-library", version = { strictly = "[2.12, 2.13[", prefer = "2.12.18" }}

Diff for: gradle/projects.main.properties

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ nessie-jaxrs-testextension=servers/jax-rs-testextension
2121
nessie-jaxrs-tests=servers/jax-rs-tests
2222
nessie-keycloak-testcontainer=testing/keycloak-container
2323
nessie-nessie-testcontainer=testing/nessie-container
24+
nessie-operator=operator
2425
nessie-quarkus-auth=servers/quarkus-auth
2526
nessie-quarkus-cli=servers/quarkus-cli
2627
nessie-quarkus-common=servers/quarkus-common

Diff for: operator/Makefile

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
2+
VERSION ?= 0.0.1
3+
4+
# CHANNELS define the bundle channels used in the bundle.
5+
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
6+
# To re-generate a bundle for other specific channels without changing the standard setup, you can:
7+
# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable)
8+
# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable")
9+
ifneq ($(origin CHANNELS), undefined)
10+
BUNDLE_CHANNELS := --channels=$(CHANNELS)
11+
endif
12+
13+
# DEFAULT_CHANNEL defines the default channel used in the bundle.
14+
# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable")
15+
# To re-generate a bundle for any other default channel without changing the default setup, you can:
16+
# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable)
17+
# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable")
18+
ifneq ($(origin DEFAULT_CHANNEL), undefined)
19+
BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
20+
endif
21+
BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
22+
23+
# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images.
24+
# This variable is used to construct full image tags for bundle and catalog images.
25+
#
26+
# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both
27+
# projectnessie.org/nessie-operator-bundle:$VERSION and projectnessie.org/nessie-operator-catalog:$VERSION.
28+
IMAGE_TAG_BASE ?= projectnessie/nessie-operator
29+
30+
# BUNDLE_IMG defines the image:tag used for the bundle.
31+
# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>)
32+
BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)
33+
34+
# Image URL to use all building/pushing image targets
35+
IMG ?= $(IMAGE_TAG_BASE):latest
36+
37+
PULL_POLICY ?= Always
38+
39+
all: docker-build
40+
41+
##@ General
42+
43+
# The help target prints out all targets with their descriptions organized
44+
# beneath their categories. The categories are represented by '##@' and the
45+
# target descriptions by '##'. The awk commands is responsible for reading the
46+
# entire set of makefiles included in this invocation, looking for lines of the
47+
# file as xyz: ## something, and then pretty-format the target and help. Then,
48+
# if there's a line with ##@ something, that gets pretty-printed as a category.
49+
# More info on the usage of ANSI control characters for terminal formatting:
50+
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
51+
# More info on the awk command:
52+
# http://linuxcommand.org/lc3_adv_awk.php
53+
54+
help: ## Display this help.
55+
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
56+
57+
##@ Build
58+
59+
docker-build: ## Build docker image with the manager.
60+
../gradlew --no-build-cache :nessie-operator:clean :nessie-operator:build \
61+
-Dquarkus.container-image.build=true \
62+
-Dquarkus.container-image.image=${IMG} \
63+
-Dquarkus.kubernetes.image-pull-policy=${PULL_POLICY}
64+
65+
docker-push: ## Build and push docker image with the manager.
66+
../gradlew --no-build-cache :nessie-operator:clean :nessie-operator:build \
67+
-Dquarkus.container-image.build=true \
68+
-Dquarkus.container-image.push=true \
69+
-Dquarkus.container-image.image=${IMG} \
70+
-Dquarkus.kubernetes.image-pull-policy=${PULL_POLICY}
71+
72+
##@ Deployment
73+
74+
install: ## Install CRDs into the K8s cluster specified in ~/.kube/config.
75+
@$(foreach file, $(wildcard build/kubernetes/*-v1.yml), kubectl apply -f $(file);)
76+
77+
uninstall: ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config.
78+
@$(foreach file, $(wildcard build/kubernetes/*-v1.yml), kubectl delete -f $(file);)
79+
80+
deploy: ## Deploy controller to the K8s cluster specified in ~/.kube/config.
81+
kubectl apply -f build/kubernetes/kubernetes.yml
82+
83+
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.
84+
kubectl delete -f build/kubernetes/kubernetes.yml
85+
86+
##@Bundle
87+
.PHONY: bundle
88+
bundle: ## Generate bundle manifests and metadata, then validate generated files.
89+
## marker
90+
cat build/kubernetes/nessies.nessie.projectnessie.org-v1alpha1.yml target/kubernetes/kubernetes.yml | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)
91+
operator-sdk bundle validate ./bundle
92+
93+
.PHONY: bundle-build
94+
bundle-build: ## Build the bundle image.
95+
docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) .
96+
97+
.PHONY: bundle-push
98+
bundle-push: ## Push the bundle image.
99+
docker push $(BUNDLE_IMG)

Diff for: operator/PROJECT

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Code generated by tool. DO NOT EDIT.
2+
# This file is used to track the info used to scaffold your project
3+
# and allow the plugins properly work.
4+
# More info: https://book.kubebuilder.io/reference/project-config.html
5+
domain: projectnessie.org
6+
layout:
7+
- quarkus.javaoperatorsdk.io/v1-alpha
8+
projectName: nessie-operator
9+
resources:
10+
- api:
11+
crdVersion: v1
12+
namespaced: true
13+
domain: projectnessie.org
14+
group: nessie
15+
kind: Nessie
16+
version: v1alpha1
17+
version: "3"

Diff for: operator/README.md

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Kubernetes Operator for Nessie
2+
3+
## Overview
4+
5+
This module is a Kubernetes Operator for Nessie.
6+
7+
**WARNING: This is a work in progress and is not ready for production use.**
8+
9+
## Usage
10+
11+
TODO describe typical deployment scenarios.
12+
13+
## Development
14+
15+
### Prerequisites
16+
17+
Install the following tools:
18+
19+
- Kubectl: https://kubernetes.io/docs/tasks/tools/
20+
- Operator SDK: https://sdk.operatorframework.io/docs/installation/
21+
- Optional:
22+
- yq: https://github.com/mikefarah/yq
23+
24+
**IMPORTANT**: The current Operator SDK version, 1.33.0, has [a bug] that prevents it from working
25+
with the latest version of the Kubernetes API (or Quarkus plugin). To work around this, install the
26+
version 1.32.0 of the operator-sdk.
27+
28+
[a bug]:https://github.com/operator-framework/operator-sdk/issues/6645
29+
30+
Using brew:
31+
32+
```bash
33+
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/6b039d0d8907b70704cd1d87ad235705a77620ae/Formula/o/operator-sdk.rb
34+
brew install -s operator-sdk.rb
35+
operator-sdk version
36+
```
37+
38+
### Project generation
39+
40+
```bash
41+
operator-sdk init --plugins=quarkus --domain=projectnessie.org --project-name=nessie-operator
42+
operator-sdk create api --plugins=quarkus --group nessie --version=v1alpha1 --kind=Nessie
43+
```
44+
45+
### Building the operator image
46+
47+
```bash
48+
make docker-build
49+
```
50+
51+
### Adhoc testing with Minikube
52+
53+
Install [minikube](https://minikube.sigs.k8s.io/docs/start/).
54+
55+
Build the operator docker image _inside_ minikube to facilitate testing (doesn't need a registry):
56+
57+
```bash
58+
eval $(minikube docker-env)
59+
make docker-build PULL_POLICY=IfNotPresent
60+
```
61+
62+
Note: the `PULL_POLICY=IfNotPresent` is required to avoid pulling the image from a registry.
63+
64+
Create the nessie-operator and nessie-ns namespaces:
65+
66+
```bash
67+
kubectl create namespace nessie-operator
68+
kubectl create namespace nessie-ns
69+
```
70+
71+
Install the CRDs and deploy the operator in the nessie-operator namespace:
72+
73+
```bash
74+
make install deploy
75+
```
76+
77+
Grant admin rights to the nessie-operator service account:
78+
79+
```bash
80+
kubectl apply -f examples/nessie-operator-rbac.yaml
81+
```
82+
83+
Create a Nessie resource in the nessie-ns namespace:
84+
85+
```bash
86+
kubectl apply -n nessie-ns -f examples/nessie.yaml
87+
```
88+
89+
You should see 1 pod, 1 deployment and 1 service running.

Diff for: operator/build.gradle.kts

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (C) 2024 Dremio
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
plugins {
18+
alias(libs.plugins.quarkus)
19+
id("nessie-conventions-quarkus")
20+
id("nessie-jacoco")
21+
}
22+
23+
extra["maven.name"] = "Nessie - Kubernetes Operator"
24+
25+
dependencies {
26+
implementation(enforcedPlatform(libs.quarkus.bom))
27+
implementation(enforcedPlatform(libs.quarkus.operator.sdk.bom))
28+
29+
implementation("io.quarkiverse.operatorsdk:quarkus-operator-sdk")
30+
implementation("io.quarkiverse.operatorsdk:quarkus-operator-sdk-bundle-generator")
31+
implementation("io.quarkus:quarkus-micrometer-registry-prometheus")
32+
implementation("io.quarkus:quarkus-container-image-jib")
33+
34+
testImplementation(enforcedPlatform(libs.quarkus.bom))
35+
testImplementation("io.quarkus:quarkus-junit5")
36+
testImplementation("io.quarkus:quarkus-junit5-mockito")
37+
testImplementation("io.quarkus:quarkus-test-kubernetes-client")
38+
testImplementation("org.bouncycastle:bcpkix-jdk18on")
39+
testImplementation(platform(libs.junit.bom))
40+
testImplementation(libs.bundles.junit.testing)
41+
testImplementation(libs.awaitility)
42+
}
43+
44+
listOf("javadoc", "sourcesJar").forEach { name ->
45+
tasks.named(name).configure { dependsOn(tasks.named("compileQuarkusGeneratedSourcesJava")) }
46+
}
47+
48+
listOf("checkstyleTest", "compileTestJava").forEach { name ->
49+
tasks.named(name).configure { dependsOn(tasks.named("compileQuarkusTestGeneratedSourcesJava")) }
50+
}

Diff for: operator/examples/nessie-operator-rbac.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRoleBinding
3+
metadata:
4+
name: nessie-operator-admin
5+
subjects:
6+
- kind: ServiceAccount
7+
name: nessie-operator
8+
namespace: nessie-operator
9+
roleRef:
10+
kind: ClusterRole
11+
name: cluster-admin
12+
apiGroup: ""

Diff for: operator/examples/nessie.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: nessie.projectnessie.org/v1alpha1
2+
kind: Nessie
3+
metadata:
4+
name: nessie1
5+
spec:
6+
size: 1
7+
versionStoreType: IN_MEMORY
8+
logLevel: INFO

0 commit comments

Comments
 (0)