Skip to content

Commit 4813765

Browse files
committed
Create v1alpha2/APIBindings
Signed-off-by: Marko Mudrinić <[email protected]> On-behalf-of: @SAP [email protected]
1 parent 538e5bc commit 4813765

31 files changed

+3145
-0
lines changed

config/crds/apis.kcp.io_apibindings.yaml

Lines changed: 414 additions & 0 deletions
Large diffs are not rendered by default.

pkg/openapi/zz_generated.openapi.go

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

sdk/apis/apis/v1alpha2/register.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ var (
4646
// Adds the list of known types to Scheme.
4747
func addKnownTypes(scheme *runtime.Scheme) error {
4848
scheme.AddKnownTypes(SchemeGroupVersion,
49+
&APIBinding{},
50+
&APIBindingList{},
51+
4952
&APIExport{},
5053
&APIExportList{},
5154
)
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
/*
2+
Copyright 2025 The KCP Authors.
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 v1alpha2
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
22+
conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1"
23+
)
24+
25+
// APIBinding enables a set of resources and their behaviour through an external
26+
// service provider in this workspace.
27+
//
28+
// The service provider uses an APIExport to expose the API.
29+
//
30+
// +crd
31+
// +genclient
32+
// +genclient:nonNamespaced
33+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
34+
// +kubebuilder:storageversion
35+
// +kubebuilder:subresource:status
36+
// +kubebuilder:resource:scope=Cluster,categories=kcp
37+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
38+
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=`.status.conditions[?(@.type=="Ready")].status`
39+
type APIBinding struct {
40+
metav1.TypeMeta `json:",inline"`
41+
// +optional
42+
metav1.ObjectMeta `json:"metadata,omitempty"`
43+
44+
// Spec holds the desired state.
45+
// +required
46+
// +kubebuilder:validation:Required
47+
Spec APIBindingSpec `json:"spec,omitempty"`
48+
49+
// Status communicates the observed state.
50+
// +optional
51+
Status APIBindingStatus `json:"status,omitempty"`
52+
}
53+
54+
func (in *APIBinding) GetConditions() conditionsv1alpha1.Conditions {
55+
return in.Status.Conditions
56+
}
57+
58+
func (in *APIBinding) SetConditions(conditions conditionsv1alpha1.Conditions) {
59+
in.Status.Conditions = conditions
60+
}
61+
62+
// APIBindingSpec records the APIs and implementations that are to be bound.
63+
type APIBindingSpec struct {
64+
// reference uniquely identifies an API to bind to.
65+
//
66+
// +required
67+
// +kubebuilder:validation:Required
68+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="APIExport reference must not be changed"
69+
Reference BindingReference `json:"reference"`
70+
71+
// permissionClaims records decisions about permission claims requested by the API service provider.
72+
// Individual claims can be accepted or rejected. If accepted, the API service provider gets the
73+
// requested access to the specified resources in this workspace. Access is granted per
74+
// GroupResource, identity, and other properties.
75+
//
76+
// +optional
77+
PermissionClaims []AcceptablePermissionClaim `json:"permissionClaims,omitempty"`
78+
}
79+
80+
// AcceptablePermissionClaim is a PermissionClaim that records if the user accepts or rejects it.
81+
type AcceptablePermissionClaim struct {
82+
PermissionClaim `json:",inline"`
83+
84+
// state indicates if the claim is accepted or rejected.
85+
86+
// +required
87+
// +kubebuilder:validation:Required
88+
// +kubebuilder:validation:Enum=Accepted;Rejected
89+
State AcceptablePermissionClaimState `json:"state"`
90+
}
91+
92+
type AcceptablePermissionClaimState string
93+
94+
const (
95+
ClaimAccepted AcceptablePermissionClaimState = "Accepted"
96+
ClaimRejected AcceptablePermissionClaimState = "Rejected"
97+
)
98+
99+
// BindingReference describes a reference to an APIExport. Exactly one of the
100+
// fields must be set.
101+
type BindingReference struct {
102+
// export is a reference to an APIExport by cluster name and export name.
103+
// The creator of the APIBinding needs to have access to the APIExport with the
104+
// verb `bind` in order to bind to it.
105+
//
106+
// +optional
107+
Export *ExportBindingReference `json:"export,omitempty"`
108+
}
109+
110+
// ExportBindingReference is a reference to an APIExport by cluster and name.
111+
type ExportBindingReference struct {
112+
// path is a logical cluster path where the APIExport is defined.
113+
// If the path is unset, the logical cluster of the APIBinding is used.
114+
//
115+
// +optional
116+
// +kubebuilder:validation:Pattern:="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(:[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"
117+
Path string `json:"path,omitempty"`
118+
119+
// name is the name of the APIExport that describes the API.
120+
//
121+
// +required
122+
// +kubebuilder:validation:Required
123+
// +kube:validation:MinLength=1
124+
Name string `json:"name"`
125+
}
126+
127+
// APIBindingPhaseType is the type of the current phase of an APIBinding.
128+
type APIBindingPhaseType string
129+
130+
const (
131+
APIBindingPhaseBinding APIBindingPhaseType = "Binding"
132+
APIBindingPhaseBound APIBindingPhaseType = "Bound"
133+
)
134+
135+
// APIBindingStatus records which schemas are bound.
136+
type APIBindingStatus struct {
137+
// APIExportClusterName records the name (not path) of the logical cluster that contains the APIExport.
138+
//
139+
// +optional
140+
APIExportClusterName string `json:"apiExportClusterName,omitempty"`
141+
142+
// boundResources records the state of bound APIs.
143+
//
144+
// +optional
145+
// +listType=map
146+
// +listMapKey=group
147+
// +listMapKey=resource
148+
BoundResources []BoundAPIResource `json:"boundResources,omitempty"`
149+
150+
// phase is the current phase of the APIBinding:
151+
// - "": the APIBinding has just been created, waiting to be bound.
152+
// - Binding: the APIBinding is being bound.
153+
// - Bound: the APIBinding is bound and the referenced APIs are available in the workspace.
154+
//
155+
// +optional
156+
// +kubebuilder:validation:Enum="";Binding;Bound
157+
Phase APIBindingPhaseType `json:"phase,omitempty"`
158+
159+
// conditions is a list of conditions that apply to the APIBinding.
160+
//
161+
// +optional
162+
Conditions conditionsv1alpha1.Conditions `json:"conditions,omitempty"`
163+
164+
// appliedPermissionClaims is a list of the permission claims the system has seen and applied,
165+
// according to the requests of the API service provider in the APIExport and the acceptance
166+
// state in spec.permissionClaims.
167+
//
168+
// +optional
169+
AppliedPermissionClaims []PermissionClaim `json:"appliedPermissionClaims,omitempty"`
170+
171+
// exportPermissionClaims records the permissions that the export provider is asking for
172+
// the binding to grant.
173+
// +optional
174+
ExportPermissionClaims []PermissionClaim `json:"exportPermissionClaims,omitempty"`
175+
}
176+
177+
// These are valid conditions of APIBinding.
178+
const (
179+
// APIExportValid is a condition for APIBinding that reflects the validity of the referenced APIExport.
180+
APIExportValid conditionsv1alpha1.ConditionType = "APIExportValid"
181+
182+
// APIExportInvalidReferenceReason is a reason for the APIExportValid condition of APIBinding that the referenced
183+
// APIExport reference is invalid.
184+
APIExportInvalidReferenceReason = "APIExportInvalidReference"
185+
// APIExportNotFoundReason is a reason for the APIExportValid condition that the referenced APIExport is not found.
186+
APIExportNotFoundReason = "APIExportNotFound"
187+
188+
// APIResourceSchemaInvalidReason is a reason for the InitialBindingCompleted and BindingUpToDate conditions when one of generated CRD is invalid.
189+
APIResourceSchemaInvalidReason = "APIResourceSchemaInvalid"
190+
191+
// InternalErrorReason is a reason used by multiple conditions that something went wrong.
192+
InternalErrorReason = "InternalError"
193+
194+
// InitialBindingCompleted is a condition for APIBinding that indicates the initial binding completed successfully.
195+
// Once true, this can never be reset to false.
196+
InitialBindingCompleted conditionsv1alpha1.ConditionType = "InitialBindingCompleted"
197+
198+
// LogicalClusterNotFoundReason is a reason for the InitialBindingCompleted condition that
199+
// the LogicalCluster has not been found.
200+
LogicalClusterNotFoundReason = "LogicalClusterNotFound"
201+
202+
// WaitingForEstablishedReason is a reason for the InitialBindingCompleted condition that the bound CRDs are not ready.
203+
WaitingForEstablishedReason = "WaitingForEstablished"
204+
205+
// BindingUpToDate is a condition for APIBinding that indicates that the APIs currently bound are up-to-date with
206+
// the binding's desired export.
207+
BindingUpToDate conditionsv1alpha1.ConditionType = "BindingUpToDate"
208+
209+
// NamingConflictsReason is a reason for the BindingUpToDate condition that at least one API coming in from the APIBinding
210+
// has a naming conflict with other APIs.
211+
NamingConflictsReason = "NamingConflicts"
212+
213+
// BindingResourceDeleteSuccess is a condition for APIBinding that indicates the resources relating this binding are deleted
214+
// successfully when the APIBinding is deleting.
215+
BindingResourceDeleteSuccess conditionsv1alpha1.ConditionType = "BindingResourceDeleteSuccess"
216+
217+
// PermissionClaimsValid is a condition for APIBinding that indicates that the permission claims were valid or not.
218+
PermissionClaimsValid conditionsv1alpha1.ConditionType = "PermissionClaimsValid"
219+
220+
// InvalidPermissionClaimsReason indicates there were unexpected and/or invalid permission claims (e.g. due to
221+
// identity mismatch).
222+
InvalidPermissionClaimsReason = "InvalidPermissionClaims"
223+
224+
// PermissionClaimsApplied is a condition for APIBinding that indicates that all the accepted permission claims
225+
// have been applied.
226+
PermissionClaimsApplied conditionsv1alpha1.ConditionType = "PermissionClaimsApplied"
227+
)
228+
229+
// BoundAPIResource describes a bound GroupVersionResource through an APIResourceSchema of an APIExport..
230+
type BoundAPIResource struct {
231+
// group is the group of the bound API. Empty string for the core API group.
232+
//
233+
// +required
234+
Group string `json:"group"`
235+
236+
// resource is the resource of the bound API.
237+
//
238+
// kubebuilder:validation:MinLength=1
239+
// +required
240+
Resource string `json:"resource"`
241+
242+
// Schema references the APIResourceSchema that is bound to this API.
243+
//
244+
// +required
245+
Schema BoundAPIResourceSchema `json:"schema"`
246+
247+
// storageVersions lists all versions of a resource that were ever persisted. Tracking these
248+
// versions allows a migration path for stored versions in etcd. The field is mutable
249+
// so a migration controller can finish a migration to another version (ensuring
250+
// no old objects are left in storage), and then remove the rest of the
251+
// versions from this list.
252+
//
253+
// Versions may not be removed while they exist in this list.
254+
//
255+
// +optional
256+
// +listType=set
257+
StorageVersions []string `json:"storageVersions,omitempty"`
258+
}
259+
260+
// BoundAPIResourceSchema is a reference to an APIResourceSchema.
261+
type BoundAPIResourceSchema struct {
262+
// name is the bound APIResourceSchema name.
263+
//
264+
// +required
265+
// +kubebuilder:validation:MinLength=1
266+
Name string `json:"name"`
267+
268+
// UID is the UID of the APIResourceSchema that is bound to this API.
269+
//
270+
// +required
271+
// +kubebuilder:validation:MinLength=1
272+
UID string `json:"UID"`
273+
274+
// identityHash is the hash of the API identity that this schema is bound to.
275+
// The API identity determines the etcd prefix used to persist the object.
276+
// Different identity means that the objects are effectively served and stored
277+
// under a distinct resource. A CRD of the same GroupVersionResource uses a
278+
// different identity and hence a separate etcd prefix.
279+
//
280+
// +required
281+
// +kubebuilder:validation:MinLength=1
282+
IdentityHash string `json:"identityHash"`
283+
}
284+
285+
// APIBindingList is a list of APIBinding resources
286+
//
287+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
288+
type APIBindingList struct {
289+
metav1.TypeMeta `json:",inline"`
290+
metav1.ListMeta `json:"metadata"`
291+
292+
Items []APIBinding `json:"items"`
293+
}

0 commit comments

Comments
 (0)