From c5e3d37f0f9771dc6e3c26bb5d9e5dbb5a8c92ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Tue, 28 Apr 2026 08:41:02 +0200 Subject: [PATCH 1/2] Add service information in status --- api/v1alpha1/function_types.go | 17 +++++++---- api/v1alpha1/zz_generated.deepcopy.go | 30 ++++++++++++++----- config/crd/bases/functions.dev_functions.yaml | 7 +++++ internal/controller/function_controller.go | 10 +++++++ .../controller/function_controller_test.go | 18 +++++++++++ 5 files changed, 70 insertions(+), 12 deletions(-) diff --git a/api/v1alpha1/function_types.go b/api/v1alpha1/function_types.go index 8b2c1a0..740dd07 100644 --- a/api/v1alpha1/function_types.go +++ b/api/v1alpha1/function_types.go @@ -77,12 +77,14 @@ type FunctionSpecRegistry struct { type FunctionStatus struct { Name string `json:"name"` - Conditions []metav1.Condition `json:"conditions,omitempty"` + Git FunctionStatusGit `json:"git,omitempty"` + Deployment FunctionStatusDeployment `json:"deployment,omitempty"` + Middleware FunctionStatusMiddleware `json:"middleware,omitempty"` + Service FunctionServiceStatus `json:"service,omitempty"` + + History []FunctionStatusHistoryEntry `json:"history,omitempty"` - Git FunctionStatusGit `json:"git,omitempty"` - Deployment FunctionStatusDeployment `json:"deployment,omitempty"` - Middleware FunctionStatusMiddleware `json:"middleware,omitempty"` - History []FunctionStatusHistoryEntry `json:"history,omitempty"` + Conditions []metav1.Condition `json:"conditions,omitempty"` } type FunctionStatusHistoryEntry struct { @@ -112,6 +114,11 @@ type FunctionStatusMiddleware struct { LastRebuild metav1.Time `json:"lastRebuild,omitempty"` } +type FunctionServiceStatus struct { + URL string `json:"url,omitempty"` + Ready string `json:"ready,omitempty"` // string, as it can be UNKNOWN too +} + type FunctionStatusMiddlewareAutoUpdate struct { Enabled bool `json:"enabled"` // no omitempty to have it always shown Source string `json:"source,omitempty"` diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 087cf55..ddc1015 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -85,6 +85,21 @@ func (in *FunctionList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FunctionServiceStatus) DeepCopyInto(out *FunctionServiceStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionServiceStatus. +func (in *FunctionServiceStatus) DeepCopy() *FunctionServiceStatus { + if in == nil { + return nil + } + out := new(FunctionServiceStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FunctionSpec) DeepCopyInto(out *FunctionSpec) { *out = *in @@ -150,16 +165,10 @@ func (in *FunctionSpecRepository) DeepCopy() *FunctionSpecRepository { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *FunctionStatus) DeepCopyInto(out *FunctionStatus) { *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } in.Git.DeepCopyInto(&out.Git) in.Deployment.DeepCopyInto(&out.Deployment) in.Middleware.DeepCopyInto(&out.Middleware) + out.Service = in.Service if in.History != nil { in, out := &in.History, &out.History *out = make([]FunctionStatusHistoryEntry, len(*in)) @@ -167,6 +176,13 @@ func (in *FunctionStatus) DeepCopyInto(out *FunctionStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FunctionStatus. diff --git a/config/crd/bases/functions.dev_functions.yaml b/config/crd/bases/functions.dev_functions.yaml index 8ef81d8..55917cc 100644 --- a/config/crd/bases/functions.dev_functions.yaml +++ b/config/crd/bases/functions.dev_functions.yaml @@ -238,6 +238,13 @@ spec: type: object name: type: string + service: + properties: + ready: + type: string + url: + type: string + type: object required: - name type: object diff --git a/internal/controller/function_controller.go b/internal/controller/function_controller.go index 6fbf30c..f9ff283 100644 --- a/internal/controller/function_controller.go +++ b/internal/controller/function_controller.go @@ -255,6 +255,7 @@ type middlewareUpToDate struct { currentRevision string serviceReady string currentVersion string + serviceUrl string autoUpdate autoUpdateStatus } @@ -266,6 +267,7 @@ type middlewareOutdated struct { serviceReady string currentVersion string availableVersion string + serviceUrl string autoUpdate autoUpdateStatus } @@ -297,6 +299,7 @@ func (r *FunctionReconciler) checkMiddlewareState(ctx context.Context, function currentImage: desc.Image, currentRevision: desc.Revision, serviceReady: desc.Ready, + serviceUrl: desc.Route, currentVersion: desc.Middleware.Version, autoUpdate: autoUpdate, }, nil @@ -306,6 +309,7 @@ func (r *FunctionReconciler) checkMiddlewareState(ctx context.Context, function currentImage: desc.Image, currentRevision: desc.Revision, serviceReady: desc.Ready, + serviceUrl: desc.Route, currentVersion: desc.Middleware.Version, availableVersion: latestVersion, autoUpdate: autoUpdate, @@ -339,6 +343,8 @@ func (r *FunctionReconciler) handleMiddlewareUpdate(ctx context.Context, functio function.Status.Middleware.AutoUpdate.Enabled = check.autoUpdate.enabled function.Status.Middleware.AutoUpdate.Source = check.autoUpdate.source function.Status.Middleware.PendingRebuild = false + function.Status.Service.URL = check.serviceUrl + function.Status.Service.Ready = check.serviceReady markServiceStatus(check.serviceReady, function) function.MarkMiddlewareUpToDate() @@ -350,6 +356,8 @@ func (r *FunctionReconciler) handleMiddlewareUpdate(ctx context.Context, functio function.Status.Middleware.AutoUpdate.Source = check.autoUpdate.source function.Status.Middleware.Available = ptr.To(check.availableVersion) function.Status.Middleware.PendingRebuild = false + function.Status.Service.URL = check.serviceUrl + function.Status.Service.Ready = check.serviceReady markServiceStatus(check.serviceReady, function) if !check.autoUpdate.enabled { @@ -379,6 +387,8 @@ func (r *FunctionReconciler) handleMiddlewareUpdate(ctx context.Context, functio function.Status.Middleware.LastRebuild = metav1.Now() function.Status.Deployment.ImageBuilt = metav1.Now() function.Status.Middleware.Available = nil + function.Status.Service.URL = desc.Route + function.Status.Service.Ready = desc.Ready markServiceStatus(desc.Ready, function) function.RecordHistoryEvent(fmt.Sprintf("Middleware updated from %q to %q", check.currentVersion, check.availableVersion)) diff --git a/internal/controller/function_controller_test.go b/internal/controller/function_controller_test.go index 2431322..ad73467 100644 --- a/internal/controller/function_controller_test.go +++ b/internal/controller/function_controller_test.go @@ -321,7 +321,25 @@ var _ = Describe("Function Controller", func() { Expect(status.Middleware.Available).Should(BeNil()) }, }), + Entry("should populate Service information in the status", reconcileTestCase{ + spec: defaultSpec, + configureMocks: func(funcMock *funccli.MockManager, gitMock *git.MockManager) { + funcMock.EXPECT().Describe(mock.Anything, functionName, resourceNamespace).Return(functions.Instance{ + Middleware: functions.Middleware{ + Version: "v1.0.0", + }, + Ready: "true", + Route: "http://example.com", + }, nil) + funcMock.EXPECT().GetLatestMiddlewareVersion(mock.Anything, mock.Anything, mock.Anything).Return("v1.0.0", nil) + gitMock.EXPECT().CloneRepository(mock.Anything, "https://github.com/foo/bar", "", "my-branch", mock.Anything).Return(createTmpGitRepo(functions.Function{Name: "func-go"}), nil) + }, + statusChecks: func(status *functionsdevv1alpha1.FunctionStatus) { + Expect(status.Service.Ready).To(Equal("true")) + Expect(status.Service.URL).To(Equal("http://example.com")) + }, + }), Entry("should set ServiceReady condition to true when service is ready", reconcileTestCase{ spec: defaultSpec, configureMocks: func(funcMock *funccli.MockManager, gitMock *git.MockManager) { From eda91231801c339e48b39f03457dac8ccf995cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20St=C3=A4bler?= Date: Tue, 28 Apr 2026 09:54:17 +0200 Subject: [PATCH 2/2] Update readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b01f676..e255681 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ The status will include: - Git information (branch, commit, last checked time) - Deployment details (image, runtime, build time, deployer) - Middleware status (current and available versions, auto-update settings, pending rebuild status) +- Service status (URL and readiness) ## Advanced Use Cases @@ -325,6 +326,8 @@ make lint | `middleware.autoUpdate.source` | string | Source of the autoUpdate setting ("function" or "operator") | | `middleware.pendingRebuild` | boolean | Whether a rebuild is pending due to outdated middleware | | `middleware.lastRebuild` | timestamp | Last time the function was rebuilt for middleware updates | +| `service.url` | string | URL of the function's service | +| `service.ready` | string | Whether the function's service is ready (e.g., "true", "false", "UNKNOWN") | #### Status Conditions