Skip to content

Commit e3bf14d

Browse files
samuelattwoodadriandieterdependabot[bot]
authored
Add Control Loop (nats-io#225)
* Migrate to kube_codegen.sh * Migrate to reconciliation loop using controller-runtime (nats-io#208) * Setup optional controller-runtime manager in main Removes the kubeconfig flag and instead uses ctrl.RegisterFlags(fs) and ctrl.GetConfig(). The controller-runtime currently registers the kubeconfig flag, which lead to a redefined flag error when registering it again. * Add update permissions for resource finalizers * Add envtest to Makefile This is based on the Makefile of an operator-sdk based project. * Update test to include envtest and run the internal/controller test suite * Add account, consumer and stream controller stubs to be implemented Controllers and tests are based on files generated by operator-sdk. Adds a minimal test suite for the controllers with a etcd test env and a test nats jetStream server to test against. * Add logs to Reconcile functions * Add internal/controller to jetstreamSrc * Register account, consumer and stream reconcilers * Add jsClient to test suit variables * Remove format from log string * feat(controller-runtime): Implement stream controller (nats-io#211) * Add account, consumer and stream controller stubs to be implemented Controllers and tests are based on files generated by operator-sdk. Adds a minimal test suite for the controllers with a etcd test env and a test nats jetStream server to test against. * Add logs to Reconcile functions * Add jsClient to test suit variables * Remove format from log string * Make upsertCondition public to be used in new controllers * Implement basic cases for stream reconciliation See TODOs on what still needs to be implemented. * refactor to use shared base controller * Support jetstream connection options in stream spec * implement stream deletion * update observedGeneration of status * check Spec.PreventDelete before stream deletion * remove base js client Use a single use client on every connection. This should be replaced by a client pool in the future. * move asJsonString to jetstream_controller * check namespace read only and prevent update mode * Update comments and log * Fix test docs and check precondition * Add preventUpdate test cases * Add tests for read-only or namespace restricted mode * fix empty ca when no ca set Setting CAs: []string{*ca} resulted in []string{""} when no CA was set, leading to an error when creating clients. * simplify error message * fix error loop when the underlying stream was deleted * refactor each phase into separate method * Fix errors during parallel reconciliation & Refactor tests - Trigger only on generation changes - Split initialization and create into separate calls to Reconcile * make test description strings more uniform * Update docs and log messages * extract configuration to buildNatsConfig method * fix checking for preventDelete in the update step Instead check for preventUpdate. Introduced during refactor. * fix k8s binaries not downloaded for tests * add /bin to gitignore * rename stream helper functions Prefix with stream to prevent conflict with other resources. * update naming as suggested * fix assumed reason in log message * Update todo comments marked with review - Add note on opts.Account - Add comment on possible feature to expose TLSFirst in the spec. * separate CA config from client cert and key * set streamName and consumerName fields once on logger Reword log messages. * feat(controller-runtime): Add consumer controller (nats-io#212) * implement consumerSpecToConfig * implement consumer resource initialization * implement consumer update/creation * implement preventUpdate, readonly and namespace restrictions Checks for the PreventUpdate or readonly mode during creation/update. Skips reconciliation when resource is in namespace not matching restriction. * test consumer creation on alternative server * implement consumer deletion * handle deletion when the underlying stream was deleted * add missing GenerationChanged event filter to consumerReconciler * update logging Set streamName and consumerName fields once. Reword log messages. * feat(controller-runtime): Add keyvalue store spec and controller (nats-io#215) * Bump helm/kind-action from 1.10.0 to 1.11.0 (nats-io#213) Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.10.0 to 1.11.0. - [Release notes](https://github.com/helm/kind-action/releases) - [Commits](helm/kind-action@v1.10.0...v1.11.0) --- updated-dependencies: - dependency-name: helm/kind-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump helm/kind-action from 1.11.0 to 1.12.0 (nats-io#214) Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.11.0 to 1.12.0. - [Release notes](https://github.com/helm/kind-action/releases) - [Commits](helm/kind-action@v1.11.0...v1.12.0) --- updated-dependencies: - dependency-name: helm/kind-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * * Formatting * Add initial definitions for KeyValue store * Deps * Fix test * Add KeyValue controller * Add KeyValue tests * Update PreventUpdate behavior * Minor error handling change --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add initial object store types. Update Stream config and reorg to keep in-line with nats client. * Add ObjectStore tests and remaining options * Add test for sealed stream option * Add Account Controller (nats-io#224) * Add explicit Scheme field to Reconciler structs to better match convention * Update spec to assume consumer field 'Name' over deprecated 'DurableName' * Add account controller and support for account CRD auth config * Update CRDs. Slight change to connection options * Namespace and error handling improvements * Improve deleted log message * Namespace fix * Add check for removed Push Consumer options * Revert consumer name change * Add InactiveThreshold parsing * Fix test * Add Watch for Account resource changes to trigger reconcile of dependent resources. Improve connection opts handling * Add actual/desired state comparison for stream/consumer to avoid unnecessary update calls. Corrected ready state * Fix duplicate resource tracking * Improve config comparison logic * Add flags for sync interval and cache directory * Add back generation changed filter. Move finalizer add to after deletion check. * Rework Reconcile scheduled sync * Deps * Create configured cache dir if DNE * Move stream controller to jsm.go for pedantic mode * Move consumer controller to jsm.go for pedantic mode * Remove debug log entry * deps * Improve connection config priority. Add missing option from consumer CRD. * Deps. Fix placement config enforcement * Bump jsm.go. Fix typo * Log diff on resource update * Improve README. Modernize examples. * Avoid excess disk writes to cache directory. README tweaks. --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Adrian <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent 6c5157e commit e3bf14d

File tree

112 files changed

+13623
-2442
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+13623
-2442
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@
1818
/nats-boot-config
1919
/nats-boot-config.docker
2020
/tools
21+
/bin
2122
/.idea

Makefile

+50-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
export GO111MODULE := on
22

3+
SHELL=/usr/bin/env bash
4+
5+
ENVTEST_K8S_VERSION = 1.31.0
6+
37
now := $(shell date -u +%Y-%m-%dT%H:%M:%S%z)
48
gitBranch := $(shell git rev-parse --abbrev-ref HEAD)
59
gitCommit := $(shell git rev-parse --short HEAD)
@@ -9,8 +13,7 @@ VERSION ?= version-not-set
913
linkerVars := -X main.BuildTime=$(now) -X main.GitInfo=$(gitBranch)-$(gitCommit)$(repoDirty) -X main.Version=$(VERSION)
1014
drepo ?= natsio
1115

12-
jetstreamGenIn:= $(shell grep -l -R -F "// +k8s:" pkg/jetstream/apis)
13-
jetstreamSrc := $(shell find cmd/jetstream-controller pkg/jetstream controllers/jetstream -name "*.go") pkg/jetstream/apis/jetstream/v1beta2/zz_generated.deepcopy.go
16+
jetstreamSrc := $(shell find cmd/jetstream-controller pkg/jetstream internal/controller controllers/jetstream -name "*.go") pkg/jetstream/apis/jetstream/v1beta2/zz_generated.deepcopy.go
1417

1518
configReloaderSrc := $(shell find cmd/nats-server-config-reloader/ pkg/natsreloader/ -name "*.go")
1619

@@ -27,20 +30,21 @@ default:
2730
# make nats-server-config-reloader
2831
# make nats-boot-config
2932

30-
pkg/jetstream/generated pkg/jetstream/apis/jetstream/v1beta2/zz_generated.deepcopy.go: fetch-modules $(jetstreamGenIn) pkg/k8scodegen/file-header.txt
33+
generate: fetch-modules pkg/k8scodegen/file-header.txt
3134
rm -rf pkg/jetstream/generated
32-
# Temporary chmod fix until we migrate to kube_codegen.sh
3335
D="$(codeGeneratorDir)"; : "$${D:=`go list -m -f '{{.Dir}}' k8s.io/code-generator`}"; \
34-
chmod u+x "$$D/generate-internal-groups.sh"; \
35-
GOFLAGS='' bash "$$D/generate-groups.sh" all \
36-
github.com/nats-io/nack/pkg/jetstream/generated \
37-
github.com/nats-io/nack/pkg/jetstream/apis \
38-
"jetstream:v1beta2" \
39-
--output-base . \
40-
--go-header-file pkg/k8scodegen/file-header.txt
41-
mv github.com/nats-io/nack/pkg/jetstream/generated pkg/jetstream/generated
42-
mv github.com/nats-io/nack/pkg/jetstream/apis/jetstream/v1beta2/zz_generated.deepcopy.go pkg/jetstream/apis/jetstream/v1beta2/zz_generated.deepcopy.go
43-
rm -rf github.com
36+
source "$$D/kube_codegen.sh" ; \
37+
kube::codegen::gen_helpers \
38+
--boilerplate pkg/k8scodegen/file-header.txt \
39+
pkg/jetstream/apis; \
40+
kube::codegen::gen_client \
41+
--with-watch \
42+
--with-applyconfig \
43+
--boilerplate pkg/k8scodegen/file-header.txt \
44+
--output-dir pkg/jetstream/generated \
45+
--output-pkg github.com/nats-io/nack/pkg/jetstream/generated \
46+
--one-input-api jetstream/v1beta2 \
47+
pkg/jetstream/apis
4448

4549
jetstream-controller: $(jetstreamSrc)
4650
go build -race -o $@ \
@@ -173,10 +177,39 @@ fetch-modules:
173177
.PHONY: build
174178
build: jetstream-controller nats-server-config-reloader nats-boot-config
175179

180+
# Setup envtest tools based on a operator-sdk project makefile
181+
LOCALBIN ?= $(shell pwd)/bin
182+
$(LOCALBIN):
183+
mkdir -p $(LOCALBIN)
184+
185+
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
186+
# $1 - target path with name of binary (ideally with version)
187+
# $2 - package url which can be installed
188+
# $3 - specific version of package
189+
define go-install-tool
190+
@[ -f $(1) ] || { \
191+
set -e; \
192+
package=$(2)@$(3) ;\
193+
echo "Downloading $${package}" ;\
194+
GOBIN=$(LOCALBIN) go install $${package} ;\
195+
mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\
196+
}
197+
endef
198+
199+
ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
200+
ENVTEST_VERSION ?= release-0.19
201+
202+
.PHONY: envtest
203+
envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.
204+
$(ENVTEST): $(LOCALBIN)
205+
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))
206+
207+
176208
.PHONY: test
177-
test:
178-
go vet ./controllers/... ./pkg/natsreloader/...
179-
go test -race -cover -count=1 -timeout 10s ./controllers/... ./pkg/natsreloader/...
209+
test: envtest
210+
go vet ./controllers/... ./pkg/natsreloader/... ./internal/controller/...
211+
$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path ## Get k8s binaries
212+
go test -race -cover -count=1 -timeout 10s ./controllers/... ./pkg/natsreloader/... ./internal/controller/...
180213

181214
.PHONY: clean
182215
clean:

README.md

+63-30
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,30 @@
99

1010
## JetStream Controller
1111

12-
The JetStream controllers allows you to manage [NATS JetStream](https://github.com/nats-io/jetstream) [Streams](https://github.com/nats-io/jetstream#streams-1) and [Consumers](https://github.com/nats-io/jetstream#consumers-1) via K8S CRDs.
12+
The JetStream controllers allows you to manage [NATS JetStream](https://docs.nats.io/nats-concepts/jetstream) [Streams](https://docs.nats.io/nats-concepts/jetstream/streams), [Consumers](https://docs.nats.io/nats-concepts/jetstream/consumers), [Key/Value Stores](https://docs.nats.io/nats-concepts/jetstream/key-value-store), and [Object Stores](https://docs.nats.io/nats-concepts/jetstream/obj_store) via Kubernetes CRDs.
13+
14+
Resources managed by NACK controllers are expected to _exclusively_ be managed by NACK, and configuration state will be enforced if mutated by an external client.
15+
16+
## [API Reference](docs/api.md)
1317

1418
### Getting started
1519

16-
First install the JetStream CRDs:
20+
Install with Helm:
1721

18-
```sh
19-
$ kubectl apply -f https://github.com/nats-io/nack/releases/latest/download/crds.yml
2022
```
23+
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
24+
helm upgrade --install nats nats/nats --set config.jetstream.enabled=true --set config.cluster.enabled=true
25+
helm upgrade --install nack nats/nack --set jetstream.nats.url=nats://nats.default.svc.cluster.local:4222
26+
```
27+
28+
#### (Optional) Enable Experimental `controller-runtime` Controllers
2129

22-
Now install with Helm:
30+
> **Note**: The updated controllers will more reliably enforce resource state. If migrating from an older version of NACK, as long as all NATS resources are in-sync with NACK resources no modifications are expected.
31+
>
32+
> The `jetstream-controller` logs will contain a diff of any changes the controller has made.
2333
2434
```
25-
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
26-
helm install nats nats/nats --set=config.jetstream.enabled=true
27-
helm install nack nats/nack --set jetstream.nats.url=nats://nats:4222
35+
helm upgrade nack nats/nack --set jetstream.additionalArgs={--control-loop=true}
2836
```
2937

3038
#### Creating Streams and Consumers
@@ -66,6 +74,28 @@ spec:
6674
filterSubject: orders.received
6775
maxDeliver: 20
6876
ackPolicy: explicit
77+
---
78+
apiVersion: jetstream.nats.io/v1beta2
79+
kind: KeyValue
80+
metadata:
81+
name: my-key-value
82+
spec:
83+
bucket: my-key-value
84+
history: 20
85+
storage: file
86+
maxBytes: 2048
87+
compression: true
88+
---
89+
apiVersion: jetstream.nats.io/v1beta2
90+
kind: ObjectStore
91+
metadata:
92+
name: my-object-store
93+
spec:
94+
bucket: my-object-store
95+
storage: file
96+
replicas: 1
97+
maxBytes: 536870912 # 512 MB
98+
compression: true
6999
```
70100
71101
```sh
@@ -75,7 +105,7 @@ $ kubectl apply -f https://raw.githubusercontent.com/nats-io/nack/main/deploy/ex
75105
# Check if it was successfully created.
76106
$ kubectl get streams
77107
NAME STATE STREAM NAME SUBJECTS
78-
mystream Created mystream [orders.*]
108+
mystream Ready mystream [orders.*]
79109

80110
# Create a push-based consumer
81111
$ kubectl apply -f https://raw.githubusercontent.com/nats-io/nack/main/deploy/examples/consumer_push.yml
@@ -86,8 +116,8 @@ $ kubectl apply -f https://raw.githubusercontent.com/nats-io/nack/main/deploy/ex
86116
# Check if they were successfully created.
87117
$ kubectl get consumers
88118
NAME STATE STREAM CONSUMER ACK POLICY
89-
my-pull-consumer Created mystream my-pull-consumer explicit
90-
my-push-consumer Created mystream my-push-consumer none
119+
my-pull-consumer Ready mystream my-pull-consumer explicit
120+
my-push-consumer Ready mystream my-push-consumer none
91121

92122
# If you end up in an Errored state, run kubectl describe for more info.
93123
# kubectl describe streams mystream
@@ -178,7 +208,7 @@ metadata:
178208
spec:
179209
name: a
180210
servers:
181-
- nats://nats:4222
211+
- nats://nats:4222
182212
tls:
183213
secret:
184214
name: nack-a-tls
@@ -209,31 +239,32 @@ Server URL and TLS certificates.
209239
210240
```sh
211241
# Install cert-manager
212-
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.6.0/cert-manager.yaml
242+
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.17.0/cert-manager.yaml
213243
214244
# Install TLS certs
215245
cd examples/secure
246+
216247
# Install certificate issuer
217248
kubectl apply -f issuer.yaml
249+
218250
# Install account A cert
219251
kubectl apply -f nack-a-client-tls.yaml
252+
220253
# Install server cert
221254
kubectl apply -f server-tls.yaml
255+
222256
# Install nats-box cert
223257
kubectl apply -f client-tls.yaml
224258
225259
# Install NATS cluster
226-
helm install -f nats-helm.yaml nats nats/nats
260+
helm upgrade --install -f nats-helm.yaml nats nats/nats
261+
227262
# Verify pods are healthy
228263
kubectl get pods
229264
230-
# Install nats-box to run nats cli later
231-
kubectl apply -f nats-client-box.yaml
232-
233265
# Install JetStream Controller from nack
234-
helm install --set jetstream.enabled=true jetstream-controller nats/nack
235-
# Install CRDs
236-
kubectl apply -f ../../deploy/crds.yml
266+
helm upgrade --install nack nats/nack --set jetstream.enabled=true
267+
237268
# Verify pods are healthy
238269
kubectl get pods
239270
@@ -242,6 +273,7 @@ kubectl apply -f nack/nats-account-a.yaml
242273
243274
# Create stream using account A
244275
kubectl apply -f nack/nats-stream-foo-a.yaml
276+
245277
# Create consumer using account A
246278
kubectl apply -f nack/nats-consumer-bar-a.yaml
247279
```
@@ -251,30 +283,28 @@ container to run the management CLI.
251283
252284
```sh
253285
# Get container shell
254-
kubectl exec -it nats-client-box-abc-123 -- sh
255-
# Change to TLS directory
256-
cd /etc/nats-certs/clients/nack-a-tls
286+
kubectl exec -it deployment/nats-box -- /bin/sh
257287
```
258288
259289
There should now be some Streams available, verify with `nats` command.
260290
261291
```sh
262292
# List streams
263-
nats --tlscert tls.crt --tlskey tls.key --tlsca ca.crt -s tls://nats.default.svc.cluster.local stream ls
293+
nats stream ls
264294
```
265295
266296
You can now publish messages on a Stream.
267297
268298
```sh
269299
# Push message
270-
nats --tlscert tls.crt --tlskey tls.key --tlsca ca.crt -s tls://nats.default.svc.cluster.local pub foo hi
300+
nats pub foo hi
271301
```
272302
273303
And pull messages from a Consumer.
274304
275305
```sh
276306
# Pull message
277-
nats --tlscert tls.crt --tlskey tls.key --tlsca ca.crt -s tls://nats.default.svc.cluster.local consumer next foo bar
307+
nats consumer next foo bar
278308
```
279309
280310
### Local Development
@@ -298,6 +328,7 @@ nats-server -DV -js
298328
```
299329
300330
Build Docker image
331+
301332
```sh
302333
make jetstream-controller-docker ver=1.2.3
303334
```
@@ -314,15 +345,15 @@ For more information see the
314345
315346
```
316347
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
317-
helm install my-nats nats/nats
348+
helm upgrade --install nats nats/nats
318349
```
319350
320351
### Configuring
321352
322353
```yaml
323354
reloader:
324355
enabled: true
325-
image: natsio/nats-server-config-reloader:0.6.0
356+
image: natsio/nats-server-config-reloader:0.16.1
326357
pullPolicy: IfNotPresent
327358
```
328359
@@ -337,6 +368,7 @@ make nats-server-config-reloader
337368
```
338369
339370
Build Docker image
371+
340372
```sh
341373
make nats-server-config-reloader-docker ver=1.2.3
342374
```
@@ -350,14 +382,14 @@ For more information see the
350382
351383
```
352384
helm repo add nats https://nats-io.github.io/k8s/helm/charts/
353-
helm install my-nats nats/nats
385+
helm upgrade --install nats nats/nats
354386
```
355387
356388
### Configuring
357389
358390
```yaml
359391
bootconfig:
360-
image: natsio/nats-boot-config:0.5.2
392+
image: natsio/nats-boot-config:0.16.1
361393
pullPolicy: IfNotPresent
362394
```
363395
@@ -372,6 +404,7 @@ make nats-boot-config
372404
```
373405
374406
Build Docker image
407+
375408
```sh
376409
make nats-boot-config-docker ver=1.2.3
377410
```

cicd/Dockerfile

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#syntax=docker/dockerfile-upstream:1.5
1+
#syntax=docker/dockerfile:1.13
22
ARG GO_APP
33

4-
FROM alpine:3.21.2 as deps
4+
FROM alpine:3.21.3 as deps
55

66
ARG GO_APP
77
ARG GORELEASER_DIST_DIR=/go/src/dist
@@ -28,7 +28,7 @@ RUN <<EOT
2828
cp ${BIN_PATH} /go/bin
2929
EOT
3030

31-
FROM alpine:3.21.2
31+
FROM alpine:3.21.3
3232

3333
ARG GO_APP
3434
ENV GO_APP ${GO_APP}

cicd/Dockerfile_goreleaser

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
#syntax=docker/dockerfile-upstream:1.5
1+
#syntax=docker/dockerfile:1.13
22
FROM --platform=$BUILDPLATFORM golang:1.24.0-bullseye as build
33

4+
45
RUN <<EOT
56
set -e
67

0 commit comments

Comments
 (0)