diff --git a/cmd/sharded-test-server/shard.go b/cmd/sharded-test-server/shard.go index 6884a5d9b40..a782a36aee6 100644 --- a/cmd/sharded-test-server/shard.go +++ b/cmd/sharded-test-server/shard.go @@ -82,7 +82,6 @@ func newShard(ctx context.Context, n int, args []string, servingCA *crypto.CA, h fmt.Sprintf("--tls-cert-file=%s", filepath.Join(workDirPath, fmt.Sprintf(".kcp-%d/apiserver.crt", n))), fmt.Sprintf("--tls-private-key-file=%s", filepath.Join(workDirPath, fmt.Sprintf(".kcp-%d/apiserver.key", n))), fmt.Sprintf("--secure-port=%d", 6444+n), - "--virtual-workspaces-workspaces.authorization-cache.resync-period=1s", fmt.Sprintf("--logical-cluster-admin-kubeconfig=%s", filepath.Join(workDirPath, ".kcp/logical-cluster-admin.kubeconfig")), ) if len(cacheServerConfigPath) > 0 { diff --git a/cmd/test-server/kcp/shard.go b/cmd/test-server/kcp/shard.go index 89068be1810..cddc523e5e0 100644 --- a/cmd/test-server/kcp/shard.go +++ b/cmd/test-server/kcp/shard.go @@ -105,7 +105,6 @@ func (s *Shard) Start(ctx context.Context, quiet bool) error { "--audit-log-batch-throttle-enable=true", "--audit-log-batch-throttle-qps=10", "--audit-policy-file", filepath.Join(s.runtimeDir, "audit-policy.yaml"), - "--virtual-workspaces-workspaces.authorization-cache.resync-period=1s", ) fmt.Fprintf(out, "running: %v\n", strings.Join(commandLine, " ")) diff --git a/hack/logcheck.out b/hack/logcheck.out index b9452c9ee58..348dc8e33be 100644 --- a/hack/logcheck.out +++ b/hack/logcheck.out @@ -155,7 +155,4 @@ /pkg/virtual/syncer/transformations/transformer.go:399:11: Key positional arguments are expected to be inlined constant strings. Please replace SyncTargetKey provided with string value. /pkg/virtual/syncer/transformations/transformer.go:93:12: Key positional arguments are expected to be inlined constant strings. Please replace SyncTargetName provided with string value. /pkg/virtual/syncer/transformations/transformer.go:95:11: Additional arguments to WithValues should always be Key Value pairs. Please check if there is any key or value missing. -/pkg/virtual/workspaces/builder/build.go:100:4: function "Errorf" should not be used, convert to contextual logging -/pkg/virtual/workspaces/builder/build.go:108:4: function "Errorf" should not be used, convert to contextual logging -/pkg/virtual/workspaces/builder/build.go:123:4: function "Errorf" should not be used, convert to contextual logging /test/e2e/framework/config.go:42:2: function "InitFlags" should not be used, convert to contextual logging diff --git a/pkg/admission/reservednames/admission_test.go b/pkg/admission/reservednames/admission_test.go index 965c80d1e94..67aab0656ec 100644 --- a/pkg/admission/reservednames/admission_test.go +++ b/pkg/admission/reservednames/admission_test.go @@ -29,6 +29,7 @@ import ( "k8s.io/apiserver/pkg/authentication/user" tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" + tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" ) func createAttr(name string, obj runtime.Object, kind, resource string) admission.Attributes { @@ -64,10 +65,10 @@ func TestAdmission(t *testing.T) { attr: createAttr("cool-cwt", &tenancyv1alpha1.WorkspaceType{}, "WorkspaceType", "workspacetypes"), }, "NotApplicableResource": { - attr: createAttr("root", &tenancyv1alpha1.ClusterWorkspace{}, "ClusterWorkspace", "notacworcwt"), + attr: createAttr("root", &tenancyv1beta1.Workspace{}, "ClusterWorkspace", "notacworcwt"), }, "NotApplicableKind": { - attr: createAttr("root", &tenancyv1alpha1.ClusterWorkspace{}, "NotaCWorCWT", "clusterworkspaces"), + attr: createAttr("root", &tenancyv1beta1.Workspace{}, "NotaCWorCWT", "workspaces"), }, } for name, tc := range cases { diff --git a/pkg/admission/workspace/admission_test.go b/pkg/admission/workspace/admission_test.go index f08742f23bb..4d428b692be 100644 --- a/pkg/admission/workspace/admission_test.go +++ b/pkg/admission/workspace/admission_test.go @@ -106,7 +106,7 @@ func TestAdmit(t *testing.T) { Name: "test", }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -127,7 +127,7 @@ func TestAdmit(t *testing.T) { }, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -148,7 +148,7 @@ func TestAdmit(t *testing.T) { }, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "Foo", Path: "root:org", }, @@ -169,7 +169,7 @@ func TestAdmit(t *testing.T) { }, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "Foo", Path: "root:org", }, @@ -190,7 +190,7 @@ func TestAdmit(t *testing.T) { }, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "Foo", Path: "root:org", }, @@ -211,7 +211,7 @@ func TestAdmit(t *testing.T) { }, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "Foo", Path: "root:org", }, @@ -335,7 +335,7 @@ func TestValidate(t *testing.T) { Annotations: map[string]string{"experimental.tenancy.kcp.io/owner": "{}"}, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -347,7 +347,7 @@ func TestValidate(t *testing.T) { Annotations: map[string]string{"experimental.tenancy.kcp.io/owner": "{}"}, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "universal", Path: "root:org", }, @@ -366,7 +366,7 @@ func TestValidate(t *testing.T) { Annotations: map[string]string{"experimental.tenancy.kcp.io/owner": "{}"}, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -379,7 +379,7 @@ func TestValidate(t *testing.T) { }, Spec: tenancyv1beta1.WorkspaceSpec{ Cluster: "somewhere", - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -400,7 +400,7 @@ func TestValidate(t *testing.T) { Spec: tenancyv1beta1.WorkspaceSpec{ Cluster: "somewhere", URL: "https://kcp.bigcorp.com/clusters/org:test", - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -416,7 +416,7 @@ func TestValidate(t *testing.T) { Annotations: map[string]string{"experimental.tenancy.kcp.io/owner": "{}"}, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -440,7 +440,7 @@ func TestValidate(t *testing.T) { Spec: tenancyv1beta1.WorkspaceSpec{ Cluster: "somewhere", URL: "https://kcp.bigcorp.com/clusters/org:test", - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -464,7 +464,7 @@ func TestValidate(t *testing.T) { Spec: tenancyv1beta1.WorkspaceSpec{ Cluster: "somewhere", URL: "https://kcp.bigcorp.com/clusters/org:test", - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -489,7 +489,7 @@ func TestValidate(t *testing.T) { Spec: tenancyv1beta1.WorkspaceSpec{ Cluster: "somewhere", URL: "https://kcp.bigcorp.com/clusters/org:test", - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -507,7 +507,7 @@ func TestValidate(t *testing.T) { Spec: tenancyv1beta1.WorkspaceSpec{ Cluster: "somewhere", URL: "https://kcp.otherbigcorp.com/clusters/org:test", - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -531,7 +531,7 @@ func TestValidate(t *testing.T) { }, Spec: tenancyv1beta1.WorkspaceSpec{ Cluster: "somewhere", - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -547,7 +547,7 @@ func TestValidate(t *testing.T) { Annotations: map[string]string{"experimental.tenancy.kcp.io/owner": "{}"}, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -594,7 +594,7 @@ func TestValidate(t *testing.T) { Annotations: map[string]string{"experimental.tenancy.kcp.io/owner": "{}"}, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root:org", }, @@ -622,7 +622,7 @@ func TestValidate(t *testing.T) { }, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "Foo", Path: "root:org", }, @@ -652,7 +652,7 @@ func TestValidate(t *testing.T) { }, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "Foo", Path: "root:org", }, diff --git a/pkg/admission/workspacetypeexists/admission.go b/pkg/admission/workspacetypeexists/admission.go index e9c94ca5323..154fc8abf21 100644 --- a/pkg/admission/workspacetypeexists/admission.go +++ b/pkg/admission/workspacetypeexists/admission.go @@ -132,7 +132,7 @@ func (o *workspacetypeExists) Admit(ctx context.Context, a admission.Attributes, } // if the user has not provided any type, use the default from the parent workspace - empty := tenancyv1beta1.WorkspaceTypeReference{} + empty := tenancyv1alpha1.WorkspaceTypeReference{} if ws.Spec.Type == empty { typeAnnotation, found := logicalCluster.Annotations[tenancyv1beta1.LogicalClusterTypeAnnotationKey] if !found { @@ -149,7 +149,7 @@ func (o *workspacetypeExists) Admit(ctx context.Context, a admission.Attributes, if parentCwt.Spec.DefaultChildWorkspaceType == nil { return admission.NewForbidden(a, errors.New("spec.defaultChildWorkspaceType of workspace type %s:%s must be set")) } - ws.Spec.Type = tenancyv1beta1.WorkspaceTypeReference{ + ws.Spec.Type = tenancyv1alpha1.WorkspaceTypeReference{ Path: parentCwt.Spec.DefaultChildWorkspaceType.Path, Name: parentCwt.Spec.DefaultChildWorkspaceType.Name, } diff --git a/pkg/admission/workspacetypeexists/admission_test.go b/pkg/admission/workspacetypeexists/admission_test.go index 58da46122d9..04f53afbded 100644 --- a/pkg/admission/workspacetypeexists/admission_test.go +++ b/pkg/admission/workspacetypeexists/admission_test.go @@ -868,7 +868,7 @@ func newWorkspace(qualifiedName string) wsBuilder { func (b wsBuilder) withType(qualifiedName string) wsBuilder { path, name := logicalcluster.NewPath(qualifiedName).Split() - b.Spec.Type = tenancyv1beta1.WorkspaceTypeReference{ + b.Spec.Type = tenancyv1alpha1.WorkspaceTypeReference{ Path: path.String(), Name: tenancyv1alpha1.WorkspaceTypeName(name), } diff --git a/pkg/apis/tenancy/projection/workspaces.go b/pkg/apis/tenancy/projection/workspaces.go deleted file mode 100644 index 80aa43abef6..00000000000 --- a/pkg/apis/tenancy/projection/workspaces.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2022 The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package projection - -import ( - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" - tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" -) - -func ProjectWorkspaceToClusterWorkspace(from *tenancyv1beta1.Workspace, to *tenancyv1alpha1.ClusterWorkspace) { - to.ObjectMeta = from.ObjectMeta - to.Spec.Type = tenancyv1alpha1.WorkspaceTypeReference{ - Path: from.Spec.Type.Path, - Name: from.Spec.Type.Name, - } - if from.Spec.Location != nil { - to.Spec.Shard = &tenancyv1alpha1.ShardConstraints{ - Selector: from.Spec.Location.Selector, - } - } - to.Status.Cluster = from.Spec.Cluster - to.Status.BaseURL = from.Spec.URL - to.Status.Phase = from.Status.Phase - to.Status.Initializers = from.Status.Initializers - to.Status.Conditions = from.Status.Conditions -} diff --git a/pkg/apis/tenancy/v1alpha1/register.go b/pkg/apis/tenancy/v1alpha1/register.go index abe15232a78..5c29f2d9dff 100644 --- a/pkg/apis/tenancy/v1alpha1/register.go +++ b/pkg/apis/tenancy/v1alpha1/register.go @@ -45,8 +45,6 @@ var ( // Adds the list of known types to Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, - &ClusterWorkspace{}, - &ClusterWorkspaceList{}, &WorkspaceType{}, &WorkspaceTypeList{}, ) diff --git a/pkg/apis/tenancy/v1alpha1/types_clusterworkspace.go b/pkg/apis/tenancy/v1alpha1/types_clusterworkspace.go index 97896824e83..a3de2730ea1 100644 --- a/pkg/apis/tenancy/v1alpha1/types_clusterworkspace.go +++ b/pkg/apis/tenancy/v1alpha1/types_clusterworkspace.go @@ -19,84 +19,9 @@ package v1alpha1 import ( "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - corev1alpha1 "github.com/kcp-dev/kcp/pkg/apis/core/v1alpha1" conditionsv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/third_party/conditions/apis/conditions/v1alpha1" - "github.com/kcp-dev/kcp/pkg/apis/third_party/conditions/util/conditions" ) -// ClusterWorkspace defines a Kubernetes-cluster-like endpoint that holds a default set -// of resources and exhibits standard Kubernetes API semantics of CRUD operations. It represents -// the full life-cycle of the persisted data in this workspace in a KCP installation. -// -// ClusterWorkspace is a concrete type that implements a workspace. -// -// +crd -// +genclient -// +genclient:nonNamespaced -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// +kubebuilder:subresource:status -// +kubebuilder:resource:scope=Cluster,categories=kcp -// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`,description="The current phase (e.g. Scheduling, Initializing, Ready)" -// +kubebuilder:printcolumn:name="Type",type=string,JSONPath=`.spec.type.name`,description="Type of the workspace" -// +kubebuilder:printcolumn:name="URL",type=string,JSONPath=`.status.baseURL`,description="URL to access the workspace" -// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" -type ClusterWorkspace struct { - metav1.TypeMeta `json:",inline"` - // +optional - metav1.ObjectMeta `json:"metadata,omitempty"` - - // +optional - Spec ClusterWorkspaceSpec `json:"spec,omitempty"` - - // +optional - Status ClusterWorkspaceStatus `json:"status,omitempty"` -} - -// ClusterWorkspaceSpec holds the desired state of the ClusterWorkspace. -type ClusterWorkspaceSpec struct { - // +optional - ReadOnly bool `json:"readOnly,omitempty"` - - // type defines properties of the workspace both on creation (e.g. initial - // resources and initially installed APIs) and during runtime (e.g. permissions). - // If no type is provided, the default type for the workspace in which this workspace - // is nesting will be used. - // - // The type is a reference to a WorkspaceType in the listed workspace, but - // lower-cased. The WorkspaceType existence is validated at admission during - // creation. The type is immutable after creation. The use of a type is gated via - // the RBAC workspacetypes/use resource permission. - // - // +optional - Type WorkspaceTypeReference `json:"type,omitempty"` - - // shard constraints onto which shards this cluster workspace can be scheduled to. - // if the constraint is not fulfilled by the current location stored in the status, - // movement will be attempted. - // - // Either shard name or shard selector must be specified. - // - // If the no shard constraints are specified, an arbitrary shard is chosen. - // - // +optional - Shard *ShardConstraints `json:"shard,omitempty"` -} - -type ShardConstraints struct { - // name is the name of Shard. - // - // +optional - // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` - Name string `json:"name,omitempty"` - - // selector is a label selector that filters shard scheduling targets. - // - // +optional - Selector *metav1.LabelSelector `json:"selector,omitempty"` -} - // WorkspaceTypeReference is a globally unique, fully qualified reference to a // cluster workspace type. type WorkspaceTypeReference struct { @@ -125,77 +50,8 @@ func (r WorkspaceTypeReference) String() string { return fmt.Sprintf("%s:%s", r.Path, r.Name) } -// ClusterWorkspaceStatus communicates the observed state of the ClusterWorkspace. -// -// +kubebuilder:validation:XValidation:rule="!has(oldSelf.cluster) || has(self.cluster)",message="status.cluster is immutable" -type ClusterWorkspaceStatus struct { - // Phase of the workspace (Scheduling / Initializing / Ready) - // - // +kubebuilder:default=Scheduling - Phase corev1alpha1.LogicalClusterPhaseType `json:"phase,omitempty"` - - // Current processing state of the ClusterWorkspace. - // +optional - Conditions conditionsv1alpha1.Conditions `json:"conditions,omitempty"` - - // Base URL where this ClusterWorkspace can be targeted. - // This will generally be of the form: https:///cluster/. - // But a workspace could also be targetable by a unique hostname in the future. - // - // +kubebuilder:validation:Pattern:https://[^/].* - // +optional - BaseURL string `json:"baseURL,omitempty"` - - // cluster is the name of the logical cluster this workspace is stored under. - // - // +optional - // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="cluster is immutable" - Cluster string `json:"cluster,omitempty"` - - // Contains workspace placement information. - // - // +optional - Location ClusterWorkspaceLocation `json:"location,omitempty"` - - // initializers are set on creation by the system and must be cleared - // by a controller before the workspace can be used. The workspace will - // stay in the phase "Initializing" state until all initializers are cleared. - // - // A cluster workspace in "Initializing" state are gated via the RBAC - // clusterworkspaces/initialize resource permission. - // - // +optional - Initializers []corev1alpha1.LogicalClusterInitializer `json:"initializers,omitempty"` -} - const ExperimentalWorkspaceOwnerAnnotationKey string = "experimental.tenancy.kcp.io/owner" -// ClusterWorkspaceLocation specifies workspace placement information, including current, desired (target), and -// historical information. -type ClusterWorkspaceLocation struct { - // Current workspace placement (shard). - // - // +optional - Current string `json:"current,omitempty"` - - // Target workspace placement (shard). - // - // +optional - // +kubebuilder:validation:Enum="" - Target string `json:"target,omitempty"` -} - -func (in *ClusterWorkspace) SetConditions(c conditionsv1alpha1.Conditions) { - in.Status.Conditions = c -} - -func (in *ClusterWorkspace) GetConditions() conditionsv1alpha1.Conditions { - return in.Status.Conditions -} - -var _ conditions.Getter = &ClusterWorkspace{} -var _ conditions.Setter = &ClusterWorkspace{} - // These are valid conditions of workspace. const ( // WorkspaceScheduled represents status of the scheduling process for this workspace. @@ -232,13 +88,3 @@ const ( // were errors trying to initialize APIBindings for the workspace. WorkspaceInitializedAPIBindingErrors = "APIBindingErrors" ) - -// ClusterWorkspaceList is a list of ClusterWorkspace resources -// -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -type ClusterWorkspaceList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata"` - - Items []ClusterWorkspace `json:"items"` -} diff --git a/pkg/apis/tenancy/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/tenancy/v1alpha1/zz_generated.deepcopy.go index 4f063e059fa..e5e24796c80 100644 --- a/pkg/apis/tenancy/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/tenancy/v1alpha1/zz_generated.deepcopy.go @@ -22,10 +22,8 @@ limitations under the License. package v1alpha1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" - corev1alpha1 "github.com/kcp-dev/kcp/pkg/apis/core/v1alpha1" conditionsv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/third_party/conditions/apis/conditions/v1alpha1" ) @@ -45,155 +43,6 @@ func (in *APIExportReference) DeepCopy() *APIExportReference { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterWorkspace) DeepCopyInto(out *ClusterWorkspace) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWorkspace. -func (in *ClusterWorkspace) DeepCopy() *ClusterWorkspace { - if in == nil { - return nil - } - out := new(ClusterWorkspace) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ClusterWorkspace) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterWorkspaceList) DeepCopyInto(out *ClusterWorkspaceList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ClusterWorkspace, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWorkspaceList. -func (in *ClusterWorkspaceList) DeepCopy() *ClusterWorkspaceList { - if in == nil { - return nil - } - out := new(ClusterWorkspaceList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ClusterWorkspaceList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterWorkspaceLocation) DeepCopyInto(out *ClusterWorkspaceLocation) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWorkspaceLocation. -func (in *ClusterWorkspaceLocation) DeepCopy() *ClusterWorkspaceLocation { - if in == nil { - return nil - } - out := new(ClusterWorkspaceLocation) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterWorkspaceSpec) DeepCopyInto(out *ClusterWorkspaceSpec) { - *out = *in - out.Type = in.Type - if in.Shard != nil { - in, out := &in.Shard, &out.Shard - *out = new(ShardConstraints) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWorkspaceSpec. -func (in *ClusterWorkspaceSpec) DeepCopy() *ClusterWorkspaceSpec { - if in == nil { - return nil - } - out := new(ClusterWorkspaceSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterWorkspaceStatus) DeepCopyInto(out *ClusterWorkspaceStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make(conditionsv1alpha1.Conditions, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - out.Location = in.Location - if in.Initializers != nil { - in, out := &in.Initializers, &out.Initializers - *out = make([]corev1alpha1.LogicalClusterInitializer, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWorkspaceStatus. -func (in *ClusterWorkspaceStatus) DeepCopy() *ClusterWorkspaceStatus { - if in == nil { - return nil - } - out := new(ClusterWorkspaceStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ShardConstraints) DeepCopyInto(out *ShardConstraints) { - *out = *in - if in.Selector != nil { - in, out := &in.Selector, &out.Selector - *out = new(v1.LabelSelector) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ShardConstraints. -func (in *ShardConstraints) DeepCopy() *ShardConstraints { - if in == nil { - return nil - } - out := new(ShardConstraints) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *VirtualWorkspace) DeepCopyInto(out *VirtualWorkspace) { *out = *in diff --git a/pkg/apis/tenancy/v1beta1/types.go b/pkg/apis/tenancy/v1beta1/types.go index 86d8c1bbcb7..c03435bc600 100644 --- a/pkg/apis/tenancy/v1beta1/types.go +++ b/pkg/apis/tenancy/v1beta1/types.go @@ -75,7 +75,7 @@ type WorkspaceSpec struct { // +kubebuilder:validation:XValidation:rule="self.name == oldSelf.name",message="name is immutable" // +kubebuilder:validation:XValidation:rule="has(oldSelf.path) == has(self.path)",message="path is immutable" // +kubebuilder:validation:XValidation:rule="!has(oldSelf.path) || !has(self.path) || self.path == oldSelf.path",message="path is immutable" - Type WorkspaceTypeReference `json:"type,omitempty"` + Type v1alpha1.WorkspaceTypeReference `json:"type,omitempty"` // location constraints where this workspace can be scheduled to. // @@ -102,21 +102,6 @@ type WorkspaceSpec struct { URL string `json:"URL,omitempty"` } -// WorkspaceTypeReference is a reference to a workspace type. -type WorkspaceTypeReference struct { - // name is the name of the WorkspaceType - // - // +required - // +kubebuilder:validation:Required - Name v1alpha1.WorkspaceTypeName `json:"name"` - - // path is an absolute reference to the workspace that owns this type, e.g. root:org:ws. - // - // +optional - // +kubebuilder:validation:Pattern:="^[a-z0-9]([-a-z0-9]*[a-z0-9])?(:[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" - Path string `json:"path,omitempty"` -} - type WorkspaceLocation struct { // selector is a label selector that filters workspace scheduling targets. diff --git a/pkg/apis/tenancy/v1beta1/zz_generated.deepcopy.go b/pkg/apis/tenancy/v1beta1/zz_generated.deepcopy.go index 585fb8bb6eb..665f3c2e7a6 100644 --- a/pkg/apis/tenancy/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/tenancy/v1beta1/zz_generated.deepcopy.go @@ -160,19 +160,3 @@ func (in *WorkspaceStatus) DeepCopy() *WorkspaceStatus { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *WorkspaceTypeReference) DeepCopyInto(out *WorkspaceTypeReference) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceTypeReference. -func (in *WorkspaceTypeReference) DeepCopy() *WorkspaceTypeReference { - if in == nil { - return nil - } - out := new(WorkspaceTypeReference) - in.DeepCopyInto(out) - return out -} diff --git a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/clusterworkspace.go b/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/clusterworkspace.go deleted file mode 100644 index 3f30326efaa..00000000000 --- a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/clusterworkspace.go +++ /dev/null @@ -1,72 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by kcp code-generator. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - - kcpclient "github.com/kcp-dev/apimachinery/v2/pkg/client" - "github.com/kcp-dev/logicalcluster/v3" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" - - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" - tenancyv1alpha1client "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/typed/tenancy/v1alpha1" -) - -// ClusterWorkspacesClusterGetter has a method to return a ClusterWorkspaceClusterInterface. -// A group's cluster client should implement this interface. -type ClusterWorkspacesClusterGetter interface { - ClusterWorkspaces() ClusterWorkspaceClusterInterface -} - -// ClusterWorkspaceClusterInterface can operate on ClusterWorkspaces across all clusters, -// or scope down to one cluster and return a tenancyv1alpha1client.ClusterWorkspaceInterface. -type ClusterWorkspaceClusterInterface interface { - Cluster(logicalcluster.Path) tenancyv1alpha1client.ClusterWorkspaceInterface - List(ctx context.Context, opts metav1.ListOptions) (*tenancyv1alpha1.ClusterWorkspaceList, error) - Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) -} - -type clusterWorkspacesClusterInterface struct { - clientCache kcpclient.Cache[*tenancyv1alpha1client.TenancyV1alpha1Client] -} - -// Cluster scopes the client down to a particular cluster. -func (c *clusterWorkspacesClusterInterface) Cluster(clusterPath logicalcluster.Path) tenancyv1alpha1client.ClusterWorkspaceInterface { - if clusterPath == logicalcluster.Wildcard { - panic("A specific cluster must be provided when scoping, not the wildcard.") - } - - return c.clientCache.ClusterOrDie(clusterPath).ClusterWorkspaces() -} - -// List returns the entire collection of all ClusterWorkspaces across all clusters. -func (c *clusterWorkspacesClusterInterface) List(ctx context.Context, opts metav1.ListOptions) (*tenancyv1alpha1.ClusterWorkspaceList, error) { - return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).ClusterWorkspaces().List(ctx, opts) -} - -// Watch begins to watch all ClusterWorkspaces across all clusters. -func (c *clusterWorkspacesClusterInterface) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { - return c.clientCache.ClusterOrDie(logicalcluster.Wildcard).ClusterWorkspaces().Watch(ctx, opts) -} diff --git a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/fake/clusterworkspace.go b/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/fake/clusterworkspace.go deleted file mode 100644 index 8a112ba13a7..00000000000 --- a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/fake/clusterworkspace.go +++ /dev/null @@ -1,161 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by kcp code-generator. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - - "github.com/kcp-dev/logicalcluster/v3" - - kcptesting "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/testing" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/testing" - - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" - tenancyv1alpha1client "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/typed/tenancy/v1alpha1" -) - -var clusterWorkspacesResource = schema.GroupVersionResource{Group: "tenancy.kcp.io", Version: "v1alpha1", Resource: "clusterworkspaces"} -var clusterWorkspacesKind = schema.GroupVersionKind{Group: "tenancy.kcp.io", Version: "v1alpha1", Kind: "ClusterWorkspace"} - -type clusterWorkspacesClusterClient struct { - *kcptesting.Fake -} - -// Cluster scopes the client down to a particular cluster. -func (c *clusterWorkspacesClusterClient) Cluster(clusterPath logicalcluster.Path) tenancyv1alpha1client.ClusterWorkspaceInterface { - if clusterPath == logicalcluster.Wildcard { - panic("A specific cluster must be provided when scoping, not the wildcard.") - } - - return &clusterWorkspacesClient{Fake: c.Fake, ClusterPath: clusterPath} -} - -// List takes label and field selectors, and returns the list of ClusterWorkspaces that match those selectors across all clusters. -func (c *clusterWorkspacesClusterClient) List(ctx context.Context, opts metav1.ListOptions) (*tenancyv1alpha1.ClusterWorkspaceList, error) { - obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(clusterWorkspacesResource, clusterWorkspacesKind, logicalcluster.Wildcard, opts), &tenancyv1alpha1.ClusterWorkspaceList{}) - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &tenancyv1alpha1.ClusterWorkspaceList{ListMeta: obj.(*tenancyv1alpha1.ClusterWorkspaceList).ListMeta} - for _, item := range obj.(*tenancyv1alpha1.ClusterWorkspaceList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested ClusterWorkspaces across all clusters. -func (c *clusterWorkspacesClusterClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(clusterWorkspacesResource, logicalcluster.Wildcard, opts)) -} - -type clusterWorkspacesClient struct { - *kcptesting.Fake - ClusterPath logicalcluster.Path -} - -func (c *clusterWorkspacesClient) Create(ctx context.Context, clusterWorkspace *tenancyv1alpha1.ClusterWorkspace, opts metav1.CreateOptions) (*tenancyv1alpha1.ClusterWorkspace, error) { - obj, err := c.Fake.Invokes(kcptesting.NewRootCreateAction(clusterWorkspacesResource, c.ClusterPath, clusterWorkspace), &tenancyv1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*tenancyv1alpha1.ClusterWorkspace), err -} - -func (c *clusterWorkspacesClient) Update(ctx context.Context, clusterWorkspace *tenancyv1alpha1.ClusterWorkspace, opts metav1.UpdateOptions) (*tenancyv1alpha1.ClusterWorkspace, error) { - obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateAction(clusterWorkspacesResource, c.ClusterPath, clusterWorkspace), &tenancyv1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*tenancyv1alpha1.ClusterWorkspace), err -} - -func (c *clusterWorkspacesClient) UpdateStatus(ctx context.Context, clusterWorkspace *tenancyv1alpha1.ClusterWorkspace, opts metav1.UpdateOptions) (*tenancyv1alpha1.ClusterWorkspace, error) { - obj, err := c.Fake.Invokes(kcptesting.NewRootUpdateSubresourceAction(clusterWorkspacesResource, c.ClusterPath, "status", clusterWorkspace), &tenancyv1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*tenancyv1alpha1.ClusterWorkspace), err -} - -func (c *clusterWorkspacesClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { - _, err := c.Fake.Invokes(kcptesting.NewRootDeleteActionWithOptions(clusterWorkspacesResource, c.ClusterPath, name, opts), &tenancyv1alpha1.ClusterWorkspace{}) - return err -} - -func (c *clusterWorkspacesClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { - action := kcptesting.NewRootDeleteCollectionAction(clusterWorkspacesResource, c.ClusterPath, listOpts) - - _, err := c.Fake.Invokes(action, &tenancyv1alpha1.ClusterWorkspaceList{}) - return err -} - -func (c *clusterWorkspacesClient) Get(ctx context.Context, name string, options metav1.GetOptions) (*tenancyv1alpha1.ClusterWorkspace, error) { - obj, err := c.Fake.Invokes(kcptesting.NewRootGetAction(clusterWorkspacesResource, c.ClusterPath, name), &tenancyv1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*tenancyv1alpha1.ClusterWorkspace), err -} - -// List takes label and field selectors, and returns the list of ClusterWorkspaces that match those selectors. -func (c *clusterWorkspacesClient) List(ctx context.Context, opts metav1.ListOptions) (*tenancyv1alpha1.ClusterWorkspaceList, error) { - obj, err := c.Fake.Invokes(kcptesting.NewRootListAction(clusterWorkspacesResource, clusterWorkspacesKind, c.ClusterPath, opts), &tenancyv1alpha1.ClusterWorkspaceList{}) - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &tenancyv1alpha1.ClusterWorkspaceList{ListMeta: obj.(*tenancyv1alpha1.ClusterWorkspaceList).ListMeta} - for _, item := range obj.(*tenancyv1alpha1.ClusterWorkspaceList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -func (c *clusterWorkspacesClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { - return c.Fake.InvokesWatch(kcptesting.NewRootWatchAction(clusterWorkspacesResource, c.ClusterPath, opts)) -} - -func (c *clusterWorkspacesClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*tenancyv1alpha1.ClusterWorkspace, error) { - obj, err := c.Fake.Invokes(kcptesting.NewRootPatchSubresourceAction(clusterWorkspacesResource, c.ClusterPath, name, pt, data, subresources...), &tenancyv1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*tenancyv1alpha1.ClusterWorkspace), err -} diff --git a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/fake/tenancy_client.go b/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/fake/tenancy_client.go index c6ab810e14d..32a1eee98ad 100644 --- a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/fake/tenancy_client.go +++ b/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/fake/tenancy_client.go @@ -44,10 +44,6 @@ func (c *TenancyV1alpha1ClusterClient) Cluster(clusterPath logicalcluster.Path) return &TenancyV1alpha1Client{Fake: c.Fake, ClusterPath: clusterPath} } -func (c *TenancyV1alpha1ClusterClient) ClusterWorkspaces() kcptenancyv1alpha1.ClusterWorkspaceClusterInterface { - return &clusterWorkspacesClusterClient{Fake: c.Fake} -} - func (c *TenancyV1alpha1ClusterClient) WorkspaceTypes() kcptenancyv1alpha1.WorkspaceTypeClusterInterface { return &workspaceTypesClusterClient{Fake: c.Fake} } @@ -64,10 +60,6 @@ func (c *TenancyV1alpha1Client) RESTClient() rest.Interface { return ret } -func (c *TenancyV1alpha1Client) ClusterWorkspaces() tenancyv1alpha1.ClusterWorkspaceInterface { - return &clusterWorkspacesClient{Fake: c.Fake, ClusterPath: c.ClusterPath} -} - func (c *TenancyV1alpha1Client) WorkspaceTypes() tenancyv1alpha1.WorkspaceTypeInterface { return &workspaceTypesClient{Fake: c.Fake, ClusterPath: c.ClusterPath} } diff --git a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/tenancy_client.go b/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/tenancy_client.go index a07febb8a8c..bc096050465 100644 --- a/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/tenancy_client.go +++ b/pkg/client/clientset/versioned/cluster/typed/tenancy/v1alpha1/tenancy_client.go @@ -34,7 +34,6 @@ import ( type TenancyV1alpha1ClusterInterface interface { TenancyV1alpha1ClusterScoper - ClusterWorkspacesClusterGetter WorkspaceTypesClusterGetter } @@ -53,10 +52,6 @@ func (c *TenancyV1alpha1ClusterClient) Cluster(clusterPath logicalcluster.Path) return c.clientCache.ClusterOrDie(clusterPath) } -func (c *TenancyV1alpha1ClusterClient) ClusterWorkspaces() ClusterWorkspaceClusterInterface { - return &clusterWorkspacesClusterInterface{clientCache: c.clientCache} -} - func (c *TenancyV1alpha1ClusterClient) WorkspaceTypes() WorkspaceTypeClusterInterface { return &workspaceTypesClusterInterface{clientCache: c.clientCache} } diff --git a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/clusterworkspace.go b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/clusterworkspace.go deleted file mode 100644 index 72252703744..00000000000 --- a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/clusterworkspace.go +++ /dev/null @@ -1,185 +0,0 @@ -/* -Copyright The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - "time" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" - - v1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" - scheme "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/scheme" -) - -// ClusterWorkspacesGetter has a method to return a ClusterWorkspaceInterface. -// A group's client should implement this interface. -type ClusterWorkspacesGetter interface { - ClusterWorkspaces() ClusterWorkspaceInterface -} - -// ClusterWorkspaceInterface has methods to work with ClusterWorkspace resources. -type ClusterWorkspaceInterface interface { - Create(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.CreateOptions) (*v1alpha1.ClusterWorkspace, error) - Update(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.UpdateOptions) (*v1alpha1.ClusterWorkspace, error) - UpdateStatus(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.UpdateOptions) (*v1alpha1.ClusterWorkspace, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ClusterWorkspace, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ClusterWorkspaceList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterWorkspace, err error) - ClusterWorkspaceExpansion -} - -// clusterWorkspaces implements ClusterWorkspaceInterface -type clusterWorkspaces struct { - client rest.Interface -} - -// newClusterWorkspaces returns a ClusterWorkspaces -func newClusterWorkspaces(c *TenancyV1alpha1Client) *clusterWorkspaces { - return &clusterWorkspaces{ - client: c.RESTClient(), - } -} - -// Get takes name of the clusterWorkspace, and returns the corresponding clusterWorkspace object, and an error if there is any. -func (c *clusterWorkspaces) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterWorkspace, err error) { - result = &v1alpha1.ClusterWorkspace{} - err = c.client.Get(). - Resource("clusterworkspaces"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ClusterWorkspaces that match those selectors. -func (c *clusterWorkspaces) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterWorkspaceList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.ClusterWorkspaceList{} - err = c.client.Get(). - Resource("clusterworkspaces"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested clusterWorkspaces. -func (c *clusterWorkspaces) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Resource("clusterworkspaces"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a clusterWorkspace and creates it. Returns the server's representation of the clusterWorkspace, and an error, if there is any. -func (c *clusterWorkspaces) Create(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.CreateOptions) (result *v1alpha1.ClusterWorkspace, err error) { - result = &v1alpha1.ClusterWorkspace{} - err = c.client.Post(). - Resource("clusterworkspaces"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterWorkspace). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a clusterWorkspace and updates it. Returns the server's representation of the clusterWorkspace, and an error, if there is any. -func (c *clusterWorkspaces) Update(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.UpdateOptions) (result *v1alpha1.ClusterWorkspace, err error) { - result = &v1alpha1.ClusterWorkspace{} - err = c.client.Put(). - Resource("clusterworkspaces"). - Name(clusterWorkspace.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterWorkspace). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *clusterWorkspaces) UpdateStatus(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.UpdateOptions) (result *v1alpha1.ClusterWorkspace, err error) { - result = &v1alpha1.ClusterWorkspace{} - err = c.client.Put(). - Resource("clusterworkspaces"). - Name(clusterWorkspace.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(clusterWorkspace). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the clusterWorkspace and deletes it. Returns an error if one occurs. -func (c *clusterWorkspaces) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Resource("clusterworkspaces"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *clusterWorkspaces) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Resource("clusterworkspaces"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched clusterWorkspace. -func (c *clusterWorkspaces) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterWorkspace, err error) { - result = &v1alpha1.ClusterWorkspace{} - err = c.client.Patch(pt). - Resource("clusterworkspaces"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/fake/fake_clusterworkspace.go b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/fake/fake_clusterworkspace.go deleted file mode 100644 index 7cd2d96ca90..00000000000 --- a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/fake/fake_clusterworkspace.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -Copyright The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - schema "k8s.io/apimachinery/pkg/runtime/schema" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" - - v1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" -) - -// FakeClusterWorkspaces implements ClusterWorkspaceInterface -type FakeClusterWorkspaces struct { - Fake *FakeTenancyV1alpha1 -} - -var clusterworkspacesResource = schema.GroupVersionResource{Group: "tenancy.kcp.io", Version: "v1alpha1", Resource: "clusterworkspaces"} - -var clusterworkspacesKind = schema.GroupVersionKind{Group: "tenancy.kcp.io", Version: "v1alpha1", Kind: "ClusterWorkspace"} - -// Get takes name of the clusterWorkspace, and returns the corresponding clusterWorkspace object, and an error if there is any. -func (c *FakeClusterWorkspaces) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterWorkspace, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootGetAction(clusterworkspacesResource, name), &v1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterWorkspace), err -} - -// List takes label and field selectors, and returns the list of ClusterWorkspaces that match those selectors. -func (c *FakeClusterWorkspaces) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterWorkspaceList, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootListAction(clusterworkspacesResource, clusterworkspacesKind, opts), &v1alpha1.ClusterWorkspaceList{}) - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.ClusterWorkspaceList{ListMeta: obj.(*v1alpha1.ClusterWorkspaceList).ListMeta} - for _, item := range obj.(*v1alpha1.ClusterWorkspaceList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested clusterWorkspaces. -func (c *FakeClusterWorkspaces) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewRootWatchAction(clusterworkspacesResource, opts)) -} - -// Create takes the representation of a clusterWorkspace and creates it. Returns the server's representation of the clusterWorkspace, and an error, if there is any. -func (c *FakeClusterWorkspaces) Create(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.CreateOptions) (result *v1alpha1.ClusterWorkspace, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootCreateAction(clusterworkspacesResource, clusterWorkspace), &v1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterWorkspace), err -} - -// Update takes the representation of a clusterWorkspace and updates it. Returns the server's representation of the clusterWorkspace, and an error, if there is any. -func (c *FakeClusterWorkspaces) Update(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.UpdateOptions) (result *v1alpha1.ClusterWorkspace, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateAction(clusterworkspacesResource, clusterWorkspace), &v1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterWorkspace), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeClusterWorkspaces) UpdateStatus(ctx context.Context, clusterWorkspace *v1alpha1.ClusterWorkspace, opts v1.UpdateOptions) (*v1alpha1.ClusterWorkspace, error) { - obj, err := c.Fake. - Invokes(testing.NewRootUpdateSubresourceAction(clusterworkspacesResource, "status", clusterWorkspace), &v1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterWorkspace), err -} - -// Delete takes name of the clusterWorkspace and deletes it. Returns an error if one occurs. -func (c *FakeClusterWorkspaces) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewRootDeleteActionWithOptions(clusterworkspacesResource, name, opts), &v1alpha1.ClusterWorkspace{}) - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeClusterWorkspaces) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewRootDeleteCollectionAction(clusterworkspacesResource, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha1.ClusterWorkspaceList{}) - return err -} - -// Patch applies the patch and returns the patched clusterWorkspace. -func (c *FakeClusterWorkspaces) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterWorkspace, err error) { - obj, err := c.Fake. - Invokes(testing.NewRootPatchSubresourceAction(clusterworkspacesResource, name, pt, data, subresources...), &v1alpha1.ClusterWorkspace{}) - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ClusterWorkspace), err -} diff --git a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/fake/fake_tenancy_client.go b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/fake/fake_tenancy_client.go index 1ae47c3dc3e..9078f28f055 100644 --- a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/fake/fake_tenancy_client.go +++ b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/fake/fake_tenancy_client.go @@ -29,10 +29,6 @@ type FakeTenancyV1alpha1 struct { *testing.Fake } -func (c *FakeTenancyV1alpha1) ClusterWorkspaces() v1alpha1.ClusterWorkspaceInterface { - return &FakeClusterWorkspaces{c} -} - func (c *FakeTenancyV1alpha1) WorkspaceTypes() v1alpha1.WorkspaceTypeInterface { return &FakeWorkspaceTypes{c} } diff --git a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/generated_expansion.go index 1e59dfa1158..2335dc20dc2 100644 --- a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/generated_expansion.go @@ -18,6 +18,4 @@ limitations under the License. package v1alpha1 -type ClusterWorkspaceExpansion interface{} - type WorkspaceTypeExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/tenancy_client.go b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/tenancy_client.go index 518a127bda0..980ee1d6292 100644 --- a/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/tenancy_client.go +++ b/pkg/client/clientset/versioned/typed/tenancy/v1alpha1/tenancy_client.go @@ -29,7 +29,6 @@ import ( type TenancyV1alpha1Interface interface { RESTClient() rest.Interface - ClusterWorkspacesGetter WorkspaceTypesGetter } @@ -38,10 +37,6 @@ type TenancyV1alpha1Client struct { restClient rest.Interface } -func (c *TenancyV1alpha1Client) ClusterWorkspaces() ClusterWorkspaceInterface { - return newClusterWorkspaces(c) -} - func (c *TenancyV1alpha1Client) WorkspaceTypes() WorkspaceTypeInterface { return newWorkspaceTypes(c) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 131face6732..967b10cb45e 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -118,8 +118,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case schedulingv1alpha1.SchemeGroupVersion.WithResource("placements"): return &genericClusterInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1alpha1().Placements().Informer()}, nil // Group=tenancy.kcp.io, Version=V1alpha1 - case tenancyv1alpha1.SchemeGroupVersion.WithResource("clusterworkspaces"): - return &genericClusterInformer{resource: resource.GroupResource(), informer: f.Tenancy().V1alpha1().ClusterWorkspaces().Informer()}, nil case tenancyv1alpha1.SchemeGroupVersion.WithResource("workspacetypes"): return &genericClusterInformer{resource: resource.GroupResource(), informer: f.Tenancy().V1alpha1().WorkspaceTypes().Informer()}, nil // Group=tenancy.kcp.io, Version=V1beta1 @@ -177,9 +175,6 @@ func (f *sharedScopedInformerFactory) ForResource(resource schema.GroupVersionRe informer := f.Scheduling().V1alpha1().Placements().Informer() return &genericInformer{lister: cache.NewGenericLister(informer.GetIndexer(), resource.GroupResource()), informer: informer}, nil // Group=tenancy.kcp.io, Version=V1alpha1 - case tenancyv1alpha1.SchemeGroupVersion.WithResource("clusterworkspaces"): - informer := f.Tenancy().V1alpha1().ClusterWorkspaces().Informer() - return &genericInformer{lister: cache.NewGenericLister(informer.GetIndexer(), resource.GroupResource()), informer: informer}, nil case tenancyv1alpha1.SchemeGroupVersion.WithResource("workspacetypes"): informer := f.Tenancy().V1alpha1().WorkspaceTypes().Informer() return &genericInformer{lister: cache.NewGenericLister(informer.GetIndexer(), resource.GroupResource()), informer: informer}, nil diff --git a/pkg/client/informers/externalversions/tenancy/v1alpha1/clusterworkspace.go b/pkg/client/informers/externalversions/tenancy/v1alpha1/clusterworkspace.go deleted file mode 100644 index f166a6cb619..00000000000 --- a/pkg/client/informers/externalversions/tenancy/v1alpha1/clusterworkspace.go +++ /dev/null @@ -1,179 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by kcp code-generator. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - "time" - - kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" - kcpinformers "github.com/kcp-dev/apimachinery/v2/third_party/informers" - "github.com/kcp-dev/logicalcluster/v3" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" - - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" - scopedclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned" - clientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" - "github.com/kcp-dev/kcp/pkg/client/informers/externalversions/internalinterfaces" - tenancyv1alpha1listers "github.com/kcp-dev/kcp/pkg/client/listers/tenancy/v1alpha1" -) - -// ClusterWorkspaceClusterInformer provides access to a shared informer and lister for -// ClusterWorkspaces. -type ClusterWorkspaceClusterInformer interface { - Cluster(logicalcluster.Name) ClusterWorkspaceInformer - Informer() kcpcache.ScopeableSharedIndexInformer - Lister() tenancyv1alpha1listers.ClusterWorkspaceClusterLister -} - -type clusterWorkspaceClusterInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// NewClusterWorkspaceClusterInformer constructs a new informer for ClusterWorkspace type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewClusterWorkspaceClusterInformer(client clientset.ClusterInterface, resyncPeriod time.Duration, indexers cache.Indexers) kcpcache.ScopeableSharedIndexInformer { - return NewFilteredClusterWorkspaceClusterInformer(client, resyncPeriod, indexers, nil) -} - -// NewFilteredClusterWorkspaceClusterInformer constructs a new informer for ClusterWorkspace type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredClusterWorkspaceClusterInformer(client clientset.ClusterInterface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) kcpcache.ScopeableSharedIndexInformer { - return kcpinformers.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.TenancyV1alpha1().ClusterWorkspaces().List(context.TODO(), options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.TenancyV1alpha1().ClusterWorkspaces().Watch(context.TODO(), options) - }, - }, - &tenancyv1alpha1.ClusterWorkspace{}, - resyncPeriod, - indexers, - ) -} - -func (f *clusterWorkspaceClusterInformer) defaultInformer(client clientset.ClusterInterface, resyncPeriod time.Duration) kcpcache.ScopeableSharedIndexInformer { - return NewFilteredClusterWorkspaceClusterInformer(client, resyncPeriod, cache.Indexers{ - kcpcache.ClusterIndexName: kcpcache.ClusterIndexFunc, - }, - f.tweakListOptions, - ) -} - -func (f *clusterWorkspaceClusterInformer) Informer() kcpcache.ScopeableSharedIndexInformer { - return f.factory.InformerFor(&tenancyv1alpha1.ClusterWorkspace{}, f.defaultInformer) -} - -func (f *clusterWorkspaceClusterInformer) Lister() tenancyv1alpha1listers.ClusterWorkspaceClusterLister { - return tenancyv1alpha1listers.NewClusterWorkspaceClusterLister(f.Informer().GetIndexer()) -} - -// ClusterWorkspaceInformer provides access to a shared informer and lister for -// ClusterWorkspaces. -type ClusterWorkspaceInformer interface { - Informer() cache.SharedIndexInformer - Lister() tenancyv1alpha1listers.ClusterWorkspaceLister -} - -func (f *clusterWorkspaceClusterInformer) Cluster(clusterName logicalcluster.Name) ClusterWorkspaceInformer { - return &clusterWorkspaceInformer{ - informer: f.Informer().Cluster(clusterName), - lister: f.Lister().Cluster(clusterName), - } -} - -type clusterWorkspaceInformer struct { - informer cache.SharedIndexInformer - lister tenancyv1alpha1listers.ClusterWorkspaceLister -} - -func (f *clusterWorkspaceInformer) Informer() cache.SharedIndexInformer { - return f.informer -} - -func (f *clusterWorkspaceInformer) Lister() tenancyv1alpha1listers.ClusterWorkspaceLister { - return f.lister -} - -type clusterWorkspaceScopedInformer struct { - factory internalinterfaces.SharedScopedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -func (f *clusterWorkspaceScopedInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&tenancyv1alpha1.ClusterWorkspace{}, f.defaultInformer) -} - -func (f *clusterWorkspaceScopedInformer) Lister() tenancyv1alpha1listers.ClusterWorkspaceLister { - return tenancyv1alpha1listers.NewClusterWorkspaceLister(f.Informer().GetIndexer()) -} - -// NewClusterWorkspaceInformer constructs a new informer for ClusterWorkspace type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewClusterWorkspaceInformer(client scopedclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredClusterWorkspaceInformer(client, resyncPeriod, indexers, nil) -} - -// NewFilteredClusterWorkspaceInformer constructs a new informer for ClusterWorkspace type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredClusterWorkspaceInformer(client scopedclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.TenancyV1alpha1().ClusterWorkspaces().List(context.TODO(), options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.TenancyV1alpha1().ClusterWorkspaces().Watch(context.TODO(), options) - }, - }, - &tenancyv1alpha1.ClusterWorkspace{}, - resyncPeriod, - indexers, - ) -} - -func (f *clusterWorkspaceScopedInformer) defaultInformer(client scopedclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredClusterWorkspaceInformer(client, resyncPeriod, cache.Indexers{}, f.tweakListOptions) -} diff --git a/pkg/client/informers/externalversions/tenancy/v1alpha1/interface.go b/pkg/client/informers/externalversions/tenancy/v1alpha1/interface.go index 7d9aafc15bf..6f9dcab5ed7 100644 --- a/pkg/client/informers/externalversions/tenancy/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/tenancy/v1alpha1/interface.go @@ -26,8 +26,6 @@ import ( ) type ClusterInterface interface { - // ClusterWorkspaces returns a ClusterWorkspaceClusterInformer - ClusterWorkspaces() ClusterWorkspaceClusterInformer // WorkspaceTypes returns a WorkspaceTypeClusterInformer WorkspaceTypes() WorkspaceTypeClusterInformer } @@ -42,19 +40,12 @@ func New(f internalinterfaces.SharedInformerFactory, tweakListOptions internalin return &version{factory: f, tweakListOptions: tweakListOptions} } -// ClusterWorkspaces returns a ClusterWorkspaceClusterInformer -func (v *version) ClusterWorkspaces() ClusterWorkspaceClusterInformer { - return &clusterWorkspaceClusterInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} -} - // WorkspaceTypes returns a WorkspaceTypeClusterInformer func (v *version) WorkspaceTypes() WorkspaceTypeClusterInformer { return &workspaceTypeClusterInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } type Interface interface { - // ClusterWorkspaces returns a ClusterWorkspaceInformer - ClusterWorkspaces() ClusterWorkspaceInformer // WorkspaceTypes returns a WorkspaceTypeInformer WorkspaceTypes() WorkspaceTypeInformer } @@ -70,11 +61,6 @@ func NewScoped(f internalinterfaces.SharedScopedInformerFactory, namespace strin return &scopedVersion{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// ClusterWorkspaces returns a ClusterWorkspaceInformer -func (v *scopedVersion) ClusterWorkspaces() ClusterWorkspaceInformer { - return &clusterWorkspaceScopedInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} -} - // WorkspaceTypes returns a WorkspaceTypeInformer func (v *scopedVersion) WorkspaceTypes() WorkspaceTypeInformer { return &workspaceTypeScopedInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/listers/tenancy/v1alpha1/clusterworkspace.go b/pkg/client/listers/tenancy/v1alpha1/clusterworkspace.go deleted file mode 100644 index f82530dc328..00000000000 --- a/pkg/client/listers/tenancy/v1alpha1/clusterworkspace.go +++ /dev/null @@ -1,143 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by kcp code-generator. DO NOT EDIT. - -package v1alpha1 - -import ( - kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" - "github.com/kcp-dev/logicalcluster/v3" - - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" - - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" -) - -// ClusterWorkspaceClusterLister can list ClusterWorkspaces across all workspaces, or scope down to a ClusterWorkspaceLister for one workspace. -// All objects returned here must be treated as read-only. -type ClusterWorkspaceClusterLister interface { - // List lists all ClusterWorkspaces in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*tenancyv1alpha1.ClusterWorkspace, err error) - // Cluster returns a lister that can list and get ClusterWorkspaces in one workspace. - Cluster(clusterName logicalcluster.Name) ClusterWorkspaceLister - ClusterWorkspaceClusterListerExpansion -} - -type clusterWorkspaceClusterLister struct { - indexer cache.Indexer -} - -// NewClusterWorkspaceClusterLister returns a new ClusterWorkspaceClusterLister. -// We assume that the indexer: -// - is fed by a cross-workspace LIST+WATCH -// - uses kcpcache.MetaClusterNamespaceKeyFunc as the key function -// - has the kcpcache.ClusterIndex as an index -func NewClusterWorkspaceClusterLister(indexer cache.Indexer) *clusterWorkspaceClusterLister { - return &clusterWorkspaceClusterLister{indexer: indexer} -} - -// List lists all ClusterWorkspaces in the indexer across all workspaces. -func (s *clusterWorkspaceClusterLister) List(selector labels.Selector) (ret []*tenancyv1alpha1.ClusterWorkspace, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*tenancyv1alpha1.ClusterWorkspace)) - }) - return ret, err -} - -// Cluster scopes the lister to one workspace, allowing users to list and get ClusterWorkspaces. -func (s *clusterWorkspaceClusterLister) Cluster(clusterName logicalcluster.Name) ClusterWorkspaceLister { - return &clusterWorkspaceLister{indexer: s.indexer, clusterName: clusterName} -} - -// ClusterWorkspaceLister can list all ClusterWorkspaces, or get one in particular. -// All objects returned here must be treated as read-only. -type ClusterWorkspaceLister interface { - // List lists all ClusterWorkspaces in the workspace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*tenancyv1alpha1.ClusterWorkspace, err error) - // Get retrieves the ClusterWorkspace from the indexer for a given workspace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*tenancyv1alpha1.ClusterWorkspace, error) - ClusterWorkspaceListerExpansion -} - -// clusterWorkspaceLister can list all ClusterWorkspaces inside a workspace. -type clusterWorkspaceLister struct { - indexer cache.Indexer - clusterName logicalcluster.Name -} - -// List lists all ClusterWorkspaces in the indexer for a workspace. -func (s *clusterWorkspaceLister) List(selector labels.Selector) (ret []*tenancyv1alpha1.ClusterWorkspace, err error) { - err = kcpcache.ListAllByCluster(s.indexer, s.clusterName, selector, func(i interface{}) { - ret = append(ret, i.(*tenancyv1alpha1.ClusterWorkspace)) - }) - return ret, err -} - -// Get retrieves the ClusterWorkspace from the indexer for a given workspace and name. -func (s *clusterWorkspaceLister) Get(name string) (*tenancyv1alpha1.ClusterWorkspace, error) { - key := kcpcache.ToClusterAwareKey(s.clusterName.String(), "", name) - obj, exists, err := s.indexer.GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(tenancyv1alpha1.Resource("ClusterWorkspace"), name) - } - return obj.(*tenancyv1alpha1.ClusterWorkspace), nil -} - -// NewClusterWorkspaceLister returns a new ClusterWorkspaceLister. -// We assume that the indexer: -// - is fed by a workspace-scoped LIST+WATCH -// - uses cache.MetaNamespaceKeyFunc as the key function -func NewClusterWorkspaceLister(indexer cache.Indexer) *clusterWorkspaceScopedLister { - return &clusterWorkspaceScopedLister{indexer: indexer} -} - -// clusterWorkspaceScopedLister can list all ClusterWorkspaces inside a workspace. -type clusterWorkspaceScopedLister struct { - indexer cache.Indexer -} - -// List lists all ClusterWorkspaces in the indexer for a workspace. -func (s *clusterWorkspaceScopedLister) List(selector labels.Selector) (ret []*tenancyv1alpha1.ClusterWorkspace, err error) { - err = cache.ListAll(s.indexer, selector, func(i interface{}) { - ret = append(ret, i.(*tenancyv1alpha1.ClusterWorkspace)) - }) - return ret, err -} - -// Get retrieves the ClusterWorkspace from the indexer for a given workspace and name. -func (s *clusterWorkspaceScopedLister) Get(name string) (*tenancyv1alpha1.ClusterWorkspace, error) { - key := name - obj, exists, err := s.indexer.GetByKey(key) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(tenancyv1alpha1.Resource("ClusterWorkspace"), name) - } - return obj.(*tenancyv1alpha1.ClusterWorkspace), nil -} diff --git a/pkg/client/listers/tenancy/v1alpha1/clusterworkspace_expansion.go b/pkg/client/listers/tenancy/v1alpha1/clusterworkspace_expansion.go deleted file mode 100644 index 0ad3e3fbffe..00000000000 --- a/pkg/client/listers/tenancy/v1alpha1/clusterworkspace_expansion.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by kcp code-generator. DO NOT EDIT. - -package v1alpha1 - -// ClusterWorkspaceClusterListerExpansion allows custom methods to be added to ClusterWorkspaceClusterLister. -type ClusterWorkspaceClusterListerExpansion interface{} - -// ClusterWorkspaceListerExpansion allows custom methods to be added to ClusterWorkspaceLister. -type ClusterWorkspaceListerExpansion interface{} diff --git a/pkg/cliplugins/workspace/plugin/kubeconfig.go b/pkg/cliplugins/workspace/plugin/kubeconfig.go index fefc2f29087..0c53925f2d7 100644 --- a/pkg/cliplugins/workspace/plugin/kubeconfig.go +++ b/pkg/cliplugins/workspace/plugin/kubeconfig.go @@ -132,7 +132,7 @@ func (o *UseWorkspaceOptions) Run(ctx context.Context) error { } var newServerHost string - var workspaceType *tenancyv1beta1.WorkspaceTypeReference + var workspaceType *tenancyv1alpha1.WorkspaceTypeReference switch o.Name { case "-": prev, exists := o.startingConfig.Contexts[kcpPreviousWorkspaceContextKey] @@ -412,7 +412,7 @@ func (o *CurrentWorkspaceOptions) Run(ctx context.Context) error { type shortWorkspaceOutput bool -func currentWorkspace(out io.Writer, host string, shortWorkspaceOutput shortWorkspaceOutput, workspaceType *tenancyv1beta1.WorkspaceTypeReference) error { +func currentWorkspace(out io.Writer, host string, shortWorkspaceOutput shortWorkspaceOutput, workspaceType *tenancyv1alpha1.WorkspaceTypeReference) error { _, clusterName, err := pluginhelpers.ParseClusterURL(host) if err != nil { if shortWorkspaceOutput { @@ -519,17 +519,17 @@ func (o *CreateWorkspaceOptions) Run(ctx context.Context) error { return fmt.Errorf("--ignore-existing must not be used with non-absolute type path") } - var structuredWorkspaceType tenancyv1beta1.WorkspaceTypeReference + var structuredWorkspaceType tenancyv1alpha1.WorkspaceTypeReference if o.Type != "" { separatorIndex := strings.LastIndex(o.Type, ":") switch separatorIndex { case -1: - structuredWorkspaceType = tenancyv1beta1.WorkspaceTypeReference{ + structuredWorkspaceType = tenancyv1alpha1.WorkspaceTypeReference{ Name: tenancyv1alpha1.WorkspaceTypeName(strings.ToLower(o.Type)), // path is defaulted through admission } default: - structuredWorkspaceType = tenancyv1beta1.WorkspaceTypeReference{ + structuredWorkspaceType = tenancyv1alpha1.WorkspaceTypeReference{ Name: tenancyv1alpha1.WorkspaceTypeName(strings.ToLower(o.Type[separatorIndex+1:])), Path: o.Type[:separatorIndex], } diff --git a/pkg/cliplugins/workspace/plugin/kubeconfig_test.go b/pkg/cliplugins/workspace/plugin/kubeconfig_test.go index c2fdd97c1cc..614020d0fa8 100644 --- a/pkg/cliplugins/workspace/plugin/kubeconfig_test.go +++ b/pkg/cliplugins/workspace/plugin/kubeconfig_test.go @@ -42,6 +42,7 @@ import ( apisv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/apis/v1alpha1" "github.com/kcp-dev/kcp/pkg/apis/core" corev1alpha1 "github.com/kcp-dev/kcp/pkg/apis/core/v1alpha1" + tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" kcpclient "github.com/kcp-dev/kcp/pkg/client/clientset/versioned" kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" @@ -57,7 +58,7 @@ func TestCreate(t *testing.T) { markReady bool newWorkspaceName string - newWorkspaceType tenancyv1beta1.WorkspaceTypeReference + newWorkspaceType tenancyv1alpha1.WorkspaceTypeReference useAfterCreation, ignoreExisting bool expected *clientcmdapi.Config @@ -152,7 +153,7 @@ func TestCreate(t *testing.T) { }, existingWorkspaces: []string{"bar"}, newWorkspaceName: "bar", - newWorkspaceType: tenancyv1beta1.WorkspaceTypeReference{Path: "root", Name: "universal"}, + newWorkspaceType: tenancyv1alpha1.WorkspaceTypeReference{Path: "root", Name: "universal"}, useAfterCreation: true, markReady: true, ignoreExisting: true, @@ -178,7 +179,7 @@ func TestCreate(t *testing.T) { }, newWorkspaceName: "bar", ignoreExisting: true, - newWorkspaceType: tenancyv1beta1.WorkspaceTypeReference{Name: "universal"}, + newWorkspaceType: tenancyv1alpha1.WorkspaceTypeReference{Name: "universal"}, wantErr: true, }, } @@ -201,7 +202,7 @@ func TestCreate(t *testing.T) { }, Spec: tenancyv1beta1.WorkspaceSpec{ URL: fmt.Sprintf("https://test%s", currentClusterName.Join(name).RequestPath()), - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "universal", Path: "root", }, @@ -214,9 +215,9 @@ func TestCreate(t *testing.T) { client := kcpfakeclient.NewSimpleClientset(objects...) workspaceType := tt.newWorkspaceType - empty := tenancyv1beta1.WorkspaceTypeReference{} + empty := tenancyv1alpha1.WorkspaceTypeReference{} if workspaceType == empty { - workspaceType = tenancyv1beta1.WorkspaceTypeReference{ + workspaceType = tenancyv1alpha1.WorkspaceTypeReference{ Name: "universal", Path: "root", } @@ -1196,7 +1197,7 @@ func TestUse(t *testing.T) { Annotations: map[string]string{logicalcluster.AnnotationKey: lcluster.String()}, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "universal", Path: "root", }, @@ -1222,7 +1223,7 @@ func TestUse(t *testing.T) { }, Spec: tenancyv1beta1.WorkspaceSpec{ URL: fmt.Sprintf("https://test%s", homeWorkspaceLogicalCluster.RequestPath()), - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "home", Path: "root", }, diff --git a/pkg/openapi/zz_generated.openapi.go b/pkg/openapi/zz_generated.openapi.go index b4e5988459c..64f1c43a027 100644 --- a/pkg/openapi/zz_generated.openapi.go +++ b/pkg/openapi/zz_generated.openapi.go @@ -95,12 +95,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/kcp-dev/kcp/pkg/apis/scheduling/v1alpha1.PlacementSpec": schema_pkg_apis_scheduling_v1alpha1_PlacementSpec(ref), "github.com/kcp-dev/kcp/pkg/apis/scheduling/v1alpha1.PlacementStatus": schema_pkg_apis_scheduling_v1alpha1_PlacementStatus(ref), "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.APIExportReference": schema_pkg_apis_tenancy_v1alpha1_APIExportReference(ref), - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspace": schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspace(ref), - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceList": schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceList(ref), - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceLocation": schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceLocation(ref), - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceSpec": schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceSpec(ref), - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceStatus": schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceStatus(ref), - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ShardConstraints": schema_pkg_apis_tenancy_v1alpha1_ShardConstraints(ref), "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.VirtualWorkspace": schema_pkg_apis_tenancy_v1alpha1_VirtualWorkspace(ref), "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.WorkspaceType": schema_pkg_apis_tenancy_v1alpha1_WorkspaceType(ref), "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.WorkspaceTypeExtension": schema_pkg_apis_tenancy_v1alpha1_WorkspaceTypeExtension(ref), @@ -114,7 +108,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceLocation": schema_pkg_apis_tenancy_v1beta1_WorkspaceLocation(ref), "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceSpec": schema_pkg_apis_tenancy_v1beta1_WorkspaceSpec(ref), "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceStatus": schema_pkg_apis_tenancy_v1beta1_WorkspaceStatus(ref), - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceTypeReference": schema_pkg_apis_tenancy_v1beta1_WorkspaceTypeReference(ref), "github.com/kcp-dev/kcp/pkg/apis/third_party/conditions/apis/conditions/v1alpha1.Condition": schema_conditions_apis_conditions_v1alpha1_Condition(ref), "github.com/kcp-dev/kcp/pkg/apis/topology/v1alpha1.Partition": schema_pkg_apis_topology_v1alpha1_Partition(ref), "github.com/kcp-dev/kcp/pkg/apis/topology/v1alpha1.PartitionList": schema_pkg_apis_topology_v1alpha1_PartitionList(ref), @@ -3274,262 +3267,6 @@ func schema_pkg_apis_tenancy_v1alpha1_APIExportReference(ref common.ReferenceCal } } -func schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspace(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "ClusterWorkspace defines a Kubernetes-cluster-like endpoint that holds a default set of resources and exhibits standard Kubernetes API semantics of CRUD operations. It represents the full life-cycle of the persisted data in this workspace in a KCP installation.\n\nClusterWorkspace is a concrete type that implements a workspace.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "kind": { - SchemaProps: spec.SchemaProps{ - Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", - Type: []string{"string"}, - Format: "", - }, - }, - "apiVersion": { - SchemaProps: spec.SchemaProps{ - Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", - Type: []string{"string"}, - Format: "", - }, - }, - "metadata": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), - }, - }, - "spec": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceSpec"), - }, - }, - "status": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceStatus"), - }, - }, - }, - }, - }, - Dependencies: []string{ - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceSpec", "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, - } -} - -func schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceList(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "ClusterWorkspaceList is a list of ClusterWorkspace resources", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "kind": { - SchemaProps: spec.SchemaProps{ - Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", - Type: []string{"string"}, - Format: "", - }, - }, - "apiVersion": { - SchemaProps: spec.SchemaProps{ - Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", - Type: []string{"string"}, - Format: "", - }, - }, - "metadata": { - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), - }, - }, - "items": { - SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspace"), - }, - }, - }, - }, - }, - }, - Required: []string{"metadata", "items"}, - }, - }, - Dependencies: []string{ - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspace", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, - } -} - -func schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceLocation(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "ClusterWorkspaceLocation specifies workspace placement information, including current, desired (target), and historical information.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "current": { - SchemaProps: spec.SchemaProps{ - Description: "Current workspace placement (shard).", - Type: []string{"string"}, - Format: "", - }, - }, - "target": { - SchemaProps: spec.SchemaProps{ - Description: "Target workspace placement (shard).", - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - } -} - -func schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "ClusterWorkspaceSpec holds the desired state of the ClusterWorkspace.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "readOnly": { - SchemaProps: spec.SchemaProps{ - Type: []string{"boolean"}, - Format: "", - }, - }, - "type": { - SchemaProps: spec.SchemaProps{ - Description: "type defines properties of the workspace both on creation (e.g. initial resources and initially installed APIs) and during runtime (e.g. permissions). If no type is provided, the default type for the workspace in which this workspace is nesting will be used.\n\nThe type is a reference to a WorkspaceType in the listed workspace, but lower-cased. The WorkspaceType existence is validated at admission during creation. The type is immutable after creation. The use of a type is gated via the RBAC workspacetypes/use resource permission.", - Default: map[string]interface{}{}, - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.WorkspaceTypeReference"), - }, - }, - "shard": { - SchemaProps: spec.SchemaProps{ - Description: "shard constraints onto which shards this cluster workspace can be scheduled to. if the constraint is not fulfilled by the current location stored in the status, movement will be attempted.\n\nEither shard name or shard selector must be specified.\n\nIf the no shard constraints are specified, an arbitrary shard is chosen.", - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ShardConstraints"), - }, - }, - }, - }, - }, - Dependencies: []string{ - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ShardConstraints", "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.WorkspaceTypeReference"}, - } -} - -func schema_pkg_apis_tenancy_v1alpha1_ClusterWorkspaceStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "ClusterWorkspaceStatus communicates the observed state of the ClusterWorkspace.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "phase": { - SchemaProps: spec.SchemaProps{ - Description: "Phase of the workspace (Scheduling / Initializing / Ready)", - Type: []string{"string"}, - Format: "", - }, - }, - "conditions": { - SchemaProps: spec.SchemaProps{ - Description: "Current processing state of the ClusterWorkspace.", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/third_party/conditions/apis/conditions/v1alpha1.Condition"), - }, - }, - }, - }, - }, - "baseURL": { - SchemaProps: spec.SchemaProps{ - Description: "Base URL where this ClusterWorkspace can be targeted. This will generally be of the form: https:///cluster/. But a workspace could also be targetable by a unique hostname in the future.", - Type: []string{"string"}, - Format: "", - }, - }, - "cluster": { - SchemaProps: spec.SchemaProps{ - Description: "cluster is the name of the logical cluster this workspace is stored under.", - Type: []string{"string"}, - Format: "", - }, - }, - "location": { - SchemaProps: spec.SchemaProps{ - Description: "Contains workspace placement information.", - Default: map[string]interface{}{}, - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceLocation"), - }, - }, - "initializers": { - SchemaProps: spec.SchemaProps{ - Description: "initializers are set on creation by the system and must be cleared by a controller before the workspace can be used. The workspace will stay in the phase \"Initializing\" state until all initializers are cleared.\n\nA cluster workspace in \"Initializing\" state are gated via the RBAC clusterworkspaces/initialize resource permission.", - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - }, - }, - }, - Dependencies: []string{ - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.ClusterWorkspaceLocation", "github.com/kcp-dev/kcp/pkg/apis/third_party/conditions/apis/conditions/v1alpha1.Condition"}, - } -} - -func schema_pkg_apis_tenancy_v1alpha1_ShardConstraints(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Description: "name is the name of Shard.", - Type: []string{"string"}, - Format: "", - }, - }, - "selector": { - SchemaProps: spec.SchemaProps{ - Description: "selector is a label selector that filters shard scheduling targets.", - Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"), - }, - }, - }, - }, - }, - Dependencies: []string{ - "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"}, - } -} - func schema_pkg_apis_tenancy_v1alpha1_VirtualWorkspace(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3988,7 +3725,7 @@ func schema_pkg_apis_tenancy_v1beta1_WorkspaceSpec(ref common.ReferenceCallback) SchemaProps: spec.SchemaProps{ Description: "type defines properties of the workspace both on creation (e.g. initial resources and initially installed APIs) and during runtime (e.g. permissions). If no type is provided, the default type for the workspace in which this workspace is nesting will be used.\n\nThe type is a reference to a WorkspaceType in the listed workspace, but lower-cased. The WorkspaceType existence is validated at admission during creation. The type is immutable after creation. The use of a type is gated via the RBAC workspacetypes/use resource permission.", Default: map[string]interface{}{}, - Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceTypeReference"), + Ref: ref("github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.WorkspaceTypeReference"), }, }, "shard": { @@ -4015,7 +3752,7 @@ func schema_pkg_apis_tenancy_v1beta1_WorkspaceSpec(ref common.ReferenceCallback) }, }, Dependencies: []string{ - "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceLocation", "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceTypeReference"}, + "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1.WorkspaceTypeReference", "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1.WorkspaceLocation"}, } } @@ -4070,35 +3807,6 @@ func schema_pkg_apis_tenancy_v1beta1_WorkspaceStatus(ref common.ReferenceCallbac } } -func schema_pkg_apis_tenancy_v1beta1_WorkspaceTypeReference(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "WorkspaceTypeReference is a reference to a workspace type.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Description: "name is the name of the WorkspaceType", - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "path": { - SchemaProps: spec.SchemaProps{ - Description: "path is an absolute reference to the workspace that owns this type, e.g. root:org:ws.", - Type: []string{"string"}, - Format: "", - }, - }, - }, - Required: []string{"name"}, - }, - }, - } -} - func schema_conditions_apis_conditions_v1alpha1_Condition(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/reconciler/tenancy/workspace/workspace_reconcile_scheduling_test.go b/pkg/reconciler/tenancy/workspace/workspace_reconcile_scheduling_test.go index fe5b4edf8ce..415e405f9d8 100644 --- a/pkg/reconciler/tenancy/workspace/workspace_reconcile_scheduling_test.go +++ b/pkg/reconciler/tenancy/workspace/workspace_reconcile_scheduling_test.go @@ -374,7 +374,7 @@ func wellKnownFooWSForPhaseTwo() *tenancyv1beta1.Workspace { ws.Annotations["experimental.tenancy.kcp.io/owner"] = `{"username":"kcp-admin"}` ws.Finalizers = append(ws.Finalizers, "core.kcp.io/logicalcluster") // type info is assigned by an admission plugin - ws.Spec.Type = tenancyv1beta1.WorkspaceTypeReference{ + ws.Spec.Type = tenancyv1alpha1.WorkspaceTypeReference{ Name: "universal", Path: "root", } diff --git a/pkg/server/config.go b/pkg/server/config.go index 2594ffcfd02..6b0cb9af170 100644 --- a/pkg/server/config.go +++ b/pkg/server/config.go @@ -153,7 +153,7 @@ func (c *Config) Complete() (CompletedConfig, error) { }}, nil } -const kcpBootstrapperUserName = "system:kcp:bootstrapper" +const KcpBootstrapperUserName = "system:kcp:bootstrapper" func NewConfig(opts *kcpserveroptions.CompletedOptions) (*Config, error) { c := &Config{ @@ -295,7 +295,7 @@ func NewConfig(opts *kcpserveroptions.CompletedOptions) (*Config, error) { } bootstrapConfig := rest.CopyConfig(c.GenericConfig.LoopbackClientConfig) - bootstrapConfig.Impersonate.UserName = kcpBootstrapperUserName + bootstrapConfig.Impersonate.UserName = KcpBootstrapperUserName bootstrapConfig.Impersonate.Groups = []string{bootstrappolicy.SystemKcpWorkspaceBootstrapper} bootstrapConfig = rest.AddUserAgent(bootstrapConfig, "kcp-bootstrapper") diff --git a/pkg/server/controllers.go b/pkg/server/controllers.go index 4bfd603641f..d987bf91271 100644 --- a/pkg/server/controllers.go +++ b/pkg/server/controllers.go @@ -504,7 +504,7 @@ func (s *Server) installWorkspaceScheduler(ctx context.Context, config *rest.Con bootstrapConfig := rest.CopyConfig(config) universalControllerName := fmt.Sprintf("%s-%s", bootstrap.ControllerNameBase, "universal") bootstrapConfig = rest.AddUserAgent(bootstrapConfig, universalControllerName) - bootstrapConfig.Impersonate.UserName = kcpBootstrapperUserName + bootstrapConfig.Impersonate.UserName = KcpBootstrapperUserName bootstrapConfig.Impersonate.Groups = []string{bootstrappolicy.SystemKcpWorkspaceBootstrapper} dynamicClusterClient, err := kcpdynamic.NewForConfig(bootstrapConfig) diff --git a/pkg/server/options/authorization.go b/pkg/server/options/authorization.go index 9323331ae95..3fc6f71f7c2 100644 --- a/pkg/server/options/authorization.go +++ b/pkg/server/options/authorization.go @@ -100,22 +100,38 @@ func (s *Authorization) ApplyTo(config *genericapiserver.Config, informer kcpkub authorizers = append(authorizers, a) } - // kcp authorizers + // kcp authorizers, these are evaluated in reverse order + // TODO: link the markdown + + // bootstrap rules defined once for every workspace bootstrapAuth, bootstrapRules := authz.NewBootstrapPolicyAuthorizer(informer) bootstrapAuth = authz.NewDecorator("bootstrap.authorization.kcp.io", bootstrapAuth).AddAuditLogging().AddAnonymization().AddReasonAnnotation() + // resolves RBAC resources in the workspace localAuth, localResolver := authz.NewLocalAuthorizer(informer) localAuth = authz.NewDecorator("local.authorization.kcp.io", localAuth).AddAuditLogging().AddAnonymization().AddReasonAnnotation() + // everything below - skipped for Deep SAR + + // enforce maximal permission policy maxPermissionPolicyAuth := authz.NewMaximalPermissionPolicyAuthorizer(informer, kcpinformer, union.New(bootstrapAuth, localAuth)) maxPermissionPolicyAuth = authz.NewDecorator("maxpermissionpolicy.authorization.kcp.io", maxPermissionPolicyAuth).AddAuditLogging().AddAnonymization().AddReasonAnnotation() + // protect status updates to apiexport and apibinding systemCRDAuth := authz.NewSystemCRDAuthorizer(maxPermissionPolicyAuth) systemCRDAuth = authz.NewDecorator("systemcrd.authorization.kcp.io", systemCRDAuth).AddAuditLogging().AddAnonymization().AddReasonAnnotation() + // content auth deteremines if users have access to the workspace itself - by default, in Kube there is a set + // of default permissions given even to system:authenticated (like access to discovery) - this authorizer allows + // kcp to make workspaces entirely invisible to users that have not been given access, by making system:authenticated + // mean nothing unless they also have `verb=access` on `/` contentAuth := authz.NewWorkspaceContentAuthorizer(informer, workspaceLister, systemCRDAuth) contentAuth = authz.NewDecorator("content.authorization.kcp.io", contentAuth).AddAuditLogging().AddAnonymization().AddReasonAnnotation() + // workspaces are annotated to list the groups required on users wishing to access the workspace - + // this is mostly useful when adding a core set of groups to an org workspace and having them inherited + // by child workspaces; this gives administrators of an org control over which users can be given access + // to content in sub-workspaces requiredGroupsAuth := authz.NewRequiredGroupsAuthorizer(workspaceLister, contentAuth) requiredGroupsAuth = authz.NewDecorator("requiredgroups.authorization.kcp.io", requiredGroupsAuth).AddAuditLogging().AddAnonymization() diff --git a/pkg/server/options/flags.go b/pkg/server/options/flags.go index e73c4b68925..842164429e3 100644 --- a/pkg/server/options/flags.go +++ b/pkg/server/options/flags.go @@ -182,11 +182,6 @@ var ( // KCP Cache Server flags "cache-server-kubeconfig-file", // Kubeconfig for the cache server this instance connects to (defaults to loopback configuration). - // KCP Virtual Workspaces flags - "virtual-workspaces-workspaces.authorization-cache.jitter-factor", // Jitter factor for cache re-sync. Leave unset to use a default factor. - "virtual-workspaces-workspaces.authorization-cache.resync-period", // Period for cache re-sync. - "virtual-workspaces-workspaces.authorization-cache.sliding", // Whether or not to take into account sync duration in period calculations. - // generic flags "cors-allowed-origins", // List of allowed origins for CORS, comma separated. An allowed origin can be a regular expression to support subdomain matching. If this list is empty CORS will not be enabled. "goaway-chance", // To prevent HTTP/2 clients from getting stuck on a single apiserver, randomly close a connection (GOAWAY). The client's other in-flight requests won't be affected, and the client will reconnect, likely landing on a different apiserver after going through the load balancer again. This argument sets the fraction of requests that will be sent a GOAWAY. Clusters with single apiservers, or which don't use a load balancer, should NOT enable this. Min is 0 (off), Max is .02 (1/50 requests); .001 (1/1000) is a recommended starting point. diff --git a/pkg/virtual/options/options.go b/pkg/virtual/options/options.go index 54a74a794e8..323d2cb9fd9 100644 --- a/pkg/virtual/options/options.go +++ b/pkg/virtual/options/options.go @@ -29,13 +29,11 @@ import ( "github.com/kcp-dev/kcp/pkg/virtual/framework/rootapiserver" initializingworkspacesoptions "github.com/kcp-dev/kcp/pkg/virtual/initializingworkspaces/options" synceroptions "github.com/kcp-dev/kcp/pkg/virtual/syncer/options" - workspacesoptions "github.com/kcp-dev/kcp/pkg/virtual/workspaces/options" ) const virtualWorkspacesFlagPrefix = "virtual-workspaces-" type Options struct { - Workspaces *workspacesoptions.Workspaces Syncer *synceroptions.Syncer APIExport *apiexportoptions.APIExport InitializingWorkspaces *initializingworkspacesoptions.InitializingWorkspaces @@ -43,7 +41,6 @@ type Options struct { func NewOptions() *Options { return &Options{ - Workspaces: workspacesoptions.New(), Syncer: synceroptions.New(), APIExport: apiexportoptions.New(), InitializingWorkspaces: initializingworkspacesoptions.New(), @@ -53,7 +50,6 @@ func NewOptions() *Options { func (o *Options) Validate() []error { var errs []error - errs = append(errs, o.Workspaces.Validate(virtualWorkspacesFlagPrefix)...) errs = append(errs, o.Syncer.Validate(virtualWorkspacesFlagPrefix)...) errs = append(errs, o.APIExport.Validate(virtualWorkspacesFlagPrefix)...) errs = append(errs, o.InitializingWorkspaces.Validate(virtualWorkspacesFlagPrefix)...) @@ -62,7 +58,6 @@ func (o *Options) Validate() []error { } func (o *Options) AddFlags(fs *pflag.FlagSet) { - o.Workspaces.AddFlags(fs, virtualWorkspacesFlagPrefix) o.InitializingWorkspaces.AddFlags(fs, virtualWorkspacesFlagPrefix) } @@ -72,11 +67,6 @@ func (o *Options) NewVirtualWorkspaces( wildcardKubeInformers kcpkubernetesinformers.SharedInformerFactory, wildcardKcpInformers kcpinformers.SharedInformerFactory, ) ([]rootapiserver.NamedVirtualWorkspace, error) { - workspaces, err := o.Workspaces.NewVirtualWorkspaces(rootPathPrefix, config) - if err != nil { - return nil, err - } - syncer, err := o.Syncer.NewVirtualWorkspaces(rootPathPrefix, config, wildcardKcpInformers) if err != nil { return nil, err @@ -92,7 +82,7 @@ func (o *Options) NewVirtualWorkspaces( return nil, err } - all, err := merge(workspaces, syncer, apiexports, initializingworkspaces) + all, err := merge(syncer, apiexports, initializingworkspaces) if err != nil { return nil, err } diff --git a/pkg/virtual/workspaces/builder/build.go b/pkg/virtual/workspaces/builder/build.go deleted file mode 100644 index e4339b424e7..00000000000 --- a/pkg/virtual/workspaces/builder/build.go +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright 2021 The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package builder - -import ( - "context" - "strings" - - kcpkubernetesclientset "github.com/kcp-dev/client-go/kubernetes" - "github.com/kcp-dev/logicalcluster/v3" - - "k8s.io/apimachinery/pkg/util/sets" - kuser "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/apiserver/pkg/registry/rest" - genericapiserver "k8s.io/apiserver/pkg/server" - clientrest "k8s.io/client-go/rest" - "k8s.io/klog/v2" - - "github.com/kcp-dev/kcp/pkg/apis/tenancy" - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" - "github.com/kcp-dev/kcp/pkg/authorization/delegated" - kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" - kcpopenapi "github.com/kcp-dev/kcp/pkg/openapi" - "github.com/kcp-dev/kcp/pkg/virtual/framework" - "github.com/kcp-dev/kcp/pkg/virtual/framework/fixedgvs" - "github.com/kcp-dev/kcp/pkg/virtual/workspaces/registry" -) - -func BuildVirtualWorkspace(cfg *clientrest.Config, rootPathPrefix string, kcpClusterClient kcpclientset.ClusterInterface) framework.VirtualWorkspace { - if !strings.HasSuffix(rootPathPrefix, "/") { - rootPathPrefix += "/" - } - - return &fixedgvs.FixedGroupVersionsVirtualWorkspace{ - ReadyChecker: framework.ReadyFunc(func() error { - return nil - }), - RootPathResolver: framework.RootPathResolverFunc(func(urlPath string, requestContext context.Context) (accepted bool, prefixToStrip string, completedContext context.Context) { - completedContext = requestContext - if path := urlPath; strings.HasPrefix(path, rootPathPrefix) { - path = strings.TrimPrefix(path, rootPathPrefix) - segments := strings.SplitN(path, "/", 2) - if len(segments) < 2 { - return - } - org := segments[0] - - return true, rootPathPrefix + strings.Join(segments[:1], "/"), context.WithValue(requestContext, registry.ClusterKey, logicalcluster.Name(org)) - } - return - }), - Authorizer: authorizer.AuthorizerFunc(newAuthorizer(cfg)), - GroupVersionAPISets: []fixedgvs.GroupVersionAPISet{ - { - // since we are projecting clusterworkspaces to v1beta1.Workspaces - // we need Scheme for v1beta1 - GroupVersion: tenancyv1alpha1.SchemeGroupVersion, - AddToScheme: tenancyv1alpha1.AddToScheme, - OpenAPIDefinitions: kcpopenapi.GetOpenAPIDefinitions, - BootstrapRestResources: func(mainConfig genericapiserver.CompletedConfig) (map[string]fixedgvs.RestStorageBuilder, error) { - workspacesRest := registry.NewREST(kcpClusterClient) - return map[string]fixedgvs.RestStorageBuilder{ - "clusterworkspaces": func(apiGroupAPIServerConfig genericapiserver.CompletedConfig) (rest.Storage, error) { - return workspacesRest, nil - }, - }, nil - }, - }, - }, - } -} - -func newAuthorizer(cfg *clientrest.Config) func(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) { - return func(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) { - if sets.NewString(a.GetUser().GetGroups()...).Has(kuser.SystemPrivilegedGroup) { - return authorizer.DecisionAllow, "", nil - } - - if a.GetAPIGroup() != tenancy.GroupName || a.GetResource() != "clusterworkspaces" || !a.IsResourceRequest() { - return authorizer.DecisionNoOpinion, "", nil - } - - sarClient, err := kcpkubernetesclientset.NewForConfig(cfg) - if err != nil { - klog.Errorf("failed to create impersonated kube cluster client: %v", err) - return authorizer.DecisionNoOpinion, "", nil - } - - // check for permission on the ClusterWorkspace workspace subresource for the - clusterName := ctx.Value(registry.ClusterKey).(logicalcluster.Name) - authz, err := delegated.NewDelegatedAuthorizer(clusterName, sarClient) - if err != nil { - klog.Errorf("failed to get delegated authorizer for logical cluster %s", a.GetUser().GetName(), clusterName) - return authorizer.DecisionNoOpinion, "", nil //nolint:nilerr - } - workspaceAttr := authorizer.AttributesRecord{ - User: a.GetUser(), - Verb: a.GetVerb(), - APIGroup: tenancyv1alpha1.SchemeGroupVersion.Group, - APIVersion: tenancyv1alpha1.SchemeGroupVersion.Version, - Resource: "clusterworkspaces", - Subresource: a.GetSubresource(), - Name: a.GetName(), - ResourceRequest: true, - } - decision, reason, err := authz.Authorize(ctx, workspaceAttr) - if err != nil { - klog.Errorf("failed to authorize user %q to %q clusterworkspace name %q in %s", a.GetUser().GetName(), a.GetVerb(), a.GetName(), clusterName) - return authorizer.DecisionNoOpinion, "", nil //nolint:nilerr - } - - return decision, reason, nil - } -} diff --git a/pkg/virtual/workspaces/options/options.go b/pkg/virtual/workspaces/options/options.go deleted file mode 100644 index a74dea3ff11..00000000000 --- a/pkg/virtual/workspaces/options/options.go +++ /dev/null @@ -1,107 +0,0 @@ -/* -Copyright 2021 The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package options - -import ( - "fmt" - "path" - "time" - - "github.com/spf13/pflag" - - "k8s.io/client-go/rest" - - kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" - "github.com/kcp-dev/kcp/pkg/virtual/framework/rootapiserver" - "github.com/kcp-dev/kcp/pkg/virtual/workspaces/builder" -) - -type Workspaces struct { - AuthorizationCache AuthorizationCache -} - -// AuthorizationCache contains options for the authorization caches in the workspaces service. -type AuthorizationCache struct { - Period time.Duration - JitterFactor float64 - Sliding bool -} - -func New() *Workspaces { - return &Workspaces{ - AuthorizationCache: AuthorizationCache{ - Period: 1 * time.Minute, - JitterFactor: 0, // use the default - Sliding: true, // take into account processing time - }, - } -} - -const workspacesPrefix = "workspaces." -const authorizationCachePrefix = "authorization-cache." - -func (o *Workspaces) AddFlags(flags *pflag.FlagSet, prefix string) { - if o == nil { - return - } - o.AuthorizationCache.AddFlags(flags, prefix+workspacesPrefix+authorizationCachePrefix) -} - -func (o *AuthorizationCache) AddFlags(flags *pflag.FlagSet, prefix string) { - if o == nil { - return - } - flags.DurationVar(&o.Period, prefix+"resync-period", o.Period, "Period for cache re-sync.") - flags.Float64Var(&o.JitterFactor, prefix+"jitter-factor", o.JitterFactor, "Jitter factor for cache re-sync. Leave unset to use a default factor.") - flags.BoolVar(&o.Sliding, prefix+"sliding", o.Sliding, "Whether or not to take into account sync duration in period calculations.") -} - -func (o *Workspaces) Validate(flagPrefix string) []error { - if o == nil { - return nil - } - errs := []error{} - errs = append(errs, o.AuthorizationCache.Validate(flagPrefix+workspacesPrefix+authorizationCachePrefix)...) - - return errs -} - -func (o *AuthorizationCache) Validate(flagPrefix string) []error { - var errs []error - if o.Period == 0 { - errs = append(errs, fmt.Errorf("--%sresync-period cannot be 0", flagPrefix)) - } - if o.JitterFactor < 0 { - errs = append(errs, fmt.Errorf("--%sjitter-factor cannot be less than 0", flagPrefix)) - } - return errs -} - -func (o *Workspaces) NewVirtualWorkspaces( - rootPathPrefix string, - config *rest.Config, -) (workspaces []rootapiserver.NamedVirtualWorkspace, err error) { - config = rest.AddUserAgent(rest.CopyConfig(config), "clusterworkspaces-virtual-workspace") - kcpClusterClient, err := kcpclientset.NewForConfig(config) - if err != nil { - return nil, err - } - - return []rootapiserver.NamedVirtualWorkspace{ - {Name: "clusterworkspaces", VirtualWorkspace: builder.BuildVirtualWorkspace(config, path.Join(rootPathPrefix, "clusterworkspaces"), kcpClusterClient)}, - }, nil -} diff --git a/pkg/virtual/workspaces/printers/printer.go b/pkg/virtual/workspaces/printers/printer.go deleted file mode 100644 index 05e71d1b32a..00000000000 --- a/pkg/virtual/workspaces/printers/printer.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright 2021 The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package printers - -import ( - "sort" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - kprinters "k8s.io/kubernetes/pkg/printers" - - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" -) - -func AddWorkspacePrintHandlers(h kprinters.PrintHandler) { - workspaceColumnDefinitions := []metav1.TableColumnDefinition{ - { - Name: "Name", - Type: "string", - Format: "name", - Description: metav1.ObjectMeta{}.SwaggerDoc()["name"], - Priority: 0, - }, - { - Name: "Type", - Type: "string", - Description: "Type of the workspace", - Priority: 0, - }, - { - Name: "Phase", - Type: "string", - Description: "The current phase (e.g. Scheduling, Initializing, Ready, Deleting)", - Priority: 0, - }, - { - Name: "URL", - Type: "string", - Description: "URL to access the workspace", - Priority: 0, - }, - } - - if err := h.TableHandler(workspaceColumnDefinitions, printWorkspaceList); err != nil { - panic(err) - } - if err := h.TableHandler(workspaceColumnDefinitions, printWorkspace); err != nil { - panic(err) - } -} - -func printWorkspace(workspace *tenancyv1alpha1.ClusterWorkspace, options kprinters.GenerateOptions) ([]metav1.TableRow, error) { - row := metav1.TableRow{ - Object: runtime.RawExtension{Object: workspace}, - } - - phase := workspace.Status.Phase - if workspace.DeletionTimestamp != nil { - phase = "Deleting" - } - row.Cells = append(row.Cells, workspace.Name, workspace.Spec.Type.Name, phase, workspace.Status.BaseURL) - - return []metav1.TableRow{row}, nil -} - -func printWorkspaceList(list *tenancyv1alpha1.ClusterWorkspaceList, options kprinters.GenerateOptions) ([]metav1.TableRow, error) { - sort.Sort(SortableWorkspaces(list.Items)) - rows := make([]metav1.TableRow, 0, len(list.Items)) - for i := range list.Items { - r, err := printWorkspace(&list.Items[i], options) - if err != nil { - return nil, err - } - rows = append(rows, r...) - } - return rows, nil -} - -// SortableWorkspaces is a list of workspaces that can be sorted. -type SortableWorkspaces []tenancyv1alpha1.ClusterWorkspace - -func (list SortableWorkspaces) Len() int { - return len(list) -} - -func (list SortableWorkspaces) Swap(i, j int) { - list[i], list[j] = list[j], list[i] -} - -func (list SortableWorkspaces) Less(i, j int) bool { - return list[i].ObjectMeta.Name < list[j].ObjectMeta.Name -} diff --git a/pkg/virtual/workspaces/registry/rest.go b/pkg/virtual/workspaces/registry/rest.go deleted file mode 100644 index 92e9b88163a..00000000000 --- a/pkg/virtual/workspaces/registry/rest.go +++ /dev/null @@ -1,259 +0,0 @@ -/* -Copyright 2021 The KCP Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package registry - -import ( - "context" - "fmt" - - "github.com/kcp-dev/logicalcluster/v3" - - kerrors "k8s.io/apimachinery/pkg/api/errors" - metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - "k8s.io/apimachinery/pkg/watch" - apirequest "k8s.io/apiserver/pkg/endpoints/request" - "k8s.io/apiserver/pkg/registry/rest" - "k8s.io/klog/v2" - "k8s.io/kubernetes/pkg/printers" - printerstorage "k8s.io/kubernetes/pkg/printers/storage" - - clusterworkspaceadmission "github.com/kcp-dev/kcp/pkg/admission/workspace" - "github.com/kcp-dev/kcp/pkg/apis/tenancy/projection" - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" - tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" - "github.com/kcp-dev/kcp/pkg/authorization/delegated" - kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" - workspaceprinters "github.com/kcp-dev/kcp/pkg/virtual/workspaces/printers" -) - -type WorkspacesScopeKeyType string - -const ( - ClusterKey WorkspacesScopeKeyType = "VirtualWorkspaceWorkspacesOrg" -) - -type REST struct { - kcpClusterClient kcpclientset.ClusterInterface - delegatedAuthz delegated.DelegatedAuthorizerFactory - rest.TableConvertor -} - -var _ rest.Getter = &REST{} -var _ rest.Lister = &REST{} -var _ rest.Watcher = &REST{} -var _ rest.Scoper = &REST{} -var _ rest.Creater = &REST{} -var _ rest.GracefulDeleter = &REST{} - -// NewREST returns a RESTStorage object that will work against Workspace resources, -// projecting them to the Workspace type. -func NewREST( - kcpClusterClient kcpclientset.ClusterInterface, -) *REST { - mainRest := &REST{ - kcpClusterClient: kcpClusterClient, - delegatedAuthz: delegated.NewDelegatedAuthorizer, - - TableConvertor: printerstorage.TableConvertor{TableGenerator: printers.NewTableGenerator().With(workspaceprinters.AddWorkspacePrintHandlers)}, - } - - return mainRest -} - -// New returns a new ClusterWorkspace. -func (s *REST) New() runtime.Object { - return &tenancyv1alpha1.ClusterWorkspace{} -} - -// Destroy implements rest.Storage. -func (s *REST) Destroy() { - // Do nothing -} - -// NewList returns a new ClusterWorkspaceList. -func (*REST) NewList() runtime.Object { - return &tenancyv1alpha1.ClusterWorkspaceList{} -} - -func (s *REST) NamespaceScoped() bool { - return false -} - -// List retrieves a list of Workspaces that match label. -func (s *REST) List(ctx context.Context, options *metainternal.ListOptions) (runtime.Object, error) { - clusterName := ctx.Value(ClusterKey).(logicalcluster.Name) - - v1Opts := metav1.ListOptions{} - if err := metainternal.Convert_internalversion_ListOptions_To_v1_ListOptions(options, &v1Opts, nil); err != nil { - return nil, err - } - ws, err := s.kcpClusterClient.Cluster(clusterName.Path()).TenancyV1beta1().Workspaces().List(ctx, v1Opts) - if err != nil { - return nil, err - } - - cws := &tenancyv1alpha1.ClusterWorkspaceList{ - ListMeta: ws.ListMeta, - Items: make([]tenancyv1alpha1.ClusterWorkspace, len(ws.Items)), - } - - for i := range ws.Items { - w := &ws.Items[i] - projection.ProjectWorkspaceToClusterWorkspace(w, &cws.Items[i]) - } - - return cws, nil -} - -func (s *REST) Watch(ctx context.Context, options *metainternal.ListOptions) (watch.Interface, error) { - clusterName := ctx.Value(ClusterKey).(logicalcluster.Name) - - v1Opts := metav1.ListOptions{} - if err := metainternal.Convert_internalversion_ListOptions_To_v1_ListOptions(options, &v1Opts, nil); err != nil { - return nil, err - } - w, err := s.kcpClusterClient.Cluster(clusterName.Path()).TenancyV1beta1().Workspaces().Watch(ctx, v1Opts) - if err != nil { - return nil, err - } - return withProjection{delegate: w, ch: make(chan watch.Event)}, nil -} - -// Get retrieves a Workspace by name. -func (s *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { - opts := metav1.GetOptions{} - if options != nil { - opts = *options - } - clusterName := ctx.Value(ClusterKey).(logicalcluster.Name) - ws, err := s.kcpClusterClient.Cluster(clusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, name, opts) - if err != nil { - return nil, err - } - - var cws tenancyv1alpha1.ClusterWorkspace - projection.ProjectWorkspaceToClusterWorkspace(ws, &cws) - return &cws, nil -} - -// Create creates a new workspace. -func (s *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { - cws, isWorkspace := obj.(*tenancyv1alpha1.ClusterWorkspace) - if !isWorkspace { - return nil, kerrors.NewInvalid(tenancyv1alpha1.SchemeGroupVersion.WithKind("ClusterWorkspace").GroupKind(), obj.GetObjectKind().GroupVersionKind().String(), []*field.Error{}) - } - - userInfo, ok := apirequest.UserFrom(ctx) - if !ok { - return nil, kerrors.NewForbidden(tenancyv1alpha1.Resource("clusterworkspaces"), "", fmt.Errorf("unable to create a clustersworkspace without a user on the context")) - } - - clusterName := ctx.Value(ClusterKey).(logicalcluster.Name) - ws := &tenancyv1beta1.Workspace{ - ObjectMeta: cws.ObjectMeta, - Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ - Path: cws.Spec.Type.Path, - Name: cws.Spec.Type.Name, - }, - }, - } - - ownerRaw, err := clusterworkspaceadmission.WorkspaceOwnerAnnotationValue(userInfo) - if err != nil { - return nil, fmt.Errorf("error constructing workspace owner annotation from user info: %w", err) - } - - if ws.Annotations == nil { - ws.Annotations = make(map[string]string) - } - ws.Annotations[tenancyv1alpha1.ExperimentalWorkspaceOwnerAnnotationKey] = ownerRaw - - if cws.Spec.Shard != nil { - ws.Spec.Location = &tenancyv1beta1.WorkspaceLocation{ - Selector: cws.Spec.Shard.Selector, - } - if cws.Spec.Shard.Name != "" { - if ws.Spec.Location.Selector == nil { - ws.Spec.Location.Selector = &metav1.LabelSelector{} - } - if ws.Spec.Location.Selector.MatchLabels == nil { - ws.Spec.Location.Selector.MatchLabels = make(map[string]string) - } - ws.Spec.Location.Selector.MatchLabels["name"] = cws.Spec.Shard.Name - } - } - - createdWS, err := s.kcpClusterClient.Cluster(clusterName.Path()).TenancyV1beta1().Workspaces().Create(ctx, ws, metav1.CreateOptions{}) - if kerrors.IsAlreadyExists(err) { - return nil, kerrors.NewAlreadyExists(tenancyv1alpha1.Resource("clusterworkspaces"), cws.Name) - } - if err != nil { - return nil, err - } - var createdCWS tenancyv1alpha1.ClusterWorkspace - projection.ProjectWorkspaceToClusterWorkspace(createdWS, &createdCWS) - - return &createdCWS, nil -} - -func (s *REST) Delete(ctx context.Context, name string, deleteValidation rest.ValidateObjectFunc, options *metav1.DeleteOptions) (runtime.Object, bool, error) { - clusterName := ctx.Value(ClusterKey).(logicalcluster.Name) - logger := klog.FromContext(ctx).WithValues("cluster", clusterName, "name", name) - ctx = klog.NewContext(ctx, logger) - - err := s.kcpClusterClient.Cluster(clusterName.Path()).TenancyV1beta1().Workspaces().Delete(ctx, name, *options) - if kerrors.IsNotFound(err) { - err = kerrors.NewNotFound(tenancyv1beta1.Resource("clusterworkspaces"), name) - } - - return nil, false, err -} - -type withProjection struct { - delegate watch.Interface - ch chan watch.Event -} - -func (w withProjection) ResultChan() <-chan watch.Event { - ch := w.delegate.ResultChan() - - go func() { - defer close(w.ch) - for ev := range ch { - if ev.Object == nil { - w.ch <- ev - continue - } - if ws, ok := ev.Object.(*tenancyv1beta1.Workspace); ok { - cws := &tenancyv1alpha1.ClusterWorkspace{} - projection.ProjectWorkspaceToClusterWorkspace(ws, cws) - ev.Object = cws - } - w.ch <- ev - } - }() - - return w.ch -} - -func (w withProjection) Stop() { - w.delegate.Stop() -} diff --git a/test/e2e/apibinding/maximalpermissionpolicy_authorizer_test.go b/test/e2e/apibinding/maximalpermissionpolicy_authorizer_test.go index 8a9ea88c609..3f8e4bac348 100644 --- a/test/e2e/apibinding/maximalpermissionpolicy_authorizer_test.go +++ b/test/e2e/apibinding/maximalpermissionpolicy_authorizer_test.go @@ -65,9 +65,7 @@ func TestMaximalPermissionPolicyAuthorizerSystemGroupProtection(t *testing.T) { require.NoError(t, err) t.Logf("Creating workspace") - orgClusterName := framework.NewOrganizationFixture(t, server, framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{ - Name: "root", - })) + orgClusterName := framework.NewOrganizationFixture(t, server, framework.WithRootShard()) t.Logf("Giving user-1 admin access") framework.AdmitWorkspaceAccess(ctx, t, kubeClusterClient, orgClusterName.Path(), []string{"user-1"}, nil, true) diff --git a/test/e2e/authorizer/authorizer_test.go b/test/e2e/authorizer/authorizer_test.go index 67e5de7278b..8a2ea6e8619 100644 --- a/test/e2e/authorizer/authorizer_test.go +++ b/test/e2e/authorizer/authorizer_test.go @@ -43,8 +43,6 @@ import ( "k8s.io/kubernetes/pkg/genericcontrolplane" confighelpers "github.com/kcp-dev/kcp/config/helpers" - corev1alpha1 "github.com/kcp-dev/kcp/pkg/apis/core/v1alpha1" - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" "github.com/kcp-dev/kcp/pkg/authorization" "github.com/kcp-dev/kcp/test/e2e/framework" ) @@ -71,11 +69,11 @@ func TestAuthorizer(t *testing.T) { require.NoError(t, err) org1 := framework.NewOrganizationFixture(t, server) - org2 := framework.NewOrganizationFixture(t, server, framework.WithRequiredGroups("empty-group")) + org2 := framework.NewPrivilegedOrganizationFixture(t, server, framework.WithRequiredGroups("empty-group")) framework.NewWorkspaceFixture(t, server, org1.Path(), framework.WithName("workspace1")) framework.NewWorkspaceFixture(t, server, org1.Path(), framework.WithName("workspace2")) - framework.NewWorkspaceFixture(t, server, org2.Path(), framework.WithName("workspace1"), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: corev1alpha1.RootShard})) // on root for deep SAR test + framework.NewWorkspaceFixture(t, server, org2.Path(), framework.WithName("workspace1"), framework.WithRootShard()) // on root for deep SAR test framework.NewWorkspaceFixture(t, server, org2.Path(), framework.WithName("workspace2")) createResources(ctx, t, dynamicClusterClient, kubeDiscoveryClient, org1.Path().Join("workspace1"), "workspace1-resources.yaml") @@ -121,9 +119,9 @@ func TestAuthorizer(t *testing.T) { "with org access, workspace1 non-admin user-2 can access according to local policy": func(t *testing.T) { t.Helper() _, err := user2KubeClusterClient.Cluster(org1.Path().Join("workspace1")).CoreV1().Namespaces().Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test"}}, metav1.CreateOptions{}) - require.Error(t, err, "user-2 should not be able to create namespace in workspace1") + require.Errorf(t, err, "user-2 should not be able to create namespace in %s", org1.Path().Join("workspace1")) _, err = user2KubeClusterClient.Cluster(org1.Path().Join("workspace1")).CoreV1().Secrets("default").List(ctx, metav1.ListOptions{}) - require.NoError(t, err, "user-2 should be able to list secrets in workspace1 as defined in the local policy") + require.NoErrorf(t, err, "user-2 should be able to list secrets in %s as defined in the local policy", org1.Path().Join("workspace1")) }, "with org access, workspace1 non-admin user-2 can access /healthz, /livez, /readyz etc": func(t *testing.T) { t.Helper() @@ -150,21 +148,21 @@ func TestAuthorizer(t *testing.T) { "without org access, org1 workspace1 admin user-1 cannot access org2, not even discovery": func(t *testing.T) { t.Helper() _, err := user1KubeClusterClient.Cluster(org2.Path().Join("workspace1")).CoreV1().ConfigMaps("default").List(ctx, metav1.ListOptions{}) - require.Error(t, err, "user-1 should not be able to list configmaps in a different org") + require.Errorf(t, err, "user-1 should not be able to list configmaps in a different org (%s)", org2.Path().Join("workspace1")) _, err = user1KubeDiscoveryClient.Cluster(org2.Path().Join("workspace1")).ServerResourcesForGroupVersion("rbac.authorization.k8s.io/v1") // can't be core because that always returns nil - require.Error(t, err, "user-1 should not be able to list server resources in a different org") + require.Errorf(t, err, "user-1 should not be able to list server resources in a different org (%s)", org2.Path().Join("workspace1")) }, "as org member, workspace1 admin user-1 cannot access workspace2, not even discovery": func(t *testing.T) { t.Helper() _, err := user1KubeClusterClient.Cluster(org1.Path().Join("workspace2")).CoreV1().ConfigMaps("default").List(ctx, metav1.ListOptions{}) - require.Error(t, err, "user-1 should not be able to list configmaps in a different workspace") + require.Errorf(t, err, "user-1 should not be able to list configmaps in a different workspace (%s)", org1.Path().Join("workspace2")) _, err = user1KubeDiscoveryClient.Cluster(org2.Path().Join("workspace1")).ServerResourcesForGroupVersion("rbac.authorization.k8s.io/v1") // can't be core because that always returns nil - require.Error(t, err, "user-1 should not be able to list server resources in a different workspace") + require.Errorf(t, err, "user-1 should not be able to list server resources in a different workspace (%s)", org1.Path().Join("workspace2")) }, "with org access, workspace2 admin user-2 can access workspace2": func(t *testing.T) { t.Helper() _, err := user2KubeClusterClient.Cluster(org1.Path().Join("workspace2")).CoreV1().ConfigMaps("default").List(ctx, metav1.ListOptions{}) - require.NoError(t, err, "user-2 should be able to list configmaps in workspace2") + require.NoError(t, err, "user-2 should be able to list configmaps in workspace2 (%s)", org1.Path().Join("workspace2")) }, "cluster admins can use wildcard clusters, non-cluster admin cannot": func(t *testing.T) { t.Helper() @@ -232,7 +230,7 @@ func TestAuthorizer(t *testing.T) { return false } return true - }, wait.ForeverTestTimeout, time.Millisecond*100, "User-3 should now be able to list Namespaces") + }, wait.ForeverTestTimeout, time.Millisecond*100, "User-3 should now be able to list Namespaces in %s", org1.Path().Join("workspace2")) }, "without org access, a deep SAR with user-1 against org2 succeeds even without org access for user-1": func(t *testing.T) { t.Helper() diff --git a/test/e2e/conformance/cross_logical_cluster_list_test.go b/test/e2e/conformance/cross_logical_cluster_list_test.go index 62516831608..0e553d04c8f 100644 --- a/test/e2e/conformance/cross_logical_cluster_list_test.go +++ b/test/e2e/conformance/cross_logical_cluster_list_test.go @@ -43,7 +43,6 @@ import ( configcrds "github.com/kcp-dev/kcp/config/crds" "github.com/kcp-dev/kcp/pkg/apis/core" - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" "github.com/kcp-dev/kcp/pkg/informer" @@ -69,25 +68,25 @@ func TestCrossLogicalClusterList(t *testing.T) { // Note: we put all consumer workspaces onto root shard in order to enforce conflicts. logicalClusters := []logicalcluster.Name{ - framework.NewOrganizationFixture(t, server, framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})), - framework.NewOrganizationFixture(t, server, framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})), + framework.NewOrganizationFixture(t, server, framework.WithRootShard()), + framework.NewOrganizationFixture(t, server, framework.WithRootShard()), } expectedWorkspaces := sets.NewString() for i, clusterName := range logicalClusters { clusterName := clusterName // shadow t.Logf("Creating ClusterWorkspace CRs in logical cluster %s", clusterName) - sourceWorkspace := &tenancyv1alpha1.ClusterWorkspace{ + sourceWorkspace := &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("ws-%d", i), }, } - cws, err := kcpClusterClient.Cluster(clusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Create(ctx, sourceWorkspace, metav1.CreateOptions{}) + cws, err := kcpClusterClient.Cluster(clusterName.Path()).TenancyV1beta1().Workspaces().Create(ctx, sourceWorkspace, metav1.CreateOptions{}) require.NoError(t, err, "error creating source workspace") expectedWorkspaces.Insert(logicalcluster.From(cws).String()) server.Artifact(t, func() (runtime.Object, error) { - obj, err := kcpClusterClient.Cluster(clusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, sourceWorkspace.Name, metav1.GetOptions{}) + obj, err := kcpClusterClient.Cluster(clusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, sourceWorkspace.Name, metav1.GetOptions{}) return obj, err }) } @@ -137,11 +136,11 @@ func TestCRDCrossLogicalClusterListPartialObjectMetadata(t *testing.T) { // Note: we put all consumer workspaces onto root shard in order to enforce conflicts. // These 2 workspaces will have the same sheriffs CRD schema as normal CRDs - wsNormalCRD1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) - wsNormalCRD1b := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + wsNormalCRD1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) + wsNormalCRD1b := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) // This workspace will have a different sherrifs CRD schema as a normal CRD - will conflict with 1a/1b. - wsNormalCRD2 := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + wsNormalCRD2 := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) // These 2 workspaces will export a sheriffs API with the same schema wsExport1a := framework.NewWorkspaceFixture(t, server, org.Path()) @@ -151,13 +150,13 @@ func TestCRDCrossLogicalClusterListPartialObjectMetadata(t *testing.T) { wsExport2 := framework.NewWorkspaceFixture(t, server, org.Path()) // This workspace will consume from wsExport1a - wsConsume1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + wsConsume1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) // This workspace will consume from wsExport1b - wsConsume1b := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + wsConsume1b := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) // This workspace will consume from wsExport2 - wsConsume2 := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + wsConsume2 := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) cfg := server.BaseConfig(t) rootShardConfig := server.RootShardSystemMasterBaseConfig(t) @@ -289,7 +288,7 @@ func TestBuiltInCrossLogicalClusterListPartialObjectMetadata(t *testing.T) { require.NoError(t, err, "error creating kube cluster client") for i := 0; i < 3; i++ { - ws := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + ws := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) configMapName := fmt.Sprintf("test-cm-%d", i) configMap := &corev1.ConfigMap{ diff --git a/test/e2e/framework/kcp.go b/test/e2e/framework/kcp.go index 1253523bfa1..b27d417af48 100644 --- a/test/e2e/framework/kcp.go +++ b/test/e2e/framework/kcp.go @@ -324,7 +324,6 @@ func newKcpServer(t *testing.T, cfg kcpConfig, artifactDir, dataDir string) (*kc "--kubeconfig-path=" + filepath.Join(dataDir, "admin.kubeconfig"), "--feature-gates=" + fmt.Sprintf("%s", utilfeature.DefaultFeatureGate), "--audit-log-path", filepath.Join(artifactDir, "kcp.audit"), - "--virtual-workspaces-workspaces.authorization-cache.resync-period=1s", }, cfg.Args...), dataDir: dataDir, diff --git a/test/e2e/framework/workspaces.go b/test/e2e/framework/workspaces.go index 8d45bdbb5e0..19c11c1e548 100644 --- a/test/e2e/framework/workspaces.go +++ b/test/e2e/framework/workspaces.go @@ -29,33 +29,69 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apiserver/pkg/authentication/user" + "github.com/kcp-dev/kcp/pkg/admission/workspace" "github.com/kcp-dev/kcp/pkg/apis/core" corev1alpha1 "github.com/kcp-dev/kcp/pkg/apis/core/v1alpha1" tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" + tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" "github.com/kcp-dev/kcp/pkg/authorization" + bootstrappolicy "github.com/kcp-dev/kcp/pkg/authorization/bootstrap" kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" + "github.com/kcp-dev/kcp/pkg/server" ) -type ClusterWorkspaceOption func(ws *tenancyv1alpha1.ClusterWorkspace) +type ClusterWorkspaceOption interface { + PrivilegedClusterWorkspaceOption | UnprivilegedClusterWorkspaceOption +} + +type PrivilegedClusterWorkspaceOption func(ws *tenancyv1beta1.Workspace) + +type UnprivilegedClusterWorkspaceOption func(ws *tenancyv1beta1.Workspace) + +func WithRootShard() UnprivilegedClusterWorkspaceOption { + return WithShard(corev1alpha1.RootShard) +} -func WithShardConstraints(c tenancyv1alpha1.ShardConstraints) ClusterWorkspaceOption { - return func(ws *tenancyv1alpha1.ClusterWorkspace) { - ws.Spec.Shard = &c +func WithShard(name string) UnprivilegedClusterWorkspaceOption { + return WithLocation(tenancyv1beta1.WorkspaceLocation{Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "name": name, + }, + }}) +} + +func WithLocation(c tenancyv1beta1.WorkspaceLocation) UnprivilegedClusterWorkspaceOption { + return func(ws *tenancyv1beta1.Workspace) { + ws.Spec.Location = &c } } -func WithRequiredGroups(groups ...string) ClusterWorkspaceOption { - return func(ws *tenancyv1alpha1.ClusterWorkspace) { +// WithRequiredGroups is a privileged action, so we return a privileged option type, and only the helpers that +// use the system:master config can consume this. However, workspace initialization requires a valid user annotation +// on the workspace object to impersonate during initialization, and system:master bypasses setting that, so we +// end up needing to hard-code something conceivable. +func WithRequiredGroups(groups ...string) PrivilegedClusterWorkspaceOption { + return func(ws *tenancyv1beta1.Workspace) { if ws.Annotations == nil { ws.Annotations = map[string]string{} } ws.Annotations[authorization.RequiredGroupsAnnotationKey] = strings.Join(groups, ",") + userInfo, err := workspace.WorkspaceOwnerAnnotationValue(&user.DefaultInfo{ + Name: server.KcpBootstrapperUserName, + Groups: []string{user.AllAuthenticated, bootstrappolicy.SystemKcpWorkspaceBootstrapper}, + }) + if err != nil { + // should never happen + panic(err) + } + ws.Annotations[tenancyv1alpha1.ExperimentalWorkspaceOwnerAnnotationKey] = userInfo } } -func WithType(path logicalcluster.Path, name tenancyv1alpha1.WorkspaceTypeName) ClusterWorkspaceOption { - return func(ws *tenancyv1alpha1.ClusterWorkspace) { +func WithType(path logicalcluster.Path, name tenancyv1alpha1.WorkspaceTypeName) UnprivilegedClusterWorkspaceOption { + return func(ws *tenancyv1beta1.Workspace) { ws.Spec.Type = tenancyv1alpha1.WorkspaceTypeReference{ Name: name, Path: path.String(), @@ -63,28 +99,24 @@ func WithType(path logicalcluster.Path, name tenancyv1alpha1.WorkspaceTypeName) } } -func WithName(s string, formatArgs ...interface{}) ClusterWorkspaceOption { - return func(ws *tenancyv1alpha1.ClusterWorkspace) { +func WithName(s string, formatArgs ...interface{}) UnprivilegedClusterWorkspaceOption { + return func(ws *tenancyv1beta1.Workspace) { ws.Name = fmt.Sprintf(s, formatArgs...) ws.GenerateName = "" } } -func NewWorkspaceFixtureObject(t *testing.T, server RunningServer, parent logicalcluster.Path, options ...ClusterWorkspaceOption) *tenancyv1alpha1.ClusterWorkspace { +func NewWorkspaceFixtureObject[O ClusterWorkspaceOption](t *testing.T, clusterClient kcpclientset.ClusterInterface, parent logicalcluster.Path, options ...O) *tenancyv1beta1.Workspace { t.Helper() ctx, cancelFunc := context.WithCancel(context.Background()) t.Cleanup(cancelFunc) - cfg := server.BaseConfig(t) - clusterClient, err := kcpclientset.NewForConfig(cfg) - require.NoError(t, err, "failed to construct client for server") - - tmpl := &tenancyv1alpha1.ClusterWorkspace{ + tmpl := &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "e2e-workspace-", }, - Spec: tenancyv1alpha1.ClusterWorkspaceSpec{ + Spec: tenancyv1beta1.WorkspaceSpec{ Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: tenancyv1alpha1.WorkspaceTypeName("universal"), Path: "root", @@ -99,14 +131,11 @@ func NewWorkspaceFixtureObject(t *testing.T, server RunningServer, parent logica // does not have a fresh enough cache, our request will be denied as the admission controller does not know the // type exists. Therefore, we can require.Eventually our way out of this problem. We expect users to create new // types very infrequently, so we do not think this will be a serious UX issue in the product. - var ws *tenancyv1alpha1.ClusterWorkspace - require.Eventually(t, func() bool { + var ws *tenancyv1beta1.Workspace + Eventually(t, func() (bool, string) { var err error - ws, err = clusterClient.Cluster(parent).TenancyV1alpha1().ClusterWorkspaces().Create(ctx, tmpl, metav1.CreateOptions{}) - if err != nil { - t.Logf("error creating workspace under %s: %v", parent, err) - } - return err == nil + ws, err = clusterClient.Cluster(parent).TenancyV1beta1().Workspaces().Create(ctx, tmpl, metav1.CreateOptions{}) + return err == nil, fmt.Sprintf("error creating workspace under %s: %v", parent, err) }, wait.ForeverTestTimeout, time.Millisecond*100, "failed to create %s workspace under %s", tmpl.Spec.Type.Name, parent) t.Cleanup(func() { @@ -117,7 +146,7 @@ func NewWorkspaceFixtureObject(t *testing.T, server RunningServer, parent logica ctx, cancelFn := context.WithDeadline(context.Background(), time.Now().Add(time.Second*30)) defer cancelFn() - err := clusterClient.Cluster(parent).TenancyV1alpha1().ClusterWorkspaces().Delete(ctx, ws.Name, metav1.DeleteOptions{}) + err := clusterClient.Cluster(parent).TenancyV1beta1().Workspaces().Delete(ctx, ws.Name, metav1.DeleteOptions{}) if apierrors.IsNotFound(err) || apierrors.IsForbidden(err) { return // ignore not found and forbidden because this probably means the parent has been deleted } @@ -125,7 +154,8 @@ func NewWorkspaceFixtureObject(t *testing.T, server RunningServer, parent logica }) Eventually(t, func() (bool, string) { - ws, err = clusterClient.Cluster(parent).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, ws.Name, metav1.GetOptions{}) + var err error + ws, err = clusterClient.Cluster(parent).TenancyV1beta1().Workspaces().Get(ctx, ws.Name, metav1.GetOptions{}) require.Falsef(t, apierrors.IsNotFound(err), "workspace %s was deleted", parent.Join(ws.Name)) require.NoError(t, err, "failed to get workspace %s", parent.Join(ws.Name)) if actual, expected := ws.Status.Phase, corev1alpha1.LogicalClusterPhaseReady; actual != expected { @@ -135,6 +165,7 @@ func NewWorkspaceFixtureObject(t *testing.T, server RunningServer, parent logica }, wait.ForeverTestTimeout, time.Millisecond*100, "failed to wait for %s workspace %s to become ready", ws.Spec.Type, parent.Join(ws.Name)) Eventually(t, func() (bool, string) { + var err error _, err = clusterClient.Cluster(parent.Join(ws.Name)).CoreV1alpha1().LogicalClusters().Get(ctx, corev1alpha1.LogicalClusterName, metav1.GetOptions{}) require.Falsef(t, apierrors.IsNotFound(err), "workspace %s was deleted", parent.Join(ws.Name)) require.NoError(t, err, "failed to get LogicalCluster %s", parent.Join(ws.Name).Join(corev1alpha1.LogicalClusterName)) @@ -145,19 +176,40 @@ func NewWorkspaceFixtureObject(t *testing.T, server RunningServer, parent logica return ws } -func NewWorkspaceFixture(t *testing.T, server RunningServer, orgClusterName logicalcluster.Path, options ...ClusterWorkspaceOption) (clusterName logicalcluster.Name) { +func NewWorkspaceFixture(t *testing.T, server RunningServer, orgClusterName logicalcluster.Path, options ...UnprivilegedClusterWorkspaceOption) (clusterName logicalcluster.Name) { t.Helper() - ws := NewWorkspaceFixtureObject(t, server, orgClusterName, options...) - return logicalcluster.Name(ws.Status.Cluster) + + cfg := server.BaseConfig(t) + clusterClient, err := kcpclientset.NewForConfig(cfg) + require.NoError(t, err, "failed to construct client for server") + + ws := NewWorkspaceFixtureObject(t, clusterClient, orgClusterName, options...) + return logicalcluster.Name(ws.Spec.Cluster) } -func NewOrganizationFixtureObject(t *testing.T, server RunningServer, options ...ClusterWorkspaceOption) *tenancyv1alpha1.ClusterWorkspace { +func NewOrganizationFixtureObject(t *testing.T, server RunningServer, options ...UnprivilegedClusterWorkspaceOption) *tenancyv1beta1.Workspace { t.Helper() - return NewWorkspaceFixtureObject(t, server, core.RootCluster.Path(), append(options, WithType(core.RootCluster.Path(), "organization"))...) + + cfg := server.BaseConfig(t) + clusterClient, err := kcpclientset.NewForConfig(cfg) + require.NoError(t, err, "failed to construct client for server") + + return NewWorkspaceFixtureObject(t, clusterClient, core.RootCluster.Path(), append(options, WithType(core.RootCluster.Path(), "organization"))...) } -func NewOrganizationFixture(t *testing.T, server RunningServer, options ...ClusterWorkspaceOption) (orgClusterName logicalcluster.Name) { +func NewOrganizationFixture(t *testing.T, server RunningServer, options ...UnprivilegedClusterWorkspaceOption) (orgClusterName logicalcluster.Name) { t.Helper() org := NewOrganizationFixtureObject(t, server, options...) - return logicalcluster.Name(org.Status.Cluster) + return logicalcluster.Name(org.Spec.Cluster) +} + +func NewPrivilegedOrganizationFixture[O ClusterWorkspaceOption](t *testing.T, server RunningServer, options ...O) (orgClusterName logicalcluster.Name) { + t.Helper() + + cfg := server.RootShardSystemMasterBaseConfig(t) + clusterClient, err := kcpclientset.NewForConfig(cfg) + require.NoError(t, err, "failed to construct client for server") + + org := NewWorkspaceFixtureObject(t, clusterClient, core.RootCluster.Path(), append(options, O(WithType(core.RootCluster.Path(), "organization")))...) + return logicalcluster.Name(org.Spec.Cluster) } diff --git a/test/e2e/reconciler/cache/replication_test.go b/test/e2e/reconciler/cache/replication_test.go index 1cf17bb1cc6..b992e5081ae 100644 --- a/test/e2e/reconciler/cache/replication_test.go +++ b/test/e2e/reconciler/cache/replication_test.go @@ -40,7 +40,6 @@ import ( apisv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/apis/v1alpha1" "github.com/kcp-dev/kcp/pkg/apis/core" corev1alpha1 "github.com/kcp-dev/kcp/pkg/apis/core/v1alpha1" - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" cacheclient "github.com/kcp-dev/kcp/pkg/cache/client" "github.com/kcp-dev/kcp/pkg/cache/client/shard" kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" @@ -69,7 +68,7 @@ func replicateAPIResourceSchemaScenario(ctx context.Context, t *testing.T, serve t.Helper() org := framework.NewOrganizationFixture(t, server) - clusterName := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + clusterName := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) resourceName := "today.sheriffs.wild.wild.west" scenario := &replicateResourceScenario{resourceName: resourceName, resourceKind: "APIResourceSchema", server: server, kcpShardClusterClient: kcpShardClusterClient, cacheKcpClusterClient: cacheKcpClusterClient} @@ -105,7 +104,7 @@ func replicateAPIResourceSchemaNegativeScenario(ctx context.Context, t *testing. t.Helper() org := framework.NewOrganizationFixture(t, server) - cluster := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + cluster := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) resourceName := "juicy.mangodbs.db.io" scenario := &replicateResourceScenario{resourceName: resourceName, resourceKind: "APIResourceSchema", server: server, kcpShardClusterClient: kcpShardClusterClient, cacheKcpClusterClient: cacheKcpClusterClient} @@ -181,7 +180,7 @@ func replicateAPIExportScenario(ctx context.Context, t *testing.T, server framew t.Helper() org := framework.NewOrganizationFixture(t, server) - cluster := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + cluster := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) resourceName := "wild.wild.west" scenario := &replicateResourceScenario{resourceName: resourceName, resourceKind: "APIExport", server: server, kcpShardClusterClient: kcpShardClusterClient, cacheKcpClusterClient: cacheKcpClusterClient} @@ -228,7 +227,7 @@ func replicateAPIExportNegativeScenario(ctx context.Context, t *testing.T, serve t.Helper() org := framework.NewOrganizationFixture(t, server) - cluster := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + cluster := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) resourceName := "mangodb" scenario := &replicateResourceScenario{resourceName: resourceName, resourceKind: "APIExport", server: server, kcpShardClusterClient: kcpShardClusterClient, cacheKcpClusterClient: cacheKcpClusterClient} diff --git a/test/e2e/reconciler/clusterworkspace/apibinding_initializer_test.go b/test/e2e/reconciler/clusterworkspace/apibinding_initializer_test.go index 5598a3338ca..7bcae4bb7c6 100644 --- a/test/e2e/reconciler/clusterworkspace/apibinding_initializer_test.go +++ b/test/e2e/reconciler/clusterworkspace/apibinding_initializer_test.go @@ -46,10 +46,13 @@ func TestWorkspaceTypesAPIBindingInitialization(t *testing.T) { org := framework.NewOrganizationFixtureObject(t, server) orgPath := core.RootCluster.Path().Join(org.Name) - cowboysProviderWorkspace := framework.NewWorkspaceFixtureObject(t, server, orgPath, framework.WithName("cowboys-provider")) - cowboysProviderPath := orgPath.Join(cowboysProviderWorkspace.Name) cfg := server.BaseConfig(t) + clusterClient, err := kcpclientset.NewForConfig(cfg) + require.NoError(t, err, "failed to construct client for server") + + cowboysProviderWorkspace := framework.NewWorkspaceFixtureObject(t, clusterClient, orgPath, framework.WithName("cowboys-provider")) + cowboysProviderPath := orgPath.Join(cowboysProviderWorkspace.Name) kcpClusterClient, err := kcpclientset.NewForConfig(cfg) require.NoError(t, err, "error creating kcp cluster client") @@ -85,7 +88,7 @@ func TestWorkspaceTypesAPIBindingInitialization(t *testing.T) { cowboysAPIExport, err = kcpClusterClient.Cluster(cowboysProviderPath).ApisV1alpha1().APIExports().Create(ctx, cowboysAPIExport, metav1.CreateOptions{}) require.NoError(t, err, "error creating APIExport") - universal := framework.NewWorkspaceFixtureObject(t, server, orgPath, framework.WithName("universal")) + universal := framework.NewWorkspaceFixtureObject(t, clusterClient, orgPath, framework.WithName("universal")) universalPath := orgPath.Join(universal.Name) cwtParent1 := &tenancyv1alpha1.WorkspaceType{ diff --git a/test/e2e/reconciler/workspacedeletion/controller_test.go b/test/e2e/reconciler/workspacedeletion/controller_test.go index 20526625ef6..38519fc95f9 100644 --- a/test/e2e/reconciler/workspacedeletion/controller_test.go +++ b/test/e2e/reconciler/workspacedeletion/controller_test.go @@ -36,6 +36,7 @@ import ( "github.com/kcp-dev/kcp/pkg/apis/core" corev1alpha1 "github.com/kcp-dev/kcp/pkg/apis/core/v1alpha1" tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" + tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" "github.com/kcp-dev/kcp/pkg/apis/third_party/conditions/util/conditions" kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" "github.com/kcp-dev/kcp/test/e2e/framework" @@ -62,15 +63,19 @@ func TestWorkspaceDeletion(t *testing.T) { orgClusterName := framework.NewOrganizationFixture(t, server) t.Logf("Create a workspace with a shard") - workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Create(ctx, &tenancyv1alpha1.ClusterWorkspace{ + workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1beta1().Workspaces().Create(ctx, &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{Name: "ws-cleanup"}, - Spec: tenancyv1alpha1.ClusterWorkspaceSpec{ + Spec: tenancyv1beta1.WorkspaceSpec{ Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "universal", Path: "root", }, - Shard: &tenancyv1alpha1.ShardConstraints{ - Name: "root", + Location: &tenancyv1beta1.WorkspaceLocation{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "name": corev1alpha1.RootShard, + }, + }, }, }, }, metav1.CreateOptions{}) @@ -78,7 +83,7 @@ func TestWorkspaceDeletion(t *testing.T) { t.Logf("Should have finalizer added in workspace") framework.Eventually(t, func() (bool, string) { - workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, workspace.Name, metav1.GetOptions{}) + workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, workspace.Name, metav1.GetOptions{}) require.NoError(t, err, "failed to get workspace") if len(workspace.Finalizers) == 0 { @@ -90,7 +95,7 @@ func TestWorkspaceDeletion(t *testing.T) { t.Logf("Wait until the %q workspace is ready", workspace.Name) framework.Eventually(t, func() (bool, string) { - workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, workspace.Name, metav1.GetOptions{}) + workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, workspace.Name, metav1.GetOptions{}) require.NoError(t, err, "failed to get workspace") if actual, expected := workspace.Status.Phase, corev1alpha1.LogicalClusterPhaseReady; actual != expected { return false, fmt.Sprintf("workspace phase is %s, not %s", actual, expected) @@ -139,12 +144,12 @@ func TestWorkspaceDeletion(t *testing.T) { _, err = server.kubeClusterClient.Cluster(workspaceCluster).CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}) require.NoError(t, err, "failed to create ns in workspace %s", workspace.Name) - err = server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Delete(ctx, workspace.Name, metav1.DeleteOptions{}) + err = server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1beta1().Workspaces().Delete(ctx, workspace.Name, metav1.DeleteOptions{}) require.NoError(t, err, "failed to delete workspace %s", workspace.Name) t.Logf("The workspace condition should be updated since there is resource in the workspace pending finalization.") framework.Eventually(t, func() (bool, string) { - workspace, err := server.kcpClusterClient.TenancyV1alpha1().ClusterWorkspaces().Cluster(orgClusterName.Path()).Get(ctx, workspace.Name, metav1.GetOptions{}) + workspace, err := server.kcpClusterClient.TenancyV1beta1().Workspaces().Cluster(orgClusterName.Path()).Get(ctx, workspace.Name, metav1.GetOptions{}) require.NoError(t, err) return conditions.IsFalse(workspace, tenancyv1alpha1.WorkspaceContentDeleted), toYAML(t, workspace) }, wait.ForeverTestTimeout, 100*time.Millisecond) @@ -163,7 +168,7 @@ func TestWorkspaceDeletion(t *testing.T) { t.Logf("Ensure workspace is removed") require.Eventually(t, func() bool { - _, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, workspace.Name, metav1.GetOptions{}) + _, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, workspace.Name, metav1.GetOptions{}) return apierrors.IsNotFound(err) }, wait.ForeverTestTimeout, 100*time.Millisecond) @@ -186,23 +191,27 @@ func TestWorkspaceDeletion(t *testing.T) { work: func(ctx context.Context, t *testing.T, server runningServer) { t.Helper() - org := framework.NewOrganizationFixtureObject(t, server, framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) - orgClusterName := logicalcluster.Name(org.Status.Cluster) + org := framework.NewOrganizationFixtureObject(t, server, framework.WithRootShard()) + orgClusterName := logicalcluster.Name(org.Spec.Cluster) t.Logf("Should have finalizer in org workspace") require.Eventually(t, func() bool { - orgWorkspace, err := server.kcpClusterClient.Cluster(core.RootCluster.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, org.Name, metav1.GetOptions{}) + orgWorkspace, err := server.kcpClusterClient.Cluster(core.RootCluster.Path()).TenancyV1beta1().Workspaces().Get(ctx, org.Name, metav1.GetOptions{}) require.NoError(t, err, "failed to get org workspace %s", org.Name) return len(orgWorkspace.Finalizers) > 0 }, wait.ForeverTestTimeout, 100*time.Millisecond) + cfg := server.RunningServer.BaseConfig(t) + clusterClient, err := kcpclientset.NewForConfig(cfg) + require.NoError(t, err, "failed to construct client for server") + t.Logf("Create a workspace with in the org workspace") - ws := framework.NewWorkspaceFixtureObject(t, server.RunningServer, orgClusterName.Path(), framework.WithName("org-ws-cleanup"), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) - wsClusterName := logicalcluster.Name(ws.Status.Cluster) + ws := framework.NewWorkspaceFixtureObject(t, clusterClient, orgClusterName.Path(), framework.WithName("org-ws-cleanup"), framework.WithRootShard()) + wsClusterName := logicalcluster.Name(ws.Spec.Cluster) t.Logf("Should have finalizer added in workspace") require.Eventually(t, func() bool { - workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, ws.Name, metav1.GetOptions{}) + workspace, err := server.kcpClusterClient.Cluster(orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, ws.Name, metav1.GetOptions{}) require.NoError(t, err, "failed to get workspace %s", ws.Name) return len(workspace.Finalizers) > 0 }, wait.ForeverTestTimeout, 100*time.Millisecond) @@ -214,7 +223,7 @@ func TestWorkspaceDeletion(t *testing.T) { }, } - _, err := server.kubeClusterClient.Cluster(wsClusterName.Path()).CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}) + _, err = server.kubeClusterClient.Cluster(wsClusterName.Path()).CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}) require.NoError(t, err, "failed to create ns in workspace root:%s", ws) _, err = server.kubeClusterClient.Cluster(orgClusterName.Path()).CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{}) @@ -228,7 +237,7 @@ func TestWorkspaceDeletion(t *testing.T) { require.NoError(t, err, "failed to create kube client for root shard") t.Logf("Delete org workspace") - err = server.kcpClusterClient.Cluster(core.RootCluster.Path()).TenancyV1alpha1().ClusterWorkspaces().Delete(ctx, org.Name, metav1.DeleteOptions{}) + err = server.kcpClusterClient.Cluster(core.RootCluster.Path()).TenancyV1beta1().Workspaces().Delete(ctx, org.Name, metav1.DeleteOptions{}) require.NoError(t, err, "failed to delete workspace %s", org.Name) t.Logf("Ensure namespace %q in the workspace is deleted", ns.Name) @@ -257,7 +266,7 @@ func TestWorkspaceDeletion(t *testing.T) { t.Logf("Ensure workspace in the org workspace is deleted") framework.Eventually(t, func() (bool, string) { - wslist, err := rootShardKcpClusterClient.TenancyV1alpha1().ClusterWorkspaces().Cluster(orgClusterName.Path()).List(ctx, metav1.ListOptions{}) + wslist, err := rootShardKcpClusterClient.TenancyV1beta1().Workspaces().Cluster(orgClusterName.Path()).List(ctx, metav1.ListOptions{}) // 404 could be returned if the org workspace is deleted. if apierrors.IsNotFound(err) { return true, err.Error() @@ -269,7 +278,7 @@ func TestWorkspaceDeletion(t *testing.T) { t.Logf("Ensure the org workspace is deleted") require.Eventually(t, func() bool { - _, err := rootShardKcpClusterClient.Cluster(core.RootCluster.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, org.Name, metav1.GetOptions{}) + _, err := rootShardKcpClusterClient.Cluster(core.RootCluster.Path()).TenancyV1beta1().Workspaces().Get(ctx, org.Name, metav1.GetOptions{}) return apierrors.IsNotFound(err) }, wait.ForeverTestTimeout, 100*time.Millisecond) }, diff --git a/test/e2e/virtual/clusterworkspaces/virtual_workspace_test.go b/test/e2e/virtual/clusterworkspaces/virtual_workspace_test.go index fb13ae3ba4c..e8adf52bcdc 100644 --- a/test/e2e/virtual/clusterworkspaces/virtual_workspace_test.go +++ b/test/e2e/virtual/clusterworkspaces/virtual_workspace_test.go @@ -41,7 +41,6 @@ import ( virtualcommand "github.com/kcp-dev/kcp/cmd/virtual-workspaces/command" virtualoptions "github.com/kcp-dev/kcp/cmd/virtual-workspaces/options" - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" tenancyv1beta1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1beta1" kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" "github.com/kcp-dev/kcp/test/e2e/framework" @@ -88,7 +87,7 @@ var testCases = []struct { t.Helper() t.Logf("Create ClusterWorkspace workspace1 in the virtual workspace") - workspace1, err := server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Create(ctx, &tenancyv1alpha1.ClusterWorkspace{ + workspace1, err := server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1beta1().Workspaces().Create(ctx, &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{Name: "workspace1"}, }, metav1.CreateOptions{}) require.NoError(t, err) @@ -98,16 +97,16 @@ var testCases = []struct { require.NoError(t, err, "expected to see workspace1 as Workspace") t.Logf("Verify that the ClusterWorkspace results in a ClusterWorkspace of the same name in the org workspace") - _, err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, workspace1.Name, metav1.GetOptions{}) + _, err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, workspace1.Name, metav1.GetOptions{}) require.NoError(t, err, "expected to see workspace1 as Workspace") t.Logf("ClusterWorkspace will show up in a list") - list, err := server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().List(ctx, metav1.ListOptions{}) + list, err := server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1beta1().Workspaces().List(ctx, metav1.ListOptions{}) require.NoError(t, err) require.Len(t, list.Items, 1) t.Logf("Deleting ClusterWorkspace results in Workspace deletion") - err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Delete(ctx, workspace1.Name, metav1.DeleteOptions{}) + err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1beta1().Workspaces().Delete(ctx, workspace1.Name, metav1.DeleteOptions{}) require.NoError(t, err) require.Eventually(t, func() bool { if _, err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, workspace1.Name, metav1.GetOptions{}); kerrors.IsNotFound(err) { @@ -118,7 +117,7 @@ var testCases = []struct { }, wait.ForeverTestTimeout, time.Millisecond*100, "expected Workspace to be deleted") t.Logf("Deleting ClusterWorkspace results in ClusterWorkspace deletion") - _, err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, workspace1.Name, metav1.GetOptions{}) + _, err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, workspace1.Name, metav1.GetOptions{}) if !kerrors.IsNotFound(err) { require.NoError(t, err) } @@ -136,7 +135,7 @@ var testCases = []struct { require.NoError(t, err) t.Logf("Verify that the Workspace results in a ClusterWorkspace of the same name in the org workspace") - _, err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, workspace1.Name, metav1.GetOptions{}) + _, err = server.kcpClusterClient.Cluster(server.orgClusterName.Path()).TenancyV1beta1().Workspaces().Get(ctx, workspace1.Name, metav1.GetOptions{}) require.NoError(t, err, "expected to see workspace1 as Workspace") }, }, @@ -234,7 +233,7 @@ func testWorkspacesVirtualWorkspaces(t *testing.T, standalone bool) { ctx, cancelFunc := context.WithCancel(context.Background()) t.Cleanup(cancelFunc) - orgClusterName := framework.NewOrganizationFixture(t, server, framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + orgClusterName := framework.NewOrganizationFixture(t, server, framework.WithRootShard()) // create non-virtual clients kcpConfig := server.RootShardSystemMasterBaseConfig(t) diff --git a/test/e2e/virtual/initializingworkspaces/virtualworkspace_test.go b/test/e2e/virtual/initializingworkspaces/virtualworkspace_test.go index 0e132bd1116..f09ad445bdd 100644 --- a/test/e2e/virtual/initializingworkspaces/virtualworkspace_test.go +++ b/test/e2e/virtual/initializingworkspaces/virtualworkspace_test.go @@ -571,7 +571,7 @@ func workspaceForType(workspaceType *tenancyv1alpha1.WorkspaceType, testLabelSel Labels: testLabelSelector, }, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: tenancyv1alpha1.WorkspaceTypeName(workspaceType.Name), Path: logicalcluster.From(workspaceType).String(), }, diff --git a/test/e2e/watchcache/watchcache_enabled_test.go b/test/e2e/watchcache/watchcache_enabled_test.go index 63476b2667e..8797fbaf393 100644 --- a/test/e2e/watchcache/watchcache_enabled_test.go +++ b/test/e2e/watchcache/watchcache_enabled_test.go @@ -37,7 +37,6 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/rest" - tenancyv1alpha1 "github.com/kcp-dev/kcp/pkg/apis/tenancy/v1alpha1" kcpclientset "github.com/kcp-dev/kcp/pkg/client/clientset/versioned/cluster" "github.com/kcp-dev/kcp/test/e2e/fixtures/apifixtures" "github.com/kcp-dev/kcp/test/e2e/fixtures/wildwest" @@ -54,7 +53,7 @@ func TestWatchCacheEnabledForCRD(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) org := framework.NewOrganizationFixture(t, server) - clusterName := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + clusterName := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) rootShardConfig := server.RootShardSystemMasterBaseConfig(t) cowBoysGR := metav1.GroupResource{Group: "wildwest.dev", Resource: "cowboys"} @@ -118,8 +117,8 @@ func TestWatchCacheEnabledForAPIBindings(t *testing.T) { require.NoError(t, err) org := framework.NewOrganizationFixture(t, server) - wsExport1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) - wsConsume1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + wsExport1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) + wsConsume1a := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) group := "newyork.io" apifixtures.CreateSheriffsSchemaAndExport(ctx, t, wsExport1a.Path(), kcpClusterClient, group, "export1") @@ -167,7 +166,7 @@ func TestWatchCacheEnabledForBuiltinTypes(t *testing.T) { secretsGR := metav1.GroupResource{Group: "", Resource: "secrets"} org := framework.NewOrganizationFixture(t, server) - clusterName := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithShardConstraints(tenancyv1alpha1.ShardConstraints{Name: "root"})) + clusterName := framework.NewWorkspaceFixture(t, server, org.Path(), framework.WithRootShard()) t.Logf("Creating a secret in the default namespace for %q cluster", clusterName) _, err = kubeClusterClient.Cluster(clusterName.Path()).CoreV1().Secrets("default").Create(ctx, &v1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "topsecret"}}, metav1.CreateOptions{}) diff --git a/test/e2e/workspacetype/controller_test.go b/test/e2e/workspacetype/controller_test.go index 5234c586ae7..2871aab555c 100644 --- a/test/e2e/workspacetype/controller_test.go +++ b/test/e2e/workspacetype/controller_test.go @@ -79,7 +79,7 @@ func TestWorkspaceTypes(t *testing.T) { t.Logf("Expect workspace to be of universal type, and no initializers") workspace, err = server.kcpClusterClient.TenancyV1beta1().Workspaces().Cluster(server.orgClusterName).Get(ctx, workspace.Name, metav1.GetOptions{}) require.NoError(t, err, "failed to get workspace") - require.Equalf(t, workspace.Spec.Type, tenancyv1beta1.WorkspaceTypeReference{ + require.Equalf(t, workspace.Spec.Type, tenancyv1alpha1.WorkspaceTypeReference{ Name: "universal", Path: "root", }, "workspace type is not universal") @@ -96,7 +96,7 @@ func TestWorkspaceTypes(t *testing.T) { workspace, err := server.kcpClusterClient.TenancyV1beta1().Workspaces().Cluster(universal.Path()).Create(ctx, &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{Name: "myapp"}, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: "root", }, @@ -123,7 +123,7 @@ func TestWorkspaceTypes(t *testing.T) { // note: admission is informer based and hence would race with this create call workspace, err = server.kcpClusterClient.TenancyV1beta1().Workspaces().Cluster(universal.Path()).Create(ctx, &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{Name: "myapp"}, - Spec: tenancyv1beta1.WorkspaceSpec{Type: tenancyv1beta1.WorkspaceTypeReference{ + Spec: tenancyv1beta1.WorkspaceSpec{Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: tenancyv1alpha1.TypeName(cwt.Name), Path: logicalcluster.From(cwt).String(), }}, @@ -136,7 +136,7 @@ func TestWorkspaceTypes(t *testing.T) { server.Artifact(t, func() (runtime.Object, error) { return server.kcpClusterClient.TenancyV1beta1().Workspaces().Cluster(universal.Path()).Get(ctx, "myapp", metav1.GetOptions{}) }) - require.Equal(t, workspace.Spec.Type, tenancyv1beta1.WorkspaceTypeReference{ + require.Equal(t, workspace.Spec.Type, tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: logicalcluster.From(cwt).String(), }) @@ -217,7 +217,7 @@ func TestWorkspaceTypes(t *testing.T) { // note: admission is informer based and hence would race with this create call workspace, err = user1KcpClient.TenancyV1beta1().Workspaces().Cluster(universal.Path()).Create(ctx, &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{Name: "myapp"}, - Spec: tenancyv1beta1.WorkspaceSpec{Type: tenancyv1beta1.WorkspaceTypeReference{ + Spec: tenancyv1beta1.WorkspaceSpec{Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: tenancyv1alpha1.TypeName(cwt.Name), Path: logicalcluster.From(cwt).String(), }}, @@ -228,10 +228,10 @@ func TestWorkspaceTypes(t *testing.T) { return err == nil }, wait.ForeverTestTimeout, time.Millisecond*100, "failed to create workspace even with type") server.Artifact(t, func() (runtime.Object, error) { - return server.kcpClusterClient.Cluster(universal.Path()).TenancyV1alpha1().ClusterWorkspaces().Get(ctx, "myapp", metav1.GetOptions{}) + return server.kcpClusterClient.Cluster(universal.Path()).TenancyV1beta1().Workspaces().Get(ctx, "myapp", metav1.GetOptions{}) }) require.Equal(t, workspace.Spec.Type, - tenancyv1beta1.WorkspaceTypeReference{ + tenancyv1alpha1.WorkspaceTypeReference{ Name: "bar", Path: logicalcluster.From(cwt).String(), }) @@ -276,7 +276,7 @@ func TestWorkspaceTypes(t *testing.T) { workspace, err = server.kcpClusterClient.TenancyV1beta1().Workspaces().Cluster(universal.Path()).Create(ctx, &tenancyv1beta1.Workspace{ ObjectMeta: metav1.ObjectMeta{Name: "myapp"}, Spec: tenancyv1beta1.WorkspaceSpec{ - Type: tenancyv1beta1.WorkspaceTypeReference{ + Type: tenancyv1alpha1.WorkspaceTypeReference{ Name: "foo", Path: logicalcluster.From(cwt).String(), },