Skip to content

Commit e169781

Browse files
authored
add objectbucketsource-adapter (#176)
1 parent b0d0932 commit e169781

65 files changed

Lines changed: 4340 additions & 12 deletions

File tree

Some content is hidden

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

‎Dockerfile‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ COPY go.sum go.sum
1212
RUN go mod download
1313

1414
# Copy the go source
15-
COPY cmd/main.go cmd/main.go
15+
COPY cmd/func-operator/main.go cmd/func-operator/main.go
1616
COPY api/ api/
1717
COPY internal/ internal/
1818

@@ -21,11 +21,11 @@ COPY internal/ internal/
2121
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
2222
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
2323
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
24-
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
24+
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/func-operator/main.go
2525

2626
FROM builder AS builder-debug
2727
# Build with debug symbols for delve
28-
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -gcflags="all=-N -l" -o manager-debug cmd/main.go
28+
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -gcflags="all=-N -l" -o manager-debug cmd/func-operator/main.go
2929
# Install Delve
3030
RUN go install github.com/go-delve/delve/cmd/dlv@latest
3131

‎Dockerfile.source-objectbucket‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Build the manager binary
2+
FROM golang:1.26 AS builder
3+
ARG TARGETOS
4+
ARG TARGETARCH
5+
6+
WORKDIR /workspace
7+
# Copy the Go Modules manifests
8+
COPY go.mod go.mod
9+
COPY go.sum go.sum
10+
# cache deps before building and copying source so that we don't need to re-download as much
11+
# and so that source changes don't invalidate our downloaded layer
12+
RUN go mod download
13+
14+
# Copy the go source
15+
COPY cmd/objectbucket-notifications-adapter/main.go cmd/objectbucket-notifications-adapter/main.go
16+
COPY api/ api/
17+
COPY internal/ internal/
18+
19+
# Build
20+
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/objectbucket-notifications-adapter/main.go
21+
22+
# Use distroless as minimal base image to package the manager binary
23+
# Refer to https://github.com/GoogleContainerTools/distroless for more details
24+
FROM gcr.io/distroless/static:nonroot
25+
WORKDIR /
26+
COPY --from=builder /workspace/manager .
27+
USER 65532:65532
28+
29+
ENTRYPOINT ["/manager"]

‎Makefile‎

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
3333
# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both
3434
# functions.dev/func-operator-bundle:$VERSION and functions.dev/func-operator-catalog:$VERSION.
3535
IMAGE_TAG_BASE ?= localhost:5001/func-operator
36+
IMAGE_TAG_BASE_SOURCE_OBJECTBUCKET ?= localhost:5001/objectbucket-notifications-adapter
3637

3738
DEBUG_IMAGE_TAG_BASE ?= $(IMAGE_TAG_BASE)-debug
3839

@@ -56,6 +57,7 @@ endif
5657
OPERATOR_SDK_VERSION ?= v1.41.1
5758
# Image URL to use all building/pushing image targets
5859
IMG ?= $(IMAGE_TAG_BASE):$(VERSION)
60+
IMG_SOURCE_OBJECTBUCKET ?= $(IMAGE_TAG_BASE_SOURCE_OBJECTBUCKET):$(VERSION)
5961
DEBUG_IMG ?= $(DEBUG_IMAGE_TAG_BASE):v$(VERSION)
6062

6163
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
@@ -116,7 +118,7 @@ vet: ## Run go vet against code.
116118

117119
.PHONY: test
118120
test: manifests generate fmt vet setup-envtest ## Run tests.
119-
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
121+
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v e2e) -coverprofile cover.out
120122

121123
.PHONY: test-e2e ## Run e2e tests.
122124
test-e2e: ginkgo
@@ -145,12 +147,23 @@ lint-config: golangci-lint ## Verify golangci-lint linter configuration
145147
##@ Build
146148

147149
.PHONY: build
148-
build: manifests generate fmt vet ## Build manager binary.
149-
go build -o bin/manager cmd/main.go
150+
build: manifests generate fmt vet ## Build func-operator manager binary.
151+
go build -o bin/manager cmd/func-operator/main.go
152+
153+
.PHONY: build-source-objectbucket
154+
build-source-objectbucket: manifests generate fmt vet ## Build objectbucket-notifications-adapter binary.
155+
go build -o bin/source-objectbucket cmd/objectbucket-notifications-adapter/main.go
156+
157+
.PHONY: build-sources
158+
build-sources: build-source-objectbucket ## Build all event source binaries.
150159

151160
.PHONY: run
152-
run: manifests generate fmt vet ## Run a controller from your host.
153-
go run ./cmd/main.go
161+
run: manifests generate fmt vet ## Run the func-operator controller from your host.
162+
go run ./cmd/func-operator/main.go
163+
164+
.PHONY: run-source-objectbucket
165+
run-source-objectbucket: manifests generate fmt vet ## Run the objectbucket-notifications-adapter controller from your host.
166+
go run ./cmd/objectbucket-notifications-adapter/main.go
154167

155168
# If you wish to build the manager image targeting other platforms you can use the --platform flag.
156169
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
@@ -178,6 +191,20 @@ docker-push-debugger: ## Push debugger docker image with the manager.
178191
# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)
179192
# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.
180193
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
194+
.PHONY: docker-build-source-objectbucket
195+
docker-build-source-objectbucket: ## Build docker image for the objectbucket-notifications-adapter.
196+
$(CONTAINER_TOOL) build -t ${IMG_SOURCE_OBJECTBUCKET} -f Dockerfile.source-objectbucket .
197+
198+
.PHONY: docker-push-source-objectbucket
199+
docker-push-source-objectbucket: ## Push docker image for the objectbucket-notifications-adapter.
200+
$(CONTAINER_TOOL) push ${IMG_SOURCE_OBJECTBUCKET}
201+
202+
.PHONY: docker-build-sources
203+
docker-build-sources: docker-build-source-objectbucket ## Build docker images for all event sources.
204+
205+
.PHONY: docker-push-sources
206+
docker-push-sources: docker-push-source-objectbucket ## Push docker images for all event sources.
207+
181208
.PHONY: docker-buildx
182209
docker-buildx: ## Build and push docker image for the manager for cross-platform support
183210
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
@@ -239,12 +266,31 @@ patch-registry-cert: ## Patch deployment to mount local registry certificate (fo
239266
fi
240267

241268
.PHONY: deploy
242-
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
269+
deploy: manifests kustomize ## Deploy func-operator controller to the K8s cluster specified in ~/.kube/config.
243270
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
244271
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
245272
$(MAKE) patch-registry-cert
246273
$(KUBECTL) wait deployment --all --timeout=120s --for=condition=Available -n func-operator-system
247274

275+
.PHONY: deploy-source-objectbucket
276+
deploy-source-objectbucket: manifests kustomize ## Deploy objectbucket-notifications-adapter to the K8s cluster.
277+
cd config/sources/objectbucket/manager && $(KUSTOMIZE) edit set image controller=${IMG_SOURCE_OBJECTBUCKET}
278+
$(KUSTOMIZE) build config/sources/objectbucket/default | $(KUBECTL) apply -f -
279+
$(KUBECTL) wait deployment --all --timeout=120s --for=condition=Available -n objectbucket-notifications-adapter-system
280+
281+
.PHONY: deploy-source-objectbucket-kafka
282+
deploy-source-objectbucket-kafka: manifests kustomize ## Deploy objectbucket-notifications-adapter in Kafka mode.
283+
cd config/sources/objectbucket/manager && $(KUSTOMIZE) edit set image controller=${IMG_SOURCE_OBJECTBUCKET}
284+
$(KUSTOMIZE) build config/sources/objectbucket/kafka | $(KUBECTL) apply -f -
285+
$(KUBECTL) wait deployment --all --timeout=120s --for=condition=Available -n objectbucket-notifications-adapter-system
286+
287+
.PHONY: deploy-combined
288+
deploy-combined: manifests kustomize ## Deploy both func-operator and all event sources in a single namespace.
289+
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
290+
cd config/sources/objectbucket/manager && $(KUSTOMIZE) edit set image controller=${IMG_SOURCE_OBJECTBUCKET}
291+
$(KUSTOMIZE) build config/combined | $(KUBECTL) apply -f -
292+
$(KUBECTL) wait deployment --all --timeout=120s --for=condition=Available -n func-operator-system
293+
248294
.PHONY: deploy-debugger
249295
deploy-debugger: manifests kustomize ## Deploy debug controller to the K8s cluster specified in ~/.kube/config.
250296
cd config/manager && $(KUSTOMIZE) edit set image controller=${DEBUG_IMG}
@@ -253,9 +299,17 @@ deploy-debugger: manifests kustomize ## Deploy debug controller to the K8s clust
253299
$(MAKE) patch-registry-cert
254300

255301
.PHONY: undeploy
256-
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
302+
undeploy: kustomize ## Undeploy func-operator controller from the K8s cluster. Call with ignore-not-found=true to ignore resource not found errors during deletion.
257303
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
258304

305+
.PHONY: undeploy-source-objectbucket
306+
undeploy-source-objectbucket: kustomize ## Undeploy objectbucket-notifications-adapter from the K8s cluster.
307+
$(KUSTOMIZE) build config/sources/objectbucket/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
308+
309+
.PHONY: undeploy-combined
310+
undeploy-combined: kustomize ## Undeploy both func-operator and all event sources from the K8s cluster.
311+
$(KUSTOMIZE) build config/combined | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
312+
259313
.PHONY: create-kind-cluster
260314
create-kind-cluster:
261315
./hack/create-kind-cluster.sh
@@ -382,6 +436,13 @@ bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metada
382436
$(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)
383437
$(OPERATOR_SDK) bundle validate ./bundle
384438

439+
.PHONY: bundle-combined
440+
bundle-combined: manifests kustomize operator-sdk ## Generate combined OLM bundle with both func-operator and all event sources.
441+
cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)
442+
cd config/sources/objectbucket/manager && $(KUSTOMIZE) edit set image controller=$(IMG_SOURCE_OBJECTBUCKET)
443+
$(KUSTOMIZE) build config/combined/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)
444+
$(OPERATOR_SDK) bundle validate ./bundle
445+
385446
.PHONY: bundle-build
386447
bundle-build: ## Build the bundle image.
387448
$(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) .

‎PROJECT‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,13 @@ resources:
1919
kind: Function
2020
path: github.com/functions-dev/func-operator/api/v1alpha1
2121
version: v1alpha1
22+
- api:
23+
crdVersion: v1
24+
namespaced: true
25+
controller: true
26+
domain: functions.dev
27+
group: sources
28+
kind: ObjectBucketSource
29+
path: github.com/functions-dev/func-operator/api/sources/v1alpha1
30+
version: v1alpha1
2231
version: "3"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright 2026.
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+
// Package v1alpha1 contains API Schema definitions for the sources v1alpha1 API group.
18+
// +kubebuilder:object:generate=true
19+
// +groupName=sources.functions.dev
20+
package v1alpha1
21+
22+
import (
23+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"k8s.io/apimachinery/pkg/runtime"
25+
"k8s.io/apimachinery/pkg/runtime/schema"
26+
)
27+
28+
var (
29+
// GroupVersion is group version used to register these objects.
30+
GroupVersion = schema.GroupVersion{Group: "sources.functions.dev", Version: "v1alpha1"}
31+
32+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
33+
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
34+
35+
// AddToScheme adds the types in this group-version to the given scheme.
36+
AddToScheme = SchemeBuilder.AddToScheme
37+
)
38+
39+
func addKnownTypes(scheme *runtime.Scheme) error {
40+
scheme.AddKnownTypes(GroupVersion,
41+
&ObjectBucketSource{},
42+
&ObjectBucketSourceList{},
43+
)
44+
45+
metav1.AddToGroupVersion(scheme, GroupVersion)
46+
47+
return nil
48+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Copyright 2026.
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+
package v1alpha1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
const (
24+
ConditionOBCCredentialsAvailable = "OBCCredentialsAvailable"
25+
ConditionBucketNotificationSet = "BucketNotificationSet"
26+
ConditionTestEventReceived = "TestEventReceived"
27+
28+
FinalizerName = "sources.functions.dev/objectbucketsource"
29+
)
30+
31+
// ObjectBucketSourceSpec defines the desired state of ObjectBucketSource.
32+
type ObjectBucketSourceSpec struct {
33+
// ObjectBucketClaim is a reference to the ObjectBucketClaim in the same namespace.
34+
ObjectBucketClaim OBCReference `json:"objectBucketClaim"`
35+
// Events is the list of S3 event types to subscribe to (e.g. "s3:ObjectCreated:*").
36+
Events []string `json:"events"`
37+
// Sink is the endpoint to dispatch matching CloudEvents to.
38+
Sink SinkSpec `json:"sink"`
39+
}
40+
41+
type OBCReference struct {
42+
// Name of the ObjectBucketClaim in the same namespace.
43+
Name string `json:"name"`
44+
}
45+
46+
// SinkSpec defines the destination for CloudEvents. URI can be an HTTP URL
47+
// (e.g. "http://foo.bar.svc.cluster.local") or a Kafka topic reference
48+
// (e.g. "kafka:my-topic").
49+
type SinkSpec struct {
50+
// URI is the destination to send CloudEvents to. Use an HTTP URL for
51+
// HTTP delivery, or "kafka:<topic>" for Kafka delivery.
52+
URI string `json:"uri"`
53+
}
54+
55+
// ObjectBucketSourceStatus defines the observed state of ObjectBucketSource.
56+
type ObjectBucketSourceStatus struct {
57+
Conditions []metav1.Condition `json:"conditions,omitempty"`
58+
}
59+
60+
// +kubebuilder:object:root=true
61+
// +kubebuilder:subresource:status
62+
63+
// ObjectBucketSource is the Schema for the objectbucketsources API.
64+
type ObjectBucketSource struct {
65+
metav1.TypeMeta `json:",inline"`
66+
metav1.ObjectMeta `json:"metadata,omitempty"`
67+
68+
Spec ObjectBucketSourceSpec `json:"spec,omitempty"`
69+
Status ObjectBucketSourceStatus `json:"status,omitempty"`
70+
}
71+
72+
// +kubebuilder:object:root=true
73+
74+
// ObjectBucketSourceList contains a list of ObjectBucketSource.
75+
type ObjectBucketSourceList struct {
76+
metav1.TypeMeta `json:",inline"`
77+
metav1.ListMeta `json:"metadata,omitempty"`
78+
Items []ObjectBucketSource `json:"items"`
79+
}

0 commit comments

Comments
 (0)