Skip to content

Commit fa8aeb5

Browse files
committed
✨ feat(sink): postgres and kafka export backends
Add first-class postgres upsert and kafka event sinks per ADR-0025 with testcontainers integration tests; drop invalid prometheus sink stub.
1 parent 7a31d15 commit fa8aeb5

24 files changed

Lines changed: 1403 additions & 111 deletions

api/v1alpha1/kollectsink_types.go

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@ import (
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
88
)
99

10-
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
11-
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
12-
1310
// KollectSinkSpec defines the desired state of KollectSink.
1411
type KollectSinkSpec struct {
1512
// type selects the sink backend implementation.
16-
// +kubebuilder:validation:Enum=git;gitlab;s3;gcs;prometheus
13+
// +kubebuilder:validation:Enum=git;gitlab;s3;gcs;postgres;kafka
1714
// +required
1815
Type string `json:"type"`
1916

@@ -33,6 +30,49 @@ type KollectSinkSpec struct {
3330
// The annotation kollect.dev/test-connection=true has the same effect.
3431
// +optional
3532
ConnectionTest bool `json:"connectionTest,omitempty"`
33+
34+
// cluster labels exported inventory in multi-cluster installs.
35+
// +optional
36+
Cluster string `json:"cluster,omitempty"`
37+
38+
// postgres configures a PostgreSQL database sink.
39+
// +optional
40+
Postgres *PostgresSpec `json:"postgres,omitempty"`
41+
42+
// kafka configures a Kafka or Redpanda event sink.
43+
// +optional
44+
Kafka *KafkaSpec `json:"kafka,omitempty"`
45+
}
46+
47+
// PostgresSpec configures PostgreSQL upsert export.
48+
type PostgresSpec struct {
49+
// databaseRef references a Secret containing the connection string (key dsn or url).
50+
// +required
51+
DatabaseRef *SecretReference `json:"databaseRef"`
52+
53+
// table is the destination table name.
54+
// +required
55+
Table string `json:"table"`
56+
57+
// schema is the PostgreSQL schema (default public).
58+
// +optional
59+
Schema string `json:"schema,omitempty"`
60+
}
61+
62+
// KafkaSpec configures Kafka inventory change events.
63+
type KafkaSpec struct {
64+
// brokers lists Kafka bootstrap addresses (host:port).
65+
// +required
66+
// +listType=atomic
67+
Brokers []string `json:"brokers"`
68+
69+
// topic is the destination topic for inventory events.
70+
// +required
71+
Topic string `json:"topic"`
72+
73+
// secretRef references a Secret with optional SASL/TLS credentials.
74+
// +optional
75+
SecretRef *SecretReference `json:"secretRef,omitempty"`
3676
}
3777

3878
// TLSSpec configures custom CA trust for sink endpoints.
@@ -64,20 +104,7 @@ type SecretReference struct {
64104

65105
// KollectSinkStatus defines the observed state of KollectSink.
66106
type KollectSinkStatus struct {
67-
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
68-
// Important: Run "make" to regenerate code after modifying this file
69-
70-
// See Kubernetes API conventions for typical status properties.
71-
72107
// conditions represent the current state of the KollectSink resource.
73-
// Each condition has a unique type and reflects the status of a specific aspect of the resource.
74-
//
75-
// Standard condition types include:
76-
// - "Available": the resource is fully functional
77-
// - "Progressing": the resource is being created or updated
78-
// - "Degraded": the resource failed to reach or maintain its desired state
79-
//
80-
// The status of each condition is one of True, False, or Unknown.
81108
// +listType=map
82109
// +listMapKey=type
83110
// +optional

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 55 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/kollect.dev_kollectsinks.yaml

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ spec:
4141
spec:
4242
description: spec defines the desired state of KollectSink
4343
properties:
44+
cluster:
45+
description: cluster labels exported inventory in multi-cluster installs.
46+
type: string
4447
connectionTest:
4548
description: |-
4649
connectionTest requests a connectivity check on create/update when true.
@@ -50,6 +53,63 @@ spec:
5053
description: endpoint is the backend-specific destination (URL, bucket,
5154
and so on).
5255
type: string
56+
kafka:
57+
description: kafka configures a Kafka or Redpanda event sink.
58+
properties:
59+
brokers:
60+
description: brokers lists Kafka bootstrap addresses (host:port).
61+
items:
62+
type: string
63+
type: array
64+
x-kubernetes-list-type: atomic
65+
secretRef:
66+
description: secretRef references a Secret with optional SASL/TLS
67+
credentials.
68+
properties:
69+
name:
70+
description: name is the name of the referenced Secret.
71+
type: string
72+
namespace:
73+
description: namespace is the namespace of the referenced
74+
Secret.
75+
type: string
76+
required:
77+
- name
78+
type: object
79+
topic:
80+
description: topic is the destination topic for inventory events.
81+
type: string
82+
required:
83+
- brokers
84+
- topic
85+
type: object
86+
postgres:
87+
description: postgres configures a PostgreSQL database sink.
88+
properties:
89+
databaseRef:
90+
description: databaseRef references a Secret containing the connection
91+
string (key dsn or url).
92+
properties:
93+
name:
94+
description: name is the name of the referenced Secret.
95+
type: string
96+
namespace:
97+
description: namespace is the namespace of the referenced
98+
Secret.
99+
type: string
100+
required:
101+
- name
102+
type: object
103+
schema:
104+
description: schema is the PostgreSQL schema (default public).
105+
type: string
106+
table:
107+
description: table is the destination table name.
108+
type: string
109+
required:
110+
- databaseRef
111+
- table
112+
type: object
53113
secretRef:
54114
description: secretRef references a Secret holding credentials for
55115
the sink.
@@ -99,7 +159,8 @@ spec:
99159
- gitlab
100160
- s3
101161
- gcs
102-
- prometheus
162+
- postgres
163+
- kafka
103164
type: string
104165
required:
105166
- type
@@ -108,16 +169,8 @@ spec:
108169
description: status defines the observed state of KollectSink
109170
properties:
110171
conditions:
111-
description: |-
112-
conditions represent the current state of the KollectSink resource.
113-
Each condition has a unique type and reflects the status of a specific aspect of the resource.
114-
115-
Standard condition types include:
116-
- "Available": the resource is fully functional
117-
- "Progressing": the resource is being created or updated
118-
- "Degraded": the resource failed to reach or maintain its desired state
119-
120-
The status of each condition is one of True, False, or Unknown.
172+
description: conditions represent the current state of the KollectSink
173+
resource.
121174
items:
122175
description: Condition contains details for one aspect of the current
123176
state of this API Resource.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
apiVersion: kollect.dev/v1alpha1
2+
kind: KollectSink
3+
metadata:
4+
name: kafka-inventory-demo
5+
labels:
6+
app.kubernetes.io/name: kollect
7+
app.kubernetes.io/managed-by: kustomize
8+
spec:
9+
type: kafka
10+
cluster: kind-kollect-dev
11+
connectionTest: true
12+
kafka:
13+
brokers:
14+
- redpanda.kollect-system.svc:9092
15+
topic: kollect-inventory-events
16+
secretRef:
17+
name: kafka-sasl-credentials
18+
namespace: kollect-system
19+
# Secret example (optional SASL; create separately):
20+
# apiVersion: v1
21+
# kind: Secret
22+
# metadata:
23+
# name: kafka-sasl-credentials
24+
# namespace: kollect-system
25+
# stringData:
26+
# username: kollect
27+
# password: example
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: kollect.dev/v1alpha1
2+
kind: KollectSink
3+
metadata:
4+
name: postgres-inventory-demo
5+
labels:
6+
app.kubernetes.io/name: kollect
7+
app.kubernetes.io/managed-by: kustomize
8+
spec:
9+
type: postgres
10+
cluster: kind-kollect-dev
11+
connectionTest: true
12+
postgres:
13+
databaseRef:
14+
name: inventory-postgres-dsn
15+
namespace: kollect-system
16+
schema: public
17+
table: inventory_items
18+
# Secret example (create separately; never commit real credentials):
19+
# apiVersion: v1
20+
# kind: Secret
21+
# metadata:
22+
# name: inventory-postgres-dsn
23+
# namespace: kollect-system
24+
# stringData:
25+
# dsn: postgres://kollect:example@postgres.kollect-system.svc:5432/inventory?sslmode=disable

config/samples/kustomization.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ resources:
44
- kollect_v1alpha1_kollectprofile_service-endpoints.yaml
55
- kollect_v1alpha1_kollectprofile_ingress-hosts.yaml
66
- kollect_v1alpha1_kollectsink.yaml
7+
- kollect_v1alpha1_kollectsink_postgres.yaml
8+
- kollect_v1alpha1_kollectsink_kafka.yaml
79
- kollect_v1alpha1_kollecttarget.yaml
810
- kollect_v1alpha1_kollectinventory.yaml
911
# +kubebuilder:scaffold:manifestskustomizesamples

go.mod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ require (
1010
github.com/go-git/go-billy/v5 v5.9.0
1111
github.com/go-git/go-git/v5 v5.19.1
1212
github.com/google/cel-go v0.26.0
13+
github.com/jackc/pgx/v5 v5.10.0
1314
github.com/onsi/ginkgo/v2 v2.27.2
1415
github.com/onsi/gomega v1.38.2
1516
github.com/prometheus/client_golang v1.23.2
1617
github.com/redis/go-redis/v9 v9.20.0
18+
github.com/segmentio/kafka-go v0.4.51
1719
github.com/testcontainers/testcontainers-go/modules/minio v0.42.0
20+
github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0
1821
github.com/testcontainers/testcontainers-go/modules/redis v0.42.0
22+
github.com/testcontainers/testcontainers-go/modules/redpanda v0.42.0
1923
k8s.io/api v0.35.0
2024
k8s.io/apimachinery v0.35.0
2125
k8s.io/client-go v0.35.0
@@ -83,6 +87,9 @@ require (
8387
github.com/google/uuid v1.6.0 // indirect
8488
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
8589
github.com/inconshreveable/mousetrap v1.1.0 // indirect
90+
github.com/jackc/pgpassfile v1.0.0 // indirect
91+
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
92+
github.com/jackc/puddle/v2 v2.2.2 // indirect
8693
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
8794
github.com/josharian/intern v1.0.0 // indirect
8895
github.com/json-iterator/go v1.1.12 // indirect
@@ -108,6 +115,7 @@ require (
108115
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
109116
github.com/opencontainers/go-digest v1.0.0 // indirect
110117
github.com/opencontainers/image-spec v1.1.1 // indirect
118+
github.com/pierrec/lz4/v4 v4.1.19 // indirect
111119
github.com/pjbgf/sha1cd v0.6.0 // indirect
112120
github.com/pmezard/go-difflib v1.0.0 // indirect
113121
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
@@ -127,6 +135,9 @@ require (
127135
github.com/tklauser/numcpus v0.11.0 // indirect
128136
github.com/x448/float16 v0.8.4 // indirect
129137
github.com/xanzy/ssh-agent v0.3.3 // indirect
138+
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
139+
github.com/xdg-go/scram v1.1.2 // indirect
140+
github.com/xdg-go/stringprep v1.0.4 // indirect
130141
github.com/yusufpapurcu/wmi v1.2.4 // indirect
131142
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
132143
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect

0 commit comments

Comments
 (0)