Skip to content

Commit 600abe8

Browse files
committed
move preemptive requests into own API type (todo: tests)
1 parent 44f1238 commit 600abe8

36 files changed

+1426
-864
lines changed

api/clusters/v1alpha1/clusterrequest_types.go

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,6 @@ type ClusterRequestSpec struct {
99
// Purpose is the purpose of the requested cluster.
1010
// +kubebuilder:validation:MinLength=1
1111
Purpose string `json:"purpose"`
12-
13-
// Preemptive determines whether the request is preemptive.
14-
// Preemptive requests are used to create clusters in advance, so that they are ready when needed.
15-
// AccessRequests for preemptive clusters are not allowed.
16-
// +optional
17-
// +kubebuilder:default=false
18-
Preemptive bool `json:"preemptive,omitempty"`
1912
}
2013

2114
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.cluster) || has(self.cluster)", message="cluster may not be removed once set"
@@ -53,11 +46,9 @@ func (p RequestPhase) IsPending() bool {
5346
// +kubebuilder:resource:shortName=cr;creq
5447
// +kubebuilder:metadata:labels="openmcp.cloud/cluster=platform"
5548
// +kubebuilder:selectablefield:JSONPath=".spec.purpose"
56-
// +kubebuilder:selectablefield:JSONPath=".spec.preemptive"
5749
// +kubebuilder:selectablefield:JSONPath=".status.phase"
5850
// +kubebuilder:printcolumn:JSONPath=".spec.purpose",name="Purpose",type=string
5951
// +kubebuilder:printcolumn:JSONPath=".status.phase",name="Phase",type=string
60-
// +kubebuilder:printcolumn:JSONPath=".spec.preemptive",name="Preemptive",type=string
6152
// +kubebuilder:printcolumn:JSONPath=".status.cluster.name",name="Cluster",type=string
6253
// +kubebuilder:printcolumn:JSONPath=".status.cluster.namespace",name="Cluster-NS",type=string
6354

@@ -86,9 +77,5 @@ func init() {
8677
// FinalizerForCluster returns the finalizer that is used to mark that a specific request has pointed to a specific cluster.
8778
// Apart from preventing the Cluster's deletion, this information is used to recover the Cluster if the status of the ClusterRequest ever gets lost.
8879
func (cr *ClusterRequest) FinalizerForCluster() string {
89-
prefix := RequestFinalizerOnClusterPrefix
90-
if cr.Spec.Preemptive {
91-
prefix = PreemptiveRequestFinalizerOnClusterPrefix
92-
}
93-
return prefix + string(cr.UID)
80+
return RequestFinalizerOnClusterPrefix + string(cr.UID)
9481
}

api/clusters/v1alpha1/constants/reasons.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ const (
1111
ReasonConfigurationProblem = "ConfigurationProblem"
1212
// ReasonInternalError indicates that something went wrong internally.
1313
ReasonInternalError = "InternalError"
14-
// ReasonPreemptiveRequest indicates that the ClusterRequest is preemptive and AccessRequests referencing it are denied.
15-
ReasonPreemptiveRequest = "PreemptiveRequest"
1614
// ReasonSchedulingFailed indicates that there was a problem with scheduling a request.
1715
ReasonSchedulingFailed = "SchedulingFailed"
1816
)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package v1alpha1
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
)
6+
7+
type PreemptiveClusterRequestSpec struct {
8+
// Purpose is the purpose of the requested cluster.
9+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="purpose is immutable"
10+
// +kubebuilder:validation:MinLength=1
11+
Purpose string `json:"purpose"`
12+
13+
// Workload specifies for how many workloads this preemptive cluster request should account.
14+
// Must be greater than 0.
15+
// +kubebuilder:validation:Minimum=1
16+
Workload int `json:"workload"`
17+
}
18+
19+
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.cluster) || has(self.cluster)", message="cluster may not be removed once set"
20+
type PreemptiveClusterRequestStatus struct {
21+
CommonStatus `json:",inline"`
22+
23+
// Phase is the current phase of the request.
24+
// +kubebuilder:default=Pending
25+
// +kubebuilder:validation:Enum=Pending;Granted;Denied
26+
Phase RequestPhase `json:"phase"`
27+
}
28+
29+
// +kubebuilder:object:root=true
30+
// +kubebuilder:subresource:status
31+
// +kubebuilder:resource:shortName=pcr;pcreq
32+
// +kubebuilder:metadata:labels="openmcp.cloud/cluster=platform"
33+
// +kubebuilder:selectablefield:JSONPath=".spec.purpose"
34+
// +kubebuilder:selectablefield:JSONPath=".status.phase"
35+
// +kubebuilder:printcolumn:JSONPath=".spec.purpose",name="Purpose",type=string
36+
// +kubebuilder:printcolumn:JSONPath=".spec.workload",name="Workload",type=string
37+
// +kubebuilder:printcolumn:JSONPath=".status.phase",name="Phase",type=string
38+
39+
type PreemptiveClusterRequest struct {
40+
metav1.TypeMeta `json:",inline"`
41+
metav1.ObjectMeta `json:"metadata,omitempty"`
42+
43+
Spec PreemptiveClusterRequestSpec `json:"spec,omitempty"`
44+
Status PreemptiveClusterRequestStatus `json:"status,omitempty"`
45+
}
46+
47+
// +kubebuilder:object:root=true
48+
49+
// PreemptiveClusterRequestList contains a list of Cluster
50+
type PreemptiveClusterRequestList struct {
51+
metav1.TypeMeta `json:",inline"`
52+
metav1.ListMeta `json:"metadata,omitempty"`
53+
Items []PreemptiveClusterRequest `json:"items"`
54+
}
55+
56+
func init() {
57+
SchemeBuilder.Register(&PreemptiveClusterRequest{}, &PreemptiveClusterRequestList{})
58+
}
59+
60+
// FinalizerForCluster returns the finalizer that is used to mark that a specific request has pointed to a specific cluster.
61+
// Apart from preventing the Cluster's deletion, this information is used to recover the Cluster if the status of the PreemptiveClusterRequest ever gets lost.
62+
func (cr *PreemptiveClusterRequest) FinalizerForCluster() string {
63+
return PreemptiveRequestFinalizerOnClusterPrefix + string(cr.UID)
64+
}

api/clusters/v1alpha1/zz_generated.deepcopy.go

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

api/crds/manifests/clusters.openmcp.cloud_clusterrequests.yaml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ spec:
2626
- jsonPath: .status.phase
2727
name: Phase
2828
type: string
29-
- jsonPath: .spec.preemptive
30-
name: Preemptive
31-
type: string
3229
- jsonPath: .status.cluster.name
3330
name: Cluster
3431
type: string
@@ -59,13 +56,6 @@ spec:
5956
type: object
6057
spec:
6158
properties:
62-
preemptive:
63-
default: false
64-
description: |-
65-
Preemptive determines whether the request is preemptive.
66-
Preemptive requests are used to create clusters in advance, so that they are ready when needed.
67-
AccessRequests for preemptive clusters are not allowed.
68-
type: boolean
6959
purpose:
7060
description: Purpose is the purpose of the requested cluster.
7161
minLength: 1
@@ -168,7 +158,6 @@ spec:
168158
type: object
169159
selectableFields:
170160
- jsonPath: .spec.purpose
171-
- jsonPath: .spec.preemptive
172161
- jsonPath: .status.phase
173162
served: true
174163
storage: true
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.17.3
7+
labels:
8+
openmcp.cloud/cluster: platform
9+
name: preemptiveclusterrequests.clusters.openmcp.cloud
10+
spec:
11+
group: clusters.openmcp.cloud
12+
names:
13+
kind: PreemptiveClusterRequest
14+
listKind: PreemptiveClusterRequestList
15+
plural: preemptiveclusterrequests
16+
shortNames:
17+
- pcr
18+
- pcreq
19+
singular: preemptiveclusterrequest
20+
scope: Namespaced
21+
versions:
22+
- additionalPrinterColumns:
23+
- jsonPath: .spec.purpose
24+
name: Purpose
25+
type: string
26+
- jsonPath: .spec.workloadCount
27+
name: Workload
28+
type: string
29+
- jsonPath: .status.phase
30+
name: Phase
31+
type: string
32+
name: v1alpha1
33+
schema:
34+
openAPIV3Schema:
35+
properties:
36+
apiVersion:
37+
description: |-
38+
APIVersion defines the versioned schema of this representation of an object.
39+
Servers should convert recognized schemas to the latest internal value, and
40+
may reject unrecognized values.
41+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
42+
type: string
43+
kind:
44+
description: |-
45+
Kind is a string value representing the REST resource this object represents.
46+
Servers may infer this from the endpoint the client submits requests to.
47+
Cannot be updated.
48+
In CamelCase.
49+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
50+
type: string
51+
metadata:
52+
type: object
53+
spec:
54+
properties:
55+
purpose:
56+
description: Purpose is the purpose of the requested cluster.
57+
minLength: 1
58+
type: string
59+
x-kubernetes-validations:
60+
- message: purpose is immutable
61+
rule: self == oldSelf
62+
workloadCount:
63+
description: |-
64+
WorkloadCount specifies for how many workloads this preemptive cluster request should account.
65+
Must be greater than 0.
66+
minimum: 1
67+
type: integer
68+
required:
69+
- purpose
70+
- workloadCount
71+
type: object
72+
status:
73+
properties:
74+
conditions:
75+
description: Conditions contains the conditions.
76+
items:
77+
properties:
78+
lastTransitionTime:
79+
description: LastTransitionTime specifies the time when this
80+
condition's status last changed.
81+
format: date-time
82+
type: string
83+
message:
84+
description: |-
85+
Message contains further details regarding the condition.
86+
It is meant for human users, Reason should be used for programmatic evaluation instead.
87+
It is optional, but should be filled at least when Status is not "True".
88+
type: string
89+
reason:
90+
description: |-
91+
Reason is expected to contain a CamelCased string that provides further information regarding the condition.
92+
It should have a fixed value set (like an enum) to be machine-readable. The value set depends on the condition type.
93+
It is optional, but should be filled at least when Status is not "True".
94+
type: string
95+
status:
96+
description: Status is the status of the condition.
97+
type: string
98+
type:
99+
description: |-
100+
Type is the type of the condition.
101+
Must be unique within the resource.
102+
type: string
103+
required:
104+
- status
105+
- type
106+
type: object
107+
type: array
108+
lastReconcileTime:
109+
description: LastReconcileTime is the time when the resource was last
110+
reconciled by the controller.
111+
format: date-time
112+
type: string
113+
message:
114+
description: Message contains further details in a human-readable
115+
format.
116+
type: string
117+
observedGeneration:
118+
description: ObservedGeneration is the generation of this resource
119+
that was last reconciled by the controller.
120+
format: int64
121+
type: integer
122+
phase:
123+
default: Pending
124+
description: Phase is the current phase of the request.
125+
enum:
126+
- Pending
127+
- Granted
128+
- Denied
129+
type: string
130+
reason:
131+
description: Reason is expected to contain a CamelCased string that
132+
provides further information in a machine-readable format.
133+
type: string
134+
required:
135+
- lastReconcileTime
136+
- observedGeneration
137+
- phase
138+
type: object
139+
x-kubernetes-validations:
140+
- message: cluster may not be removed once set
141+
rule: '!has(oldSelf.cluster) || has(self.cluster)'
142+
type: object
143+
selectableFields:
144+
- jsonPath: .spec.purpose
145+
- jsonPath: .status.phase
146+
served: true
147+
storage: true
148+
subresources:
149+
status: {}

0 commit comments

Comments
 (0)