Skip to content

Commit 2fb34bc

Browse files
committed
POC mounts promotion
1 parent 4c2d106 commit 2fb34bc

File tree

22 files changed

+365
-49
lines changed

22 files changed

+365
-49
lines changed

cli/pkg/workspace/plugin/create.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,17 @@ func (o *CreateWorkspaceOptions) Run(ctx context.Context) error {
126126
return fmt.Errorf("--ignore-existing must not be used with non-absolute type path")
127127
}
128128

129-
var structuredWorkspaceType tenancyv1alpha1.WorkspaceTypeReference
129+
var structuredWorkspaceType *tenancyv1alpha1.WorkspaceTypeReference
130130
if o.Type != "" {
131131
separatorIndex := strings.LastIndex(o.Type, ":")
132132
switch separatorIndex {
133133
case -1:
134-
structuredWorkspaceType = tenancyv1alpha1.WorkspaceTypeReference{
134+
structuredWorkspaceType = &tenancyv1alpha1.WorkspaceTypeReference{
135135
Name: tenancyv1alpha1.WorkspaceTypeName(strings.ToLower(o.Type)),
136136
// path is defaulted through admission
137137
}
138138
default:
139-
structuredWorkspaceType = tenancyv1alpha1.WorkspaceTypeReference{
139+
structuredWorkspaceType = &tenancyv1alpha1.WorkspaceTypeReference{
140140
Name: tenancyv1alpha1.WorkspaceTypeName(strings.ToLower(o.Type[separatorIndex+1:])),
141141
Path: o.Type[:separatorIndex],
142142
}

cli/pkg/workspace/plugin/create_test.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestCreate(t *testing.T) {
4949
markReady bool
5050

5151
newWorkspaceName string
52-
newWorkspaceType tenancyv1alpha1.WorkspaceTypeReference
52+
newWorkspaceType *tenancyv1alpha1.WorkspaceTypeReference
5353
useAfterCreation, ignoreExisting bool
5454

5555
expected *clientcmdapi.Config
@@ -144,7 +144,7 @@ func TestCreate(t *testing.T) {
144144
},
145145
existingWorkspaces: []string{"bar"},
146146
newWorkspaceName: "bar",
147-
newWorkspaceType: tenancyv1alpha1.WorkspaceTypeReference{Path: "root", Name: "universal"},
147+
newWorkspaceType: &tenancyv1alpha1.WorkspaceTypeReference{Path: "root", Name: "universal"},
148148
useAfterCreation: true,
149149
markReady: true,
150150
ignoreExisting: true,
@@ -170,7 +170,7 @@ func TestCreate(t *testing.T) {
170170
},
171171
newWorkspaceName: "bar",
172172
ignoreExisting: true,
173-
newWorkspaceType: tenancyv1alpha1.WorkspaceTypeReference{Name: "universal"},
173+
newWorkspaceType: &tenancyv1alpha1.WorkspaceTypeReference{Name: "universal"},
174174
wantErr: true,
175175
},
176176
}
@@ -196,7 +196,7 @@ func TestCreate(t *testing.T) {
196196
},
197197
Spec: tenancyv1alpha1.WorkspaceSpec{
198198
URL: fmt.Sprintf("https://test%s", currentClusterName.Join(name).RequestPath()),
199-
Type: tenancyv1alpha1.WorkspaceTypeReference{
199+
Type: &tenancyv1alpha1.WorkspaceTypeReference{
200200
Name: "universal",
201201
Path: "root",
202202
},
@@ -208,10 +208,9 @@ func TestCreate(t *testing.T) {
208208
}
209209
client := kcpfakeclient.NewSimpleClientset(objects...)
210210

211-
workspaceType := tt.newWorkspaceType //nolint:govet // TODO(sttts): fixing this above breaks the test
212-
empty := tenancyv1alpha1.WorkspaceTypeReference{}
213-
if workspaceType == empty {
214-
workspaceType = tenancyv1alpha1.WorkspaceTypeReference{
211+
workspaceType := tt.newWorkspaceType
212+
if tt.newWorkspaceType == nil {
213+
workspaceType = &tenancyv1alpha1.WorkspaceTypeReference{
215214
Name: "universal",
216215
Path: "root",
217216
}

cli/pkg/workspace/plugin/use.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func (o *UseWorkspaceOptions) Run(ctx context.Context) (err error) {
224224
if ws, err := o.kcpClusterClient.Cluster(parentClusterName).TenancyV1alpha1().Workspaces().Get(ctx, workspaceName, metav1.GetOptions{}); apierrors.IsNotFound(err) {
225225
notFound = true
226226
} else if err == nil {
227-
workspaceType = &ws.Spec.Type
227+
workspaceType = ws.Spec.Type
228228
}
229229
}
230230
}

cli/pkg/workspace/plugin/use_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ func TestUse(t *testing.T) {
753753
Annotations: map[string]string{logicalcluster.AnnotationKey: lcluster.String()},
754754
},
755755
Spec: tenancyv1alpha1.WorkspaceSpec{
756-
Type: tenancyv1alpha1.WorkspaceTypeReference{
756+
Type: &tenancyv1alpha1.WorkspaceTypeReference{
757757
Name: "universal",
758758
Path: "root",
759759
},
@@ -779,7 +779,7 @@ func TestUse(t *testing.T) {
779779
},
780780
Spec: tenancyv1alpha1.WorkspaceSpec{
781781
URL: fmt.Sprintf("https://test%s", homeWorkspace.RequestPath()),
782-
Type: tenancyv1alpha1.WorkspaceTypeReference{
782+
Type: &tenancyv1alpha1.WorkspaceTypeReference{
783783
Name: "home",
784784
Path: "root",
785785
},

config/crds/tenancy.kcp.io_workspaces.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,55 @@ spec:
147147
type: object
148148
x-kubernetes-map-type: atomic
149149
type: object
150+
mount:
151+
description: |-
152+
Mount is a reference to a mount that is used to mount the workspace.
153+
If specified, logicalcluster will not be created and the workspace will be mounted
154+
using reference mount object.
155+
properties:
156+
apiVersion:
157+
description: API version of the referent.
158+
type: string
159+
fieldPath:
160+
description: |-
161+
If referring to a piece of an object instead of an entire object, this string
162+
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
163+
For example, if the object reference is to a container within a pod, this would take on a value like:
164+
"spec.containers{name}" (where "name" refers to the name of the container that triggered
165+
the event) or if no container name is specified "spec.containers[2]" (container with
166+
index 2 in this pod). This syntax is chosen only to have some well-defined way of
167+
referencing a part of an object.
168+
type: string
169+
kind:
170+
description: |-
171+
Kind of the referent.
172+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
173+
type: string
174+
name:
175+
description: |-
176+
Name of the referent.
177+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
178+
type: string
179+
namespace:
180+
description: |-
181+
Namespace of the referent.
182+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
183+
type: string
184+
resourceVersion:
185+
description: |-
186+
Specific resourceVersion to which this reference is made, if any.
187+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
188+
type: string
189+
uid:
190+
description: |-
191+
UID of the referent.
192+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
193+
type: string
194+
type: object
195+
x-kubernetes-map-type: atomic
196+
x-kubernetes-validations:
197+
- message: mount is immutable
198+
rule: self == oldSelf
150199
type:
151200
description: |-
152201
type defines properties of the workspace both on creation (e.g. initial
@@ -184,6 +233,8 @@ spec:
184233
rule: '!has(oldSelf.URL) || has(self.URL)'
185234
- message: cluster cannot be unset
186235
rule: '!has(oldSelf.cluster) || has(self.cluster)'
236+
- message: spec.mount and spec.type cannot both be set
237+
rule: '!(has(self.mount) && has(self.type))'
187238
status:
188239
default: {}
189240
description: WorkspaceStatus communicates the observed state of the Workspace.

config/root-phase0/apiexport-tenancy.kcp.io.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ metadata:
66
spec:
77
latestResourceSchemas:
88
- v240903-d6797056a.workspacetypes.tenancy.kcp.io
9-
- v241020-fce06d31d.workspaces.tenancy.kcp.io
9+
- v250202-4c2d1061d.workspaces.tenancy.kcp.io
1010
maximalPermissionPolicy:
1111
local: {}
1212
status: {}

config/root-phase0/apiresourceschema-workspaces.tenancy.kcp.io.yaml

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: apis.kcp.io/v1alpha1
22
kind: APIResourceSchema
33
metadata:
44
creationTimestamp: null
5-
name: v241020-fce06d31d.workspaces.tenancy.kcp.io
5+
name: v250202-4c2d1061d.workspaces.tenancy.kcp.io
66
spec:
77
group: tenancy.kcp.io
88
names:
@@ -145,6 +145,55 @@ spec:
145145
type: object
146146
x-kubernetes-map-type: atomic
147147
type: object
148+
mount:
149+
description: |-
150+
Mount is a reference to a mount that is used to mount the workspace.
151+
If specified, logicalcluster will not be created and the workspace will be mounted
152+
using reference mount object.
153+
properties:
154+
apiVersion:
155+
description: API version of the referent.
156+
type: string
157+
fieldPath:
158+
description: |-
159+
If referring to a piece of an object instead of an entire object, this string
160+
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
161+
For example, if the object reference is to a container within a pod, this would take on a value like:
162+
"spec.containers{name}" (where "name" refers to the name of the container that triggered
163+
the event) or if no container name is specified "spec.containers[2]" (container with
164+
index 2 in this pod). This syntax is chosen only to have some well-defined way of
165+
referencing a part of an object.
166+
type: string
167+
kind:
168+
description: |-
169+
Kind of the referent.
170+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
171+
type: string
172+
name:
173+
description: |-
174+
Name of the referent.
175+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
176+
type: string
177+
namespace:
178+
description: |-
179+
Namespace of the referent.
180+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
181+
type: string
182+
resourceVersion:
183+
description: |-
184+
Specific resourceVersion to which this reference is made, if any.
185+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
186+
type: string
187+
uid:
188+
description: |-
189+
UID of the referent.
190+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
191+
type: string
192+
type: object
193+
x-kubernetes-map-type: atomic
194+
x-kubernetes-validations:
195+
- message: mount is immutable
196+
rule: self == oldSelf
148197
type:
149198
description: |-
150199
type defines properties of the workspace both on creation (e.g. initial
@@ -182,6 +231,8 @@ spec:
182231
rule: '!has(oldSelf.URL) || has(self.URL)'
183232
- message: cluster cannot be unset
184233
rule: '!has(oldSelf.cluster) || has(self.cluster)'
234+
- message: spec.mount and spec.type cannot both be set
235+
rule: '!(has(self.mount) && has(self.type))'
185236
status:
186237
default: {}
187238
description: WorkspaceStatus communicates the observed state of the Workspace.

mounts/crd.yaml

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.16.1
7+
name: kubeclusters.contrib.kcp.io
8+
spec:
9+
group: contrib.kcp.io
10+
names:
11+
kind: KubeCluster
12+
listKind: KubeClusterList
13+
plural: kubeclusters
14+
singular: kubecluster
15+
scope: Cluster
16+
versions:
17+
- additionalPrinterColumns:
18+
- jsonPath: .status.conditions[?(@.type=="KubeClusterReady")].status
19+
name: Ready
20+
type: string
21+
- jsonPath: .status.phase
22+
name: Phase
23+
type: string
24+
name: v1alpha1
25+
schema:
26+
openAPIV3Schema:
27+
description: KubeCluster describes the current KubeCluster proxy object.
28+
properties:
29+
apiVersion:
30+
description: |-
31+
APIVersion defines the versioned schema of this representation of an object.
32+
Servers should convert recognized schemas to the latest internal value, and
33+
may reject unrecognized values.
34+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
35+
type: string
36+
kind:
37+
description: |-
38+
Kind is a string value representing the REST resource this object represents.
39+
Servers may infer this from the endpoint the client submits requests to.
40+
Cannot be updated.
41+
In CamelCase.
42+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
43+
type: string
44+
metadata:
45+
type: object
46+
spec:
47+
description: KubeClusterSpec is the specification of the Kube cluster
48+
proxy resource.
49+
properties:
50+
workspaceURL:
51+
description: workspaceURL is the address under which the workspace
52+
can be found.
53+
type: string
54+
type: object
55+
status:
56+
description: KubeClusterStatus communicates the observed state of the
57+
Kube cluster proxy.
58+
properties:
59+
URL:
60+
description: |-
61+
url is the address under which the Kubernetes-cluster-like endpoint
62+
can be found. This URL can be used to access the cluster with standard Kubernetes
63+
client libraries and command line tools via proxy.
64+
type: string
65+
conditions:
66+
description: Current processing state of the Cluster proxy.
67+
items:
68+
description: Condition defines an observation of a object operational
69+
state.
70+
properties:
71+
lastTransitionTime:
72+
description: |-
73+
Last time the condition transitioned from one status to another.
74+
This should be when the underlying condition changed. If that is not known, then using the time when
75+
the API field changed is acceptable.
76+
format: date-time
77+
type: string
78+
message:
79+
description: |-
80+
A human readable message indicating details about the transition.
81+
This field may be empty.
82+
type: string
83+
reason:
84+
description: |-
85+
The reason for the condition's last transition in CamelCase.
86+
The specific API may choose whether or not this field is considered a guaranteed API.
87+
This field may not be empty.
88+
type: string
89+
severity:
90+
description: |-
91+
Severity provides an explicit classification of Reason code, so the users or machines can immediately
92+
understand the current situation and act accordingly.
93+
The Severity field MUST be set only when Status=False.
94+
type: string
95+
status:
96+
description: Status of the condition, one of True, False, Unknown.
97+
type: string
98+
type:
99+
description: |-
100+
Type of condition in CamelCase or in foo.example.com/CamelCase.
101+
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions
102+
can be useful (see .node.status.conditions), the ability to deconflict is important.
103+
type: string
104+
required:
105+
- lastTransitionTime
106+
- status
107+
- type
108+
type: object
109+
type: array
110+
lastProxyHeartbeatTime:
111+
description: A timestamp indicating when the proxy last reported status.
112+
format: date-time
113+
type: string
114+
phase:
115+
default: Initializing
116+
description: Phase of the cluster proxy (Initializing, Ready).
117+
enum:
118+
- Initializing
119+
- Connecting
120+
- Ready
121+
- Unknown
122+
type: string
123+
tunnelWorkspaces:
124+
description: |-
125+
TunnelWorkspaces contains all URLs (one per shard) that is being used
126+
by the proxy to connect to the tunnel for a given shard.
127+
items:
128+
properties:
129+
url:
130+
description: |-
131+
url is the URL the Proxy should use to connect
132+
to the Proxy tunnel for a given shard.
133+
minLength: 1
134+
type: string
135+
required:
136+
- url
137+
type: object
138+
type: array
139+
type: object
140+
type: object
141+
served: true
142+
storage: true
143+
subresources:
144+
status: {}

mounts/mount.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
apiVersion: contrib.kcp.io/v1alpha1
3+
kind: KubeCluster
4+
metadata:
5+
name: proxy-cluster
6+
spec:

0 commit comments

Comments
 (0)