Skip to content

Commit 43dfdfe

Browse files
committed
Add OCI Functions Operator for OKE MVP
1 parent 291ed5d commit 43dfdfe

98 files changed

Lines changed: 15099 additions & 0 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.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.git
2+
.github
3+
.idea
4+
.vscode
5+
bin
6+
dist
7+
tmp
8+
9+
*.test
10+
*.out
11+
coverage.*
12+
13+
.DS_Store
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# OCI Functions Operator for OKE
2+
3+
## Goal
4+
5+
Build a Kubernetes operator that lets OKE users manage and invoke OCI Functions through Kubernetes-native CRDs.
6+
7+
## MVP
8+
9+
The MVP has two CRDs:
10+
11+
- Function
12+
- FunctionJob
13+
14+
FunctionJob should support:
15+
- functionRef
16+
- inline JSON payloads
17+
- parallelism
18+
- retryLimit
19+
- Kubernetes status aggregation
20+
21+
## Design principles
22+
23+
- Do not pretend OCI Functions are Kubernetes Pods.
24+
- Do not support arbitrary PodTemplateSpec in v1alpha1.
25+
- Prefer explicit validation errors over silent behavior.
26+
- Keep OCI SDK access behind small interfaces.
27+
- Make controllers idempotent.
28+
- Make status useful from `kubectl get` and `kubectl describe`.
29+
- Prefer small, testable packages.
30+
31+
## Out of scope for MVP
32+
33+
- Cron scheduling
34+
- Event sources
35+
- Native Kubernetes Job compatibility
36+
- Volumes
37+
- Sidecars
38+
- Init containers
39+
- GPU
40+
- Privileged execution
41+
- Full OCI Function lifecycle management before invocation spike works
42+
43+
## Build commands
44+
45+
Use:
46+
- `make generate`
47+
- `make manifests`
48+
- `make test`
49+
50+
## Language
51+
52+
Go, Kubebuilder/controller-runtime.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Build the manager binary.
2+
ARG GO_VERSION=1.26.0
3+
FROM golang:${GO_VERSION} AS builder
4+
5+
WORKDIR /workspace
6+
7+
COPY go.mod go.sum ./
8+
RUN go mod download
9+
10+
COPY . .
11+
12+
ARG TARGETOS=linux
13+
ARG TARGETARCH=amd64
14+
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -ldflags="-s -w" -o manager ./cmd
15+
16+
# Run as a non-root user in a minimal image.
17+
FROM gcr.io/distroless/static-debian12:nonroot
18+
19+
WORKDIR /
20+
COPY --from=builder /workspace/manager /manager
21+
22+
USER 65532:65532
23+
ENTRYPOINT ["/manager"]
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
LOCALBIN ?= $(shell pwd)/bin
2+
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
3+
CONTROLLER_TOOLS_VERSION ?= v0.21.0
4+
5+
.PHONY: all
6+
all: generate manifests test
7+
8+
.PHONY: generate
9+
generate: controller-gen
10+
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
11+
12+
.PHONY: manifests
13+
manifests: controller-gen
14+
$(CONTROLLER_GEN) rbac:roleName=manager-role crd paths="./..." output:crd:artifacts:config=config/crd/bases output:rbac:artifacts:config=config/rbac
15+
16+
.PHONY: test
17+
test:
18+
go test ./...
19+
20+
.PHONY: helm-chart
21+
helm-chart: manifests
22+
mkdir -p charts/oci-functions-operator/crds
23+
cp config/crd/bases/functions.oci.oracle.com_functions.yaml charts/oci-functions-operator/crds/functions.functions.oci.oracle.com.yaml
24+
cp config/crd/bases/functions.oci.oracle.com_functionjobs.yaml charts/oci-functions-operator/crds/functionjobs.functions.oci.oracle.com.yaml
25+
cp config/crd/bases/functions.oci.oracle.com_functionevents.yaml charts/oci-functions-operator/crds/functionevents.functions.oci.oracle.com.yaml
26+
cp config/crd/bases/functions.oci.oracle.com_functioneventtriggers.yaml charts/oci-functions-operator/crds/functioneventtriggers.functions.oci.oracle.com.yaml
27+
28+
.PHONY: helm-template
29+
helm-template: helm-chart
30+
helm template oci-functions-operator charts/oci-functions-operator \
31+
--namespace oci-functions-operator-system
32+
33+
.PHONY: fmt
34+
fmt:
35+
go fmt ./...
36+
37+
.PHONY: vet
38+
vet:
39+
go vet ./...
40+
41+
.PHONY: controller-gen
42+
controller-gen: $(CONTROLLER_GEN)
43+
44+
$(CONTROLLER_GEN):
45+
mkdir -p $(LOCALBIN)
46+
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
domain: oci.oracle.com
2+
layout:
3+
- go.kubebuilder.io/v4
4+
projectName: oci-functions-operator
5+
repo: github.com/oracle/oci-functions-operator
6+
resources:
7+
- api:
8+
crdVersion: v1
9+
namespaced: true
10+
controller: true
11+
domain: oci.oracle.com
12+
group: functions
13+
kind: Function
14+
path: github.com/oracle/oci-functions-operator/api/v1alpha1
15+
version: v1alpha1
16+
- api:
17+
crdVersion: v1
18+
namespaced: true
19+
controller: true
20+
domain: oci.oracle.com
21+
group: functions
22+
kind: FunctionJob
23+
path: github.com/oracle/oci-functions-operator/api/v1alpha1
24+
version: v1alpha1
25+
version: "3"
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# OCI Functions Operator
2+
3+
Kubernetes-native management and job-style invocation of OCI Functions from OKE.
4+
5+
MVP controller image:
6+
7+
```text
8+
ghcr.io/ronsevet/oci-functions-operator/controller:mvp-events-functionevents-v1
9+
```
10+
11+
## MVP Feature Summary
12+
13+
The MVP adds four namespaced CRDs:
14+
15+
- `Function`: references an existing OCI Function or manages an OCI Functions application/function.
16+
- `FunctionJob`: invokes a referenced `Function`, fans out inline JSON payloads, retries failed invocations, and records aggregate/per-payload status.
17+
- `FunctionEventTrigger`: creates OCI Events Rules for OCI service events such as Object Storage events, or routes Kubernetes-native `functionevent.*` events to a referenced `Function`.
18+
- `FunctionEvent`: Kubernetes-native event object for direct operator-routed invocation through `functionevent.*` event types.
19+
20+
## Two Images
21+
22+
The operator image and function runtime image are different artifacts:
23+
24+
- Operator/controller image: runs as a Kubernetes Deployment in OKE. It can be in GHCR, OCIR, or any registry OKE can pull from.
25+
- Function runtime image: runs in OCI Functions. It must be an OCI Functions-compatible Fn image in same-region OCIR, for example `jed.ocir.io/<TENANCY_NAMESPACE>/hello-function:fn-v1` for Jeddah.
26+
27+
Do not use GHCR for the OCI Functions runtime image. OCI Functions pulls the runtime image from the Functions application network during invocation, so the application subnet/NSG must have egress to Oracle Services Network/OCIR even when the OCIR repository is public.
28+
29+
## Start Here
30+
31+
- [Helm install](docs/helm-install.md): recommended OKE installation and upgrade path.
32+
- [MVP demo flow](docs/demo/mvp-demo-flow.md): primary concise handoff/demo guide for the final MVP image.
33+
- [MVP checklist](docs/demo/mvp-checklist.md): short secondary pre-demo checklist.
34+
- [MVP video script](docs/demo/mvp-video-script.md): short secondary narration outline.
35+
- [Managed Function demo](docs/managed-function-demo.md): primary OKE walkthrough for managed application/function creation and invocation.
36+
- [Function events](docs/function-events.md): Kubernetes-native `functionevent.*` events routed directly by the operator.
37+
- [Function event triggers](docs/event-triggers.md): OCI Events Rule and FunctionEvent trigger setup.
38+
- [OKE deployment](docs/oke-deployment.md): supported Helm deployment, Workload Identity, IAM, and network setup.
39+
- [Design overview](docs/design.md): CRDs, controllers, lifecycle, invoker contracts, and limitations.
40+
- [Local existing Function demo](docs/oci-mode-demo.md): local `OCI_AUTH_MODE=config` path against an already-created OCI Function.
41+
- [Debugging Functions](docs/debugging-functions.md): image, CRD, Workload Identity, NSG, and invocation failure checks.
42+
- [Validation notes](docs/validation-notes.md): template for recording real OCI-mode runs.
43+
- [Sample function image](examples/hello-function/README.md): Fn-compatible Python function runtime image for the managed demo.
44+
45+
## Modes
46+
47+
`INVOKER_MODE=fake` is the default. It requires no OCI auth, creates no OCI resources, and is useful only for CRD/controller/status demos.
48+
49+
`INVOKER_MODE=oci` uses the OCI Go SDK:
50+
51+
- On OKE, the Helm chart configures Workload Identity with `oci.authMode=workload`.
52+
- For local development only, use `OCI_AUTH_MODE=config` with `OCI_CONFIG_FILE` and `OCI_CONFIG_PROFILE`.
53+
54+
Existing mode requires `spec.functionId` and `spec.invokeEndpoint` on the `Function`. Managed mode uses `spec.config` to create/update the OCI Functions application and function, then writes `status.applicationId`, `status.functionId`, and `status.invokeEndpoint`.
55+
56+
## Local Fake Demo
57+
58+
Install or refresh generated manifests:
59+
60+
```sh
61+
make generate
62+
make manifests
63+
kubectl apply -k config/crd
64+
```
65+
66+
Run the manager against your current kubeconfig:
67+
68+
```sh
69+
INVOKER_MODE=fake go run ./cmd
70+
```
71+
72+
In another terminal:
73+
74+
```sh
75+
scripts/check-demo-prereqs.sh
76+
scripts/demo-fake.sh
77+
```
78+
79+
Fake mode proves only the Kubernetes reconciliation/status path. It does not prove OCI auth, OCI Functions network egress, OCIR image access, or function image compatibility.
80+
81+
## Primary OKE Path
82+
83+
For OKE managed mode:
84+
85+
1. Build and push the operator/controller image to a registry OKE can pull.
86+
2. Build a Fn-compatible function runtime image and push it to same-region OCIR.
87+
3. Deploy the operator with Helm. The chart is the supported OKE path and defaults to OCI mode with Workload Identity.
88+
4. Apply a managed `Function` with `spec.config.region`, `compartmentId`, `applicationName`, `subnetIds`, optional `nsgIds`, and same-region OCIR `image`.
89+
5. Submit a `FunctionJob`, create a `FunctionEventTrigger`, or emit a `FunctionEvent` after the `Function` is Ready.
90+
91+
See [docs/helm-install.md](docs/helm-install.md) for installation and [docs/managed-function-demo.md](docs/managed-function-demo.md) for the full Function sequence.
92+
93+
Kustomize under `config/` is kept for Kubebuilder-generated manifests and local controller development only. Do not mix Helm and Kustomize for the same OKE operator install.

0 commit comments

Comments
 (0)