Skip to content

Commit 6702061

Browse files
committed
Replace per-provider VW clusters with per-consumer×provider staging workspaces
Watch and sync changes to related resources fix the reconciler fix the linter fix the linter
1 parent c421771 commit 6702061

File tree

11 files changed

+1563
-216
lines changed

11 files changed

+1563
-216
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
Copyright The Platform Mesh Authors.
3+
SPDX-License-Identifier: Apache-2.0
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package v1alpha1
19+
20+
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
22+
// StagingWorkspaceSpec defines the desired state of StagingWorkspace.
23+
type StagingWorkspaceSpec struct {
24+
// ConsumerCluster is the logical cluster name of the consumer workspace.
25+
// +kubebuilder:validation:Required
26+
ConsumerCluster string `json:"consumerCluster"`
27+
28+
// ProviderPath is the KCP workspace path of the provider
29+
// (value of the kcp.io/path annotation on AcceptAPI objects).
30+
// +kubebuilder:validation:Required
31+
ProviderPath string `json:"providerPath"`
32+
33+
// APIExportName is the name of the provider's APIExport to bind in the
34+
// staging workspace.
35+
// +kubebuilder:validation:Required
36+
APIExportName string `json:"apiExportName"`
37+
38+
// WorkspaceTreeRoot is the KCP workspace path under which the staging
39+
// workspace will be created (e.g. "root:rb").
40+
// +kubebuilder:validation:Required
41+
WorkspaceTreeRoot string `json:"workspaceTreeRoot"`
42+
}
43+
44+
// StagingWorkspacePhase is the lifecycle phase of a StagingWorkspace.
45+
type StagingWorkspacePhase string
46+
47+
const (
48+
// StagingWorkspacePhasePending indicates the staging workspace is being provisioned.
49+
StagingWorkspacePhasePending StagingWorkspacePhase = "Pending"
50+
// StagingWorkspacePhaseReady indicates the staging workspace is fully provisioned and ready for use.
51+
StagingWorkspacePhaseReady StagingWorkspacePhase = "Ready"
52+
// StagingWorkspacePhaseFailed indicates the staging workspace could not be provisioned.
53+
StagingWorkspacePhaseFailed StagingWorkspacePhase = "Failed"
54+
)
55+
56+
// StagingWorkspaceStatus defines the observed state of StagingWorkspace.
57+
type StagingWorkspaceStatus struct {
58+
// WorkspaceURL is the direct access URL of the created KCP staging
59+
// workspace. Set once the workspace reaches the Ready phase.
60+
// +optional
61+
WorkspaceURL string `json:"workspaceURL,omitempty"`
62+
63+
// Phase is the current lifecycle phase.
64+
// +optional
65+
Phase StagingWorkspacePhase `json:"phase,omitempty"`
66+
67+
// Conditions represent the current state of the StagingWorkspace.
68+
// +listType=map
69+
// +listMapKey=type
70+
// +optional
71+
Conditions []metav1.Condition `json:"conditions,omitempty"`
72+
}
73+
74+
// +kubebuilder:object:root=true
75+
// +kubebuilder:resource:scope=Cluster
76+
// +kubebuilder:subresource:status
77+
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase"
78+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
79+
80+
// StagingWorkspace represents a per-consumer×provider staging KCP workspace.
81+
// resource-broker creates one for each unique (consumer workspace, provider
82+
// workspace) pair and uses it to write consumer CRs that the provider's
83+
// api-syncagent can pick up via the APIExport virtual workspace.
84+
type StagingWorkspace struct {
85+
metav1.TypeMeta `json:",inline"`
86+
metav1.ObjectMeta `json:"metadata,omitempty"`
87+
88+
Spec StagingWorkspaceSpec `json:"spec,omitempty"`
89+
Status StagingWorkspaceStatus `json:"status,omitempty"`
90+
}
91+
92+
// +kubebuilder:object:root=true
93+
94+
// StagingWorkspaceList contains a list of StagingWorkspace.
95+
type StagingWorkspaceList struct {
96+
metav1.TypeMeta `json:",inline"`
97+
metav1.ListMeta `json:"metadata,omitempty"`
98+
Items []StagingWorkspace `json:"items"`
99+
}
100+
101+
func init() {
102+
SchemeBuilder.Register(&StagingWorkspace{}, &StagingWorkspaceList{})
103+
}

api/broker/v1alpha1/zz_generated.deepcopy.go

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.17.2
7+
name: stagingworkspaces.broker.platform-mesh.io
8+
spec:
9+
group: broker.platform-mesh.io
10+
names:
11+
kind: StagingWorkspace
12+
listKind: StagingWorkspaceList
13+
plural: stagingworkspaces
14+
singular: stagingworkspace
15+
scope: Cluster
16+
versions:
17+
- additionalPrinterColumns:
18+
- jsonPath: .status.phase
19+
name: Phase
20+
type: string
21+
- jsonPath: .metadata.creationTimestamp
22+
name: Age
23+
type: date
24+
name: v1alpha1
25+
schema:
26+
openAPIV3Schema:
27+
description: |-
28+
StagingWorkspace represents a per-consumer×provider staging KCP workspace.
29+
resource-broker creates one for each unique (consumer workspace, provider
30+
workspace) pair and uses it to write consumer CRs that the provider's
31+
api-syncagent can pick up via the APIExport virtual workspace.
32+
properties:
33+
apiVersion:
34+
description: |-
35+
APIVersion defines the versioned schema of this representation of an object.
36+
Servers should convert recognized schemas to the latest internal value, and
37+
may reject unrecognized values.
38+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
39+
type: string
40+
kind:
41+
description: |-
42+
Kind is a string value representing the REST resource this object represents.
43+
Servers may infer this from the endpoint the client submits requests to.
44+
Cannot be updated.
45+
In CamelCase.
46+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
47+
type: string
48+
metadata:
49+
type: object
50+
spec:
51+
description: StagingWorkspaceSpec defines the desired state of StagingWorkspace.
52+
properties:
53+
apiExportName:
54+
description: |-
55+
APIExportName is the name of the provider's APIExport to bind in the
56+
staging workspace.
57+
type: string
58+
consumerCluster:
59+
description: ConsumerCluster is the logical cluster name of the consumer
60+
workspace.
61+
type: string
62+
providerPath:
63+
description: |-
64+
ProviderPath is the KCP workspace path of the provider
65+
(value of the kcp.io/path annotation on AcceptAPI objects).
66+
type: string
67+
workspaceTreeRoot:
68+
description: |-
69+
WorkspaceTreeRoot is the KCP workspace path under which the staging
70+
workspace will be created (e.g. "root:rb").
71+
type: string
72+
required:
73+
- apiExportName
74+
- consumerCluster
75+
- providerPath
76+
- workspaceTreeRoot
77+
type: object
78+
status:
79+
description: StagingWorkspaceStatus defines the observed state of StagingWorkspace.
80+
properties:
81+
conditions:
82+
description: Conditions represent the current state of the StagingWorkspace.
83+
items:
84+
description: Condition contains details for one aspect of the current
85+
state of this API Resource.
86+
properties:
87+
lastTransitionTime:
88+
description: |-
89+
lastTransitionTime is the last time the condition transitioned from one status to another.
90+
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
91+
format: date-time
92+
type: string
93+
message:
94+
description: |-
95+
message is a human readable message indicating details about the transition.
96+
This may be an empty string.
97+
maxLength: 32768
98+
type: string
99+
observedGeneration:
100+
description: |-
101+
observedGeneration represents the .metadata.generation that the condition was set based upon.
102+
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
103+
with respect to the current state of the instance.
104+
format: int64
105+
minimum: 0
106+
type: integer
107+
reason:
108+
description: |-
109+
reason contains a programmatic identifier indicating the reason for the condition's last transition.
110+
Producers of specific condition types may define expected values and meanings for this field,
111+
and whether the values are considered a guaranteed API.
112+
The value should be a CamelCase string.
113+
This field may not be empty.
114+
maxLength: 1024
115+
minLength: 1
116+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
117+
type: string
118+
status:
119+
description: status of the condition, one of True, False, Unknown.
120+
enum:
121+
- "True"
122+
- "False"
123+
- Unknown
124+
type: string
125+
type:
126+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
127+
maxLength: 316
128+
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])$
129+
type: string
130+
required:
131+
- lastTransitionTime
132+
- message
133+
- reason
134+
- status
135+
- type
136+
type: object
137+
type: array
138+
x-kubernetes-list-map-keys:
139+
- type
140+
x-kubernetes-list-type: map
141+
phase:
142+
description: Phase is the current lifecycle phase.
143+
type: string
144+
workspaceURL:
145+
description: |-
146+
WorkspaceURL is the direct access URL of the created KCP staging
147+
workspace. Set once the workspace reaches the Ready phase.
148+
type: string
149+
type: object
150+
type: object
151+
served: true
152+
storage: true
153+
subresources:
154+
status: {}

contrib/kcp/cmd/main.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ var (
6464
"APIExportEndpointSlice name to watch for APIs to broker.",
6565
)
6666

67-
fOverrideKcpHost = flag.String("kcp-host-override", "", "If set, overrides the host used to connect to kcp")
68-
fOverrideKcpPort = flag.String("kcp-port-override", "", "If set, overrides the port used to connect to kcp")
67+
fWorkspaceTreeRoot = flag.String("workspace-tree-root", "root:rb", "KCP workspace path under which staging workspaces are created")
6968
)
7069

7170
func main() {
@@ -144,11 +143,9 @@ func main() {
144143
MigrationCoordination: kcpConfig,
145144
ComputeConfig: computeConfig,
146145

147-
AcceptAPIName: *fAcceptAPI,
148-
BrokerAPIName: *fBrokerAPI,
149-
150-
KcpHostOverride: *fOverrideKcpHost,
151-
KcpPortOverride: *fOverrideKcpPort,
146+
AcceptAPIName: *fAcceptAPI,
147+
BrokerAPIName: *fBrokerAPI,
148+
WorkspaceTreeRoot: *fWorkspaceTreeRoot,
152149
})
153150
if err != nil {
154151
setupLog.Error(err, "unable to setup broker")

contrib/kcp/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ require (
4545
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4646
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
4747
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
48+
github.com/onsi/gomega v1.38.2 // indirect
4849
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
4950
github.com/prometheus/client_golang v1.23.2 // indirect
5051
github.com/prometheus/client_model v0.6.2 // indirect

0 commit comments

Comments
 (0)