Skip to content

Commit 05a5756

Browse files
authored
Add conditions to httpbin CRs (#31)
* Add conditions to httpbin CRs Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com> On-behalf-of: @SAP karol.szwaj@sap.com * Update go mod Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com> On-behalf-of: @SAP karol.szwaj@sap.com * Update conditions set on the controller Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com> On-behalf-of: @SAP karol.szwaj@sap.com * generate manifests Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com> On-behalf-of: @SAP karol.szwaj@sap.com * Update conditions set on the controller Signed-off-by: Karol Szwaj <karol.szwaj@gmail.com> On-behalf-of: @SAP karol.szwaj@sap.com
1 parent 8d58523 commit 05a5756

11 files changed

Lines changed: 253 additions & 46 deletions

api/v1alpha1/httpbin_types.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,26 @@ import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2121
)
2222

23+
// HttpBinConditionType represents a condition type for HttpBin
24+
type HttpBinConditionType string
25+
26+
// HttpBinConditionReason represents a reason for a condition's last transition
27+
type HttpBinConditionReason string
28+
29+
const (
30+
// HttpBinConditionTypeReady represents whether the HttpBin resource is fully available.
31+
HttpBinConditionTypeReady = "Ready"
32+
33+
// HttpBinConditionReasonDeploymentReady means the Deployment is available and serving.
34+
HttpBinConditionReasonDeploymentReady = "DeploymentReady"
35+
36+
// HttpBinConditionReasonDeploymentProgressing means the Deployment exists but is not yet available.
37+
HttpBinConditionReasonDeploymentProgressing = "DeploymentProgressing"
38+
39+
// HttpBinConditionReasonDeploymentFailed means the Deployment could not be created.
40+
HttpBinConditionReasonDeploymentFailed = "DeploymentFailed"
41+
)
42+
2343
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
2444
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
2545

@@ -38,6 +58,10 @@ type HttpBinSpec struct {
3858

3959
// HttpBinStatus defines the observed state of HttpBin
4060
type HttpBinStatus struct {
61+
// Conditions represent the latest available observations of an object's state
62+
// +optional
63+
Conditions []metav1.Condition `json:"conditions,omitempty"`
64+
4165
// URL is the HTTPS URL for accessing the httpbin service
4266
// Format: https://HOST
4367
// +optional

api/v1alpha1/httpbindeployment_types.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,31 @@ import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2121
)
2222

23+
// HttpBinDeploymentConditionType represents a condition type for HttpBinDeployment
24+
type HttpBinDeploymentConditionType string
25+
26+
// HttpBinDeploymentConditionReason represents a reason for a condition status change
27+
type HttpBinDeploymentConditionReason string
28+
29+
const (
30+
// HttpBinDeploymentConditionReady indicates that the HttpBin instance is ready
31+
HttpBinDeploymentConditionTypeReady = "Ready"
32+
// HttpBinDeploymentConditionTypeServiceExposed indicates that the HttpBin instance Service ports or ingress have been created.
33+
HttpBinDeploymentConditionTypeServiceExposed = "ServiceExposed"
34+
// HttpBinDeploymentConditionTypeHttpBinInstanceCreated indicates that the HttpBin instance Deployment has been created.
35+
HttpBinDeploymentConditionTypeHttpBinInstanceCreated = "HttpBinInstanceCreated"
36+
// HttpBinDeploymentConditionTypeEndpointReady indicates that the HttpBin instance Endpoint is up and ready to serve.
37+
HttpBinDeploymentConditionTypeEndpointReady = "HttpBinEndpointReady"
38+
// HttpBinDeploymentConditionReasonReady means the HttpBin instance components are ready.
39+
HttpBinDeploymentConditionReasonReady = "Ready"
40+
// HttpBinDeploymentConditionReasonHttpBinInstanceProgressing means the HttpBin instance Deployment is in progress.
41+
HttpBinDeploymentConditionReasonHttpBinInstanceProgressing = "HttpBinInstanceProgressing"
42+
// HttpBinDeploymentConditionReasonDeploymentFailed means the HttpBin instance Deployment failed to be created.
43+
HttpBinDeploymentConditionReasonHttpBinInstanceFailed = "HttpBinInstanceFailed"
44+
// HttpBinDeploymentConditionReasonServiceFailed means the HttpBin instance Service ports or ingress failed to be created.
45+
HttpBinDeploymentConditionReasonHttpBinServiceExposureFailed = "ServiceExposureFailed"
46+
)
47+
2348
// ServiceConfig defines the configuration for the HttpBin service
2449
type ServiceConfig struct {
2550
// Name is the name of the service. If not provided, the HttpBinDeployment name will be used.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/example-httpbin-operator/crds/orchestrate.platform-mesh.io_httpbindeployments.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: httpbindeployments.orchestrate.platform-mesh.io
88
spec:
99
group: orchestrate.platform-mesh.io

charts/example-httpbin-operator/crds/orchestrate.platform-mesh.io_httpbins.yaml

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: httpbins.orchestrate.platform-mesh.io
88
spec:
99
group: orchestrate.platform-mesh.io
@@ -54,6 +54,64 @@ spec:
5454
status:
5555
description: HttpBinStatus defines the observed state of HttpBin
5656
properties:
57+
conditions:
58+
description: Conditions represent the latest available observations
59+
of an object's state
60+
items:
61+
description: Condition contains details for one aspect of the current
62+
state of this API Resource.
63+
properties:
64+
lastTransitionTime:
65+
description: |-
66+
lastTransitionTime is the last time the condition transitioned from one status to another.
67+
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
68+
format: date-time
69+
type: string
70+
message:
71+
description: |-
72+
message is a human readable message indicating details about the transition.
73+
This may be an empty string.
74+
maxLength: 32768
75+
type: string
76+
observedGeneration:
77+
description: |-
78+
observedGeneration represents the .metadata.generation that the condition was set based upon.
79+
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
80+
with respect to the current state of the instance.
81+
format: int64
82+
minimum: 0
83+
type: integer
84+
reason:
85+
description: |-
86+
reason contains a programmatic identifier indicating the reason for the condition's last transition.
87+
Producers of specific condition types may define expected values and meanings for this field,
88+
and whether the values are considered a guaranteed API.
89+
The value should be a CamelCase string.
90+
This field may not be empty.
91+
maxLength: 1024
92+
minLength: 1
93+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
94+
type: string
95+
status:
96+
description: status of the condition, one of True, False, Unknown.
97+
enum:
98+
- "True"
99+
- "False"
100+
- Unknown
101+
type: string
102+
type:
103+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
104+
maxLength: 316
105+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
106+
type: string
107+
required:
108+
- lastTransitionTime
109+
- message
110+
- reason
111+
- status
112+
- type
113+
type: object
114+
type: array
57115
ready:
58116
description: Ready indicates if the underlying HttpBinDeployment's
59117
deployment is ready

config/crd/bases/orchestrate.platform-mesh.io_httpbindeployments.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: httpbindeployments.orchestrate.platform-mesh.io
88
spec:
99
group: orchestrate.platform-mesh.io

config/crd/bases/orchestrate.platform-mesh.io_httpbins.yaml

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.18.0
6+
controller-gen.kubebuilder.io/version: v0.19.0
77
name: httpbins.orchestrate.platform-mesh.io
88
spec:
99
group: orchestrate.platform-mesh.io
@@ -54,6 +54,64 @@ spec:
5454
status:
5555
description: HttpBinStatus defines the observed state of HttpBin
5656
properties:
57+
conditions:
58+
description: Conditions represent the latest available observations
59+
of an object's state
60+
items:
61+
description: Condition contains details for one aspect of the current
62+
state of this API Resource.
63+
properties:
64+
lastTransitionTime:
65+
description: |-
66+
lastTransitionTime is the last time the condition transitioned from one status to another.
67+
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
68+
format: date-time
69+
type: string
70+
message:
71+
description: |-
72+
message is a human readable message indicating details about the transition.
73+
This may be an empty string.
74+
maxLength: 32768
75+
type: string
76+
observedGeneration:
77+
description: |-
78+
observedGeneration represents the .metadata.generation that the condition was set based upon.
79+
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
80+
with respect to the current state of the instance.
81+
format: int64
82+
minimum: 0
83+
type: integer
84+
reason:
85+
description: |-
86+
reason contains a programmatic identifier indicating the reason for the condition's last transition.
87+
Producers of specific condition types may define expected values and meanings for this field,
88+
and whether the values are considered a guaranteed API.
89+
The value should be a CamelCase string.
90+
This field may not be empty.
91+
maxLength: 1024
92+
minLength: 1
93+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
94+
type: string
95+
status:
96+
description: status of the condition, one of True, False, Unknown.
97+
enum:
98+
- "True"
99+
- "False"
100+
- Unknown
101+
type: string
102+
type:
103+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
104+
maxLength: 316
105+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
106+
type: string
107+
required:
108+
- lastTransitionTime
109+
- message
110+
- reason
111+
- status
112+
- type
113+
type: object
114+
type: array
57115
ready:
58116
description: Ready indicates if the underlying HttpBinDeployment's
59117
deployment is ready

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tool (
77
github.com/kcp-dev/kcp/sdk/cmd/apigen
88
sigs.k8s.io/controller-runtime/tools/setup-envtest
99
sigs.k8s.io/controller-tools/cmd/controller-gen
10-
sigs.k8s.io/kubebuilder/v3/cmd
10+
sigs.k8s.io/kubebuilder/v4/cmd
1111
sigs.k8s.io/kustomize/kustomize/v5
1212
)
1313

go.sum

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy
302302
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
303303
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
304304
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
305+
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
306+
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
307+
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
308+
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
305309
github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo=
306310
github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw=
307311
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
@@ -851,8 +855,7 @@ sigs.k8s.io/e2e-framework v0.6.0 h1:p7hFzHnLKO7eNsWGI2AbC1Mo2IYxidg49BiT4njxkrM=
851855
sigs.k8s.io/e2e-framework v0.6.0/go.mod h1:IREnCHnKgRCioLRmNi0hxSJ1kJ+aAdjEKK/gokcZu4k=
852856
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
853857
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
854-
sigs.k8s.io/kubebuilder/v3 v3.15.1 h1:a01OIfeZOew3gB2T65D97UxLC5zeEHy8FrNIgx349BE=
855-
sigs.k8s.io/kubebuilder/v3 v3.15.1/go.mod h1:/QwYUyLicWiNcdMAmV5lfWoslWz9Ro9L+AK8UQrQxbI=
858+
sigs.k8s.io/kubebuilder/v4 v4.9.0 h1:9e9LnQy/wQ24IZDIqye6iZZFOB9aKNyNfjnfsy3S8cw=
856859
sigs.k8s.io/kubebuilder/v4 v4.9.0/go.mod h1:Xql7wLeyXBQ4lJJdi1Pl8T/DeV4UXpA1kaOEumN0pzY=
857860
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=
858861
sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM=

internal/controller/httpbin_controller.go

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
orchestratev1alpha1 "http-operator/api/v1alpha1"
2626

2727
"k8s.io/apimachinery/pkg/api/errors"
28+
"k8s.io/apimachinery/pkg/api/meta"
2829
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2930
"k8s.io/apimachinery/pkg/runtime"
3031
"k8s.io/apimachinery/pkg/types"
@@ -114,11 +115,6 @@ func (r *HttpBinReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
114115
},
115116
}
116117

117-
logger.Info("Created HttpBinDeployment object",
118-
"HttpBinDeployment.Name", httpBinDeployment.Name,
119-
"HttpBinDeployment.Namespace", httpBinDeployment.Namespace,
120-
"HttpBinDeployment.Spec", httpBinDeployment.Spec)
121-
122118
// Set HttpBin instance as the owner and controller
123119
if err := controllerutil.SetControllerReference(httpBin, httpBinDeployment, r.Scheme); err != nil {
124120
logger.Error(err, "Failed to set controller reference",
@@ -145,12 +141,16 @@ func (r *HttpBinReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
145141
"error_forbidden", errors.IsForbidden(err),
146142
"error_invalid", errors.IsInvalid(err),
147143
"error_already_exists", errors.IsAlreadyExists(err))
144+
145+
setHttpBinConditionStatusCondition(httpBin, metav1.ConditionFalse, orchestratev1alpha1.HttpBinConditionReasonDeploymentFailed, "Failed to create HttpBinDeployment: "+err.Error())
146+
_ = r.RemoteClient.Status().Update(ctx, httpBin)
148147
return ctrl.Result{}, err
149148
}
150149

151150
logger.Info("Successfully created HttpBinDeployment in remote cluster",
152151
"HttpBinDeployment.Namespace", httpBinDeployment.Namespace,
153-
"HttpBinDeployment.Name", httpBinDeployment.Name)
152+
"HttpBinDeployment.Name", httpBinDeployment.Name,
153+
"HttpBinDeployment.Spec", httpBinDeployment.Spec)
154154

155155
// Deployment created successfully - return and requeue
156156
return ctrl.Result{Requeue: true}, nil
@@ -170,39 +170,38 @@ func (r *HttpBinReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
170170
"HttpBinDeployment.Spec", found.Spec,
171171
"HttpBinDeployment.Status", found.Status)
172172

173-
// Update HttpBin status based on HttpBinDeployment status
174-
statusNeedsUpdate := false
175-
176-
// Format URL as https://HOST
177-
if found.Status.URL != "" {
178-
if httpBin.Status.URL != found.Status.URL {
179-
httpBin.Status.URL = found.Status.URL
180-
statusNeedsUpdate = true
181-
}
182-
}
173+
httpBin.Status.URL = found.Status.URL
174+
httpBin.Status.Ready = found.Status.IsDeploymentReady
183175

184-
// Sync ready status from HttpBinDeployment
185-
if httpBin.Status.Ready != found.Status.IsDeploymentReady {
186-
httpBin.Status.Ready = found.Status.IsDeploymentReady
187-
statusNeedsUpdate = true
176+
if found.Status.IsDeploymentReady {
177+
setHttpBinConditionStatusCondition(httpBin, metav1.ConditionTrue, orchestratev1alpha1.HttpBinConditionReasonDeploymentReady, "HttpBin is deployed and URL is available")
178+
} else {
179+
setHttpBinConditionStatusCondition(httpBin, metav1.ConditionFalse, orchestratev1alpha1.HttpBinConditionReasonDeploymentProgressing, "Deployment exists but is not yet available")
188180
}
189181

190-
// Update status if needed
191-
if statusNeedsUpdate {
192-
logger.Info("Updating HttpBin status",
193-
"URL", httpBin.Status.URL,
194-
"Ready", httpBin.Status.Ready)
182+
logger.Info("Updating HttpBin status",
183+
"URL", httpBin.Status.URL,
184+
"Ready", httpBin.Status.Ready,
185+
"Conditions", httpBin.Status.Conditions)
195186

196-
err = r.RemoteClient.Status().Update(ctx, httpBin)
197-
if err != nil {
198-
logger.Error(err, "Failed to update HttpBin status")
199-
return ctrl.Result{}, err
200-
}
187+
if err := r.RemoteClient.Status().Update(ctx, httpBin); err != nil {
188+
logger.Error(err, "Failed to update HttpBin status")
189+
return ctrl.Result{}, err
201190
}
202191

203192
return ctrl.Result{}, nil
204193
}
205194

195+
func setHttpBinConditionStatusCondition(httpBin *orchestratev1alpha1.HttpBin, status metav1.ConditionStatus, reason, message string) {
196+
meta.SetStatusCondition(&httpBin.Status.Conditions, metav1.Condition{
197+
Type: orchestratev1alpha1.HttpBinConditionTypeReady,
198+
Status: status,
199+
Reason: reason,
200+
Message: message,
201+
ObservedGeneration: httpBin.GetGeneration(),
202+
})
203+
}
204+
206205
// SetupWithManager sets up the controller with the Manager.
207206
func (r *HttpBinReconciler) SetupWithManager(remoteMgr ctrl.Manager) error {
208207
return ctrl.NewControllerManagedBy(remoteMgr).

0 commit comments

Comments
 (0)